Annotation of uae/src/custom.c, revision 1.1.1.23

1.1       root        1:  /*
                      2:   * UAE - The Un*x Amiga Emulator
1.1.1.3   root        3:   *
1.1       root        4:   * Custom chip emulation
1.1.1.3   root        5:   *
1.1.1.20  root        6:   * Copyright 1995-2002 Bernd Schmidt
1.1.1.2   root        7:   * Copyright 1995 Alessandro Bissacco
1.1.1.20  root        8:   * Copyright 2000-2002 Toni Wilen
1.1       root        9:   */
                     10: 
                     11: #include "sysconfig.h"
                     12: #include "sysdeps.h"
                     13: 
                     14: #include <ctype.h>
                     15: #include <assert.h>
                     16: 
                     17: #include "config.h"
                     18: #include "options.h"
1.1.1.16  root       19: #include "threaddep/thread.h"
1.1.1.3   root       20: #include "uae.h"
                     21: #include "gensound.h"
                     22: #include "sounddep/sound.h"
1.1       root       23: #include "events.h"
                     24: #include "memory.h"
                     25: #include "custom.h"
                     26: #include "newcpu.h"
                     27: #include "cia.h"
                     28: #include "disk.h"
                     29: #include "blitter.h"
                     30: #include "xwin.h"
1.1.1.23! root       31: #include "inputdevice.h"
1.1.1.3   root       32: #include "audio.h"
1.1       root       33: #include "keybuf.h"
                     34: #include "serial.h"
1.1.1.2   root       35: #include "osemu.h"
1.1.1.3   root       36: #include "autoconf.h"
                     37: #include "gui.h"
                     38: #include "picasso96.h"
1.1.1.4   root       39: #include "drawing.h"
1.1.1.15  root       40: #include "savestate.h"
1.1.1.2   root       41: 
1.1.1.20  root       42: #define SPRITE_COLLISIONS
                     43: 
                     44: static uae_u16 last_custom_value;
                     45: 
1.1.1.6   root       46: static unsigned int n_consecutive_skipped = 0;
                     47: static unsigned int total_skipped = 0;
                     48: 
1.1.1.3   root       49: /* Events */
1.1       root       50: 
1.1.1.14  root       51: unsigned long int currcycle, nextevent, is_lastline;
1.1.1.4   root       52: static int rpt_did_reset;
1.1.1.2   root       53: struct ev eventtab[ev_max];
                     54: 
1.1.1.3   root       55: frame_time_t vsynctime, vsyncmintime;
                     56: 
1.1.1.23! root       57: int vpos;
1.1.1.4   root       58: static uae_u16 lof;
                     59: static int next_lineno;
                     60: static enum nln_how nextline_how;
                     61: static int lof_changed = 0;
1.1       root       62: 
1.1.1.3   root       63: static uae_u32 sprtaba[256],sprtabb[256];
1.1.1.13  root       64: static uae_u32 sprite_ab_merge[256];
                     65: /* Tables for collision detection.  */
                     66: static uae_u32 sprclx[16], clxmask[16];
1.1.1.3   root       67: 
1.1.1.2   root       68: /*
                     69:  * Hardware registers of all sorts.
                     70:  */
1.1       root       71: 
1.1.1.4   root       72: static void custom_wput_1 (int, uaecptr, uae_u32) REGPARAM;
                     73: 
1.1.1.3   root       74: static uae_u16 cregs[256];
1.1       root       75: 
1.1.1.3   root       76: uae_u16 intena,intreq;
                     77: uae_u16 dmacon;
                     78: uae_u16 adkcon; /* used by audio code */
1.1       root       79: 
1.1.1.3   root       80: static uae_u32 cop1lc,cop2lc,copcon;
1.1.1.23! root       81: 
1.1.1.7   root       82: int maxhpos = MAXHPOS_PAL;
                     83: int maxvpos = MAXVPOS_PAL;
                     84: int minfirstline = MINFIRSTLINE_PAL;
                     85: int vblank_endline = VBLANK_ENDLINE_PAL;
                     86: int vblank_hz = VBLANK_HZ_PAL;
                     87: unsigned long syncbase;
                     88: static int fmode;
                     89: static unsigned int beamcon0, new_beamcon0;
                     90: 
1.1.1.15  root       91: #define MAX_SPRITES 8
1.1       root       92: 
1.1.1.2   root       93: /* This is but an educated guess. It seems to be correct, but this stuff
                     94:  * isn't documented well. */
1.1.1.20  root       95: enum sprstate { SPR_restart, SPR_waiting_start, SPR_waiting_stop };
1.1.1.10  root       96: 
                     97: struct sprite {
                     98:     uaecptr pt;
                     99:     int xpos;
                    100:     int vstart;
                    101:     int vstop;
                    102:     int armed;
                    103:     enum sprstate state;
                    104: };
                    105: 
                    106: static struct sprite spr[8];
                    107: 
1.1.1.20  root      108: static int sprite_vblank_endline = 25;
1.1       root      109: 
1.1.1.15  root      110: static unsigned int sprctl[MAX_SPRITES], sprpos[MAX_SPRITES];
                    111: static uae_u16 sprdata[MAX_SPRITES][4], sprdatb[MAX_SPRITES][4];
1.1.1.10  root      112: static int sprite_last_drawn_at[MAX_SPRITES];
1.1.1.7   root      113: static int last_sprite_point, nr_armed;
1.1.1.15  root      114: static int sprite_width, sprres, sprite_buffer_res;
1.1.1.7   root      115: 
1.1.1.6   root      116: static uae_u32 bpl1dat, bpl2dat, bpl3dat, bpl4dat, bpl5dat, bpl6dat, bpl7dat, bpl8dat;
                    117: static uae_s16 bpl1mod, bpl2mod;
1.1       root      118: 
1.1.1.3   root      119: static uaecptr bplpt[8];
1.1.1.10  root      120: uae_u8 *real_bplpt[8];
1.1.1.15  root      121: /* Used as a debugging aid, to offset any bitplane temporarily.  */
1.1.1.16  root      122: int bpl_off[8];
1.1       root      123: 
                    124: /*static int blitcount[256];  blitter debug */
                    125: 
1.1.1.2   root      126: static struct color_entry current_colors;
1.1.1.6   root      127: static unsigned int bplcon0, bplcon1, bplcon2, bplcon3, bplcon4;
1.1.1.4   root      128: static unsigned int diwstrt, diwstop, diwhigh;
                    129: static int diwhigh_written;
                    130: static unsigned int ddfstrt, ddfstop;
1.1.1.7   root      131: 
1.1.1.4   root      132: /* The display and data fetch windows */
1.1       root      133: 
1.1.1.4   root      134: enum diw_states
                    135: {
                    136:     DIW_waiting_start, DIW_waiting_stop
                    137: };
1.1       root      138: 
1.1.1.22  root      139: int plffirstline, plflastline, plfstrt, plfstop;
1.1.1.13  root      140: static int last_diw_pix_hpos, last_ddf_pix_hpos, last_decide_line_hpos;
                    141: static int last_fetch_hpos, last_sprite_hpos;
1.1.1.6   root      142: int diwfirstword, diwlastword;
1.1.1.4   root      143: static enum diw_states diwstate, hdiwstate;
1.1       root      144: 
1.1.1.4   root      145: /* Sprite collisions */
1.1.1.14  root      146: static unsigned int clxdat, clxcon, clxcon2, clxcon_bpl_enable, clxcon_bpl_match;
                    147: static int clx_sprmask;
1.1.1.4   root      148: 
                    149: enum copper_states {
                    150:     COP_stop,
1.1.1.15  root      151:     COP_read1_in2,
                    152:     COP_read1_wr_in4,
                    153:     COP_read1_wr_in2,
                    154:     COP_read1,
                    155:     COP_read2_wr_in2,
                    156:     COP_read2,
1.1.1.4   root      157:     COP_bltwait,
1.1.1.15  root      158:     COP_wait_in4,
                    159:     COP_wait_in2,
                    160:     COP_skip_in4,
                    161:     COP_skip_in2,
                    162:     COP_wait1,
                    163:     COP_wait
1.1.1.4   root      164: };
                    165: 
                    166: struct copper {
                    167:     /* The current instruction words.  */
                    168:     unsigned int i1, i2;
1.1.1.15  root      169:     unsigned int saved_i1, saved_i2;
1.1.1.4   root      170:     enum copper_states state;
                    171:     /* Instruction pointer.  */
1.1.1.15  root      172:     uaecptr ip, saved_ip;
1.1.1.10  root      173:     int hpos, vpos;
1.1.1.4   root      174:     unsigned int ignore_next;
1.1.1.10  root      175:     int vcmp, hcmp;
1.1.1.15  root      176: 
1.1.1.22  root      177:     int strobe; /* COPJMP1 / COPJMP2 accessed */
                    178:     int last_write, last_write_hpos;
1.1.1.4   root      179: };
                    180: 
                    181: static struct copper cop_state;
1.1.1.10  root      182: static int copper_enabled_thisline;
                    183: static int cop_min_waittime;
1.1       root      184: 
                    185: /*
                    186:  * Statistics
                    187:  */
                    188: 
1.1.1.2   root      189: /* Used also by bebox.cpp */
1.1.1.6   root      190: unsigned long int msecs = 0, frametime = 0, lastframetime = 0, timeframes = 0;
1.1       root      191: static unsigned long int seconds_base;
                    192: int bogusframe;
1.1.1.12  root      193: int n_frames;
1.1.1.4   root      194: 
1.1.1.15  root      195: #define DEBUG_COPPER 0
                    196: #if DEBUG_COPPER
                    197: /* 10000 isn't enough!  */
                    198: #define NR_COPPER_RECORDS 40000
                    199: #else
                    200: #define NR_COPPER_RECORDS 1
                    201: #endif
                    202: 
                    203: /* Record copper activity for the debugger.  */
                    204: struct cop_record
                    205: {
                    206:   int hpos, vpos;
                    207:   uaecptr addr;
                    208: };
                    209: static struct cop_record cop_record[2][NR_COPPER_RECORDS];
                    210: static int nr_cop_records[2];
                    211: static int curr_cop_set;
                    212: 
                    213: /* Recording of custom chip register changes.  */
1.1.1.4   root      214: static int current_change_set;
                    215: 
                    216: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
                    217: /* sam: Those arrays uses around 7Mb of BSS... That seems  */
                    218: /* too much for AmigaDOS (uae crashes as soon as one loads */
                    219: /* it. So I use a different strategy here (realloc the     */
                    220: /* arrays when needed. That strategy might be usefull for  */
                    221: /* computer with low memory.                               */
1.1.1.13  root      222: struct sprite_entry  *sprite_entries[2];
1.1.1.4   root      223: struct color_change *color_changes[2];
1.1.1.13  root      224: static int max_sprite_entry = 400;
                    225: static int delta_sprite_entry = 0;
1.1.1.4   root      226: static int max_color_change = 400;
                    227: static int delta_color_change = 0;
                    228: #else
1.1.1.13  root      229: struct sprite_entry sprite_entries[2][MAX_SPR_PIXELS / 16];
1.1.1.4   root      230: struct color_change color_changes[2][MAX_REG_CHANGE];
                    231: #endif
                    232: 
1.1.1.7   root      233: struct decision line_decisions[2 * (MAXVPOS + 1) + 1];
                    234: struct draw_info line_drawinfo[2][2 * (MAXVPOS + 1) + 1];
                    235: struct color_entry color_tables[2][(MAXVPOS + 1) * 2];
1.1.1.4   root      236: 
1.1.1.13  root      237: static int next_sprite_entry = 0;
                    238: static int prev_next_sprite_entry;
                    239: static int next_sprite_forced = 1;
                    240: 
                    241: struct sprite_entry *curr_sprite_entries, *prev_sprite_entries;
1.1.1.4   root      242: struct color_change *curr_color_changes, *prev_color_changes;
                    243: struct draw_info *curr_drawinfo, *prev_drawinfo;
                    244: struct color_entry *curr_color_tables, *prev_color_tables;
                    245: 
1.1.1.13  root      246: static int next_color_change;
1.1.1.4   root      247: static int next_color_entry, remembered_color_entry;
                    248: static int color_src_match, color_dest_match, color_compare_result;
                    249: 
1.1.1.13  root      250: static uae_u32 thisline_changed;
1.1.1.4   root      251: 
                    252: #ifdef SMART_UPDATE
1.1.1.5   root      253: #define MARK_LINE_CHANGED do { thisline_changed = 1; } while (0)
1.1.1.4   root      254: #else
1.1.1.5   root      255: #define MARK_LINE_CHANGED do { ; } while (0)
1.1.1.4   root      256: #endif
                    257: 
                    258: static struct decision thisline_decision;
1.1.1.13  root      259: static int passed_plfstop, fetch_cycle;
                    260: 
                    261: enum fetchstate {
                    262:     fetch_not_started,
                    263:     fetch_started,
                    264:     fetch_was_plane0
                    265: } fetch_state;
1.1.1.4   root      266: 
1.1       root      267: /*
                    268:  * helper functions
                    269:  */
                    270: 
1.1.1.22  root      271: STATIC_INLINE int nodraw (void)
                    272: {
                    273:     return framecnt != 0;
                    274: }
                    275: 
1.1.1.15  root      276: uae_u32 get_copper_address (int copno)
                    277: {
                    278:     switch (copno) {
                    279:     case 1: return cop1lc;
                    280:     case 2: return cop2lc;
                    281:     default: return 0;
                    282:     }
                    283: }
                    284: 
                    285: STATIC_INLINE void record_copper (uaecptr addr, int hpos, int vpos)
                    286: {
                    287: #if DEBUG_COPPER
                    288:     int t = nr_cop_records[curr_cop_set];
                    289:     if (t < NR_COPPER_RECORDS) {
                    290:        cop_record[curr_cop_set][t].addr = addr;
                    291:        cop_record[curr_cop_set][t].hpos = hpos;
                    292:        cop_record[curr_cop_set][t].vpos = vpos;
                    293:        nr_cop_records[curr_cop_set] = t + 1;
                    294:     }
                    295: #endif
                    296: }
                    297: 
                    298: int find_copper_record (uaecptr addr, int *phpos, int *pvpos)
                    299: {
                    300:     int s = curr_cop_set ^ 1;
                    301:     int t = nr_cop_records[s];
                    302:     int i;
                    303:     for (i = 0; i < t; i++) {
                    304:        if (cop_record[s][i].addr == addr) {
                    305:            *phpos = cop_record[s][i].hpos;
                    306:            *pvpos = cop_record[s][i].vpos;
                    307:            return 1;
                    308:        }
                    309:     }
                    310:     return 0;
                    311: }
                    312: 
1.1.1.4   root      313: int rpt_available = 0;
1.1.1.3   root      314: 
1.1.1.4   root      315: void reset_frame_rate_hack (void)
                    316: {
                    317:     if (currprefs.m68k_speed != -1)
                    318:        return;
                    319: 
                    320:     if (! rpt_available) {
                    321:        currprefs.m68k_speed = 0;
                    322:        return;
                    323:     }
1.1.1.3   root      324: 
1.1.1.4   root      325:     rpt_did_reset = 1;
                    326:     is_lastline = 0;
                    327:     vsyncmintime = read_processor_time() + vsynctime;
                    328:     write_log ("Resetting frame rate hack\n");
                    329: }
1.1       root      330: 
1.1.1.8   root      331: STATIC_INLINE void setclr (uae_u16 *p, uae_u16 val)
1.1       root      332: {
1.1.1.6   root      333:     if (val & 0x8000)
1.1       root      334:        *p |= val & 0x7FFF;
1.1.1.6   root      335:     else
1.1       root      336:        *p &= ~val;
                    337: }
                    338: 
1.1.1.3   root      339: __inline__ int current_hpos (void)
1.1       root      340: {
1.1.1.14  root      341:     return (get_cycles () - eventtab[ev_hsync].oldcycles) / CYCLE_UNIT;
1.1       root      342: }
                    343: 
1.1.1.8   root      344: STATIC_INLINE uae_u8 *pfield_xlateptr (uaecptr plpt, int bytecount)
1.1.1.2   root      345: {
1.1.1.4   root      346:     if (!chipmem_bank.check (plpt, bytecount)) {
1.1.1.2   root      347:        static int count = 0;
1.1.1.3   root      348:        if (!count)
                    349:            count++, write_log ("Warning: Bad playfield pointer\n");
1.1.1.2   root      350:        return NULL;
                    351:     }
1.1.1.4   root      352:     return chipmem_bank.xlateaddr (plpt);
1.1.1.2   root      353: }
                    354: 
1.1.1.8   root      355: STATIC_INLINE void docols (struct color_entry *colentry)
1.1.1.3   root      356: {
                    357:     int i;
1.1.1.11  root      358: 
                    359:     if (currprefs.chipset_mask & CSMASK_AGA) {
1.1.1.20  root      360:        for (i = 0; i < 256; i++) {
1.1.1.11  root      361:            int v = color_reg_get (colentry, i);
1.1.1.14  root      362:            if (v < 0 || v > 16777215)
1.1.1.11  root      363:                continue;
                    364:            colentry->acolors[i] = CONVERT_RGB (v);
                    365:        }
                    366:     } else {
1.1.1.20  root      367:        for (i = 0; i < 32; i++) {
1.1.1.11  root      368:            int v = color_reg_get (colentry, i);
                    369:            if (v < 0 || v > 4095)
                    370:                continue;
                    371:            colentry->acolors[i] = xcolors[v];
                    372:        }
1.1.1.3   root      373:     }
                    374: }
                    375: 
                    376: void notice_new_xcolors (void)
                    377: {
                    378:     int i;
                    379: 
                    380:     docols(&current_colors);
1.1.1.4   root      381: /*    docols(&colors_for_drawing);*/
1.1.1.7   root      382:     for (i = 0; i < (MAXVPOS + 1)*2; i++) {
1.1.1.3   root      383:        docols(color_tables[0]+i);
                    384:        docols(color_tables[1]+i);
                    385:     }
                    386: }
                    387: 
1.1.1.20  root      388: static void do_sprites (int currhp);
1.1.1.2   root      389: 
                    390: static void remember_ctable (void)
                    391: {
                    392:     if (remembered_color_entry == -1) {
                    393:        /* The colors changed since we last recorded a color map. Record a
                    394:         * new one. */
1.1.1.11  root      395:        color_reg_cpy (curr_color_tables + next_color_entry, &current_colors);
1.1.1.2   root      396:        remembered_color_entry = next_color_entry++;
                    397:     }
                    398:     thisline_decision.ctable = remembered_color_entry;
                    399:     if (color_src_match == -1 || color_dest_match != remembered_color_entry
                    400:        || line_decisions[next_lineno].ctable != color_src_match)
                    401:     {
                    402:        /* The remembered comparison didn't help us - need to compare again. */
                    403:        int oldctable = line_decisions[next_lineno].ctable;
                    404:        int changed = 0;
                    405: 
1.1.1.3   root      406:        if (oldctable == -1) {
1.1.1.2   root      407:            changed = 1;
                    408:            color_src_match = color_dest_match = -1;
                    409:        } else {
1.1.1.11  root      410:            color_compare_result = color_reg_cmp (&prev_color_tables[oldctable], &current_colors) != 0;
1.1.1.3   root      411:            if (color_compare_result)
                    412:                changed = 1;
                    413:            color_src_match = oldctable;
1.1.1.2   root      414:            color_dest_match = remembered_color_entry;
1.1.1.3   root      415:        }
1.1.1.5   root      416:        thisline_changed |= changed;
1.1.1.3   root      417:     } else {
                    418:        /* We know the result of the comparison */
                    419:        if (color_compare_result)
1.1.1.5   root      420:            thisline_changed = 1;
1.1.1.3   root      421:     }
                    422: }
                    423: 
                    424: static void remember_ctable_for_border (void)
                    425: {
                    426:     remember_ctable ();
1.1.1.2   root      427: }
                    428: 
1.1.1.3   root      429: /* Called to determine the state of the horizontal display window state
                    430:  * machine at the current position. It might have changed since we last
                    431:  * checked.  */
1.1.1.4   root      432: static void decide_diw (int hpos)
1.1.1.2   root      433: {
1.1.1.13  root      434:     int pix_hpos = coord_diw_to_window_x (hpos * 2);
1.1.1.3   root      435:     if (hdiwstate == DIW_waiting_start && thisline_decision.diwfirstword == -1
1.1.1.9   root      436:        && pix_hpos >= diwfirstword && last_diw_pix_hpos < diwfirstword)
1.1.1.3   root      437:     {
1.1.1.13  root      438:        thisline_decision.diwfirstword = diwfirstword < 0 ? 0 : diwfirstword;
1.1.1.3   root      439:        hdiwstate = DIW_waiting_stop;
1.1.1.2   root      440:        thisline_decision.diwlastword = -1;
                    441:     }
1.1.1.3   root      442:     if (hdiwstate == DIW_waiting_stop && thisline_decision.diwlastword == -1
1.1.1.9   root      443:        && pix_hpos >= diwlastword && last_diw_pix_hpos < diwlastword)
1.1.1.3   root      444:     {
1.1.1.13  root      445:        thisline_decision.diwlastword = diwlastword < 0 ? 0 : diwlastword;
1.1.1.3   root      446:        hdiwstate = DIW_waiting_start;
1.1.1.2   root      447:     }
1.1.1.9   root      448:     last_diw_pix_hpos = pix_hpos;
1.1.1.2   root      449: }
                    450: 
1.1.1.22  root      451: 
                    452: static int fetchmode;
                    453: static int maxplanes_ocs[]={ 6,4,0,0 };
                    454: static int maxplanes_ecs[]={ 6,4,2,0 };
                    455: static int maxplanes_aga[]={ 8,4,2,0, 8,8,4,0, 8,8,8,0 };
                    456: 
                    457: static int get_maxplanes (int res)
                    458: {
                    459:     int *planes;
                    460:     if (currprefs.chipset_mask & CSMASK_AGA)
                    461:        planes = maxplanes_aga;
                    462:     else if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE))
                    463:        planes = maxplanes_ocs;
                    464:     else
                    465:        planes = maxplanes_ecs;
                    466:     return planes[fetchmode * 4 + res];
                    467: }
                    468: 
                    469: /* Disable bitplane DMA if planes > maxplanes.  This is needed e.g. by the
1.1.1.23! root      470:    Sanity WOC demo (at the "Party Effect").  */
1.1.1.22  root      471: STATIC_INLINE int GET_PLANES_LIMIT (uae_u16 v)
                    472: {
                    473:     if (GET_PLANES(v) > get_maxplanes (GET_RES(v)))
                    474:        v &= ~0x7010;
                    475:     return GET_PLANES (v);
                    476: }
                    477: 
1.1.1.13  root      478: /* The HRM says 0xD8, but that can't work... */
1.1.1.22  root      479: #define HARD_DDF_STOP 0xd4
                    480: #define HARD_DDF_START 0x18
1.1.1.2   root      481: 
1.1.1.22  root      482: static void add_modulos (void)
1.1.1.13  root      483: {
1.1.1.15  root      484:     int m1, m2;
                    485: 
1.1.1.23! root      486:     if (fmode & 0x4000) {
1.1.1.15  root      487:        if (((diwstrt >> 8) ^ vpos) & 1)
                    488:            m1 = m2 = bpl2mod;
                    489:        else
                    490:            m1 = m2 = bpl1mod;
                    491:     } else {
                    492:        m1 = bpl1mod;
                    493:        m2 = bpl2mod;
                    494:     }
                    495: 
1.1.1.13  root      496:     if (dmaen (DMA_BITPLANE))
1.1.1.23! root      497:        switch (GET_PLANES_LIMIT (bplcon0)) {
1.1.1.15  root      498:        case 8: bplpt[7] += m2;
                    499:        case 7: bplpt[6] += m1;
                    500:        case 6: bplpt[5] += m2;
                    501:        case 5: bplpt[4] += m1;
                    502:        case 4: bplpt[3] += m2;
                    503:        case 3: bplpt[2] += m1;
                    504:        case 2: bplpt[1] += m2;
                    505:        case 1: bplpt[0] += m1;
1.1.1.13  root      506:        }
1.1.1.22  root      507: }
                    508: 
                    509: static void finish_playfield_line (void)
                    510: {
                    511:     /* The latter condition might be able to happen in interlaced frames. */
                    512:     if (vpos >= minfirstline && (thisframe_first_drawn_line == -1 || vpos < thisframe_first_drawn_line))
                    513:        thisframe_first_drawn_line = vpos;
                    514:     thisframe_last_drawn_line = vpos;
                    515: 
                    516:     add_modulos ();
1.1.1.2   root      517: 
                    518:     /* These are for comparison. */
                    519:     thisline_decision.bplcon0 = bplcon0;
                    520:     thisline_decision.bplcon2 = bplcon2;
1.1.1.14  root      521:     thisline_decision.bplcon3 = bplcon3;
1.1.1.2   root      522:     thisline_decision.bplcon4 = bplcon4;
                    523: 
                    524: #ifdef SMART_UPDATE
1.1.1.13  root      525:     if (line_decisions[next_lineno].plflinelen != thisline_decision.plflinelen
                    526:        || line_decisions[next_lineno].plfleft != thisline_decision.plfleft
1.1.1.2   root      527:        || line_decisions[next_lineno].bplcon0 != thisline_decision.bplcon0
                    528:        || line_decisions[next_lineno].bplcon2 != thisline_decision.bplcon2
1.1.1.14  root      529:        || line_decisions[next_lineno].bplcon3 != thisline_decision.bplcon3
1.1.1.2   root      530:        || line_decisions[next_lineno].bplcon4 != thisline_decision.bplcon4
                    531:        )
                    532: #endif /* SMART_UPDATE */
1.1.1.5   root      533:        thisline_changed = 1;
1.1.1.2   root      534: }
                    535: 
1.1.1.15  root      536: /* The fetch unit mainly controls ddf stop.  It's the number of cycles that
                    537:    are contained in an indivisible block during which ddf is active.  E.g.
                    538:    if DDF starts at 0x30, and fetchunit is 8, then possible DDF stops are
                    539:    0x30 + n * 8.  */
                    540: static int fetchunit, fetchunit_mask;
                    541: /* The delay before fetching the same bitplane again.  Can be larger than
                    542:    the number of bitplanes; in that case there are additional empty cycles
                    543:    with no data fetch (this happens for high fetchmodes and low
                    544:    resolutions).  */
1.1.1.14  root      545: static int fetchstart, fetchstart_shift, fetchstart_mask;
1.1.1.15  root      546: /* fm_maxplane holds the maximum number of planes possible with the current
                    547:    fetch mode.  This selects the cycle diagram:
                    548:    8 planes: 73516240
                    549:    4 planes: 3120
                    550:    2 planes: 10.  */
1.1.1.14  root      551: static int fm_maxplane, fm_maxplane_shift;
                    552: 
1.1.1.15  root      553: /* The corresponding values, by fetchmode and display resolution.  */
                    554: static int fetchunits[] = { 8,8,8,0, 16,8,8,0, 32,16,8,0 };
                    555: static int fetchstarts[] = { 3,2,1,0, 4,3,2,0, 5,4,3,0 };
1.1.1.23! root      556: static int fm_maxplanes[] = { 3,2,1,0, 3,3,2,0, 3,3,3,0 };
1.1.1.15  root      557: 
1.1.1.22  root      558: static uae_u8 cycle_diagram_table[3][3][9][32];
                    559: static uae_u8 cycle_diagram_free_cycles[3][3][9];
                    560: static uae_u8 cycle_diagram_total_cycles[3][3][9];
                    561: static uae_u8 *curr_diagram;
                    562: static uae_u8 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 };
1.1.1.16  root      563: 
                    564: static void debug_cycle_diagram(void)
                    565: {
                    566:     int fm, res, planes, cycle, v;
                    567:     char aa;
                    568: 
                    569:     for (fm = 0; fm < 3; fm++) {
                    570:        write_log ("FMODE %d\n=======\n", fm);
                    571:        for (res = 0; res <= 2; res++) {
                    572:            for (planes = 0; planes <= 8; planes++) {
                    573:                write_log("%d: ",planes);
                    574:                for (cycle = 0; cycle < 32; cycle++) {
                    575:                    v=cycle_diagram_table[fm][res][planes][cycle];
                    576:                    if (v==0) aa='-'; else if(v>0) aa='1'; else aa='X';
                    577:                    write_log("%c",aa);
                    578:                }
1.1.1.22  root      579:                write_log(" %d:%d\n",
                    580:                          cycle_diagram_free_cycles[fm][res][planes], cycle_diagram_total_cycles[fm][res][planes]);
1.1.1.16  root      581:            }
                    582:            write_log("\n");
                    583:        }
                    584:     }
                    585:     fm=0;
                    586: }
                    587: 
                    588: static void create_cycle_diagram_table(void)
                    589: {
                    590:     int fm, res, cycle, planes, v;
1.1.1.22  root      591:     int fetch_start, max_planes, freecycles;
                    592:     uae_u8 *cycle_sequence;
1.1.1.16  root      593: 
                    594:     for (fm = 0; fm <= 2; fm++) {
                    595:        for (res = 0; res <= 2; res++) {
                    596:            max_planes = fm_maxplanes[fm * 4 + res];
                    597:            fetch_start = 1 << fetchstarts[fm * 4 + res];
                    598:            cycle_sequence = &cycle_sequences[(max_planes - 1) * 8];
                    599:            max_planes = 1 << max_planes;
                    600:            for (planes = 0; planes <= 8; planes++) {
1.1.1.23! root      601:                freecycles = 0;
1.1.1.16  root      602:                for (cycle = 0; cycle < 32; cycle++)
                    603:                    cycle_diagram_table[fm][res][planes][cycle] = -1;
                    604:                if (planes <= max_planes) {
                    605:                    for (cycle = 0; cycle < fetch_start; cycle++) {
                    606:                        if (cycle < max_planes && planes >= cycle_sequence[cycle & 7]) {
1.1.1.22  root      607:                            v = cycle_sequence[cycle & 7];
1.1.1.16  root      608:                        } else {
                    609:                            v = 0;
1.1.1.22  root      610:                            freecycles++;
1.1.1.16  root      611:                        }
                    612:                        cycle_diagram_table[fm][res][planes][cycle] = v;
                    613:                    }
                    614:                }
1.1.1.22  root      615:                cycle_diagram_free_cycles[fm][res][planes] = freecycles;
                    616:                cycle_diagram_total_cycles[fm][res][planes] = fetch_start;
1.1.1.16  root      617:            }
                    618:        }
                    619:     }
                    620: #if 0
                    621:     debug_cycle_diagram ();
                    622: #endif
                    623: }
                    624: 
                    625: 
1.1.1.15  root      626: /* Used by the copper.  */
1.1.1.13  root      627: static int estimated_last_fetch_cycle;
1.1.1.15  root      628: static int cycle_diagram_shift;
1.1.1.4   root      629: 
1.1.1.13  root      630: static void estimate_last_fetch_cycle (int hpos)
1.1.1.2   root      631: {
1.1.1.14  root      632:     int fetchunit = fetchunits[fetchmode * 4 + GET_RES (bplcon0)];
                    633: 
1.1.1.13  root      634:     if (! passed_plfstop) {
                    635:        int stop = plfstop < hpos || plfstop > HARD_DDF_STOP ? HARD_DDF_STOP : plfstop;
                    636:        /* We know that fetching is up-to-date up until hpos, so we can use fetch_cycle.  */
                    637:        int fetch_cycle_at_stop = fetch_cycle + (stop - hpos);
1.1.1.14  root      638:        int starting_last_block_at = (fetch_cycle_at_stop + fetchunit - 1) & ~(fetchunit - 1);
1.1.1.13  root      639: 
1.1.1.14  root      640:        estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + fetchunit;
1.1.1.13  root      641:     } else {
1.1.1.14  root      642:        int starting_last_block_at = (fetch_cycle + fetchunit - 1) & ~(fetchunit - 1);
1.1.1.13  root      643:        if (passed_plfstop == 2)
1.1.1.14  root      644:            starting_last_block_at -= fetchunit;
1.1.1.13  root      645: 
1.1.1.14  root      646:        estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + fetchunit;
1.1.1.13  root      647:     }
1.1.1.4   root      648: }
                    649: 
1.1.1.14  root      650: static uae_u32 outword[MAX_PLANES];
1.1.1.13  root      651: static int out_nbits, out_offs;
1.1.1.14  root      652: static uae_u32 todisplay[MAX_PLANES][4];
                    653: static uae_u32 fetched[MAX_PLANES];
                    654: static uae_u32 fetched_aga0[MAX_PLANES];
                    655: static uae_u32 fetched_aga1[MAX_PLANES];
1.1.1.13  root      656: 
                    657: /* Expansions from bplcon0/bplcon1.  */
1.1.1.14  root      658: static int toscr_res, toscr_delay1, toscr_delay2, toscr_nr_planes, fetchwidth;
1.1.1.13  root      659: 
1.1.1.23! root      660: /* The number of bits left from the last fetched words.
1.1.1.14  root      661:    This is an optimization - conceptually, we have to make sure the result is
                    662:    the same as if toscr is called in each clock cycle.  However, to speed this
1.1.1.23! root      663:    up, we accumulate display data; this variable keeps track of how much.
1.1.1.14  root      664:    Thus, once we do call toscr_nbits (which happens at least every 16 bits),
                    665:    we can do more work at once.  */
1.1.1.13  root      666: static int toscr_nbits;
                    667: 
1.1.1.14  root      668: static int delayoffset;
                    669: 
                    670: STATIC_INLINE void compute_delay_offset (int hpos)
1.1.1.4   root      671: {
1.1.1.14  root      672:     /* this fixes most horizontal scrolling jerkyness but can't be correct */
1.1.1.15  root      673:     delayoffset = ((hpos - fm_maxplane - 0x18) & fetchstart_mask) << 1;
1.1.1.14  root      674:     delayoffset &= ~7;
1.1.1.16  root      675:     if (delayoffset & 8)
                    676:        delayoffset = 8;
                    677:     else if (delayoffset & 16)
                    678:        delayoffset = 16;
                    679:     else if (delayoffset & 32)
                    680:        delayoffset = 32;
                    681:     else
                    682:        delayoffset = 0;
1.1.1.13  root      683: }
1.1.1.9   root      684: 
1.1.1.15  root      685: static void expand_fmodes (void)
1.1.1.14  root      686: {
                    687:     int res = GET_RES(bplcon0);
                    688:     int fm = fetchmode;
                    689:     fetchunit = fetchunits[fm * 4 + res];
                    690:     fetchunit_mask = fetchunit - 1;
                    691:     fetchstart_shift = fetchstarts[fm * 4 + res];
                    692:     fetchstart = 1 << fetchstart_shift;
                    693:     fetchstart_mask = fetchstart - 1;
                    694:     fm_maxplane_shift = fm_maxplanes[fm * 4 + res];
                    695:     fm_maxplane = 1 << fm_maxplane_shift;
1.1.1.13  root      696: }
                    697: 
                    698: /* Expand bplcon0/bplcon1 into the toscr_xxx variables.  */
1.1.1.15  root      699: static void compute_toscr_delay_1 (void)
1.1.1.13  root      700: {
                    701:     int delay1 = (bplcon1 & 0x0f) | ((bplcon1 & 0x0c00) >> 6);
                    702:     int delay2 = ((bplcon1 >> 4) & 0x0f) | (((bplcon1 >> 4) & 0x0c00) >> 6);
                    703:     int delaymask;
1.1.1.14  root      704:     int fetchwidth = 16 << fetchmode;
1.1.1.13  root      705: 
1.1.1.14  root      706:     delay1 += delayoffset;
                    707:     delay2 += delayoffset;
                    708:     delaymask = (fetchwidth - 1) >> toscr_res;
1.1.1.13  root      709:     toscr_delay1 = (delay1 & delaymask) << toscr_res;
                    710:     toscr_delay2 = (delay2 & delaymask) << toscr_res;
1.1.1.15  root      711: }
                    712: 
                    713: static void compute_toscr_delay (int hpos)
                    714: {
1.1.1.22  root      715:     toscr_res = GET_RES (bplcon0);
                    716:     toscr_nr_planes = GET_PLANES_LIMIT (bplcon0);
1.1.1.15  root      717:     compute_toscr_delay_1 ();
                    718: }
                    719: 
                    720: STATIC_INLINE void maybe_first_bpl1dat (int hpos)
                    721: {
                    722:     if (thisline_decision.plfleft == -1) {
                    723:        thisline_decision.plfleft = hpos;
                    724:        compute_delay_offset (hpos);
                    725:        compute_toscr_delay_1 ();
                    726:     }
                    727: }
1.1.1.13  root      728: 
1.1.1.15  root      729: STATIC_INLINE void fetch (int nr, int fm)
                    730: {
                    731:     uaecptr p;
                    732:     if (nr >= toscr_nr_planes)
                    733:        return;
1.1.1.16  root      734:     p = bplpt[nr] + bpl_off[nr];
1.1.1.15  root      735:     switch (fm) {
                    736:     case 0:
                    737:        fetched[nr] = chipmem_wget (p);
                    738:        bplpt[nr] += 2;
                    739:        break;
                    740:     case 1:
                    741:        fetched_aga0[nr] = chipmem_lget (p);
                    742:        bplpt[nr] += 4;
                    743:        break;
                    744:     case 2:
                    745:        fetched_aga1[nr] = chipmem_lget (p);
                    746:        fetched_aga0[nr] = chipmem_lget (p + 4);
                    747:        bplpt[nr] += 8;
                    748:        break;
                    749:     }
                    750:     if (nr == 0)
                    751:        fetch_state = fetch_was_plane0;
1.1.1.13  root      752: }
                    753: 
                    754: static void clear_fetchbuffer (uae_u32 *ptr, int nwords)
                    755: {
                    756:     int i;
                    757: 
                    758:     if (! thisline_changed)
                    759:        for (i = 0; i < nwords; i++)
                    760:            if (ptr[i]) {
                    761:                thisline_changed = 1;
                    762:                break;
1.1.1.4   root      763:            }
1.1.1.13  root      764: 
                    765:     memset (ptr, 0, nwords * 4);
                    766: }
                    767: 
                    768: static void update_toscr_planes (void)
                    769: {
                    770:     if (toscr_nr_planes > thisline_decision.nr_planes) {
                    771:        int j;
                    772:        for (j = thisline_decision.nr_planes; j < toscr_nr_planes; j++)
                    773:            clear_fetchbuffer ((uae_u32 *)(line_data[next_lineno] + 2 * MAX_WORDS_PER_LINE * j), out_offs);
                    774: #if 0
                    775:        if (thisline_decision.nr_planes > 0)
                    776:            printf ("Planes from %d to %d\n", thisline_decision.nr_planes, toscr_nr_planes);
                    777: #endif
                    778:        thisline_decision.nr_planes = toscr_nr_planes;
1.1.1.4   root      779:     }
                    780: }
1.1.1.2   root      781: 
1.1.1.14  root      782: STATIC_INLINE void toscr_3_ecs (int nbits)
1.1.1.7   root      783: {
1.1.1.13  root      784:     int delay1 = toscr_delay1;
                    785:     int delay2 = toscr_delay2;
                    786:     int i;
                    787:     uae_u32 mask = 0xFFFF >> (16 - nbits);
                    788: 
                    789:     for (i = 0; i < toscr_nr_planes; i += 2) {
                    790:        outword[i] <<= nbits;
1.1.1.14  root      791:        outword[i] |= (todisplay[i][0] >> (16 - nbits + delay1)) & mask;
                    792:        todisplay[i][0] <<= nbits;
1.1.1.13  root      793:     }
                    794:     for (i = 1; i < toscr_nr_planes; i += 2) {
                    795:        outword[i] <<= nbits;
1.1.1.14  root      796:        outword[i] |= (todisplay[i][0] >> (16 - nbits + delay2)) & mask;
                    797:        todisplay[i][0] <<= nbits;
                    798:     }
                    799: }
                    800: 
                    801: STATIC_INLINE void shift32plus (uae_u32 *p, int n)
                    802: {
                    803:     uae_u32 t = p[1];
                    804:     t <<= n;
                    805:     t |= p[0] >> (32 - n);
                    806:     p[1] = t;
                    807: }
                    808: 
                    809: STATIC_INLINE void aga_shift (uae_u32 *p, int n, int fm)
                    810: {
                    811:     if (fm == 2) {
                    812:        shift32plus (p + 2, n);
                    813:        shift32plus (p + 1, n);
1.1.1.13  root      814:     }
1.1.1.14  root      815:     shift32plus (p + 0, n);
                    816:     p[0] <<= n;
                    817: }
                    818: 
                    819: STATIC_INLINE void toscr_3_aga (int nbits, int fm)
                    820: {
                    821:     int delay1 = toscr_delay1;
                    822:     int delay2 = toscr_delay2;
                    823:     int i;
                    824:     uae_u32 mask = 0xFFFF >> (16 - nbits);
                    825: 
                    826:     {
                    827:        int offs = (16 << fm) - nbits + delay1;
                    828:        int off1 = offs >> 5;
                    829:        if (off1 == 3)
                    830:            off1 = 2;
                    831:        offs -= off1 * 32;
                    832:        for (i = 0; i < toscr_nr_planes; i += 2) {
                    833:            uae_u32 t0 = todisplay[i][off1];
                    834:            uae_u32 t1 = todisplay[i][off1 + 1];
                    835:            uae_u64 t = (((uae_u64)t1) << 32) | t0;
                    836:            outword[i] <<= nbits;
                    837:            outword[i] |= (t >> offs) & mask;
                    838:            aga_shift (todisplay[i], nbits, fm);
                    839:        }
                    840:     }
                    841:     {
                    842:        int offs = (16 << fm) - nbits + delay2;
                    843:        int off1 = offs >> 5;
                    844:        if (off1 == 3)
                    845:            off1 = 2;
                    846:        offs -= off1 * 32;
                    847:        for (i = 1; i < toscr_nr_planes; i += 2) {
                    848:            uae_u32 t0 = todisplay[i][off1];
                    849:            uae_u32 t1 = todisplay[i][off1 + 1];
                    850:            uae_u64 t = (((uae_u64)t1) << 32) | t0;
                    851:            outword[i] <<= nbits;
                    852:            outword[i] |= (t >> offs) & mask;
                    853:            aga_shift (todisplay[i], nbits, fm);
                    854:        }
                    855:     }
                    856: }
                    857: 
                    858: static void toscr_2_0 (int nbits) { toscr_3_ecs (nbits); }
                    859: static void toscr_2_1 (int nbits) { toscr_3_aga (nbits, 1); }
                    860: static void toscr_2_2 (int nbits) { toscr_3_aga (nbits, 2); }
                    861: 
                    862: STATIC_INLINE void toscr_1 (int nbits, int fm)
                    863: {
                    864:     switch (fm) {
                    865:     case 0:
                    866:        toscr_2_0 (nbits);
                    867:        break;
                    868:     case 1:
                    869:        toscr_2_1 (nbits);
                    870:        break;
                    871:     case 2:
                    872:        toscr_2_2 (nbits);
                    873:        break;
                    874:     }
                    875: 
1.1.1.13  root      876:     out_nbits += nbits;
                    877:     if (out_nbits == 32) {
1.1.1.14  root      878:        int i;
1.1.1.13  root      879:        uae_u8 *dataptr = line_data[next_lineno] + out_offs * 4;
                    880:        /* Don't use toscr_nr_planes here; if the plane count drops during the
                    881:           line we still want the data to be correct for the full number of planes
                    882:           over the full width of the line.  */
                    883:        for (i = 0; i < thisline_decision.nr_planes; i++) {
                    884:            uae_u32 *dataptr32 = (uae_u32 *)dataptr;
                    885:            if (*dataptr32 != outword[i])
                    886:                thisline_changed = 1;
                    887:            *dataptr32 = outword[i];
                    888:            dataptr += MAX_WORDS_PER_LINE * 2;
                    889:        }
                    890:        out_offs++;
                    891:        out_nbits = 0;
                    892:     }
1.1.1.7   root      893: }
                    894: 
1.1.1.14  root      895: static void toscr_fm0 (int);
                    896: static void toscr_fm1 (int);
                    897: static void toscr_fm2 (int);
                    898: 
                    899: STATIC_INLINE void toscr (int nbits, int fm)
                    900: {
                    901:     switch (fm) {
                    902:     case 0: toscr_fm0 (nbits); break;
                    903:     case 1: toscr_fm1 (nbits); break;
                    904:     case 2: toscr_fm2 (nbits); break;
                    905:     }
                    906: }
                    907: 
                    908: STATIC_INLINE void toscr_0 (int nbits, int fm)
1.1.1.4   root      909: {
1.1.1.13  root      910:     int t;
1.1.1.14  root      911: 
1.1.1.13  root      912:     if (nbits > 16) {
1.1.1.14  root      913:        toscr (16, fm);
1.1.1.13  root      914:        nbits -= 16;
1.1.1.2   root      915:     }
1.1.1.3   root      916: 
1.1.1.13  root      917:     t = 32 - out_nbits;
                    918:     if (t < nbits) {
1.1.1.14  root      919:        toscr_1 (t, fm);
1.1.1.13  root      920:        nbits -= t;
                    921:     }
1.1.1.14  root      922:     toscr_1 (nbits, fm);
1.1.1.13  root      923: }
1.1.1.14  root      924: 
                    925: static void toscr_fm0 (int nbits) { toscr_0 (nbits, 0); }
                    926: static void toscr_fm1 (int nbits) { toscr_0 (nbits, 1); }
                    927: static void toscr_fm2 (int nbits) { toscr_0 (nbits, 2); }
                    928: 
                    929: static int flush_plane_data (int fm)
1.1.1.13  root      930: {
                    931:     int i = 0;
1.1.1.14  root      932:     int fetchwidth = 16 << fm;
1.1.1.4   root      933: 
1.1.1.13  root      934:     if (out_nbits <= 16) {
                    935:        i += 16;
1.1.1.14  root      936:        toscr_1 (16, fm);
1.1.1.13  root      937:     }
                    938:     if (out_nbits != 0) {
                    939:        i += 32 - out_nbits;
1.1.1.14  root      940:        toscr_1 (32 - out_nbits, fm);
1.1.1.4   root      941:     }
1.1.1.13  root      942:     i += 32;
1.1.1.10  root      943: 
1.1.1.14  root      944:     toscr_1 (16, fm);
                    945:     toscr_1 (16, fm);
1.1.1.13  root      946:     return i >> (1 + toscr_res);
                    947: }
                    948: 
1.1.1.14  root      949: STATIC_INLINE void flush_display (int fm)
                    950: {
                    951:     if (toscr_nbits > 0 && thisline_decision.plfleft != -1)
                    952:        toscr (toscr_nbits, fm);
                    953:     toscr_nbits = 0;
                    954: }
                    955: 
                    956: /* Called when all planes have been fetched, i.e. when a new block
                    957:    of data is available to be displayed.  The data in fetched[] is
                    958:    moved into todisplay[].  */
1.1.1.22  root      959: STATIC_INLINE void beginning_of_plane_block (int pos, int fm)
1.1.1.14  root      960: {
                    961:     int i;
                    962: 
                    963:     flush_display (fm);
                    964: 
                    965:     if (fm == 0)
1.1.1.23! root      966:        for (i = 0; i < MAX_PLANES; i++)
1.1.1.14  root      967:            todisplay[i][0] |= fetched[i];
                    968:     else
                    969:        for (i = 0; i < MAX_PLANES; i++) {
                    970:            if (fm == 2)
                    971:                todisplay[i][1] = fetched_aga1[i];
                    972:            todisplay[i][0] = fetched_aga0[i];
                    973:        }
                    974: 
                    975:     maybe_first_bpl1dat (pos);
                    976: }
                    977: 
                    978: #define SPEEDUP
                    979: 
                    980: #ifdef SPEEDUP
                    981: 
1.1.1.13  root      982: /* The usual inlining tricks - don't touch unless you know what you are doing.  */
1.1.1.14  root      983: STATIC_INLINE void long_fetch_ecs (int plane, int nwords, int weird_number_of_bits, int dma)
1.1.1.13  root      984: {
1.1.1.16  root      985:     uae_u16 *real_pt = (uae_u16 *)pfield_xlateptr (bplpt[plane] + bpl_off[plane], nwords * 2);
1.1.1.23! root      986:     int delay = (plane & 1) ? toscr_delay2 : toscr_delay1;
1.1.1.13  root      987:     int tmp_nbits = out_nbits;
1.1.1.14  root      988:     uae_u32 shiftbuffer = todisplay[plane][0];
1.1.1.13  root      989:     uae_u32 outval = outword[plane];
                    990:     uae_u32 fetchval = fetched[plane];
                    991:     uae_u32 *dataptr = (uae_u32 *)(line_data[next_lineno] + 2 * plane * MAX_WORDS_PER_LINE + 4 * out_offs);
                    992: 
1.1.1.14  root      993:     if (dma)
                    994:        bplpt[plane] += nwords * 2;
1.1.1.13  root      995: 
                    996:     if (real_pt == 0)
                    997:        /* @@@ Don't do this, fall back on chipmem_wget instead.  */
1.1.1.4   root      998:        return;
                    999: 
1.1.1.13  root     1000:     while (nwords > 0) {
                   1001:        int bits_left = 32 - tmp_nbits;
1.1.1.14  root     1002:        uae_u32 t;
1.1.1.13  root     1003: 
                   1004:        shiftbuffer |= fetchval;
                   1005: 
1.1.1.14  root     1006:        t = (shiftbuffer >> delay) & 0xFFFF;
                   1007: 
1.1.1.13  root     1008:        if (weird_number_of_bits && bits_left < 16) {
                   1009:            outval <<= bits_left;
1.1.1.14  root     1010:            outval |= t >> (16 - bits_left);
1.1.1.13  root     1011:            thisline_changed |= *dataptr ^ outval;
                   1012:            *dataptr++ = outval;
                   1013: 
1.1.1.14  root     1014:            outval = t;
1.1.1.13  root     1015:            tmp_nbits = 16 - bits_left;
1.1.1.14  root     1016:            shiftbuffer <<= 16;
1.1.1.13  root     1017:        } else {
1.1.1.14  root     1018:            outval = (outval << 16) | t;
1.1.1.13  root     1019:            shiftbuffer <<= 16;
                   1020:            tmp_nbits += 16;
                   1021:            if (tmp_nbits == 32) {
                   1022:                thisline_changed |= *dataptr ^ outval;
                   1023:                *dataptr++ = outval;
                   1024:                tmp_nbits = 0;
                   1025:            }
                   1026:        }
                   1027:        nwords--;
1.1.1.14  root     1028:        if (dma) {
                   1029:            fetchval = do_get_mem_word (real_pt);
                   1030:            real_pt++;
                   1031:        }
1.1.1.13  root     1032:     }
                   1033:     fetched[plane] = fetchval;
1.1.1.14  root     1034:     todisplay[plane][0] = shiftbuffer;
1.1.1.13  root     1035:     outword[plane] = outval;
1.1.1.2   root     1036: }
                   1037: 
1.1.1.14  root     1038: STATIC_INLINE void long_fetch_aga (int plane, int nwords, int weird_number_of_bits, int fm, int dma)
                   1039: {
1.1.1.16  root     1040:     uae_u32 *real_pt = (uae_u32 *)pfield_xlateptr (bplpt[plane] + bpl_off[plane], nwords * 2);
1.1.1.23! root     1041:     int delay = (plane & 1) ? toscr_delay2 : toscr_delay1;
1.1.1.14  root     1042:     int tmp_nbits = out_nbits;
                   1043:     uae_u32 *shiftbuffer = todisplay[plane];
                   1044:     uae_u32 outval = outword[plane];
                   1045:     uae_u32 fetchval0 = fetched_aga0[plane];
                   1046:     uae_u32 fetchval1 = fetched_aga1[plane];
                   1047:     uae_u32 *dataptr = (uae_u32 *)(line_data[next_lineno] + 2 * plane * MAX_WORDS_PER_LINE + 4 * out_offs);
                   1048:     int offs = (16 << fm) - 16 + delay;
                   1049:     int off1 = offs >> 5;
                   1050:     if (off1 == 3)
                   1051:        off1 = 2;
                   1052:     offs -= off1 * 32;
                   1053: 
                   1054:     if (dma)
                   1055:        bplpt[plane] += nwords * 2;
                   1056: 
                   1057:     if (real_pt == 0)
                   1058:        /* @@@ Don't do this, fall back on chipmem_wget instead.  */
                   1059:        return;
                   1060: 
                   1061:     while (nwords > 0) {
                   1062:        int i;
                   1063: 
                   1064:        shiftbuffer[0] = fetchval0;
                   1065:        if (fm == 2)
                   1066:            shiftbuffer[1] = fetchval1;
                   1067: 
                   1068:        for (i = 0; i < (1 << fm); i++) {
                   1069:            int bits_left = 32 - tmp_nbits;
1.1.1.13  root     1070: 
1.1.1.14  root     1071:            uae_u32 t0 = shiftbuffer[off1];
                   1072:            uae_u32 t1 = shiftbuffer[off1 + 1];
                   1073:            uae_u64 t = (((uae_u64)t1) << 32) | t0;
                   1074: 
                   1075:            t0 = (t >> offs) & 0xFFFF;
                   1076: 
                   1077:            if (weird_number_of_bits && bits_left < 16) {
                   1078:                outval <<= bits_left;
                   1079:                outval |= t0 >> (16 - bits_left);
                   1080: 
                   1081:                thisline_changed |= *dataptr ^ outval;
                   1082:                *dataptr++ = outval;
                   1083: 
                   1084:                outval = t0;
                   1085:                tmp_nbits = 16 - bits_left;
                   1086:                aga_shift (shiftbuffer, 16, fm);
                   1087:            } else {
                   1088:                outval = (outval << 16) | t0;
                   1089:                aga_shift (shiftbuffer, 16, fm);
                   1090:                tmp_nbits += 16;
                   1091:                if (tmp_nbits == 32) {
                   1092:                    thisline_changed |= *dataptr ^ outval;
                   1093:                    *dataptr++ = outval;
                   1094:                    tmp_nbits = 0;
                   1095:                }
                   1096:            }
                   1097:        }
                   1098: 
                   1099:        nwords -= 1 << fm;
                   1100: 
                   1101:        if (dma) {
                   1102:            if (fm == 1)
                   1103:                fetchval0 = do_get_mem_long (real_pt);
                   1104:            else {
                   1105:                fetchval1 = do_get_mem_long (real_pt);
                   1106:                fetchval0 = do_get_mem_long (real_pt + 1);
                   1107:            }
                   1108:            real_pt += fm;
                   1109:        }
                   1110:     }
                   1111:     fetched_aga0[plane] = fetchval0;
                   1112:     fetched_aga1[plane] = fetchval1;
                   1113:     outword[plane] = outval;
                   1114: }
                   1115: 
                   1116: static void long_fetch_ecs_0 (int hpos, int nwords, int dma) { long_fetch_ecs (hpos, nwords, 0, dma); }
                   1117: static void long_fetch_ecs_1 (int hpos, int nwords, int dma) { long_fetch_ecs (hpos, nwords, 1, dma); }
                   1118: static void long_fetch_aga_1_0 (int hpos, int nwords, int dma) { long_fetch_aga (hpos, nwords,  0, 1, dma); }
                   1119: static void long_fetch_aga_1_1 (int hpos, int nwords, int dma) { long_fetch_aga (hpos, nwords,  1, 1, dma); }
                   1120: static void long_fetch_aga_2_0 (int hpos, int nwords, int dma) { long_fetch_aga (hpos, nwords,  0, 2, dma); }
                   1121: static void long_fetch_aga_2_1 (int hpos, int nwords, int dma) { long_fetch_aga (hpos, nwords,  1, 2, dma); }
                   1122: 
                   1123: static void do_long_fetch (int hpos, int nwords, int dma, int fm)
1.1.1.2   root     1124: {
1.1.1.13  root     1125:     int i;
1.1.1.2   root     1126: 
1.1.1.14  root     1127:     flush_display (fm);
                   1128:     switch (fm) {
                   1129:     case 0:
                   1130:        if (out_nbits & 15) {
                   1131:            for (i = 0; i < toscr_nr_planes; i++)
                   1132:                long_fetch_ecs_1 (i, nwords, dma);
                   1133:        } else {
                   1134:            for (i = 0; i < toscr_nr_planes; i++)
                   1135:                long_fetch_ecs_0 (i, nwords, dma);
                   1136:        }
                   1137:        break;
                   1138:     case 1:
                   1139:        if (out_nbits & 15) {
                   1140:            for (i = 0; i < toscr_nr_planes; i++)
                   1141:                long_fetch_aga_1_1 (i, nwords, dma);
                   1142:        } else {
                   1143:            for (i = 0; i < toscr_nr_planes; i++)
                   1144:                long_fetch_aga_1_0 (i, nwords, dma);
                   1145:        }
                   1146:        break;
                   1147:     case 2:
                   1148:        if (out_nbits & 15) {
                   1149:            for (i = 0; i < toscr_nr_planes; i++)
                   1150:                long_fetch_aga_2_1 (i, nwords, dma);
                   1151:        } else {
                   1152:            for (i = 0; i < toscr_nr_planes; i++)
                   1153:                long_fetch_aga_2_0 (i, nwords, dma);
                   1154:        }
                   1155:        break;
1.1.1.2   root     1156:     }
1.1.1.13  root     1157: 
1.1.1.14  root     1158:     out_nbits += nwords * 16;
1.1.1.13  root     1159:     out_offs += out_nbits >> 5;
                   1160:     out_nbits &= 31;
1.1.1.14  root     1161: 
                   1162:     if (dma && toscr_nr_planes > 0)
                   1163:        fetch_state = fetch_was_plane0;
1.1.1.13  root     1164: }
                   1165: 
1.1.1.14  root     1166: #endif
1.1.1.13  root     1167: 
1.1.1.14  root     1168: /* make sure fetch that goes beyond maxhpos is finished */
                   1169: static void finish_final_fetch (int i, int fm)
                   1170: {
                   1171:     passed_plfstop = 3;
1.1.1.15  root     1172: 
1.1.1.23! root     1173:     if (thisline_decision.plfleft == -1)
        !          1174:        return;
        !          1175: 
        !          1176:     i += flush_plane_data (fm);
        !          1177:     thisline_decision.plfright = i;
        !          1178:     thisline_decision.plflinelen = out_offs;
        !          1179:     thisline_decision.bplres = toscr_res;
        !          1180:     finish_playfield_line ();
1.1.1.14  root     1181: }
                   1182: 
                   1183: STATIC_INLINE int one_fetch_cycle_0 (int i, int ddfstop_to_test, int dma, int fm)
1.1.1.13  root     1184: {
                   1185:     if (! passed_plfstop && i == ddfstop_to_test)
                   1186:        passed_plfstop = 1;
                   1187: 
1.1.1.14  root     1188:     if ((fetch_cycle & fetchunit_mask) == 0) {
1.1.1.13  root     1189:        if (passed_plfstop == 2) {
1.1.1.14  root     1190:            finish_final_fetch (i, fm);
1.1.1.13  root     1191:            return 1;
                   1192:        }
                   1193:        if (passed_plfstop)
                   1194:            passed_plfstop++;
1.1.1.2   root     1195:     }
1.1.1.13  root     1196:     if (dma) {
1.1.1.14  root     1197:        /* fetchstart_mask can be larger than fm_maxplane if FMODE > 0.  This means
                   1198:           that the remaining cycles are idle; we'll fall through the whole switch
                   1199:           without doing anything.  */
                   1200:        int cycle_start = fetch_cycle & fetchstart_mask;
                   1201:        switch (fm_maxplane) {
                   1202:        case 8:
                   1203:            switch (cycle_start) {
                   1204:            case 0: fetch (7, fm); break;
                   1205:            case 1: fetch (3, fm); break;
                   1206:            case 2: fetch (5, fm); break;
                   1207:            case 3: fetch (1, fm); break;
                   1208:            case 4: fetch (6, fm); break;
                   1209:            case 5: fetch (2, fm); break;
                   1210:            case 6: fetch (4, fm); break;
                   1211:            case 7: fetch (0, fm); break;
                   1212:            }
                   1213:            break;
                   1214:        case 4:
                   1215:            switch (cycle_start) {
                   1216:            case 0: fetch (3, fm); break;
                   1217:            case 1: fetch (1, fm); break;
                   1218:            case 2: fetch (2, fm); break;
                   1219:            case 3: fetch (0, fm); break;
                   1220:            }
                   1221:            break;
                   1222:        case 2:
                   1223:            switch (cycle_start) {
                   1224:            case 0: fetch (1, fm); break;
                   1225:            case 1: fetch (0, fm); break;
                   1226:            }
                   1227:            break;
1.1.1.13  root     1228:        }
1.1.1.2   root     1229:     }
1.1.1.13  root     1230:     fetch_cycle++;
                   1231:     toscr_nbits += 2 << toscr_res;
1.1.1.15  root     1232: 
                   1233:     if (toscr_nbits == 16)
                   1234:        flush_display (fm);
                   1235:     if (toscr_nbits > 16)
                   1236:        abort ();
                   1237: 
1.1.1.13  root     1238:     return 0;
                   1239: }
1.1.1.3   root     1240: 
1.1.1.14  root     1241: static int one_fetch_cycle_fm0 (int i, int ddfstop_to_test, int dma) { return one_fetch_cycle_0 (i, ddfstop_to_test, dma, 0); }
                   1242: static int one_fetch_cycle_fm1 (int i, int ddfstop_to_test, int dma) { return one_fetch_cycle_0 (i, ddfstop_to_test, dma, 1); }
                   1243: static int one_fetch_cycle_fm2 (int i, int ddfstop_to_test, int dma) { return one_fetch_cycle_0 (i, ddfstop_to_test, dma, 2); }
1.1.1.13  root     1244: 
1.1.1.14  root     1245: STATIC_INLINE int one_fetch_cycle (int i, int ddfstop_to_test, int dma, int fm)
                   1246: {
                   1247:     switch (fm) {
                   1248:     case 0: return one_fetch_cycle_fm0 (i, ddfstop_to_test, dma);
                   1249:     case 1: return one_fetch_cycle_fm1 (i, ddfstop_to_test, dma);
                   1250:     case 2: return one_fetch_cycle_fm2 (i, ddfstop_to_test, dma);
                   1251:     default: abort ();
                   1252:     }
1.1.1.13  root     1253: }
                   1254: 
1.1.1.14  root     1255: STATIC_INLINE void update_fetch (int until, int fm)
1.1.1.13  root     1256: {
                   1257:     int pos;
                   1258:     int dma = dmaen (DMA_BITPLANE);
                   1259: 
                   1260:     int ddfstop_to_test;
                   1261: 
1.1.1.22  root     1262:     if (nodraw () || passed_plfstop == 3)
1.1.1.2   root     1263:        return;
1.1.1.13  root     1264: 
                   1265:     /* We need an explicit test against HARD_DDF_STOP here to guard against
                   1266:        programs that move the DDFSTOP before our current position before we
                   1267:        reach it.  */
                   1268:     ddfstop_to_test = HARD_DDF_STOP;
                   1269:     if (ddfstop >= last_fetch_hpos && ddfstop < HARD_DDF_STOP)
                   1270:        ddfstop_to_test = ddfstop;
                   1271: 
1.1.1.14  root     1272:     compute_toscr_delay (last_fetch_hpos);
1.1.1.13  root     1273:     update_toscr_planes ();
                   1274: 
                   1275:     pos = last_fetch_hpos;
1.1.1.16  root     1276:     cycle_diagram_shift = (last_fetch_hpos - fetch_cycle) & fetchstart_mask;
1.1.1.13  root     1277: 
1.1.1.14  root     1278:     /* First, a loop that prepares us for the speedup code.  We want to enter
                   1279:        the SPEEDUP case with fetch_state == fetch_was_plane0, and then unroll
                   1280:        whole blocks, so that we end on the same fetch_state again.  */
1.1.1.13  root     1281:     for (; ; pos++) {
1.1.1.14  root     1282:        if (pos == until) {
                   1283:            if (until >= maxhpos && passed_plfstop == 2) {
                   1284:                finish_final_fetch (pos, fm);
                   1285:                return;
                   1286:            }
                   1287:            flush_display (fm);
                   1288:            return;
                   1289:        }
1.1.1.13  root     1290: 
1.1.1.14  root     1291:        if (fetch_state == fetch_was_plane0)
1.1.1.13  root     1292:            break;
                   1293: 
                   1294:        fetch_state = fetch_started;
1.1.1.14  root     1295:        if (one_fetch_cycle (pos, ddfstop_to_test, dma, fm))
1.1.1.13  root     1296:            return;
1.1.1.14  root     1297:     }
1.1.1.13  root     1298: 
                   1299: #ifdef SPEEDUP
                   1300:     /* Unrolled version of the for loop below.  */
1.1.1.14  root     1301:     if (! passed_plfstop
                   1302:        && dma
1.1.1.15  root     1303:        && (fetch_cycle & fetchstart_mask) == (fm_maxplane & fetchstart_mask)
1.1.1.14  root     1304: # if 0
                   1305:        /* @@@ We handle this case, but the code would be simpler if we
                   1306:         * disallowed it - it may even be possible to guarantee that
                   1307:         * this condition never is false.  Later.  */
                   1308:        && (out_nbits & 15) == 0
                   1309: # endif
                   1310:        && toscr_nr_planes == thisline_decision.nr_planes)
                   1311:     {
1.1.1.15  root     1312:        int offs = (pos - fetch_cycle) & fetchunit_mask;
1.1.1.14  root     1313:        int ddf2 = ((ddfstop_to_test - offs + fetchunit - 1) & ~fetchunit_mask) + offs;
                   1314:        int ddf3 = ddf2 + fetchunit;
                   1315:        int stop = until < ddf2 ? until : until < ddf3 ? ddf2 : ddf3;
                   1316:        int count;
                   1317: 
                   1318:        count = stop - pos;
                   1319: 
                   1320:        if (count >= fetchstart) {
                   1321:            count &= ~fetchstart_mask;
                   1322: 
1.1.1.15  root     1323:            if (thisline_decision.plfleft == -1) {
1.1.1.14  root     1324:                compute_delay_offset (pos);
1.1.1.15  root     1325:                compute_toscr_delay_1 ();
                   1326:            }
1.1.1.14  root     1327:            do_long_fetch (pos, count >> (3 - toscr_res), dma, fm);
                   1328: 
                   1329:            /* This must come _after_ do_long_fetch so as not to confuse flush_display
                   1330:               into thinking the first fetch has produced any output worth emitting to
                   1331:               the screen.  But the calculation of delay_offset must happen _before_.  */
                   1332:            maybe_first_bpl1dat (pos);
1.1.1.13  root     1333: 
                   1334:            if (pos <= ddfstop_to_test && pos + count > ddfstop_to_test)
                   1335:                passed_plfstop = 1;
1.1.1.14  root     1336:            if (pos <= ddfstop_to_test && pos + count > ddf2)
                   1337:                passed_plfstop = 2;
1.1.1.13  root     1338:            pos += count;
                   1339:            fetch_cycle += count;
                   1340:        }
1.1.1.2   root     1341:     }
                   1342: #endif
1.1.1.13  root     1343:     for (; pos < until; pos++) {
                   1344:        if (fetch_state == fetch_was_plane0)
1.1.1.22  root     1345:            beginning_of_plane_block (pos, fm);
1.1.1.13  root     1346:        fetch_state = fetch_started;
                   1347: 
1.1.1.14  root     1348:        if (one_fetch_cycle (pos, ddfstop_to_test, dma, fm))
1.1.1.13  root     1349:            return;
                   1350:     }
1.1.1.14  root     1351:     if (until >= maxhpos && passed_plfstop == 2) {
                   1352:        finish_final_fetch (pos, fm);
                   1353:        return;
                   1354:     }
                   1355:     flush_display (fm);
1.1.1.2   root     1356: }
                   1357: 
1.1.1.14  root     1358: static void update_fetch_0 (int hpos) { update_fetch (hpos, 0); }
                   1359: static void update_fetch_1 (int hpos) { update_fetch (hpos, 1); }
                   1360: static void update_fetch_2 (int hpos) { update_fetch (hpos, 2); }
                   1361: 
1.1.1.13  root     1362: STATIC_INLINE void decide_fetch (int hpos)
                   1363: {
1.1.1.14  root     1364:     if (fetch_state != fetch_not_started && hpos > last_fetch_hpos) {
                   1365:        switch (fetchmode) {
                   1366:        case 0: update_fetch_0 (hpos); break;
                   1367:        case 1: update_fetch_1 (hpos); break;
                   1368:        case 2: update_fetch_2 (hpos); break;
                   1369:        default: abort ();
                   1370:        }
                   1371:     }
1.1.1.13  root     1372:     last_fetch_hpos = hpos;
                   1373: }
                   1374: 
                   1375: /* This function is responsible for turning on datafetch if necessary.  */
1.1.1.8   root     1376: STATIC_INLINE void decide_line (int hpos)
1.1.1.2   root     1377: {
1.1.1.15  root     1378:     if (hpos <= last_decide_line_hpos)
                   1379:        return;
1.1.1.13  root     1380:     if (fetch_state != fetch_not_started)
                   1381:        return;
                   1382: 
                   1383:     /* Test if we passed the start of the DDF window.  */
                   1384:     if (last_decide_line_hpos < plfstrt && hpos >= plfstrt) {
                   1385:        /* First, take care of the vertical DIW.  Surprisingly enough, this seems to be
                   1386:           correct here - putting this into decide_diw() results in garbage.  */
                   1387:        if (diwstate == DIW_waiting_start && vpos == plffirstline) {
                   1388:            diwstate = DIW_waiting_stop;
                   1389:        }
                   1390:        if (diwstate == DIW_waiting_stop && vpos == plflastline) {
                   1391:            diwstate = DIW_waiting_start;
                   1392:        }
                   1393: 
1.1.1.15  root     1394:        /* If DMA isn't on by the time we reach plfstrt, then there's no
                   1395:           bitplane DMA at all for the whole line.  */
                   1396:        if (dmaen (DMA_BITPLANE)
                   1397:            && diwstate == DIW_waiting_stop)
                   1398:        {
1.1.1.13  root     1399:            fetch_state = fetch_started;
                   1400:            fetch_cycle = 0;
                   1401:            last_fetch_hpos = plfstrt;
                   1402:            out_nbits = 0;
                   1403:            out_offs = 0;
                   1404:            toscr_nbits = 0;
                   1405: 
1.1.1.14  root     1406:            compute_toscr_delay (last_fetch_hpos);
1.1.1.13  root     1407: 
                   1408:            /* If someone already wrote BPL1DAT, clear the area between that point and
                   1409:               the real fetch start.  */
1.1.1.22  root     1410:            if (!nodraw ()) {
1.1.1.14  root     1411:                if (thisline_decision.plfleft != -1) {
                   1412:                    out_nbits = (plfstrt - thisline_decision.plfleft) << (1 + toscr_res);
                   1413:                    out_offs = out_nbits >> 5;
                   1414:                    out_nbits &= 31;
                   1415:                }
                   1416:                update_toscr_planes ();
1.1.1.13  root     1417:            }
                   1418:            estimate_last_fetch_cycle (plfstrt);
                   1419:            last_decide_line_hpos = hpos;
1.1.1.20  root     1420:            do_sprites (plfstrt);
1.1.1.13  root     1421:            return;
                   1422:        }
                   1423:     }
                   1424: 
                   1425:     if (last_decide_line_hpos < 0x34)
1.1.1.20  root     1426:        do_sprites (hpos);
1.1.1.13  root     1427: 
                   1428:     last_decide_line_hpos = hpos;
1.1.1.2   root     1429: }
                   1430: 
1.1.1.3   root     1431: /* Called when a color is about to be changed (write to a color register),
                   1432:  * but the new color has not been entered into the table yet. */
1.1.1.4   root     1433: static void record_color_change (int hpos, int regno, unsigned long value)
1.1.1.3   root     1434: {
1.1.1.18  root     1435:     if (regno == -1 && value) {
                   1436:        thisline_decision.ham_seen = 1;
                   1437:        if (hpos < 0x18)
                   1438:            thisline_decision.ham_at_start = 1;
                   1439:     }
                   1440: 
1.1.1.3   root     1441:     /* Early positions don't appear on-screen. */
1.1.1.22  root     1442:     if (nodraw () || vpos < minfirstline || hpos < 0x18
1.1.1.3   root     1443:        /*|| currprefs.emul_accuracy == 0*/)
                   1444:        return;
                   1445: 
1.1.1.4   root     1446:     decide_diw (hpos);
                   1447:     decide_line (hpos);
1.1.1.3   root     1448: 
1.1.1.13  root     1449:     if (thisline_decision.ctable == -1)
                   1450:        remember_ctable ();
1.1.1.3   root     1451: 
                   1452: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
1.1.1.4   root     1453:     if (next_color_change >= max_color_change) {
1.1.1.3   root     1454:        ++delta_color_change;
                   1455:        return;
                   1456:     }
                   1457: #endif
1.1.1.4   root     1458:     curr_color_changes[next_color_change].linepos = hpos;
1.1.1.3   root     1459:     curr_color_changes[next_color_change].regno = regno;
                   1460:     curr_color_changes[next_color_change++].value = value;
                   1461: }
                   1462: 
1.1.1.15  root     1463: typedef int sprbuf_res_t, cclockres_t, hwres_t, bplres_t;
                   1464: 
                   1465: static void do_playfield_collisions (void)
                   1466: {
                   1467:     uae_u8 *ld = line_data[next_lineno];
                   1468:     int i;
                   1469: 
                   1470:     if (clxcon_bpl_enable == 0) {
                   1471:        clxdat |= 1;
                   1472:        return;
                   1473:     }
1.1.1.23! root     1474: 
1.1.1.15  root     1475:     for (i = thisline_decision.plfleft; i < thisline_decision.plfright; i += 2) {
                   1476:        int j;
                   1477:        uae_u32 total = 0xFFFFFFFF;
                   1478:        for (j = 0; j < 8; j++) {
                   1479:            uae_u32 t = 0;
                   1480:            if ((clxcon_bpl_enable & (1 << j)) == 0)
                   1481:                t = 0xFFFFFFFF;
                   1482:            else if (j < thisline_decision.nr_planes) {
                   1483:                t = *(uae_u32 *)(line_data[next_lineno] + 2 * i + 2 * j * MAX_WORDS_PER_LINE);
                   1484:                t ^= ~(((clxcon_bpl_match >> j) & 1) - 1);
                   1485:            }
                   1486:            total &= t;
                   1487:        }
                   1488:        if (total)
1.1.1.23! root     1489:            clxdat |= 1;
1.1.1.15  root     1490:     }
                   1491: }
                   1492: 
1.1.1.13  root     1493: /* Sprite-to-sprite collisions are taken care of in record_sprite.  This one does
                   1494:    playfield/sprite collisions.
                   1495:    That's the theory.  In practice this doesn't work yet.  I also suspect this code
                   1496:    is way too slow.  */
                   1497: static void do_sprite_collisions (void)
1.1.1.2   root     1498: {
1.1.1.13  root     1499:     int nr_sprites = curr_drawinfo[next_lineno].nr_sprites;
                   1500:     int first = curr_drawinfo[next_lineno].first_sprite_entry;
                   1501:     int i;
                   1502:     unsigned int collision_mask = clxmask[clxcon >> 12];
1.1.1.15  root     1503:     int bplres = GET_RES (bplcon0);
                   1504:     hwres_t ddf_left = thisline_decision.plfleft * 2 << bplres;
                   1505:     hwres_t hw_diwlast = coord_window_to_diw_x (thisline_decision.diwlastword);
                   1506:     hwres_t hw_diwfirst = coord_window_to_diw_x (thisline_decision.diwfirstword);
                   1507: 
                   1508:     if (clxcon_bpl_enable == 0) {
                   1509:        clxdat |= 0x1FE;
                   1510:        return;
                   1511:     }
1.1.1.2   root     1512: 
1.1.1.13  root     1513:     for (i = 0; i < nr_sprites; i++) {
                   1514:        struct sprite_entry *e = curr_sprite_entries + first + i;
1.1.1.15  root     1515:        sprbuf_res_t j;
                   1516:        sprbuf_res_t minpos = e->pos;
                   1517:        sprbuf_res_t maxpos = e->max;
                   1518:        hwres_t minp1 = minpos >> sprite_buffer_res;
                   1519:        hwres_t maxp1 = maxpos >> sprite_buffer_res;
                   1520: 
                   1521:        if (maxp1 > hw_diwlast)
                   1522:            maxpos = hw_diwlast << sprite_buffer_res;
                   1523:        if (maxp1 > thisline_decision.plfright * 2)
                   1524:            maxpos = thisline_decision.plfright * 2 << sprite_buffer_res;
                   1525:        if (minp1 < hw_diwfirst)
                   1526:            minpos = hw_diwfirst << sprite_buffer_res;
                   1527:        if (minp1 < thisline_decision.plfleft * 2)
                   1528:            minpos = thisline_decision.plfleft * 2 << sprite_buffer_res;
1.1.1.13  root     1529: 
                   1530:        for (j = minpos; j < maxpos; j++) {
                   1531:            int sprpix = spixels[e->first_pixel + j - e->pos] & collision_mask;
                   1532:            int k;
1.1.1.15  root     1533:            int offs;
1.1.1.2   root     1534: 
1.1.1.13  root     1535:            if (sprpix == 0)
                   1536:                continue;
1.1.1.2   root     1537: 
1.1.1.15  root     1538:            offs = ((j << bplres) >> sprite_buffer_res) - ddf_left;
1.1.1.13  root     1539:            sprpix = sprite_ab_merge[sprpix & 255] | (sprite_ab_merge[sprpix >> 8] << 2);
                   1540:            sprpix <<= 1;
1.1.1.2   root     1541: 
1.1.1.13  root     1542:            /* Loop over number of playfields.  */
                   1543:            for (k = 0; k < 2; k++) {
                   1544:                int l;
                   1545:                int match = 1;
1.1.1.14  root     1546:                int planes = ((currprefs.chipset_mask & CSMASK_AGA) ? 8 : 6);
1.1.1.13  root     1547: 
1.1.1.15  root     1548:                for (l = k; match && l < planes; l += 2) {
1.1.1.14  root     1549:                    if (clxcon_bpl_enable & (1 << l)) {
1.1.1.13  root     1550:                        int t = 0;
                   1551:                        if (l < thisline_decision.nr_planes) {
                   1552:                            uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + 2 * l * MAX_WORDS_PER_LINE);
                   1553:                            uae_u32 word = ldata[offs >> 5];
                   1554:                            t = (word >> (31 - (offs & 31))) & 1;
                   1555:                        }
1.1.1.14  root     1556:                        if (t != ((clxcon_bpl_match >> l) & 1))
1.1.1.13  root     1557:                            match = 0;
                   1558:                    }
1.1.1.15  root     1559:                }
1.1.1.13  root     1560:                if (match)
                   1561:                    clxdat |= sprpix;
                   1562:                sprpix <<= 4;
                   1563:            }
1.1.1.2   root     1564:        }
                   1565:     }
                   1566: }
                   1567: 
1.1.1.15  root     1568: static void expand_sprres (void)
                   1569: {
                   1570:     switch ((bplcon3 >> 6) & 3) {
                   1571:     case 0: /* ECS defaults (LORES,HIRES=140ns,SHRES=70ns) */
                   1572:        if ((currprefs.chipset_mask & CSMASK_ECS_DENISE) && GET_RES (bplcon0) == RES_SUPERHIRES)
                   1573:            sprres = RES_HIRES;
                   1574:        else
                   1575:            sprres = RES_LORES;
                   1576:        break;
                   1577:     case 1:
                   1578:        sprres = RES_LORES;
                   1579:        break;
                   1580:     case 2:
                   1581:        sprres = RES_HIRES;
                   1582:        break;
                   1583:     case 3:
                   1584:        sprres = RES_SUPERHIRES;
                   1585:        break;
                   1586:     }
                   1587: }
                   1588: 
                   1589: STATIC_INLINE void record_sprite_1 (uae_u16 *buf, uae_u32 datab, int num, int dbl,
                   1590:                                    unsigned int mask, int do_collisions, uae_u32 collision_mask)
                   1591: {
                   1592:     int j = 0;
                   1593:     while (datab) {
                   1594:        unsigned int tmp = *buf;
                   1595:        unsigned int col = (datab & 3) << (2 * num);
                   1596:        tmp |= col;
                   1597:        if ((j & mask) == 0)
                   1598:            *buf++ = tmp;
                   1599:        if (dbl)
                   1600:            *buf++ = tmp;
                   1601:        j++;
                   1602:        datab >>= 2;
                   1603:        if (do_collisions) {
                   1604:            tmp &= collision_mask;
                   1605:            if (tmp) {
                   1606:                unsigned int shrunk_tmp = sprite_ab_merge[tmp & 255] | (sprite_ab_merge[tmp >> 8] << 2);
                   1607:                clxdat |= sprclx[shrunk_tmp];
                   1608:            }
                   1609:        }
                   1610:     }
                   1611: }
                   1612: 
1.1.1.13  root     1613: /* DATAB contains the sprite data; 16 pixels in two-bit packets.  Bits 0/1
                   1614:    determine the color of the leftmost pixel, bits 2/3 the color of the next
                   1615:    etc.
                   1616:    This function assumes that for all sprites in a given line, SPRXP either
1.1.1.15  root     1617:    stays equal or increases between successive calls.
                   1618: 
                   1619:    The data is recorded either in lores pixels (if ECS), or in hires pixels
                   1620:    (if AGA).  No support for SHRES sprites.  */
                   1621: 
                   1622: static void record_sprite (int line, int num, int sprxp, uae_u16 *data, uae_u16 *datb, unsigned int ctl)
1.1.1.2   root     1623: {
1.1.1.13  root     1624:     struct sprite_entry *e = curr_sprite_entries + next_sprite_entry;
                   1625:     int i;
                   1626:     int word_offs;
                   1627:     uae_u16 *buf;
                   1628:     uae_u32 collision_mask;
1.1.1.15  root     1629:     int width = sprite_width;
1.1.1.23! root     1630:     int dbl = 0, half = 0;
1.1.1.15  root     1631:     unsigned int mask = 0;
1.1.1.13  root     1632: 
1.1.1.15  root     1633:     if (sprres != RES_LORES)
                   1634:        thisline_decision.any_hires_sprites = 1;
                   1635: 
                   1636:     if (currprefs.chipset_mask & CSMASK_AGA) {
                   1637:        width = (width << 1) >> sprres;
                   1638:        dbl = sprite_buffer_res - sprres;
1.1.1.23! root     1639:        if (dbl < 0) {
        !          1640:            half = -dbl;
        !          1641:            dbl = 0;
        !          1642:        }
1.1.1.15  root     1643:        mask = sprres == RES_SUPERHIRES ? 1 : 0;
                   1644:     }
1.1.1.13  root     1645: 
                   1646:     /* Try to coalesce entries if they aren't too far apart.  */
1.1.1.15  root     1647:     if (! next_sprite_forced && e[-1].max + 16 >= sprxp) {
1.1.1.13  root     1648:        e--;
1.1.1.15  root     1649:     } else {
1.1.1.13  root     1650:        next_sprite_entry++;
                   1651:        e->pos = sprxp;
                   1652:        e->has_attached = 0;
                   1653:     }
1.1.1.15  root     1654: 
1.1.1.13  root     1655:     if (sprxp < e->pos)
                   1656:        abort ();
1.1.1.15  root     1657: 
                   1658:     e->max = sprxp + width;
1.1.1.13  root     1659:     e[1].first_pixel = e->first_pixel + ((e->max - e->pos + 3) & ~3);
                   1660:     next_sprite_forced = 0;
                   1661: 
                   1662:     collision_mask = clxmask[clxcon >> 12];
                   1663:     word_offs = e->first_pixel + sprxp - e->pos;
1.1.1.15  root     1664: 
                   1665:     for (i = 0; i < sprite_width; i += 16) {
                   1666:        unsigned int da = *data;
                   1667:        unsigned int db = *datb;
                   1668:        uae_u32 datab = ((sprtaba[da & 0xFF] << 16) | sprtaba[da >> 8]
                   1669:                         | (sprtabb[db & 0xFF] << 16) | sprtabb[db >> 8]);
                   1670: 
1.1.1.23! root     1671:        buf = spixels + word_offs + ((i << dbl) >> half);
1.1.1.15  root     1672:        if (currprefs.collision_level > 0 && collision_mask)
                   1673:            record_sprite_1 (buf, datab, num, dbl, mask, 1, collision_mask);
                   1674:        else
                   1675:            record_sprite_1 (buf, datab, num, dbl, mask, 0, collision_mask);
                   1676:        data++;
                   1677:        datb++;
1.1.1.2   root     1678:     }
                   1679: 
1.1.1.13  root     1680:     /* We have 8 bits per pixel in spixstate, two for every sprite pair.  The
                   1681:        low order bit records whether the attach bit was set for this pair.  */
                   1682: 
                   1683:     if (ctl & (num << 7) & 0x80) {
                   1684:        uae_u32 state = 0x01010101 << (num - 1);
                   1685:        uae_u32 *stbuf = spixstate.words + (word_offs >> 2);
1.1.1.23! root     1686:        uae_u8 *stb1 = spixstate.bytes + word_offs;
1.1.1.15  root     1687:        for (i = 0; i < width; i += 8) {
                   1688:            stb1[0] |= state;
                   1689:            stb1[1] |= state;
                   1690:            stb1[2] |= state;
                   1691:            stb1[3] |= state;
                   1692:            stb1[4] |= state;
                   1693:            stb1[5] |= state;
                   1694:            stb1[6] |= state;
                   1695:            stb1[7] |= state;
                   1696:            stb1 += 8;
                   1697:        }
1.1.1.13  root     1698:        e->has_attached = 1;
1.1.1.3   root     1699:     }
                   1700: }
1.1.1.2   root     1701: 
1.1.1.4   root     1702: static void decide_sprites (int hpos)
1.1.1.3   root     1703: {
1.1.1.7   root     1704:     int nrs[MAX_SPRITES], posns[MAX_SPRITES];
                   1705:     int count, i;
1.1.1.15  root     1706:     int point = hpos * 2;
                   1707:     int width = sprite_width;
                   1708:     int window_width = (width << lores_shift) >> sprres;
1.1.1.2   root     1709: 
1.1.1.22  root     1710:     if (nodraw () || hpos < 0x14 || nr_armed == 0 || point == last_sprite_point)
1.1.1.2   root     1711:        return;
                   1712: 
1.1.1.4   root     1713:     decide_diw (hpos);
                   1714:     decide_line (hpos);
1.1.1.3   root     1715: 
1.1.1.13  root     1716: #if 0
                   1717:     /* This tries to detect whether the line is border, but that doesn't work, it's too early.  */
                   1718:     if (thisline_decision.plfleft == -1)
1.1.1.2   root     1719:        return;
1.1.1.13  root     1720: #endif
1.1.1.3   root     1721:     count = 0;
1.1.1.15  root     1722:     for (i = 0; i < MAX_SPRITES; i++) {
1.1.1.10  root     1723:        int sprxp = spr[i].xpos;
1.1.1.15  root     1724:        int hw_xp = (sprxp >> sprite_buffer_res);
                   1725:        int window_xp = coord_hw_to_window_x (hw_xp) + (DIW_DDF_OFFSET << lores_shift);
1.1.1.3   root     1726:        int j, bestp;
1.1.1.2   root     1727: 
1.1.1.15  root     1728:        if (! spr[i].armed || sprxp < 0 || hw_xp <= last_sprite_point || hw_xp > point)
1.1.1.3   root     1729:            continue;
1.1.1.15  root     1730:        if ((thisline_decision.diwfirstword >= 0 && window_xp + window_width < thisline_decision.diwfirstword)
                   1731:            || (thisline_decision.diwlastword >= 0 && window_xp > thisline_decision.diwlastword))
1.1.1.3   root     1732:            continue;
1.1.1.2   root     1733: 
1.1.1.13  root     1734:        /* Sort the sprites in order of ascending X position before recording them.  */
1.1.1.3   root     1735:        for (bestp = 0; bestp < count; bestp++) {
                   1736:            if (posns[bestp] > sprxp)
                   1737:                break;
                   1738:            if (posns[bestp] == sprxp && nrs[bestp] < i)
                   1739:                break;
                   1740:        }
                   1741:        for (j = count; j > bestp; j--) {
                   1742:            posns[j] = posns[j-1];
                   1743:            nrs[j] = nrs[j-1];
                   1744:        }
                   1745:        posns[j] = sprxp;
                   1746:        nrs[j] = i;
                   1747:        count++;
                   1748:     }
1.1.1.13  root     1749:     for (i = 0; i < count; i++) {
1.1.1.22  root     1750:        int nr = nrs[i];
1.1.1.15  root     1751:        record_sprite (next_lineno, nr, spr[nr].xpos, sprdata[nr], sprdatb[nr], sprctl[nr]);
1.1.1.13  root     1752:     }
1.1.1.3   root     1753:     last_sprite_point = point;
1.1.1.2   root     1754: }
                   1755: 
1.1.1.13  root     1756: STATIC_INLINE int sprites_differ (struct draw_info *dip, struct draw_info *dip_old)
                   1757: {
                   1758:     struct sprite_entry *this_first = curr_sprite_entries + dip->first_sprite_entry;
                   1759:     struct sprite_entry *this_last = curr_sprite_entries + dip->last_sprite_entry;
                   1760:     struct sprite_entry *prev_first = prev_sprite_entries + dip_old->first_sprite_entry;
                   1761:     int npixels;
                   1762:     int i;
                   1763: 
                   1764:     if (dip->nr_sprites != dip_old->nr_sprites)
                   1765:        return 1;
1.1.1.23! root     1766: 
1.1.1.13  root     1767:     if (dip->nr_sprites == 0)
                   1768:        return 0;
                   1769: 
                   1770:     for (i = 0; i < dip->nr_sprites; i++)
                   1771:        if (this_first[i].pos != prev_first[i].pos
                   1772:            || this_first[i].max != prev_first[i].max
                   1773:            || this_first[i].has_attached != prev_first[i].has_attached)
                   1774:            return 1;
                   1775: 
                   1776:     npixels = this_last->first_pixel + (this_last->max - this_last->pos) - this_first->first_pixel;
                   1777:     if (memcmp (spixels + this_first->first_pixel, spixels + prev_first->first_pixel,
                   1778:                npixels * sizeof (uae_u16)) != 0)
                   1779:        return 1;
                   1780:     if (memcmp (spixstate.bytes + this_first->first_pixel, spixstate.bytes + prev_first->first_pixel, npixels) != 0)
                   1781:        return 1;
                   1782:     return 0;
                   1783: }
                   1784: 
                   1785: STATIC_INLINE int color_changes_differ (struct draw_info *dip, struct draw_info *dip_old)
                   1786: {
                   1787:     if (dip->nr_color_changes != dip_old->nr_color_changes)
                   1788:        return 1;
1.1.1.23! root     1789: 
1.1.1.13  root     1790:     if (dip->nr_color_changes == 0)
                   1791:        return 0;
                   1792:     if (memcmp (curr_color_changes + dip->first_color_change,
                   1793:                prev_color_changes + dip_old->first_color_change,
                   1794:                dip->nr_color_changes * sizeof *curr_color_changes) != 0)
                   1795:        return 1;
                   1796:     return 0;
                   1797: }
                   1798: 
1.1.1.3   root     1799: /* End of a horizontal scan line. Finish off all decisions that were not
                   1800:  * made yet. */
1.1.1.2   root     1801: static void finish_decisions (void)
                   1802: {
                   1803:     struct draw_info *dip;
                   1804:     struct draw_info *dip_old;
                   1805:     struct decision *dp;
                   1806:     int changed;
1.1.1.4   root     1807:     int hpos = current_hpos ();
1.1.1.2   root     1808: 
1.1.1.22  root     1809:     if (nodraw ())
1.1.1.2   root     1810:        return;
                   1811: 
1.1.1.4   root     1812:     decide_diw (hpos);
1.1.1.13  root     1813:     decide_line (hpos);
                   1814:     decide_fetch (hpos);
                   1815: 
                   1816:     if (thisline_decision.plfleft != -1 && thisline_decision.plflinelen == -1) {
                   1817:        if (fetch_state != fetch_not_started)
                   1818:            abort ();
                   1819:        thisline_decision.plfright = thisline_decision.plfleft;
                   1820:        thisline_decision.plflinelen = 0;
                   1821:        thisline_decision.bplres = RES_LORES;
                   1822:     }
1.1.1.3   root     1823: 
                   1824:     /* Large DIWSTOP values can cause the stop position never to be
                   1825:      * reached, so the state machine always stays in the same state and
                   1826:      * there's a more-or-less full-screen DIW. */
1.1.1.13  root     1827:     if (hdiwstate == DIW_waiting_stop || thisline_decision.diwlastword > max_diwlastword)
1.1.1.3   root     1828:        thisline_decision.diwlastword = max_diwlastword;
                   1829: 
1.1.1.13  root     1830:     if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
                   1831:        MARK_LINE_CHANGED;
                   1832:     if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword)
                   1833:        MARK_LINE_CHANGED;
1.1.1.2   root     1834: 
                   1835:     dip = curr_drawinfo + next_lineno;
                   1836:     dip_old = prev_drawinfo + next_lineno;
                   1837:     dp = line_decisions + next_lineno;
1.1.1.5   root     1838:     changed = thisline_changed;
1.1.1.2   root     1839: 
1.1.1.13  root     1840:     if (thisline_decision.plfleft != -1) {
                   1841:        record_diw_line (thisline_decision.diwfirstword, thisline_decision.diwlastword);
1.1.1.2   root     1842: 
1.1.1.4   root     1843:        decide_sprites (hpos);
1.1.1.2   root     1844:     }
                   1845: 
1.1.1.13  root     1846:     dip->last_sprite_entry = next_sprite_entry;
1.1.1.2   root     1847:     dip->last_color_change = next_color_change;
1.1.1.3   root     1848: 
                   1849:     if (thisline_decision.ctable == -1) {
1.1.1.13  root     1850:        if (thisline_decision.plfleft == -1)
1.1.1.3   root     1851:            remember_ctable_for_border ();
1.1.1.13  root     1852:        else
                   1853:            remember_ctable ();
1.1.1.3   root     1854:     }
1.1.1.2   root     1855: 
                   1856:     dip->nr_color_changes = next_color_change - dip->first_color_change;
1.1.1.13  root     1857:     dip->nr_sprites = next_sprite_entry - dip->first_sprite_entry;
1.1.1.2   root     1858: 
1.1.1.13  root     1859:     if (thisline_decision.plfleft != line_decisions[next_lineno].plfleft)
1.1.1.2   root     1860:        changed = 1;
1.1.1.13  root     1861:     if (! changed && color_changes_differ (dip, dip_old))
1.1.1.2   root     1862:        changed = 1;
1.1.1.13  root     1863:     if (!changed && thisline_decision.plfleft != -1 && sprites_differ (dip, dip_old))
1.1.1.10  root     1864:        changed = 1;
1.1.1.2   root     1865: 
                   1866:     if (changed) {
1.1.1.5   root     1867:        thisline_changed = 1;
1.1.1.2   root     1868:        *dp = thisline_decision;
                   1869:     } else
                   1870:        /* The only one that may differ: */
                   1871:        dp->ctable = thisline_decision.ctable;
                   1872: }
                   1873: 
1.1.1.3   root     1874: /* Set the state of all decisions to "undecided" for a new scanline. */
1.1.1.2   root     1875: static void reset_decisions (void)
                   1876: {
1.1.1.22  root     1877:     if (nodraw ())
1.1.1.2   root     1878:        return;
1.1.1.13  root     1879: 
1.1.1.15  root     1880:     thisline_decision.any_hires_sprites = 0;
1.1.1.13  root     1881:     thisline_decision.nr_planes = 0;
                   1882: 
1.1.1.10  root     1883:     thisline_decision.plfleft = -1;
1.1.1.13  root     1884:     thisline_decision.plflinelen = -1;
1.1.1.18  root     1885:     thisline_decision.ham_seen = !! (bplcon0 & 0x800);
                   1886:     thisline_decision.ham_at_start = !! (bplcon0 & 0x800);
1.1.1.10  root     1887: 
1.1.1.7   root     1888:     /* decided_res shouldn't be touched before it's initialized by decide_line(). */
1.1.1.2   root     1889:     thisline_decision.diwfirstword = -1;
                   1890:     thisline_decision.diwlastword = -2;
1.1.1.3   root     1891:     if (hdiwstate == DIW_waiting_stop) {
1.1.1.13  root     1892:        thisline_decision.diwfirstword = 0;
1.1.1.3   root     1893:        if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
1.1.1.5   root     1894:            MARK_LINE_CHANGED;
1.1.1.3   root     1895:     }
1.1.1.2   root     1896:     thisline_decision.ctable = -1;
                   1897: 
1.1.1.5   root     1898:     thisline_changed = 0;
1.1.1.2   root     1899:     curr_drawinfo[next_lineno].first_color_change = next_color_change;
1.1.1.13  root     1900:     curr_drawinfo[next_lineno].first_sprite_entry = next_sprite_entry;
                   1901:     next_sprite_forced = 1;
1.1.1.2   root     1902: 
1.1.1.3   root     1903:     /* memset(sprite_last_drawn_at, 0, sizeof sprite_last_drawn_at); */
                   1904:     last_sprite_point = 0;
1.1.1.13  root     1905:     fetch_state = fetch_not_started;
                   1906:     passed_plfstop = 0;
                   1907: 
                   1908:     memset (todisplay, 0, sizeof todisplay);
                   1909:     memset (fetched, 0, sizeof fetched);
1.1.1.14  root     1910:     memset (fetched_aga0, 0, sizeof fetched_aga0);
                   1911:     memset (fetched_aga1, 0, sizeof fetched_aga1);
1.1.1.13  root     1912:     memset (outword, 0, sizeof outword);
1.1.1.9   root     1913: 
1.1.1.13  root     1914:     last_decide_line_hpos = -1;
1.1.1.9   root     1915:     last_diw_pix_hpos = -1;
                   1916:     last_ddf_pix_hpos = -1;
1.1.1.13  root     1917:     last_sprite_hpos = -1;
                   1918:     last_fetch_hpos = -1;
1.1.1.2   root     1919: }
                   1920: 
1.1.1.20  root     1921: void compute_vsynctime (void)
                   1922: {
                   1923:     vsynctime = syncbase / vblank_hz;
                   1924:     if (currprefs.produce_sound > 1) {
                   1925:        vsynctime = vsynctime * 9 / 10;
                   1926:     }
                   1927: }
                   1928: 
1.1.1.7   root     1929: /* set PAL or NTSC timing variables */
                   1930: 
                   1931: static void init_hz (void)
                   1932: {
                   1933:     int isntsc;
                   1934: 
                   1935:     beamcon0 = new_beamcon0;
                   1936: 
                   1937:     isntsc = beamcon0 & 0x20 ? 0 : 1;
                   1938:     if (!isntsc) {
                   1939:        maxvpos = MAXVPOS_PAL;
                   1940:        maxhpos = MAXHPOS_PAL;
                   1941:        minfirstline = MINFIRSTLINE_PAL;
                   1942:        vblank_endline = VBLANK_ENDLINE_PAL;
                   1943:        vblank_hz = VBLANK_HZ_PAL;
                   1944:     } else {
                   1945:        maxvpos = MAXVPOS_NTSC;
                   1946:        maxhpos = MAXHPOS_NTSC;
                   1947:        minfirstline = MINFIRSTLINE_NTSC;
                   1948:        vblank_endline = VBLANK_ENDLINE_NTSC;
                   1949:        vblank_hz = VBLANK_HZ_NTSC;
                   1950:     }
1.1.1.20  root     1951:     compute_vsynctime ();
1.1.1.7   root     1952: 
                   1953:     write_log ("Using %s timing\n", isntsc ? "NTSC" : "PAL");
                   1954: }
                   1955: 
1.1.1.11  root     1956: static void calcdiw (void)
                   1957: {
1.1.1.4   root     1958:     int hstrt = diwstrt & 0xFF;
                   1959:     int hstop = diwstop & 0xFF;
                   1960:     int vstrt = diwstrt >> 8;
                   1961:     int vstop = diwstop >> 8;
                   1962: 
                   1963:     if (diwhigh_written) {
                   1964:        hstrt |= ((diwhigh >> 5) & 1) << 8;
                   1965:        hstop |= ((diwhigh >> 13) & 1) << 8;
                   1966:        vstrt |= (diwhigh & 7) << 8;
                   1967:        vstop |= ((diwhigh >> 8) & 7) << 8;
                   1968:     } else {
                   1969:        hstop += 0x100;
                   1970:        if ((vstop & 0x80) == 0)
                   1971:            vstop |= 0x100;
                   1972:     }
                   1973: 
1.1.1.13  root     1974:     diwfirstword = coord_diw_to_window_x (hstrt);
                   1975:     diwlastword = coord_diw_to_window_x (hstop);
1.1.1.2   root     1976:     if (diwfirstword < 0)
                   1977:        diwfirstword = 0;
1.1.1.3   root     1978: 
1.1.1.4   root     1979:     plffirstline = vstrt;
                   1980:     plflastline = vstop;
                   1981: 
1.1       root     1982: #if 0
                   1983:     /* This happens far too often. */
                   1984:     if (plffirstline < minfirstline) {
1.1.1.18  root     1985:        write_log ("Warning: Playfield begins before line %d!\n", minfirstline);
1.1       root     1986:        plffirstline = minfirstline;
                   1987:     }
                   1988: #endif
1.1.1.4   root     1989: 
1.1       root     1990: #if 0 /* Turrican does this */
                   1991:     if (plflastline > 313) {
1.1.1.18  root     1992:        write_log ("Warning: Playfield out of range!\n");
1.1       root     1993:        plflastline = 313;
                   1994:     }
                   1995: #endif
1.1.1.2   root     1996:     plfstrt = ddfstrt;
                   1997:     plfstop = ddfstop;
1.1.1.13  root     1998:     if (plfstrt < 0x18)
                   1999:        plfstrt = 0x18;
1.1       root     2000: }
                   2001: 
1.1.1.7   root     2002: static int timehack_alive = 0;
                   2003: 
                   2004: static uae_u32 timehack_helper (void)
                   2005: {
                   2006: #ifdef HAVE_GETTIMEOFDAY
                   2007:     struct timeval tv;
                   2008:     if (m68k_dreg (regs, 0) == 0)
                   2009:        return timehack_alive;
                   2010: 
                   2011:     timehack_alive = 10;
                   2012: 
                   2013:     gettimeofday (&tv, NULL);
                   2014:     put_long (m68k_areg (regs, 0), tv.tv_sec - (((365 * 8 + 2) * 24 - 2) * 60 * 60));
                   2015:     put_long (m68k_areg (regs, 0) + 4, tv.tv_usec);
                   2016:     return 0;
                   2017: #else
                   2018:     return 2;
                   2019: #endif
                   2020: }
                   2021: 
1.1.1.3   root     2022:  /*
1.1       root     2023:   * register functions
                   2024:   */
1.1.1.8   root     2025: STATIC_INLINE uae_u16 DENISEID (void)
1.1.1.7   root     2026: {
                   2027:     if (currprefs.chipset_mask & CSMASK_AGA)
                   2028:        return 0xF8;
                   2029:     if (currprefs.chipset_mask & CSMASK_ECS_DENISE)
                   2030:        return 0xFC;
                   2031:     return 0xFFFF;
                   2032: }
1.1.1.8   root     2033: STATIC_INLINE uae_u16 DMACONR (void)
1.1       root     2034: {
                   2035:     return (dmacon | (bltstate==BLT_done ? 0 : 0x4000)
                   2036:            | (blt_info.blitzero ? 0x2000 : 0));
                   2037: }
1.1.1.8   root     2038: STATIC_INLINE uae_u16 INTENAR (void)
1.1.1.4   root     2039: {
                   2040:     return intena;
                   2041: }
                   2042: uae_u16 INTREQR (void)
1.1       root     2043: {
1.1.1.23! root     2044:     return intreq;
1.1       root     2045: }
1.1.1.8   root     2046: STATIC_INLINE uae_u16 ADKCONR (void)
1.1.1.4   root     2047: {
                   2048:     return adkcon;
                   2049: }
1.1.1.8   root     2050: STATIC_INLINE uae_u16 VPOSR (void)
1.1       root     2051: {
1.1.1.14  root     2052:     unsigned int csbit = currprefs.ntscmode ? 0x1000 : 0;
1.1.1.7   root     2053:     csbit |= (currprefs.chipset_mask & CSMASK_AGA) ? 0x2300 : 0;
                   2054:     csbit |= (currprefs.chipset_mask & CSMASK_ECS_AGNUS) ? 0x2000 : 0;
                   2055:     return (vpos >> 8) | lof | csbit;
1.1       root     2056: }
1.1.1.4   root     2057: static void VPOSW (uae_u16 v)
1.1.1.2   root     2058: {
                   2059:     if (lof != (v & 0x8000))
                   2060:        lof_changed = 1;
                   2061:     lof = v & 0x8000;
1.1.1.3   root     2062:     /*
                   2063:      * This register is much more fun on a real Amiga. You can program
                   2064:      * refresh rates with it ;) But I won't emulate this...
                   2065:      */
1.1.1.2   root     2066: }
1.1       root     2067: 
1.1.1.8   root     2068: STATIC_INLINE uae_u16 VHPOSR (void)
1.1.1.4   root     2069: {
1.1.1.13  root     2070:     return (vpos << 8) | current_hpos ();
1.1.1.4   root     2071: }
                   2072: 
1.1.1.8   root     2073: STATIC_INLINE void COP1LCH (uae_u16 v) { cop1lc = (cop1lc & 0xffff) | ((uae_u32)v << 16); }
                   2074: STATIC_INLINE void COP1LCL (uae_u16 v) { cop1lc = (cop1lc & ~0xffff) | (v & 0xfffe); }
                   2075: STATIC_INLINE void COP2LCH (uae_u16 v) { cop2lc = (cop2lc & 0xffff) | ((uae_u32)v << 16); }
                   2076: STATIC_INLINE void COP2LCL (uae_u16 v) { cop2lc = (cop2lc & ~0xffff) | (v & 0xfffe); }
1.1.1.4   root     2077: 
1.1.1.9   root     2078: static void start_copper (void)
1.1.1.4   root     2079: {
1.1.1.10  root     2080:     int was_active = eventtab[ev_copper].active;
                   2081:     eventtab[ev_copper].active = 0;
                   2082:     if (was_active)
                   2083:        events_schedule ();
                   2084: 
1.1.1.4   root     2085:     cop_state.ignore_next = 0;
                   2086:     cop_state.state = COP_read1;
                   2087:     cop_state.vpos = vpos;
                   2088:     cop_state.hpos = current_hpos () & ~1;
1.1.1.9   root     2089: 
1.1.1.10  root     2090:     if (dmaen (DMA_COPPER)) {
                   2091:        copper_enabled_thisline = 1;
1.1.1.13  root     2092:        set_special (SPCFLAG_COPPER);
1.1.1.10  root     2093:     }
1.1.1.9   root     2094: }
                   2095: 
                   2096: static void COPJMP1 (uae_u16 a)
                   2097: {
                   2098:     cop_state.ip = cop1lc;
                   2099:     start_copper ();
1.1.1.4   root     2100: }
                   2101: 
                   2102: static void COPJMP2 (uae_u16 a)
                   2103: {
                   2104:     cop_state.ip = cop2lc;
1.1.1.9   root     2105:     start_copper ();
1.1.1.4   root     2106: }
                   2107: 
1.1.1.8   root     2108: STATIC_INLINE void COPCON (uae_u16 a)
1.1.1.4   root     2109: {
                   2110:     copcon = a;
1.1       root     2111: }
1.1.1.4   root     2112: 
1.1.1.13  root     2113: static void DMACON (int hpos, uae_u16 v)
1.1       root     2114: {
1.1.1.14  root     2115:     int i;
1.1       root     2116: 
1.1.1.3   root     2117:     uae_u16 oldcon = dmacon;
                   2118: 
1.1.1.13  root     2119:     decide_line (hpos);
                   2120:     decide_fetch (hpos);
                   2121: 
                   2122:     setclr (&dmacon, v);
                   2123:     dmacon &= 0x1FFF;
1.1.1.3   root     2124: 
                   2125:     /* FIXME? Maybe we need to think a bit more about the master DMA enable
1.1       root     2126:      * bit in these cases. */
1.1.1.10  root     2127:     if ((dmacon & DMA_COPPER) != (oldcon & DMA_COPPER)) {
                   2128:        eventtab[ev_copper].active = 0;
                   2129:     }
1.1.1.3   root     2130:     if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) {
1.1.1.4   root     2131:        cop_state.ip = cop1lc;
                   2132:        cop_state.ignore_next = 0;
                   2133:        cop_state.state = COP_read1;
                   2134:        cop_state.vpos = vpos;
1.1.1.13  root     2135:        cop_state.hpos = hpos & ~1;
1.1.1.10  root     2136:        copper_enabled_thisline = 1;
1.1.1.13  root     2137:        set_special (SPCFLAG_COPPER);
1.1       root     2138:     }
1.1.1.9   root     2139:     if (! (dmacon & DMA_COPPER)) {
1.1.1.10  root     2140:        copper_enabled_thisline = 0;
1.1.1.13  root     2141:        unset_special (SPCFLAG_COPPER);
1.1.1.9   root     2142:        cop_state.state = COP_stop;
                   2143:     }
                   2144: 
1.1       root     2145:     if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done) {
                   2146:        static int count = 0;
                   2147:        if (!count) {
                   2148:            count = 1;
1.1.1.3   root     2149:            write_log ("warning: program is doing blitpri hacks.\n");
1.1       root     2150:        }
1.1.1.13  root     2151:        set_special (SPCFLAG_BLTNASTY);
1.1       root     2152:     }
1.1.1.10  root     2153:     if ((dmacon & (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER)) != (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER))
1.1.1.13  root     2154:        unset_special (SPCFLAG_BLTNASTY);
1.1.1.4   root     2155: 
1.1.1.14  root     2156:     if (currprefs.produce_sound > 0) {
                   2157:        update_audio ();
1.1.1.3   root     2158: 
1.1.1.14  root     2159:        for (i = 0; i < 4; i++) {
                   2160:            struct audio_channel_data *cdp = audio_channel + i;
                   2161:            int chan_ena = (dmacon & 0x200) && (dmacon & (1<<i));
                   2162:            if (cdp->dmaen == chan_ena)
                   2163:                continue;
                   2164:            cdp->dmaen = chan_ena;
1.1.1.17  root     2165:            if (cdp->dmaen)
                   2166:                audio_channel_enable_dma (cdp);
                   2167:            else
                   2168:                audio_channel_disable_dma (cdp);
1.1       root     2169:        }
1.1.1.14  root     2170:        schedule_audio ();
1.1       root     2171:     }
1.1.1.14  root     2172:     events_schedule();
1.1       root     2173: }
1.1.1.2   root     2174: 
1.1.1.3   root     2175: /*static int trace_intena = 0;*/
1.1.1.2   root     2176: 
1.1.1.8   root     2177: STATIC_INLINE void INTENA (uae_u16 v)
1.1.1.2   root     2178: {
1.1.1.3   root     2179: /*    if (trace_intena)
1.1.1.18  root     2180:        write_log ("INTENA: %04x\n", v);*/
1.1.1.13  root     2181:     setclr (&intena,v);
1.1.1.15  root     2182:     /* There's stupid code out there that does
1.1.1.20  root     2183:        [some INTREQ bits at level 3 are set]
1.1.1.15  root     2184:        clear all INTREQ bits
                   2185:        Enable one INTREQ level 3 bit
                   2186:        Set level 3 handler
                   2187: 
                   2188:        If we set SPCFLAG_INT for the clear, then by the time the enable happens,
                   2189:        we'll have SPCFLAG_DOINT set, and the interrupt happens immediately, but
                   2190:        it needs to happen one insn later, when the new L3 handler has been
                   2191:        installed.  */
                   2192:     if (v & 0x8000)
                   2193:        set_special (SPCFLAG_INT);
                   2194: }
                   2195: 
                   2196: void INTREQ_0 (uae_u16 v)
                   2197: {
                   2198:     setclr (&intreq,v);
1.1.1.13  root     2199:     set_special (SPCFLAG_INT);
1.1.1.2   root     2200: }
1.1.1.15  root     2201: 
1.1.1.3   root     2202: void INTREQ (uae_u16 v)
1.1       root     2203: {
1.1.1.15  root     2204:     INTREQ_0 (v);
1.1.1.13  root     2205:     if ((v & 0x8800) == 0x0800)
1.1.1.4   root     2206:        serdat &= 0xbfff;
1.1.1.15  root     2207:     rethink_cias ();
1.1.1.3   root     2208: }
1.1       root     2209: 
1.1.1.15  root     2210: static void ADKCON (uae_u16 v)
                   2211: {
                   2212:     if (currprefs.produce_sound > 0)
                   2213:        update_audio ();
                   2214: 
                   2215:     setclr (&adkcon,v);
                   2216:     update_adkmasks ();
                   2217: }
                   2218: 
1.1.1.7   root     2219: static void BEAMCON0 (uae_u16 v)
                   2220: {
1.1.1.18  root     2221:     if (currprefs.chipset_mask & CSMASK_ECS_AGNUS)
                   2222:        new_beamcon0 = v & 0x20;
1.1.1.7   root     2223: }
                   2224: 
1.1.1.21  root     2225: static void BPLxPTH (int hpos, uae_u16 v, int num)
1.1.1.3   root     2226: {
1.1.1.4   root     2227:     decide_line (hpos);
1.1.1.13  root     2228:     decide_fetch (hpos);
1.1.1.4   root     2229:     bplpt[num] = (bplpt[num] & 0xffff) | ((uae_u32)v << 16);
1.1.1.3   root     2230: }
1.1.1.21  root     2231: static void BPLxPTL (int hpos, uae_u16 v, int num)
1.1.1.3   root     2232: {
1.1.1.4   root     2233:     decide_line (hpos);
1.1.1.13  root     2234:     decide_fetch (hpos);
1.1.1.4   root     2235:     bplpt[num] = (bplpt[num] & ~0xffff) | (v & 0xfffe);
1.1.1.3   root     2236: }
1.1       root     2237: 
1.1.1.4   root     2238: static void BPLCON0 (int hpos, uae_u16 v)
1.1       root     2239: {
1.1.1.15  root     2240:     if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE))
                   2241:        v &= ~0x00F1;
                   2242:     else if (! (currprefs.chipset_mask & CSMASK_AGA))
                   2243:        v &= ~0x00B1;
1.1.1.14  root     2244: 
1.1.1.2   root     2245:     if (bplcon0 == v)
1.1       root     2246:        return;
1.1.1.4   root     2247:     decide_line (hpos);
1.1.1.13  root     2248:     decide_fetch (hpos);
                   2249: 
1.1.1.18  root     2250:     /* HAM change?  */
                   2251:     if ((bplcon0 ^ v) & 0x800) {
                   2252:        record_color_change (hpos, -1, !! (v & 0x800));
                   2253:     }
1.1.1.23! root     2254: 
1.1.1.2   root     2255:     bplcon0 = v;
1.1.1.16  root     2256:     curr_diagram = cycle_diagram_table[fetchmode][GET_RES(bplcon0)][GET_PLANES (v)];
1.1.1.15  root     2257: 
                   2258:     if (currprefs.chipset_mask & CSMASK_AGA) {
                   2259:        decide_sprites (hpos);
                   2260:        expand_sprres ();
                   2261:     }
                   2262: 
1.1.1.14  root     2263:     expand_fmodes ();
1.1       root     2264: }
1.1.1.9   root     2265: 
1.1.1.8   root     2266: STATIC_INLINE void BPLCON1 (int hpos, uae_u16 v)
1.1       root     2267: {
1.1.1.2   root     2268:     if (bplcon1 == v)
1.1       root     2269:        return;
1.1.1.13  root     2270:     decide_line (hpos);
                   2271:     decide_fetch (hpos);
1.1.1.2   root     2272:     bplcon1 = v;
1.1       root     2273: }
1.1.1.15  root     2274: 
1.1.1.8   root     2275: STATIC_INLINE void BPLCON2 (int hpos, uae_u16 v)
1.1       root     2276: {
1.1.1.7   root     2277:     if (bplcon2 == v)
                   2278:        return;
                   2279:     decide_line (hpos);
1.1.1.2   root     2280:     bplcon2 = v;
1.1       root     2281: }
1.1.1.15  root     2282: 
1.1.1.8   root     2283: STATIC_INLINE void BPLCON3 (int hpos, uae_u16 v)
1.1       root     2284: {
1.1.1.14  root     2285:     if (! (currprefs.chipset_mask & CSMASK_AGA))
                   2286:        return;
1.1.1.7   root     2287:     if (bplcon3 == v)
                   2288:        return;
                   2289:     decide_line (hpos);
1.1.1.15  root     2290:     decide_sprites (hpos);
1.1.1.3   root     2291:     bplcon3 = v;
1.1.1.15  root     2292:     expand_sprres ();
1.1       root     2293: }
1.1.1.15  root     2294: 
1.1.1.8   root     2295: STATIC_INLINE void BPLCON4 (int hpos, uae_u16 v)
1.1       root     2296: {
1.1.1.7   root     2297:     if (! (currprefs.chipset_mask & CSMASK_AGA))
                   2298:        return;
                   2299:     if (bplcon4 == v)
                   2300:        return;
                   2301:     decide_line (hpos);
1.1.1.3   root     2302:     bplcon4 = v;
1.1       root     2303: }
                   2304: 
1.1.1.4   root     2305: static void BPL1MOD (int hpos, uae_u16 v)
1.1       root     2306: {
                   2307:     v &= ~1;
1.1.1.3   root     2308:     if ((uae_s16)bpl1mod == (uae_s16)v)
1.1       root     2309:        return;
1.1.1.13  root     2310:     decide_line (hpos);
                   2311:     decide_fetch (hpos);
1.1       root     2312:     bpl1mod = v;
                   2313: }
1.1.1.2   root     2314: 
1.1.1.4   root     2315: static void BPL2MOD (int hpos, uae_u16 v)
1.1.1.3   root     2316: {
1.1       root     2317:     v &= ~1;
1.1.1.3   root     2318:     if ((uae_s16)bpl2mod == (uae_s16)v)
1.1       root     2319:        return;
1.1.1.13  root     2320:     decide_line (hpos);
                   2321:     decide_fetch (hpos);
1.1       root     2322:     bpl2mod = v;
                   2323: }
                   2324: 
1.1.1.13  root     2325: STATIC_INLINE void BPL1DAT (int hpos, uae_u16 v)
1.1.1.10  root     2326: {
1.1.1.13  root     2327:     decide_line (hpos);
1.1.1.10  root     2328:     bpl1dat = v;
1.1.1.13  root     2329: 
                   2330:     maybe_first_bpl1dat (hpos);
1.1.1.10  root     2331: }
1.1.1.2   root     2332: /* We could do as well without those... */
1.1.1.8   root     2333: STATIC_INLINE void BPL2DAT (uae_u16 v) { bpl2dat = v; }
                   2334: STATIC_INLINE void BPL3DAT (uae_u16 v) { bpl3dat = v; }
                   2335: STATIC_INLINE void BPL4DAT (uae_u16 v) { bpl4dat = v; }
                   2336: STATIC_INLINE void BPL5DAT (uae_u16 v) { bpl5dat = v; }
                   2337: STATIC_INLINE void BPL6DAT (uae_u16 v) { bpl6dat = v; }
                   2338: STATIC_INLINE void BPL7DAT (uae_u16 v) { bpl7dat = v; }
                   2339: STATIC_INLINE void BPL8DAT (uae_u16 v) { bpl8dat = v; }
1.1       root     2340: 
1.1.1.4   root     2341: static void DIWSTRT (int hpos, uae_u16 v)
1.1       root     2342: {
1.1.1.4   root     2343:     if (diwstrt == v && ! diwhigh_written)
1.1       root     2344:        return;
1.1.1.4   root     2345:     decide_line (hpos);
                   2346:     diwhigh_written = 0;
1.1.1.3   root     2347:     diwstrt = v;
1.1.1.4   root     2348:     calcdiw ();
1.1       root     2349: }
1.1.1.4   root     2350: 
                   2351: static void DIWSTOP (int hpos, uae_u16 v)
1.1       root     2352: {
1.1.1.4   root     2353:     if (diwstop == v && ! diwhigh_written)
1.1       root     2354:        return;
1.1.1.4   root     2355:     decide_line (hpos);
                   2356:     diwhigh_written = 0;
1.1.1.3   root     2357:     diwstop = v;
1.1.1.4   root     2358:     calcdiw ();
                   2359: }
                   2360: 
                   2361: static void DIWHIGH (int hpos, uae_u16 v)
                   2362: {
1.1.1.7   root     2363:     if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE))
                   2364:        return;
1.1.1.4   root     2365:     if (diwhigh_written && diwhigh == v)
                   2366:        return;
                   2367:     decide_line (hpos);
                   2368:     diwhigh_written = 1;
                   2369:     diwhigh = v;
                   2370:     calcdiw ();
1.1       root     2371: }
1.1.1.4   root     2372: 
                   2373: static void DDFSTRT (int hpos, uae_u16 v)
1.1.1.3   root     2374: {
1.1.1.11  root     2375:     v &= 0xFC;
1.1.1.2   root     2376:     if (ddfstrt == v)
1.1       root     2377:        return;
1.1.1.4   root     2378:     decide_line (hpos);
1.1.1.3   root     2379:     ddfstrt = v;
1.1.1.4   root     2380:     calcdiw ();
1.1.1.15  root     2381:     if (ddfstop > 0xD4 && (ddfstrt & 4) == 4) {
                   2382:        static int last_warned;
                   2383:        last_warned = (last_warned + 1) & 4095;
                   2384:        if (last_warned == 0)
                   2385:            write_log ("WARNING! Very strange DDF values.\n");
                   2386:     }
1.1       root     2387: }
1.1.1.15  root     2388: 
1.1.1.4   root     2389: static void DDFSTOP (int hpos, uae_u16 v)
1.1.1.3   root     2390: {
1.1.1.15  root     2391:     /* ??? "Virtual Meltdown" sets this to 0xD2 and expects it to behave
                   2392:        differently from 0xD0.  RSI Megademo sets it to 0xd1 and expects it
1.1.1.16  root     2393:        to behave like 0xd0.  Some people also write the high 8 bits and
                   2394:        expect them to be ignored.  So mask it with 0xFE.  */
                   2395:     v &= 0xFE;
1.1.1.2   root     2396:     if (ddfstop == v)
1.1       root     2397:        return;
1.1.1.4   root     2398:     decide_line (hpos);
1.1.1.13  root     2399:     decide_fetch (hpos);
1.1.1.2   root     2400:     ddfstop = v;
1.1.1.4   root     2401:     calcdiw ();
1.1.1.13  root     2402:     if (fetch_state != fetch_not_started)
                   2403:        estimate_last_fetch_cycle (hpos);
1.1.1.15  root     2404:     if (ddfstop > 0xD4 && (ddfstrt & 4) == 4) {
                   2405:        static int last_warned;
                   2406:        last_warned = (last_warned + 1) & 4095;
                   2407:        if (last_warned == 0)
                   2408:            write_log ("WARNING! Very strange DDF values.\n");
1.1.1.14  root     2409:        write_log ("WARNING! Very strange DDF values.\n");
1.1.1.15  root     2410:     }
1.1       root     2411: }
                   2412: 
1.1.1.7   root     2413: static void FMODE (uae_u16 v)
                   2414: {
                   2415:     if (! (currprefs.chipset_mask & CSMASK_AGA))
1.1.1.14  root     2416:        v = 0;
1.1.1.13  root     2417: 
1.1.1.7   root     2418:     fmode = v;
1.1.1.14  root     2419:     sprite_width = GET_SPRITEWIDTH (fmode);
                   2420:     switch (fmode & 3) {
                   2421:     case 0:
                   2422:        fetchmode = 0;
                   2423:        break;
                   2424:     case 1:
                   2425:     case 2:
                   2426:        fetchmode = 1;
                   2427:        break;
                   2428:     case 3:
                   2429:        fetchmode = 2;
                   2430:        break;
                   2431:     }
1.1.1.16  root     2432:     curr_diagram = cycle_diagram_table[fetchmode][GET_RES (v)][GET_PLANES (bplcon0)];
1.1.1.14  root     2433:     expand_fmodes ();
1.1.1.7   root     2434: }
                   2435: 
1.1.1.4   root     2436: static void BLTADAT (uae_u16 v)
1.1       root     2437: {
1.1.1.19  root     2438:     maybe_blit (0);
1.1.1.2   root     2439: 
                   2440:     blt_info.bltadat = v;
1.1       root     2441: }
1.1.1.2   root     2442: /*
                   2443:  * "Loading data shifts it immediately" says the HRM. Well, that may
                   2444:  * be true for BLTBDAT, but not for BLTADAT - it appears the A data must be
                   2445:  * loaded for every word so that AFWM and ALWM can be applied.
                   2446:  */
1.1.1.4   root     2447: static void BLTBDAT (uae_u16 v)
1.1       root     2448: {
1.1.1.19  root     2449:     maybe_blit (0);
1.1.1.2   root     2450: 
                   2451:     if (bltcon1 & 2)
                   2452:        blt_info.bltbhold = v << (bltcon1 >> 12);
                   2453:     else
                   2454:        blt_info.bltbhold = v >> (bltcon1 >> 12);
                   2455:     blt_info.bltbdat = v;
1.1       root     2456: }
1.1.1.19  root     2457: static void BLTCDAT (uae_u16 v) { maybe_blit (0); blt_info.bltcdat = v; }
1.1       root     2458: 
1.1.1.19  root     2459: static void BLTAMOD (uae_u16 v) { maybe_blit (1); blt_info.bltamod = (uae_s16)(v & 0xFFFE); }
                   2460: static void BLTBMOD (uae_u16 v) { maybe_blit (1); blt_info.bltbmod = (uae_s16)(v & 0xFFFE); }
                   2461: static void BLTCMOD (uae_u16 v) { maybe_blit (1); blt_info.bltcmod = (uae_s16)(v & 0xFFFE); }
                   2462: static void BLTDMOD (uae_u16 v) { maybe_blit (1); blt_info.bltdmod = (uae_s16)(v & 0xFFFE); }
1.1       root     2463: 
1.1.1.19  root     2464: static void BLTCON0 (uae_u16 v) { maybe_blit (0); bltcon0 = v; blinea_shift = v >> 12; }
1.1.1.3   root     2465: /* The next category is "Most useless hardware register".
1.1       root     2466:  * And the winner is... */
1.1.1.7   root     2467: static void BLTCON0L (uae_u16 v)
                   2468: {
                   2469:     if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
                   2470:        return;
1.1.1.19  root     2471:     maybe_blit (0); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF);
1.1.1.7   root     2472: }
1.1.1.19  root     2473: static void BLTCON1 (uae_u16 v) { maybe_blit (0); bltcon1 = v; }
1.1.1.4   root     2474: 
1.1.1.19  root     2475: static void BLTAFWM (uae_u16 v) { maybe_blit (0); blt_info.bltafwm = v; }
                   2476: static void BLTALWM (uae_u16 v) { maybe_blit (0); blt_info.bltalwm = v; }
1.1       root     2477: 
1.1.1.19  root     2478: static void BLTAPTH (uae_u16 v) { maybe_blit (0); bltapt = (bltapt & 0xffff) | ((uae_u32)v << 16); }
                   2479: static void BLTAPTL (uae_u16 v) { maybe_blit (0); bltapt = (bltapt & ~0xffff) | (v & 0xFFFE); }
                   2480: static void BLTBPTH (uae_u16 v) { maybe_blit (0); bltbpt = (bltbpt & 0xffff) | ((uae_u32)v << 16); }
                   2481: static void BLTBPTL (uae_u16 v) { maybe_blit (0); bltbpt = (bltbpt & ~0xffff) | (v & 0xFFFE); }
                   2482: static void BLTCPTH (uae_u16 v) { maybe_blit (0); bltcpt = (bltcpt & 0xffff) | ((uae_u32)v << 16); }
                   2483: static void BLTCPTL (uae_u16 v) { maybe_blit (0); bltcpt = (bltcpt & ~0xffff) | (v & 0xFFFE); }
                   2484: static void BLTDPTH (uae_u16 v) { maybe_blit (0); bltdpt = (bltdpt & 0xffff) | ((uae_u32)v << 16); }
                   2485: static void BLTDPTL (uae_u16 v) { maybe_blit (0); bltdpt = (bltdpt & ~0xffff) | (v & 0xFFFE); }
1.1       root     2486: 
1.1.1.4   root     2487: static void BLTSIZE (uae_u16 v)
1.1       root     2488: {
1.1.1.19  root     2489:     maybe_blit (0);
1.1       root     2490: 
1.1.1.15  root     2491:     blt_info.vblitsize = v >> 6;
                   2492:     blt_info.hblitsize = v & 0x3F;
1.1       root     2493:     if (!blt_info.vblitsize) blt_info.vblitsize = 1024;
                   2494:     if (!blt_info.hblitsize) blt_info.hblitsize = 64;
1.1.1.3   root     2495: 
                   2496:     bltstate = BLT_init;
1.1.1.4   root     2497:     do_blitter ();
1.1       root     2498: }
1.1.1.4   root     2499: 
                   2500: static void BLTSIZV (uae_u16 v)
1.1       root     2501: {
1.1.1.7   root     2502:     if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
                   2503:        return;
1.1.1.19  root     2504:     maybe_blit (0);
1.1       root     2505:     oldvblts = v & 0x7FFF;
                   2506: }
1.1.1.4   root     2507: 
                   2508: static void BLTSIZH (uae_u16 v)
1.1       root     2509: {
1.1.1.7   root     2510:     if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
                   2511:        return;
1.1.1.19  root     2512:     maybe_blit (0);
1.1       root     2513:     blt_info.hblitsize = v & 0x7FF;
                   2514:     blt_info.vblitsize = oldvblts;
                   2515:     if (!blt_info.vblitsize) blt_info.vblitsize = 32768;
                   2516:     if (!blt_info.hblitsize) blt_info.hblitsize = 0x800;
1.1.1.2   root     2517:     bltstate = BLT_init;
1.1.1.5   root     2518:     do_blitter ();
1.1       root     2519: }
1.1.1.4   root     2520: 
1.1.1.20  root     2521: STATIC_INLINE void SPRxCTL_1 (uae_u16 v, int num, int hpos)
1.1       root     2522: {
1.1.1.2   root     2523:     int sprxp;
1.1.1.20  root     2524:     struct sprite *s = &spr[num];
1.1.1.2   root     2525:     sprctl[num] = v;
1.1.1.20  root     2526:     nr_armed -= s->armed;
                   2527:     s->armed = 0;
1.1.1.15  root     2528:     sprxp = (sprpos[num] & 0xFF) * 2 + (v & 1);
                   2529: 
                   2530:     /* Quite a bit salad in this register... */
                   2531:     if (currprefs.chipset_mask & CSMASK_AGA) {
                   2532:        /* We ignore the SHRES 35ns increment for now; SHRES support doesn't
                   2533:           work anyway, so we may as well restrict AGA sprites to a 70ns
                   2534:           resolution.  */
                   2535:        sprxp <<= 1;
                   2536:        sprxp |= (v >> 4) & 1;
                   2537:     }
1.1.1.20  root     2538:     s->xpos = sprxp;
                   2539:     s->vstart = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100);
                   2540:     s->vstop = (sprctl[num] >> 8) | ((sprctl[num] << 7) & 0x100);
                   2541:     if (vpos == s->vstart)
                   2542:        s->state = SPR_waiting_stop;
                   2543: #ifdef SPRITE_DEBUG
                   2544:     write_log ("%d:%d:SPR%dCTL V=%04.4X STATE=%d ARMED=%d\n", vpos, hpos, num, v, s->state, s->armed);
                   2545: #endif
1.1.1.2   root     2546: }
1.1.1.20  root     2547: STATIC_INLINE void SPRxPOS_1 (uae_u16 v, int num, int hpos)
1.1.1.2   root     2548: {
                   2549:     int sprxp;
1.1.1.20  root     2550:     struct sprite *s = &spr[num];
1.1.1.2   root     2551:     sprpos[num] = v;
1.1.1.15  root     2552:     sprxp = (v & 0xFF) * 2 + (sprctl[num] & 1);
                   2553: 
                   2554:     if (currprefs.chipset_mask & CSMASK_AGA) {
                   2555:        sprxp <<= 1;
                   2556:        sprxp |= (sprctl[num] >> 4) & 1;
                   2557:     }
1.1.1.20  root     2558:     s->xpos = sprxp;
                   2559:     s->vstart = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100);
                   2560: #ifdef SPRITE_DEBUG
                   2561:     write_log ("%d:%d:SPR%dPOS %04.4X STATE=%d ARMED=%d\n", vpos, hpos, num, v, s->state, s->armed);
                   2562: #endif
1.1.1.2   root     2563: }
1.1.1.8   root     2564: STATIC_INLINE void SPRxDATA_1 (uae_u16 v, int num)
1.1.1.2   root     2565: {
1.1.1.15  root     2566:     sprdata[num][0] = v;
1.1.1.10  root     2567:     nr_armed += 1 - spr[num].armed;
                   2568:     spr[num].armed = 1;
1.1.1.2   root     2569: }
1.1.1.8   root     2570: STATIC_INLINE void SPRxDATB_1 (uae_u16 v, int num)
1.1.1.2   root     2571: {
1.1.1.15  root     2572:     sprdatb[num][0] = v;
1.1.1.2   root     2573: }
1.1.1.4   root     2574: static void SPRxDATA (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxDATA_1 (v, num); }
                   2575: static void SPRxDATB (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxDATB_1 (v, num); }
1.1.1.20  root     2576: static void SPRxCTL (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxCTL_1 (v, num, hpos); }
                   2577: static void SPRxPOS (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxPOS_1 (v, num, hpos); }
1.1.1.4   root     2578: static void SPRxPTH (int hpos, uae_u16 v, int num)
1.1       root     2579: {
1.1.1.4   root     2580:     decide_sprites (hpos);
1.1.1.10  root     2581:     spr[num].pt &= 0xffff;
                   2582:     spr[num].pt |= (uae_u32)v << 16;
1.1.1.20  root     2583: #ifdef SPRITE_DEBUG
                   2584:     write_log ("%d:%d:SPR%dPTH %08.8X\n", vpos, hpos, num, spr[num].pt);
                   2585: #endif
1.1       root     2586: }
1.1.1.4   root     2587: static void SPRxPTL (int hpos, uae_u16 v, int num)
1.1       root     2588: {
1.1.1.4   root     2589:     decide_sprites (hpos);
1.1.1.10  root     2590:     spr[num].pt &= ~0xffff;
                   2591:     spr[num].pt |= v;
1.1.1.20  root     2592: #ifdef SPRITE_DEBUG
                   2593:     write_log ("%d:%d:SPR%dPTL %08.8X\n", vpos, hpos, num, spr[num].pt);
                   2594: #endif
1.1.1.3   root     2595: }
1.1.1.20  root     2596: 
1.1.1.4   root     2597: static void CLXCON (uae_u16 v)
1.1.1.3   root     2598: {
                   2599:     clxcon = v;
1.1.1.14  root     2600:     clxcon_bpl_enable = (v >> 6) & 63;
                   2601:     clxcon_bpl_match = v & 63;
                   2602:     clx_sprmask = ((((v >> 15) & 1) << 7) | (((v >> 14) & 1) << 5) | (((v >> 13) & 1) << 3) | (((v >> 12) & 1) << 1) | 0x55);
                   2603: }
                   2604: static void CLXCON2 (uae_u16 v)
                   2605: {
                   2606:     if (!(currprefs.chipset_mask & CSMASK_AGA))
                   2607:        return;
                   2608:     clxcon2 = v;
                   2609:     clxcon_bpl_enable |= v & (0x40|0x80);
                   2610:     clxcon_bpl_match |= (v & (0x01|0x02)) << 6;
                   2611:  }
1.1.1.4   root     2612: static uae_u16 CLXDAT (void)
1.1.1.3   root     2613: {
                   2614:     uae_u16 v = clxdat;
                   2615:     clxdat = 0;
                   2616:     return v;
                   2617: }
1.1.1.11  root     2618: 
1.1.1.13  root     2619: static uae_u16 COLOR_READ (int num)
1.1       root     2620: {
1.1.1.13  root     2621:     int cr, cg, cb, colreg;
                   2622:     uae_u16 cval;
                   2623: 
                   2624:     if (!(currprefs.chipset_mask & CSMASK_AGA) || !(bplcon2 & 0x0100))
                   2625:        return 0xffff;
                   2626: 
                   2627:     colreg = ((bplcon3 >> 13) & 7) * 32 + num;
                   2628:     cr = current_colors.color_regs_aga[colreg] >> 16;
                   2629:     cg = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF;
                   2630:     cb = current_colors.color_regs_aga[colreg] & 0xFF;
                   2631:     if (bplcon3 & 0x200)
1.1.1.16  root     2632:        cval = ((cr & 15) << 8) | ((cg & 15) << 4) | ((cb & 15) << 0);
1.1.1.13  root     2633:     else
1.1.1.16  root     2634:        cval = ((cr >> 4) << 8) | ((cg >> 4) << 4) | ((cb >> 4) << 0);
1.1.1.13  root     2635:     return cval;
                   2636: }
1.1.1.3   root     2637: 
1.1.1.13  root     2638: static void COLOR_WRITE (int hpos, uae_u16 v, int num)
                   2639: {
1.1       root     2640:     v &= 0xFFF;
1.1.1.11  root     2641:     if (currprefs.chipset_mask & CSMASK_AGA) {
1.1.1.4   root     2642:        int r,g,b;
                   2643:        int cr,cg,cb;
                   2644:        int colreg;
1.1.1.3   root     2645:        uae_u32 cval;
1.1.1.4   root     2646: 
1.1.1.11  root     2647:        /* writing is disabled when RDRAM=1 */
1.1.1.13  root     2648:        if (bplcon2 & 0x0100)
                   2649:            return;
1.1.1.11  root     2650: 
1.1.1.2   root     2651:        colreg = ((bplcon3 >> 13) & 7) * 32 + num;
1.1       root     2652:        r = (v & 0xF00) >> 8;
                   2653:        g = (v & 0xF0) >> 4;
                   2654:        b = (v & 0xF) >> 0;
1.1.1.11  root     2655:        cr = current_colors.color_regs_aga[colreg] >> 16;
                   2656:        cg = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF;
                   2657:        cb = current_colors.color_regs_aga[colreg] & 0xFF;
1.1       root     2658: 
1.1.1.2   root     2659:        if (bplcon3 & 0x200) {
1.1       root     2660:            cr &= 0xF0; cr |= r;
                   2661:            cg &= 0xF0; cg |= g;
                   2662:            cb &= 0xF0; cb |= b;
                   2663:        } else {
                   2664:            cr = r + (r << 4);
                   2665:            cg = g + (g << 4);
                   2666:            cb = b + (b << 4);
                   2667:        }
                   2668:        cval = (cr << 16) | (cg << 8) | cb;
1.1.1.11  root     2669:        if (cval == current_colors.color_regs_aga[colreg])
1.1       root     2670:            return;
1.1.1.5   root     2671: 
                   2672:        /* Call this with the old table still intact. */
1.1.1.11  root     2673:        record_color_change (hpos, colreg, cval);
1.1.1.5   root     2674:        remembered_color_entry = -1;
1.1.1.11  root     2675:        current_colors.color_regs_aga[colreg] = cval;
                   2676:        current_colors.acolors[colreg] = CONVERT_RGB (cval);
                   2677:    } else {
                   2678:        if (current_colors.color_regs_ecs[num] == v)
1.1       root     2679:            return;
1.1.1.2   root     2680:        /* Call this with the old table still intact. */
1.1.1.4   root     2681:        record_color_change (hpos, num, v);
1.1.1.2   root     2682:        remembered_color_entry = -1;
1.1.1.11  root     2683:        current_colors.color_regs_ecs[num] = v;
1.1.1.2   root     2684:        current_colors.acolors[num] = xcolors[v];
1.1       root     2685:     }
                   2686: }
1.1.1.3   root     2687: 
1.1.1.15  root     2688: /* The copper code.  The biggest nightmare in the whole emulator.
                   2689: 
                   2690:    Alright.  The current theory:
1.1.1.20  root     2691:    1. Copper moves happen 2 cycles after state READ2 is reached.
1.1.1.15  root     2692:       It can't happen immediately when we reach READ2, because the
1.1.1.20  root     2693:       data needs time to get back from the bus.  An additional 2
                   2694:       cycles are needed for non-Agnus registers, to take into account
                   2695:       the delay for moving data from chip to chip.
1.1.1.15  root     2696:    2. As stated in the HRM, a WAIT really does need an extra cycle
                   2697:       to wake up.  This is implemented by _not_ falling through from
                   2698:       a successful wait to READ1, but by starting the next cycle.
                   2699:       (Note: the extra cycle for the WAIT apparently really needs a
                   2700:       free cycle; i.e. contention with the bitplane fetch can slow
                   2701:       it down).
                   2702:    3. Apparently, to compensate for the extra wake up cycle, a WAIT
                   2703:       will use the _incremented_ horizontal position, so the WAIT
                   2704:       cycle normally finishes two clocks earlier than the position
                   2705:       it was waiting for.  The extra cycle then takes us to the
                   2706:       position that was waited for.
                   2707:       If the earlier cycle is busy with a bitplane, things change a bit.
                   2708:       E.g., waiting for position 0x50 in a 6 plane display: In cycle
                   2709:       0x4e, we fetch BPL5, so the wait wakes up in 0x50, the extra cycle
                   2710:       takes us to 0x54 (since 0x52 is busy), then we have READ1/READ2,
                   2711:       and the next register write is at 0x5c.
                   2712:    4. The last cycle in a line is not usable for the copper.
                   2713:    5. A 4 cycle delay also applies to the WAIT instruction.  This means
                   2714:       that the second of two back-to-back WAITs (or a WAIT whose
                   2715:       condition is immediately true) takes 8 cycles.
                   2716:    6. This also applies to a SKIP instruction.  The copper does not
                   2717:       fetch the next instruction while waiting for the second word of
                   2718:       a WAIT or a SKIP to arrive.
                   2719:    7. A SKIP also seems to need an unexplained additional two cycles
                   2720:       after its second word arrives; this is _not_ a memory cycle (I
                   2721:       think, the documentation is pretty clear on this).
                   2722:    8. Two additional cycles are inserted when writing to COPJMP1/2.  */
                   2723: 
1.1.1.4   root     2724: /* Determine which cycles are available for the copper in a display
                   2725:  * with a agiven number of planes.  */
1.1.1.2   root     2726: 
1.1.1.16  root     2727: STATIC_INLINE int copper_cant_read (int hpos)
1.1       root     2728: {
1.1.1.4   root     2729:     int t;
1.1.1.2   root     2730: 
1.1.1.15  root     2731:     if (hpos + 1 >= maxhpos)
1.1.1.2   root     2732:        return 1;
1.1.1.3   root     2733: 
1.1.1.15  root     2734:     if (fetch_state == fetch_not_started || hpos < thisline_decision.plfleft)
                   2735:        return 0;
                   2736: 
                   2737:     if ((passed_plfstop == 3 && hpos >= thisline_decision.plfright)
                   2738:        || hpos >= estimated_last_fetch_cycle)
1.1.1.4   root     2739:        return 0;
1.1.1.3   root     2740: 
1.1.1.16  root     2741:     t = curr_diagram[(hpos + cycle_diagram_shift) & fetchstart_mask];
1.1.1.4   root     2742: #if 0
                   2743:     if (t == -1)
                   2744:        abort ();
                   2745: #endif
                   2746:     return t;
1.1.1.2   root     2747: }
                   2748: 
1.1.1.10  root     2749: STATIC_INLINE int dangerous_reg (int reg)
                   2750: {
                   2751:     /* Safe:
                   2752:      * Bitplane pointers, control registers, modulos and data.
                   2753:      * Sprite pointers, control registers, and data.
                   2754:      * Color registers.  */
                   2755:     if (reg >= 0xE0 && reg < 0x1C0)
                   2756:        return 0;
                   2757:     return 1;
                   2758: }
                   2759: 
1.1.1.15  root     2760: static void perform_copper_write (int old_hpos)
                   2761: {
                   2762:     int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
                   2763:     unsigned int address = cop_state.saved_i1 & 0x1FE;
                   2764: 
                   2765:     record_copper (cop_state.saved_ip - 4, old_hpos, vpos);
                   2766: 
                   2767:     if (address < (copcon & 2 ? ((currprefs.chipset_mask & CSMASK_AGA) ? 0 : 0x40u) : 0x80u)) {
1.1.1.23! root     2768:        cop_state.state = COP_stop;
1.1.1.15  root     2769:        copper_enabled_thisline = 0;
                   2770:        unset_special (SPCFLAG_COPPER);
                   2771:        return;
                   2772:     }
                   2773: 
                   2774:     if (address == 0x88) {
                   2775:        cop_state.ip = cop1lc;
                   2776:        cop_state.state = COP_read1_in2;
                   2777:     } else if (address == 0x8A) {
                   2778:        cop_state.ip = cop2lc;
                   2779:        cop_state.state = COP_read1_in2;
                   2780:     } else
                   2781:        custom_wput_1 (old_hpos, address, cop_state.saved_i2);
                   2782: }
1.1.1.13  root     2783: 
1.1.1.20  root     2784: static int isagnus[]= {
                   2785:     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,
                   2786:     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,
                   2787:     0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
                   2788:     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,
                   2789:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* BPLxPT */
                   2790:     0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,
                   2791:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* SPRxPT */
                   2792:     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,
                   2793:     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, /* colors */
                   2794:     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
                   2795: };
                   2796: 
1.1.1.9   root     2797: static void update_copper (int until_hpos)
1.1.1.2   root     2798: {
1.1.1.23! root     2799:     int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
1.1.1.4   root     2800:     int c_hpos = cop_state.hpos;
1.1.1.2   root     2801: 
1.1.1.10  root     2802:     if (eventtab[ev_copper].active)
                   2803:        abort ();
                   2804: 
                   2805:     if (cop_state.state == COP_wait && vp < cop_state.vcmp)
                   2806:        abort ();
                   2807: 
                   2808:     until_hpos &= ~1;
                   2809: 
                   2810:     if (until_hpos > (maxhpos & ~1))
                   2811:        until_hpos = maxhpos & ~1;
1.1.1.3   root     2812: 
1.1.1.13  root     2813:     until_hpos += 2;
1.1.1.4   root     2814:     for (;;) {
1.1.1.10  root     2815:        int old_hpos = c_hpos;
                   2816:        int hp;
                   2817: 
1.1.1.13  root     2818:        if (c_hpos >= until_hpos)
1.1.1.3   root     2819:            break;
                   2820: 
1.1.1.13  root     2821:        /* So we know about the fetch state.  */
1.1.1.9   root     2822:        decide_line (c_hpos);
1.1.1.3   root     2823: 
1.1.1.15  root     2824:        switch (cop_state.state) {
                   2825:        case COP_read1_in2:
                   2826:            cop_state.state = COP_read1;
                   2827:            break;
                   2828:        case COP_read1_wr_in2:
                   2829:            cop_state.state = COP_read1;
                   2830:            perform_copper_write (old_hpos);
                   2831:            /* That could have turned off the copper.  */
                   2832:            if (! copper_enabled_thisline)
                   2833:                goto out;
                   2834: 
                   2835:            break;
                   2836:        case COP_read1_wr_in4:
                   2837:            cop_state.state = COP_read1_wr_in2;
                   2838:            break;
                   2839:        case COP_read2_wr_in2:
                   2840:            cop_state.state = COP_read2;
                   2841:            perform_copper_write (old_hpos);
                   2842:            /* That could have turned off the copper.  */
                   2843:            if (! copper_enabled_thisline)
                   2844:                goto out;
                   2845: 
                   2846:            break;
                   2847:        case COP_wait_in2:
                   2848:            cop_state.state = COP_wait1;
                   2849:            break;
                   2850:        case COP_wait_in4:
                   2851:            cop_state.state = COP_wait_in2;
                   2852:            break;
                   2853:        case COP_skip_in2:
                   2854:        {
                   2855:            static int skipped_before;
                   2856:            unsigned int vcmp, hcmp, vp1, hp1;
                   2857:            cop_state.state = COP_read1_in2;
                   2858: 
                   2859:            vcmp = (cop_state.saved_i1 & (cop_state.saved_i2 | 0x8000)) >> 8;
                   2860:            hcmp = (cop_state.saved_i1 & cop_state.saved_i2 & 0xFE);
                   2861: 
                   2862:            if (! skipped_before) {
                   2863:                skipped_before = 1;
                   2864:                write_log ("Program uses Copper SKIP instruction.\n");
                   2865:            }
                   2866: 
                   2867:            vp1 = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
                   2868:            hp1 = old_hpos & (cop_state.saved_i2 & 0xFE);
                   2869: 
                   2870:            if ((vp1 > vcmp || (vp1 == vcmp && hp1 >= hcmp))
                   2871:                && ((cop_state.saved_i2 & 0x8000) != 0 || ! (DMACONR() & 0x4000)))
                   2872:                cop_state.ignore_next = 1;
                   2873:            break;
                   2874:        }
                   2875:        case COP_skip_in4:
                   2876:            cop_state.state = COP_skip_in2;
                   2877:            break;
                   2878:        default:
                   2879:            break;
                   2880:        }
                   2881: 
1.1.1.10  root     2882:        c_hpos += 2;
1.1.1.16  root     2883:        if (copper_cant_read (old_hpos))
1.1.1.10  root     2884:            continue;
1.1.1.3   root     2885: 
1.1.1.10  root     2886:        switch (cop_state.state) {
1.1.1.15  root     2887:        case COP_read1_wr_in4:
                   2888:            abort ();
                   2889: 
                   2890:        case COP_read1_wr_in2:
1.1.1.9   root     2891:        case COP_read1:
1.1.1.15  root     2892:            cop_state.i1 = chipmem_wget (cop_state.ip);
1.1.1.9   root     2893:            cop_state.ip += 2;
1.1.1.15  root     2894:            cop_state.state = cop_state.state == COP_read1 ? COP_read2 : COP_read2_wr_in2;
1.1.1.9   root     2895:            break;
                   2896: 
1.1.1.15  root     2897:        case COP_read2_wr_in2:
                   2898:            abort ();
                   2899: 
1.1.1.9   root     2900:        case COP_read2:
1.1.1.15  root     2901:            cop_state.i2 = chipmem_wget (cop_state.ip);
1.1.1.9   root     2902:            cop_state.ip += 2;
                   2903:            if (cop_state.ignore_next) {
                   2904:                cop_state.ignore_next = 0;
1.1.1.15  root     2905:                cop_state.state = COP_read1;
1.1.1.9   root     2906:                break;
1.1.1.3   root     2907:            }
1.1.1.2   root     2908: 
1.1.1.15  root     2909:            cop_state.saved_i1 = cop_state.i1;
                   2910:            cop_state.saved_i2 = cop_state.i2;
                   2911:            cop_state.saved_ip = cop_state.ip;
                   2912: 
                   2913:            if (cop_state.i1 & 1) {
                   2914:                if (cop_state.i2 & 1)
                   2915:                    cop_state.state = COP_skip_in4;
                   2916:                else
                   2917:                    cop_state.state = COP_wait_in4;
1.1.1.20  root     2918:            } else {
                   2919:                unsigned int reg = cop_state.i1 & 0x1FE;
                   2920:                cop_state.state = isagnus[reg >> 1] ? COP_read1_wr_in2 : COP_read1_wr_in4;
                   2921:            }
1.1.1.15  root     2922:            break;
                   2923: 
                   2924:        case COP_wait1:
1.1.1.20  root     2925:            /* There's a nasty case here.  As stated in the "Theory" comment above, we
                   2926:               test against the incremented copper position.  I believe this means that
                   2927:               we have to increment the _vertical_ position at the last cycle in the line,
                   2928:               and set the horizontal position to 0.
                   2929:               Normally, this isn't going to make a difference, since we consider these
                   2930:               last cycles unavailable for the copper, so waking up in the last cycle has
                   2931:               the same effect as waking up at the start of the line.  However, there is
                   2932:               one possible problem:  If we're at 0xFFE0, any wait for an earlier position
                   2933:               must _not_ complete (since, in effect, the current position will be back
                   2934:               at 0/0).  This can be seen in the Superfrog copper list.
                   2935:               Things get monstrously complicated if we try to handle this "properly" by
                   2936:               incrementing vpos and setting c_hpos to 0.  Especially the various speedup
                   2937:               hacks really assume that vpos remains constant during one line.  Hence,
                   2938:               this hack: defer the entire decision until the next line if necessary.  */
                   2939:            if (c_hpos >= (maxhpos & ~1))
                   2940:                break;
1.1.1.9   root     2941:            cop_state.state = COP_wait;
1.1.1.13  root     2942: 
1.1.1.15  root     2943:            cop_state.vcmp = (cop_state.saved_i1 & (cop_state.saved_i2 | 0x8000)) >> 8;
                   2944:            cop_state.hcmp = (cop_state.saved_i1 & cop_state.saved_i2 & 0xFE);
                   2945: 
                   2946:            vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
1.1.1.13  root     2947: 
1.1.1.15  root     2948:            if (cop_state.saved_i1 == 0xFFFF && cop_state.saved_i2 == 0xFFFE) {
1.1.1.9   root     2949:                cop_state.state = COP_stop;
1.1.1.10  root     2950:                copper_enabled_thisline = 0;
1.1.1.13  root     2951:                unset_special (SPCFLAG_COPPER);
1.1.1.10  root     2952:                goto out;
1.1.1.2   root     2953:            }
1.1.1.9   root     2954:            if (vp < cop_state.vcmp) {
1.1.1.10  root     2955:                copper_enabled_thisline = 0;
1.1.1.13  root     2956:                unset_special (SPCFLAG_COPPER);
1.1.1.10  root     2957:                goto out;
1.1.1.2   root     2958:            }
1.1.1.10  root     2959: 
1.1.1.15  root     2960:            /* fall through */
                   2961:        do_wait:
1.1.1.10  root     2962:        case COP_wait:
                   2963:            if (vp < cop_state.vcmp)
                   2964:                abort ();
                   2965: 
1.1.1.15  root     2966:            hp = c_hpos & (cop_state.saved_i2 & 0xFE);
                   2967:            if (vp == cop_state.vcmp && hp < cop_state.hcmp) {
                   2968:                /* Position not reached yet.  */
1.1.1.4   root     2969:                break;
1.1.1.15  root     2970:            }
1.1.1.10  root     2971: 
                   2972:            /* Now we know that the comparisons were successful.  We might still
                   2973:               have to wait for the blitter though.  */
1.1.1.15  root     2974:            if ((cop_state.saved_i2 & 0x8000) == 0 && (DMACONR() & 0x4000)) {
1.1.1.9   root     2975:                /* We need to wait for the blitter.  */
1.1.1.4   root     2976:                cop_state.state = COP_bltwait;
1.1.1.10  root     2977:                copper_enabled_thisline = 0;
1.1.1.13  root     2978:                unset_special (SPCFLAG_COPPER);
1.1.1.10  root     2979:                goto out;
1.1.1.2   root     2980:            }
1.1.1.10  root     2981: 
1.1.1.15  root     2982:            record_copper (cop_state.ip - 4, old_hpos, vpos);
1.1.1.13  root     2983: 
1.1.1.10  root     2984:            cop_state.state = COP_read1;
1.1.1.4   root     2985:            break;
1.1.1.2   root     2986: 
1.1.1.13  root     2987:        default:
1.1.1.15  root     2988:            break;
1.1       root     2989:        }
1.1.1.4   root     2990:     }
1.1.1.10  root     2991: 
                   2992:   out:
1.1.1.4   root     2993:     cop_state.hpos = c_hpos;
1.1       root     2994: }
                   2995: 
1.1.1.9   root     2996: static void compute_spcflag_copper (void)
1.1       root     2997: {
1.1.1.10  root     2998:     copper_enabled_thisline = 0;
1.1.1.13  root     2999:     unset_special (SPCFLAG_COPPER);
1.1.1.10  root     3000:     if (! dmaen (DMA_COPPER) || cop_state.state == COP_stop || cop_state.state == COP_bltwait)
                   3001:        return;
                   3002: 
                   3003:     if (cop_state.state == COP_wait) {
1.1.1.15  root     3004:        int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
1.1.1.10  root     3005: 
                   3006:        if (vp < cop_state.vcmp)
                   3007:            return;
                   3008:     }
                   3009:     copper_enabled_thisline = 1;
1.1.1.15  root     3010: 
                   3011:     if (! eventtab[ev_copper].active)
                   3012:        set_special (SPCFLAG_COPPER);
1.1.1.10  root     3013: }
                   3014: 
                   3015: static void copper_handler (void)
                   3016: {
                   3017:     /* This will take effect immediately, within the same cycle.  */
1.1.1.13  root     3018:     set_special (SPCFLAG_COPPER);
1.1.1.10  root     3019: 
                   3020:     if (! copper_enabled_thisline)
                   3021:        abort ();
                   3022: 
                   3023:     eventtab[ev_copper].active = 0;
1.1.1.3   root     3024: }
1.1.1.2   root     3025: 
1.1.1.4   root     3026: void blitter_done_notify (void)
1.1       root     3027: {
1.1.1.4   root     3028:     if (cop_state.state != COP_bltwait)
                   3029:        return;
1.1.1.10  root     3030: 
1.1.1.20  root     3031:     cop_state.hpos = current_hpos () & ~1;
                   3032:     cop_state.vpos = vpos;
1.1.1.9   root     3033:     cop_state.state = COP_wait;
1.1.1.20  root     3034:     compute_spcflag_copper ();
1.1.1.2   root     3035: }
                   3036: 
1.1.1.9   root     3037: void do_copper (void)
1.1.1.2   root     3038: {
1.1.1.4   root     3039:     int hpos = current_hpos ();
                   3040:     update_copper (hpos);
1.1.1.2   root     3041: }
                   3042: 
1.1.1.15  root     3043: /* ADDR is the address that is going to be read/written; this access is
                   3044:    the reason why we want to update the copper.  This function is also
1.1.1.22  root     3045:    used from hsync_handler to finish up the line.  */
                   3046: STATIC_INLINE void sync_copper_with_cpu (int hpos, int do_schedule)
1.1.1.13  root     3047: {
1.1.1.15  root     3048:     /* Need to let the copper advance to the current position.  */
1.1.1.13  root     3049:     if (eventtab[ev_copper].active) {
1.1.1.15  root     3050:        eventtab[ev_copper].active = 0;
                   3051:        if (do_schedule)
                   3052:            events_schedule ();
                   3053:        set_special (SPCFLAG_COPPER);
1.1.1.13  root     3054:     }
1.1.1.15  root     3055:     if (copper_enabled_thisline)
1.1.1.13  root     3056:        update_copper (hpos);
                   3057: }
                   3058: 
1.1.1.20  root     3059: STATIC_INLINE uae_u16 sprite_fetch (struct sprite *s, int dma)
                   3060: {
                   3061:     uae_u16 data = last_custom_value;
                   3062:     if (dma)
                   3063:        data = last_custom_value = chipmem_wget (s->pt);
                   3064:     s->pt += 2;
                   3065:     return data;
                   3066: }
                   3067: 
                   3068: STATIC_INLINE void do_sprites_1 (int num, int cycle, int hpos)
                   3069: {
                   3070:     struct sprite *s = &spr[num];
                   3071:     int dma;
                   3072: 
                   3073:     if (cycle == 0) {
                   3074:        if (vpos == s->vstart)
                   3075:            s->state = SPR_waiting_stop;
                   3076:        if (vpos == s->vstop)
                   3077:            s->state = SPR_restart;
                   3078:     }
                   3079:     if (!dmaen (DMA_SPRITE))
                   3080:        return;
                   3081:     dma = hpos < ddfstrt || diwstate != DIW_waiting_stop || !dmaen (DMA_BITPLANE);
                   3082:     if (s->state == SPR_restart || vpos == sprite_vblank_endline) {
                   3083:        uae_u16 data = sprite_fetch (s, dma);
                   3084:        s->pt += (sprite_width >> 3) - 2;
                   3085: #ifdef SPRITE_DEBUG
                   3086:        write_log ("dma:");
                   3087: #endif
                   3088:        if (cycle == 0) {
                   3089:            SPRxPOS_1 (dma ? data : sprpos[num], num, hpos);
                   3090:        } else {
                   3091:            s->state = SPR_waiting_start;
                   3092:            SPRxCTL_1 (dma ? data : sprctl[num], num, hpos);
                   3093:        }
                   3094:     } else if (s->state == SPR_waiting_stop) {
                   3095:        uae_u16 data = sprite_fetch (s, dma);
                   3096: 
                   3097:        if (cycle == 0)
                   3098:            SPRxDATA_1 (dma ? data : sprdata[num][0], num);
                   3099:        else
                   3100:            SPRxDATB_1 (dma ? data : sprdatb[num][0], num);
                   3101:        switch (sprite_width)
                   3102:            {
                   3103:            case 64:
                   3104:            {
                   3105:                uae_u32 data32 = sprite_fetch (s, dma);
                   3106:                uae_u32 data641 = sprite_fetch (s, dma);
                   3107:                uae_u32 data642 = sprite_fetch (s, dma);
                   3108:                if (dma) {
                   3109:                    if (cycle == 0) {
                   3110:                        sprdata[num][3] = data642;
                   3111:                        sprdata[num][2] = data641;
                   3112:                        sprdata[num][1] = data32;
                   3113:                    } else {
                   3114:                        sprdatb[num][3] = data642;
                   3115:                        sprdatb[num][2] = data641;
                   3116:                        sprdatb[num][1] = data32;
                   3117:                    }
                   3118:                }
                   3119:            }
                   3120:            break;
                   3121:            case 32:
1.1.1.23! root     3122:            {
1.1.1.20  root     3123:                uae_u32 data32 = sprite_fetch (s, dma);
                   3124:                if (dma) {
                   3125:                    if (cycle == 0)
                   3126:                        sprdata[num][1] = data32;
                   3127:                    else
                   3128:                        sprdatb[num][1] = data32;
                   3129:                }
                   3130:            }
                   3131:            break;
                   3132:        }
                   3133:     }
                   3134: }
                   3135: 
                   3136: #define SPR0_HPOS 0x15
                   3137: static void do_sprites (int hpos)
1.1.1.4   root     3138: {
1.1.1.13  root     3139:     int maxspr, minspr;
1.1.1.20  root     3140:     int i;
1.1.1.2   root     3141: 
1.1.1.4   root     3142:     /* I don't know whether this is right. Some programs write the sprite pointers
1.1.1.13  root     3143:      * directly at the start of the copper list. With the test against currvp, the
1.1.1.4   root     3144:      * first two words of data are read on the second line in the frame. The problem
                   3145:      * occurs when the program jumps to another copperlist a few lines further down
                   3146:      * which _also_ writes the sprite pointer registers. This means that a) writing
                   3147:      * to the sprite pointers sets the state to SPR_restart; or b) that sprite DMA
                   3148:      * is disabled until the end of the vertical blanking interval. The HRM
                   3149:      * isn't clear - it says that the vertical sprite position can be set to any
                   3150:      * value, but this wouldn't be the first mistake... */
                   3151:     /* Update: I modified one of the programs to write the sprite pointers the
                   3152:      * second time only _after_ the VBlank interval, and it showed the same behaviour
                   3153:      * as it did unmodified under UAE with the above check. This indicates that the
                   3154:      * solution below is correct. */
1.1.1.9   root     3155:     /* Another update: seems like we have to use the NTSC value here (see Sanity Turmoil
                   3156:      * demo).  */
1.1.1.10  root     3157:     /* Maximum for Sanity Turmoil: 27.
                   3158:        Minimum for Sanity Arte: 22.  */
1.1.1.20  root     3159:     if (vpos < sprite_vblank_endline)
1.1.1.4   root     3160:        return;
1.1.1.3   root     3161: 
1.1.1.20  root     3162:     maxspr = hpos;
                   3163:     minspr = last_sprite_hpos;
1.1.1.13  root     3164: 
1.1.1.20  root     3165:     if (minspr >= SPR0_HPOS + MAX_SPRITES * 4 || maxspr < SPR0_HPOS)
1.1.1.4   root     3166:        return;
1.1.1.13  root     3167: 
1.1.1.20  root     3168:     if (maxspr > SPR0_HPOS + MAX_SPRITES * 4)
                   3169:        maxspr = SPR0_HPOS + MAX_SPRITES * 4;
                   3170:     if (minspr < SPR0_HPOS)
                   3171:        minspr = SPR0_HPOS;
1.1.1.2   root     3172: 
1.1.1.13  root     3173:     for (i = minspr; i < maxspr; i++) {
1.1.1.20  root     3174:        int cycle = -1;
                   3175:        switch ((i - SPR0_HPOS) & 3)
                   3176:        {
                   3177:        case 0:
                   3178:            cycle = 0;
                   3179:            break;
                   3180:        case 2:
                   3181:            cycle = 1;
                   3182:            break;
1.1       root     3183:        }
1.1.1.20  root     3184:        if (cycle >= 0)
                   3185:            do_sprites_1 ((i - SPR0_HPOS) / 4, cycle, i);
1.1       root     3186:     }
1.1.1.13  root     3187:     last_sprite_hpos = hpos;
1.1       root     3188: }
                   3189: 
1.1.1.4   root     3190: static void init_sprites (void)
1.1       root     3191: {
1.1.1.4   root     3192:     int i;
1.1.1.2   root     3193: 
1.1.1.20  root     3194:     for (i = 0; i < MAX_SPRITES; i++)
                   3195:        spr[i].state = SPR_restart;
1.1.1.4   root     3196:     memset (sprpos, 0, sizeof sprpos);
                   3197:     memset (sprctl, 0, sizeof sprctl);
                   3198: }
1.1.1.2   root     3199: 
1.1.1.3   root     3200: static void adjust_array_sizes (void)
1.1.1.2   root     3201: {
                   3202: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
1.1.1.13  root     3203:     if (delta_sprite_entry) {
1.1.1.3   root     3204:        void *p1,*p2;
1.1.1.13  root     3205:        int mcc = max_sprite_entry + 50 + delta_sprite_entry;
                   3206:        delta_sprite_entry = 0;
                   3207:        p1 = realloc (sprite_entries[0], mcc * sizeof (struct sprite_entry));
                   3208:        p2 = realloc (sprite_entries[1], mcc * sizeof (struct sprite_entry));
                   3209:        if (p1) sprite_entries[0] = p1;
                   3210:        if (p2) sprite_entries[1] = p2;
1.1.1.3   root     3211:        if (p1 && p2) {
1.1.1.18  root     3212:            write_log ("new max_sprite_entry=%d\n",mcc);
1.1.1.13  root     3213:            max_sprite_entry = mcc;
1.1.1.2   root     3214:        }
                   3215:     }
1.1.1.3   root     3216:     if (delta_color_change) {
                   3217:        void *p1,*p2;
                   3218:        int mcc = max_color_change + 200 + delta_color_change;
                   3219:        delta_color_change = 0;
                   3220:        p1 = realloc (color_changes[0], mcc * sizeof (struct color_change));
                   3221:        p2 = realloc (color_changes[1], mcc * sizeof (struct color_change));
                   3222:        if (p1) color_changes[0] = p1;
                   3223:        if (p2) color_changes[1] = p2;
                   3224:        if (p1 && p2) {
1.1.1.18  root     3225:            write_log ("new max_color_change=%d\n",mcc);
1.1.1.2   root     3226:            max_color_change = mcc;
1.1.1.3   root     3227:        }
                   3228:     }
1.1.1.2   root     3229: #endif
1.1.1.3   root     3230: }
                   3231: 
1.1.1.4   root     3232: static void init_hardware_frame (void)
1.1.1.3   root     3233: {
1.1.1.4   root     3234:     next_lineno = 0;
                   3235:     nextline_how = nln_normal;
                   3236:     diwstate = DIW_waiting_start;
                   3237:     hdiwstate = DIW_waiting_start;
                   3238: }
1.1.1.2   root     3239: 
1.1.1.4   root     3240: void init_hardware_for_drawing_frame (void)
                   3241: {
1.1.1.3   root     3242:     adjust_array_sizes ();
                   3243: 
1.1.1.13  root     3244:     /* Avoid this code in the first frame after a customreset.  */
                   3245:     if (prev_sprite_entries) {
                   3246:        int first_pixel = prev_sprite_entries[0].first_pixel;
                   3247:        int npixels = prev_sprite_entries[prev_next_sprite_entry].first_pixel - first_pixel;
                   3248:        memset (spixels + first_pixel, 0, npixels * sizeof *spixels);
                   3249:        memset (spixstate.bytes + first_pixel, 0, npixels * sizeof *spixstate.bytes);
                   3250:     }
                   3251:     prev_next_sprite_entry = next_sprite_entry;
1.1.1.3   root     3252: 
1.1.1.13  root     3253:     next_color_change = 0;
                   3254:     next_sprite_entry = 0;
1.1.1.2   root     3255:     next_color_entry = 0;
                   3256:     remembered_color_entry = -1;
1.1.1.13  root     3257: 
                   3258:     prev_sprite_entries = sprite_entries[current_change_set];
                   3259:     curr_sprite_entries = sprite_entries[current_change_set ^ 1];
1.1.1.2   root     3260:     prev_color_changes = color_changes[current_change_set];
                   3261:     curr_color_changes = color_changes[current_change_set ^ 1];
                   3262:     prev_color_tables = color_tables[current_change_set];
                   3263:     curr_color_tables = color_tables[current_change_set ^ 1];
1.1.1.3   root     3264: 
1.1.1.2   root     3265:     prev_drawinfo = line_drawinfo[current_change_set];
1.1.1.4   root     3266:     curr_drawinfo = line_drawinfo[current_change_set ^ 1];
                   3267:     current_change_set ^= 1;
1.1.1.3   root     3268: 
1.1.1.4   root     3269:     color_src_match = color_dest_match = -1;
1.1.1.13  root     3270: 
                   3271:     /* Use both halves of the array in alternating fashion.  */
                   3272:     curr_sprite_entries[0].first_pixel = current_change_set * MAX_SPR_PIXELS;
                   3273:     next_sprite_forced = 1;
1.1.1.3   root     3274: }
                   3275: 
1.1.1.15  root     3276: static void do_savestate(void);
                   3277: 
1.1.1.2   root     3278: static void vsync_handler (void)
1.1       root     3279: {
1.1.1.20  root     3280:     int i;
                   3281:     for (i = 0; i < MAX_SPRITES; i++)
                   3282:        spr[i].state = SPR_waiting_start;
                   3283: 
1.1.1.12  root     3284:     n_frames++;
                   3285: 
1.1.1.4   root     3286:     if (currprefs.m68k_speed == -1) {
                   3287:        frame_time_t curr_time = read_processor_time ();
1.1.1.3   root     3288:        vsyncmintime += vsynctime;
                   3289:        /* @@@ Mathias? How do you think we should do this? */
                   3290:        /* If we are too far behind, or we just did a reset, adjust the
                   3291:         * needed time. */
1.1.1.4   root     3292:        if ((long int)(curr_time - vsyncmintime) > 0 || rpt_did_reset)
1.1.1.3   root     3293:            vsyncmintime = curr_time + vsynctime;
1.1.1.4   root     3294:        rpt_did_reset = 0;
1.1.1.20  root     3295:     } else {
                   3296: #ifdef RPT_WORKS_OK
                   3297:        if (RPT_WORKS_OK) {
                   3298:            frame_time_t curr_time;
                   3299:            do
                   3300:                curr_time = read_processor_time ();
                   3301:            while ((long int)(read_processor_time () - vsyncmintime) < 0);
                   3302:            vsyncmintime = curr_time + vsynctime;
                   3303:        }
                   3304: #endif
1.1.1.3   root     3305:     }
1.1.1.4   root     3306: 
1.1.1.3   root     3307:     handle_events ();
1.1       root     3308: 
1.1.1.4   root     3309:     INTREQ (0x8020);
1.1.1.3   root     3310:     if (bplcon0 & 4)
1.1.1.2   root     3311:        lof ^= 0x8000;
1.1.1.3   root     3312: 
1.1.1.18  root     3313: #ifdef PICASSO96
1.1.1.16  root     3314:     if (picasso_on)
                   3315:        picasso_handle_vsync ();
1.1.1.18  root     3316: #endif
1.1.1.4   root     3317:     vsync_handle_redraw (lof, lof_changed);
1.1.1.16  root     3318: 
1.1.1.4   root     3319:     if (quit_program > 0)
1.1.1.3   root     3320:        return;
                   3321: 
1.1.1.4   root     3322:     {
1.1.1.3   root     3323:        static int cnt = 0;
                   3324:        if (cnt == 0) {
                   3325:            /* resolution_check_change (); */
                   3326:            DISK_check_change ();
                   3327:            cnt = 5;
                   3328:        }
                   3329:        cnt--;
1.1.1.2   root     3330:     }
1.1.1.3   root     3331: 
1.1.1.15  root     3332:     /* Start a new set of copper records.  */
                   3333:     curr_cop_set ^= 1;
                   3334:     nr_cop_records[curr_cop_set] = 0;
                   3335: 
1.1.1.7   root     3336:     /* For now, let's only allow this to change at vsync time.  It gets too
                   3337:      * hairy otherwise.  */
                   3338:     if (beamcon0 != new_beamcon0)
                   3339:        init_hz ();
                   3340: 
1.1.1.2   root     3341:     lof_changed = 0;
1.1.1.3   root     3342: 
1.1.1.4   root     3343:     cop_state.ip = cop1lc;
                   3344:     cop_state.state = COP_read1;
                   3345:     cop_state.vpos = 0;
                   3346:     cop_state.hpos = 0;
                   3347:     cop_state.ignore_next = 0;
                   3348: 
                   3349:     init_hardware_frame ();
                   3350: 
1.1       root     3351: #ifdef HAVE_GETTIMEOFDAY
                   3352:     {
                   3353:        struct timeval tv;
                   3354:        unsigned long int newtime;
1.1.1.3   root     3355: 
1.1.1.9   root     3356:        gettimeofday (&tv,NULL);
1.1       root     3357:        newtime = (tv.tv_sec-seconds_base) * 1000 + tv.tv_usec / 1000;
1.1.1.3   root     3358: 
                   3359:        if (!bogusframe) {
1.1.1.6   root     3360:            lastframetime = newtime - msecs;
                   3361: 
                   3362:            frametime += lastframetime;
1.1       root     3363:            timeframes++;
1.1.1.6   root     3364: 
                   3365:            if ((timeframes & 127) == 0)
                   3366:                gui_fps (1000 * timeframes / frametime);
1.1       root     3367:        }
                   3368:        msecs = newtime;
                   3369:        bogusframe = 0;
                   3370:     }
                   3371: #endif
1.1.1.7   root     3372:     if (timehack_alive > 0)
                   3373:        timehack_alive--;
1.1.1.23! root     3374:     inputdevice_vsync ();
1.1.1.15  root     3375:     CIA_vsync_handler ();
1.1       root     3376: }
                   3377: 
1.1.1.4   root     3378: static void hsync_handler (void)
1.1       root     3379: {
1.1.1.22  root     3380:     sync_copper_with_cpu (maxhpos, 0);
1.1.1.10  root     3381: 
1.1.1.2   root     3382:     finish_decisions ();
1.1.1.15  root     3383:     if (thisline_decision.plfleft != -1) {
                   3384:        if (currprefs.collision_level > 1)
                   3385:            do_sprite_collisions ();
                   3386:        if (currprefs.collision_level > 2)
                   3387:            do_playfield_collisions ();
                   3388:     }
1.1.1.5   root     3389:     hsync_record_line_state (next_lineno, nextline_how, thisline_changed);
1.1       root     3390: 
1.1.1.14  root     3391:     eventtab[ev_hsync].evtime += get_cycles () - eventtab[ev_hsync].oldcycles;
                   3392:     eventtab[ev_hsync].oldcycles = get_cycles ();
1.1.1.8   root     3393:     CIA_hsync_handler ();
1.1.1.3   root     3394: 
1.1.1.23! root     3395:     if (currprefs.produce_sound > 0)
        !          3396:        audio_hsync (1);
1.1.1.4   root     3397: 
                   3398:     hardware_line_completed (next_lineno);
                   3399: 
1.1.1.16  root     3400:     /* In theory only an equality test is needed here - but if a program
                   3401:        goes haywire with the VPOSW register, it can cause us to miss this,
                   3402:        with vpos going into the thousands (and all the nasty consequences
                   3403:        this has).  */
                   3404: 
1.1.1.22  root     3405:     if (++vpos >= (maxvpos + (lof == 0 ? 0 : 1))) {
1.1       root     3406:        vpos = 0;
1.1.1.15  root     3407:        vsync_handler ();
1.1       root     3408:     }
1.1.1.2   root     3409: 
1.1.1.15  root     3410:     DISK_update ();
                   3411: 
1.1.1.22  root     3412:     is_lastline = vpos + 1 == maxvpos + (lof == 0 ? 0 : 1) && currprefs.m68k_speed == -1 && ! rpt_did_reset;
1.1.1.3   root     3413: 
1.1.1.4   root     3414:     if ((bplcon0 & 4) && currprefs.gfx_linedbl)
                   3415:        notice_interlace_seen ();
1.1.1.2   root     3416: 
1.1.1.22  root     3417:     if (!nodraw ()) {
1.1.1.4   root     3418:        int lineno = vpos;
                   3419:        nextline_how = nln_normal;
1.1.1.3   root     3420:        if (currprefs.gfx_linedbl) {
1.1       root     3421:            lineno *= 2;
1.1.1.5   root     3422:            nextline_how = currprefs.gfx_linedbl == 1 ? nln_doubled : nln_nblack;
1.1.1.2   root     3423:            if (bplcon0 & 4) {
                   3424:                if (!lof) {
                   3425:                    lineno++;
1.1.1.4   root     3426:                    nextline_how = nln_lower;
1.1.1.2   root     3427:                } else {
1.1.1.4   root     3428:                    nextline_how = nln_upper;
1.1.1.2   root     3429:                }
1.1       root     3430:            }
                   3431:        }
                   3432:        next_lineno = lineno;
1.1.1.2   root     3433:        reset_decisions ();
1.1       root     3434:     }
1.1.1.3   root     3435:     if (uae_int_requested) {
                   3436:        set_uae_int_flag ();
                   3437:        INTREQ (0xA000);
                   3438:     }
1.1.1.9   root     3439:     /* See if there's a chance of a copper wait ending this line.  */
                   3440:     cop_state.hpos = 0;
                   3441:     compute_spcflag_copper ();
1.1.1.23! root     3442:     inputdevice_hsync ();
1.1.1.3   root     3443: }
                   3444: 
1.1.1.15  root     3445: void init_eventtab (void)
1.1.1.3   root     3446: {
                   3447:     int i;
                   3448: 
1.1.1.15  root     3449:     currcycle = 0;
                   3450:     for (i = 0; i < ev_max; i++) {
1.1.1.3   root     3451:        eventtab[i].active = 0;
                   3452:        eventtab[i].oldcycles = 0;
                   3453:     }
1.1.1.4   root     3454: 
1.1.1.3   root     3455:     eventtab[ev_cia].handler = CIA_handler;
                   3456:     eventtab[ev_hsync].handler = hsync_handler;
1.1.1.14  root     3457:     eventtab[ev_hsync].evtime = maxhpos * CYCLE_UNIT + get_cycles ();
1.1.1.3   root     3458:     eventtab[ev_hsync].active = 1;
                   3459: 
1.1.1.10  root     3460:     eventtab[ev_copper].handler = copper_handler;
                   3461:     eventtab[ev_copper].active = 0;
1.1.1.3   root     3462:     eventtab[ev_blitter].handler = blitter_handler;
                   3463:     eventtab[ev_blitter].active = 0;
1.1.1.11  root     3464:     eventtab[ev_disk].handler = DISK_handler;
                   3465:     eventtab[ev_disk].active = 0;
1.1.1.14  root     3466:     eventtab[ev_audio].handler = audio_evhandler;
                   3467:     eventtab[ev_audio].active = 0;
1.1.1.3   root     3468:     events_schedule ();
1.1       root     3469: }
                   3470: 
1.1.1.3   root     3471: void customreset (void)
1.1       root     3472: {
1.1.1.4   root     3473:     int i;
1.1.1.11  root     3474:     int zero = 0;
1.1       root     3475: #ifdef HAVE_GETTIMEOFDAY
                   3476:     struct timeval tv;
                   3477: #endif
1.1.1.2   root     3478: 
1.1.1.15  root     3479:     if (! savestate_state) {
                   3480:        currprefs.chipset_mask = changed_prefs.chipset_mask;
                   3481:        if ((currprefs.chipset_mask & CSMASK_AGA) == 0) {
                   3482:            for (i = 0; i < 32; i++) {
                   3483:                current_colors.color_regs_ecs[i] = 0;
                   3484:                current_colors.acolors[i] = xcolors[0];
                   3485:            }
                   3486:        } else {
1.1.1.20  root     3487:            for (i = 0; i < 256; i++) {
1.1.1.15  root     3488:                current_colors.color_regs_aga[i] = 0;
                   3489:                current_colors.acolors[i] = CONVERT_RGB (zero);
                   3490:            }
1.1.1.11  root     3491:        }
1.1.1.15  root     3492: 
                   3493:        clx_sprmask = 0xFF;
                   3494:        clxdat = 0;
                   3495: 
                   3496:        /* Clear the armed flags of all sprites.  */
                   3497:        memset (spr, 0, sizeof spr);
                   3498:        nr_armed = 0;
                   3499: 
                   3500:        dmacon = intena = 0;
                   3501: 
                   3502:        copcon = 0;
                   3503:        DSKLEN (0, 0);
                   3504: 
1.1.1.16  root     3505:        bplcon0 = 0;
1.1.1.15  root     3506:        bplcon4 = 0x11; /* Get AGA chipset into ECS compatibility mode */
                   3507:        bplcon3 = 0xC00;
                   3508: 
                   3509:        FMODE (0);
                   3510:        CLXCON (0);
1.1.1.20  root     3511:        lof = 0;
1.1.1.9   root     3512:     }
1.1.1.3   root     3513: 
1.1.1.12  root     3514:     n_frames = 0;
                   3515: 
1.1.1.3   root     3516:     expamem_reset ();
1.1.1.4   root     3517: 
1.1.1.12  root     3518:     DISK_reset ();
1.1.1.3   root     3519:     CIA_reset ();
1.1.1.13  root     3520:     unset_special (~(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE));
1.1.1.3   root     3521: 
1.1.1.2   root     3522:     vpos = 0;
1.1.1.3   root     3523: 
1.1.1.23! root     3524:     inputdevice_reset ();
1.1.1.7   root     3525:     timehack_alive = 0;
1.1.1.3   root     3526: 
1.1.1.13  root     3527:     curr_sprite_entries = 0;
                   3528:     prev_sprite_entries = 0;
                   3529:     sprite_entries[0][0].first_pixel = 0;
                   3530:     sprite_entries[1][0].first_pixel = MAX_SPR_PIXELS;
                   3531:     sprite_entries[0][1].first_pixel = 0;
                   3532:     sprite_entries[1][1].first_pixel = MAX_SPR_PIXELS;
                   3533:     memset (spixels, 0, sizeof spixels);
                   3534:     memset (&spixstate, 0, sizeof spixstate);
1.1       root     3535: 
                   3536:     bltstate = BLT_done;
1.1.1.4   root     3537:     cop_state.state = COP_stop;
1.1.1.2   root     3538:     diwstate = DIW_waiting_start;
1.1.1.3   root     3539:     hdiwstate = DIW_waiting_start;
1.1.1.14  root     3540:     currcycle = 0;
1.1.1.3   root     3541: 
1.1.1.14  root     3542:     new_beamcon0 = currprefs.ntscmode ? 0x00 : 0x20;
1.1.1.7   root     3543:     init_hz ();
                   3544: 
                   3545:     audio_reset ();
1.1.1.23! root     3546:     if (savestate_state != STATE_RESTORE) {
        !          3547:        /* must be called after audio_reset */
        !          3548:        adkcon = 0;
        !          3549:        update_adkmasks ();
        !          3550:     }
1.1.1.7   root     3551: 
1.1.1.3   root     3552:     init_sprites ();
                   3553: 
1.1.1.2   root     3554:     init_hardware_frame ();
1.1.1.4   root     3555:     reset_drawing ();
                   3556: 
1.1.1.2   root     3557:     reset_decisions ();
1.1.1.3   root     3558: 
1.1       root     3559: #ifdef HAVE_GETTIMEOFDAY
1.1.1.4   root     3560:     gettimeofday (&tv, NULL);
1.1       root     3561:     seconds_base = tv.tv_sec;
                   3562:     bogusframe = 1;
                   3563: #endif
1.1.1.15  root     3564: 
                   3565:     sprite_buffer_res = currprefs.chipset_mask & CSMASK_AGA ? RES_HIRES : RES_LORES;
                   3566:     if (savestate_state == STATE_RESTORE) {
                   3567:        uae_u16 v;
                   3568:        uae_u32 vv;
                   3569: 
                   3570:        update_adkmasks ();
                   3571:        INTENA (0);
                   3572:        INTREQ (0);
                   3573: #if 0
                   3574:        DMACON (0, 0);
                   3575: #endif
                   3576:        COPJMP1 (0);
                   3577:        if (diwhigh)
                   3578:            diwhigh_written = 1;
                   3579:        v = bplcon0;
                   3580:        BPLCON0 (0, 0);
                   3581:        BPLCON0 (0, v);
1.1.1.17  root     3582:        FMODE (fmode);
1.1.1.15  root     3583:        if (!(currprefs.chipset_mask & CSMASK_AGA)) {
                   3584:            for(i = 0 ; i < 32 ; i++)  {
                   3585:                vv = current_colors.color_regs_ecs[i];
                   3586:                current_colors.color_regs_ecs[i] = -1;
                   3587:                record_color_change (0, i, vv);
                   3588:                remembered_color_entry = -1;
                   3589:                current_colors.color_regs_ecs[i] = vv;
                   3590:                current_colors.acolors[i] = xcolors[vv];
                   3591:            }
                   3592:        } else {
                   3593:            for(i = 0 ; i < 256 ; i++)  {
1.1.1.20  root     3594:                vv = current_colors.color_regs_aga[i];
1.1.1.15  root     3595:                current_colors.color_regs_aga[i] = -1;
                   3596:                record_color_change (0, i, vv);
                   3597:                remembered_color_entry = -1;
                   3598:                current_colors.color_regs_aga[i] = vv;
                   3599:                current_colors.acolors[i] = CONVERT_RGB(vv);
                   3600:            }
                   3601:        }
1.1.1.17  root     3602:        CLXCON (clxcon);
                   3603:        CLXCON2 (clxcon2);
1.1.1.15  root     3604:        calcdiw ();
                   3605:        write_log ("State restored\n");
                   3606:        dumpcustom ();
                   3607:        for (i = 0; i < 8; i++)
                   3608:            nr_armed += spr[i].armed != 0;
                   3609:     }
                   3610:     expand_sprres ();
1.1       root     3611: }
                   3612: 
1.1.1.3   root     3613: void dumpcustom (void)
1.1       root     3614: {
1.1.1.6   root     3615:     write_log ("DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR(),
                   3616:               (unsigned int)intena, (unsigned int)intreq, (unsigned int)vpos, (unsigned int)current_hpos());
1.1.1.22  root     3617:     write_log ("COP1LC: %08lx, COP2LC: %08lx COPPTR: %08lx\n", (unsigned long)cop1lc, (unsigned long)cop2lc, cop_state.ip);
1.1.1.13  root     3618:     write_log ("DIWSTRT: %04x DIWSTOP: %04x DDFSTRT: %04x DDFSTOP: %04x\n",
                   3619:               (unsigned int)diwstrt, (unsigned int)diwstop, (unsigned int)ddfstrt, (unsigned int)ddfstop);
1.1.1.22  root     3620:     write_log ("BPLCON 0: %04x 1: %04x 2: %04x 3: %04x 4: %04x\n", bplcon0, bplcon1, bplcon2, bplcon3, bplcon4);
1.1.1.3   root     3621:     if (timeframes) {
1.1.1.22  root     3622:        write_log ("Average frame time: %f ms [frames: %d time: %d]\n",
                   3623:                   (double)frametime / timeframes, timeframes, frametime);
1.1.1.6   root     3624:        if (total_skipped)
                   3625:            write_log ("Skipped frames: %d\n", total_skipped);
1.1       root     3626:     }
1.1.1.18  root     3627:     /*for (i=0; i<256; i++) if (blitcount[i]) write_log ("minterm %x = %d\n",i,blitcount[i]);  blitter debug */
1.1       root     3628: }
                   3629: 
1.1.1.3   root     3630: int intlev (void)
1.1       root     3631: {
1.1.1.3   root     3632:     uae_u16 imask = intreq & intena;
1.1       root     3633:     if (imask && (intena & 0x4000)){
                   3634:        if (imask & 0x2000) return 6;
                   3635:        if (imask & 0x1800) return 5;
                   3636:        if (imask & 0x0780) return 4;
                   3637:        if (imask & 0x0070) return 3;
                   3638:        if (imask & 0x0008) return 2;
                   3639:        if (imask & 0x0007) return 1;
                   3640:     }
                   3641:     return -1;
                   3642: }
                   3643: 
1.1.1.4   root     3644: static void gen_custom_tables (void)
                   3645: {
                   3646:     int i;
                   3647:     for (i = 0; i < 256; i++) {
                   3648:        sprtaba[i] = ((((i >> 7) & 1) << 0)
                   3649:                      | (((i >> 6) & 1) << 2)
                   3650:                      | (((i >> 5) & 1) << 4)
                   3651:                      | (((i >> 4) & 1) << 6)
                   3652:                      | (((i >> 3) & 1) << 8)
                   3653:                      | (((i >> 2) & 1) << 10)
                   3654:                      | (((i >> 1) & 1) << 12)
                   3655:                      | (((i >> 0) & 1) << 14));
                   3656:        sprtabb[i] = sprtaba[i] * 2;
1.1.1.13  root     3657:        sprite_ab_merge[i] = (((i & 15) ? 1 : 0)
                   3658:                              | ((i & 240) ? 2 : 0));
1.1.1.4   root     3659:     }
1.1.1.13  root     3660:     for (i = 0; i < 16; i++) {
                   3661:        clxmask[i] = (((i & 1) ? 0xF : 0x3)
                   3662:                      | ((i & 2) ? 0xF0 : 0x30)
                   3663:                      | ((i & 4) ? 0xF00 : 0x300)
                   3664:                      | ((i & 8) ? 0xF000 : 0x3000));
                   3665:        sprclx[i] = (((i & 0x3) == 0x3 ? 1 : 0)
                   3666:                     | ((i & 0x5) == 0x5 ? 2 : 0)
                   3667:                     | ((i & 0x9) == 0x9 ? 4 : 0)
                   3668:                     | ((i & 0x6) == 0x6 ? 8 : 0)
                   3669:                     | ((i & 0xA) == 0xA ? 16 : 0)
                   3670:                     | ((i & 0xC) == 0xC ? 32 : 0)) << 9;
                   3671:     }
1.1.1.4   root     3672: }
                   3673: 
1.1.1.3   root     3674: void custom_init (void)
1.1       root     3675: {
1.1.1.7   root     3676:     uaecptr pos;
                   3677: 
1.1.1.4   root     3678: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
1.1       root     3679:     int num;
1.1.1.2   root     3680: 
1.1.1.4   root     3681:     for (num = 0; num < 2; num++) {
1.1.1.13  root     3682:        sprite_entries[num] = xmalloc (max_sprite_entry * sizeof (struct sprite_entry));
1.1.1.4   root     3683:        color_changes[num] = xmalloc (max_color_change * sizeof (struct color_change));
1.1.1.2   root     3684:     }
                   3685: #endif
1.1.1.3   root     3686: 
1.1.1.7   root     3687:     pos = here ();
                   3688: 
1.1.1.18  root     3689:     org (RTAREA_BASE+0xFF70);
1.1.1.7   root     3690:     calltrap (deftrap (mousehack_helper));
                   3691:     dw (RTS);
                   3692: 
1.1.1.18  root     3693:     org (RTAREA_BASE+0xFFA0);
1.1.1.7   root     3694:     calltrap (deftrap (timehack_helper));
                   3695:     dw (RTS);
                   3696: 
                   3697:     org (pos);
                   3698: 
1.1.1.4   root     3699:     gen_custom_tables ();
                   3700:     build_blitfilltable ();
                   3701: 
                   3702:     drawing_init ();
                   3703: 
1.1.1.16  root     3704:     create_cycle_diagram_table ();
1.1       root     3705: }
                   3706: 
                   3707: /* Custom chip memory bank */
                   3708: 
1.1.1.4   root     3709: static uae_u32 custom_lget (uaecptr) REGPARAM;
                   3710: static uae_u32 custom_wget (uaecptr) REGPARAM;
                   3711: static uae_u32 custom_bget (uaecptr) REGPARAM;
                   3712: static void custom_lput (uaecptr, uae_u32) REGPARAM;
                   3713: static void custom_wput (uaecptr, uae_u32) REGPARAM;
                   3714: static void custom_bput (uaecptr, uae_u32) REGPARAM;
1.1       root     3715: 
                   3716: addrbank custom_bank = {
                   3717:     custom_lget, custom_wget, custom_bget,
                   3718:     custom_lput, custom_wput, custom_bput,
1.1.1.15  root     3719:     default_xlate, default_check, NULL
1.1       root     3720: };
                   3721: 
1.1.1.13  root     3722: STATIC_INLINE uae_u32 REGPARAM2 custom_wget_1 (uaecptr addr)
1.1       root     3723: {
1.1.1.20  root     3724:     uae_u16 v;
1.1.1.13  root     3725:     special_mem |= S_READ;
1.1.1.4   root     3726:     switch (addr & 0x1FE) {
1.1.1.20  root     3727:      case 0x002: v = DMACONR (); break;
                   3728:      case 0x004: v = VPOSR (); break;
                   3729:      case 0x006: v = VHPOSR (); break;
                   3730: 
                   3731:      case 0x008: v = DSKDATR (current_hpos ()); break;
                   3732: 
                   3733:      case 0x00A: v = JOY0DAT (); break;
1.1.1.22  root     3734:      case 0x00C: v = JOY1DAT (); break;
                   3735:      case 0x00E: v = CLXDAT (); break;
1.1.1.20  root     3736:      case 0x010: v = ADKCONR (); break;
                   3737: 
                   3738:      case 0x012: v = POT0DAT (); break;
                   3739:      case 0x016: v = POTGOR (); break;
                   3740:      case 0x018: v = SERDATR (); break;
                   3741:      case 0x01A: v = DSKBYTR (current_hpos ()); break;
                   3742:      case 0x01C: v = INTENAR (); break;
                   3743:      case 0x01E: v = INTREQR (); break;
                   3744:      case 0x07C: v = DENISEID (); break;
1.1.1.13  root     3745: 
                   3746:      case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
                   3747:      case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
                   3748:      case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
                   3749:      case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
                   3750:      case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
                   3751:      case 0x1BC: case 0x1BE:
1.1.1.20  root     3752:        v = COLOR_READ ((addr & 0x3E) / 2);
1.1.1.13  root     3753:        break;
                   3754: 
1.1       root     3755:      default:
1.1.1.20  root     3756:        v = last_custom_value;
                   3757:        custom_wput (addr, v);
                   3758:        last_custom_value = 0xffff;
                   3759:        return v;
1.1       root     3760:     }
1.1.1.20  root     3761:     last_custom_value = v;
                   3762:     return v;
1.1       root     3763: }
                   3764: 
1.1.1.13  root     3765: uae_u32 REGPARAM2 custom_wget (uaecptr addr)
                   3766: {
1.1.1.22  root     3767:     sync_copper_with_cpu (current_hpos (), 1);
1.1.1.13  root     3768:     return custom_wget_1 (addr);
                   3769: }
                   3770: 
1.1.1.3   root     3771: uae_u32 REGPARAM2 custom_bget (uaecptr addr)
1.1       root     3772: {
1.1.1.13  root     3773:     special_mem |= S_READ;
                   3774:     return custom_wget (addr & 0xfffe) >> (addr & 1 ? 0 : 8);
1.1       root     3775: }
                   3776: 
1.1.1.3   root     3777: uae_u32 REGPARAM2 custom_lget (uaecptr addr)
1.1       root     3778: {
1.1.1.13  root     3779:     special_mem |= S_READ;
                   3780:     return ((uae_u32)custom_wget (addr & 0xfffe) << 16) | custom_wget ((addr + 2) & 0xfffe);
1.1       root     3781: }
                   3782: 
1.1.1.4   root     3783: void REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value)
1.1       root     3784: {
                   3785:     addr &= 0x1FE;
1.1.1.20  root     3786:     last_custom_value = value;
1.1.1.3   root     3787:     switch (addr) {
                   3788:      case 0x020: DSKPTH (value); break;
                   3789:      case 0x022: DSKPTL (value); break;
1.1.1.13  root     3790:      case 0x024: DSKLEN (value, hpos); break;
1.1.1.3   root     3791:      case 0x026: DSKDAT (value); break;
                   3792: 
                   3793:      case 0x02A: VPOSW (value); break;
1.1.1.15  root     3794:      case 0x02E: COPCON (value); break;
1.1.1.3   root     3795:      case 0x030: SERDAT (value); break;
                   3796:      case 0x032: SERPER (value); break;
1.1.1.15  root     3797:      case 0x034: POTGO (value); break;
1.1.1.3   root     3798:      case 0x040: BLTCON0 (value); break;
                   3799:      case 0x042: BLTCON1 (value); break;
                   3800: 
                   3801:      case 0x044: BLTAFWM (value); break;
                   3802:      case 0x046: BLTALWM (value); break;
                   3803: 
                   3804:      case 0x050: BLTAPTH (value); break;
                   3805:      case 0x052: BLTAPTL (value); break;
                   3806:      case 0x04C: BLTBPTH (value); break;
                   3807:      case 0x04E: BLTBPTL (value); break;
                   3808:      case 0x048: BLTCPTH (value); break;
                   3809:      case 0x04A: BLTCPTL (value); break;
                   3810:      case 0x054: BLTDPTH (value); break;
                   3811:      case 0x056: BLTDPTL (value); break;
                   3812: 
                   3813:      case 0x058: BLTSIZE (value); break;
                   3814: 
                   3815:      case 0x064: BLTAMOD (value); break;
                   3816:      case 0x062: BLTBMOD (value); break;
                   3817:      case 0x060: BLTCMOD (value); break;
                   3818:      case 0x066: BLTDMOD (value); break;
                   3819: 
                   3820:      case 0x070: BLTCDAT (value); break;
                   3821:      case 0x072: BLTBDAT (value); break;
                   3822:      case 0x074: BLTADAT (value); break;
                   3823: 
                   3824:      case 0x07E: DSKSYNC (value); break;
                   3825: 
                   3826:      case 0x080: COP1LCH (value); break;
                   3827:      case 0x082: COP1LCL (value); break;
                   3828:      case 0x084: COP2LCH (value); break;
                   3829:      case 0x086: COP2LCL (value); break;
                   3830: 
                   3831:      case 0x088: COPJMP1 (value); break;
                   3832:      case 0x08A: COPJMP2 (value); break;
                   3833: 
1.1.1.4   root     3834:      case 0x08E: DIWSTRT (hpos, value); break;
                   3835:      case 0x090: DIWSTOP (hpos, value); break;
                   3836:      case 0x092: DDFSTRT (hpos, value); break;
                   3837:      case 0x094: DDFSTOP (hpos, value); break;
1.1.1.3   root     3838: 
1.1.1.13  root     3839:      case 0x096: DMACON (hpos, value); break;
1.1.1.3   root     3840:      case 0x098: CLXCON (value); break;
                   3841:      case 0x09A: INTENA (value); break;
                   3842:      case 0x09C: INTREQ (value); break;
                   3843:      case 0x09E: ADKCON (value); break;
                   3844: 
                   3845:      case 0x0A0: AUDxLCH (0, value); break;
                   3846:      case 0x0A2: AUDxLCL (0, value); break;
                   3847:      case 0x0A4: AUDxLEN (0, value); break;
                   3848:      case 0x0A6: AUDxPER (0, value); break;
                   3849:      case 0x0A8: AUDxVOL (0, value); break;
                   3850:      case 0x0AA: AUDxDAT (0, value); break;
                   3851: 
                   3852:      case 0x0B0: AUDxLCH (1, value); break;
                   3853:      case 0x0B2: AUDxLCL (1, value); break;
                   3854:      case 0x0B4: AUDxLEN (1, value); break;
                   3855:      case 0x0B6: AUDxPER (1, value); break;
                   3856:      case 0x0B8: AUDxVOL (1, value); break;
                   3857:      case 0x0BA: AUDxDAT (1, value); break;
                   3858: 
                   3859:      case 0x0C0: AUDxLCH (2, value); break;
                   3860:      case 0x0C2: AUDxLCL (2, value); break;
                   3861:      case 0x0C4: AUDxLEN (2, value); break;
                   3862:      case 0x0C6: AUDxPER (2, value); break;
                   3863:      case 0x0C8: AUDxVOL (2, value); break;
                   3864:      case 0x0CA: AUDxDAT (2, value); break;
                   3865: 
                   3866:      case 0x0D0: AUDxLCH (3, value); break;
                   3867:      case 0x0D2: AUDxLCL (3, value); break;
                   3868:      case 0x0D4: AUDxLEN (3, value); break;
                   3869:      case 0x0D6: AUDxPER (3, value); break;
                   3870:      case 0x0D8: AUDxVOL (3, value); break;
                   3871:      case 0x0DA: AUDxDAT (3, value); break;
                   3872: 
1.1.1.21  root     3873:      case 0x0E0: BPLxPTH (hpos, value, 0); break;
                   3874:      case 0x0E2: BPLxPTL (hpos, value, 0); break;
                   3875:      case 0x0E4: BPLxPTH (hpos, value, 1); break;
                   3876:      case 0x0E6: BPLxPTL (hpos, value, 1); break;
                   3877:      case 0x0E8: BPLxPTH (hpos, value, 2); break;
                   3878:      case 0x0EA: BPLxPTL (hpos, value, 2); break;
                   3879:      case 0x0EC: BPLxPTH (hpos, value, 3); break;
                   3880:      case 0x0EE: BPLxPTL (hpos, value, 3); break;
                   3881:      case 0x0F0: BPLxPTH (hpos, value, 4); break;
                   3882:      case 0x0F2: BPLxPTL (hpos, value, 4); break;
                   3883:      case 0x0F4: BPLxPTH (hpos, value, 5); break;
                   3884:      case 0x0F6: BPLxPTL (hpos, value, 5); break;
                   3885:      case 0x0F8: BPLxPTH (hpos, value, 6); break;
                   3886:      case 0x0FA: BPLxPTL (hpos, value, 6); break;
                   3887:      case 0x0FC: BPLxPTH (hpos, value, 7); break;
                   3888:      case 0x0FE: BPLxPTL (hpos, value, 7); break;
1.1.1.4   root     3889: 
                   3890:      case 0x100: BPLCON0 (hpos, value); break;
                   3891:      case 0x102: BPLCON1 (hpos, value); break;
                   3892:      case 0x104: BPLCON2 (hpos, value); break;
                   3893:      case 0x106: BPLCON3 (hpos, value); break;
1.1.1.3   root     3894: 
1.1.1.4   root     3895:      case 0x108: BPL1MOD (hpos, value); break;
                   3896:      case 0x10A: BPL2MOD (hpos, value); break;
1.1.1.17  root     3897:      case 0x10E: CLXCON2 (value); break;
1.1.1.3   root     3898: 
1.1.1.13  root     3899:      case 0x110: BPL1DAT (hpos, value); break;
1.1.1.3   root     3900:      case 0x112: BPL2DAT (value); break;
                   3901:      case 0x114: BPL3DAT (value); break;
                   3902:      case 0x116: BPL4DAT (value); break;
                   3903:      case 0x118: BPL5DAT (value); break;
                   3904:      case 0x11A: BPL6DAT (value); break;
1.1.1.6   root     3905:      case 0x11C: BPL7DAT (value); break;
                   3906:      case 0x11E: BPL8DAT (value); break;
1.1       root     3907: 
                   3908:      case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
                   3909:      case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
                   3910:      case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
                   3911:      case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
                   3912:      case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
1.1.1.2   root     3913:      case 0x1BC: case 0x1BE:
1.1.1.13  root     3914:        COLOR_WRITE (hpos, value & 0xFFF, (addr & 0x3E) / 2);
1.1.1.2   root     3915:        break;
                   3916:      case 0x120: case 0x124: case 0x128: case 0x12C:
1.1       root     3917:      case 0x130: case 0x134: case 0x138: case 0x13C:
1.1.1.4   root     3918:        SPRxPTH (hpos, value, (addr - 0x120) / 4);
1.1       root     3919:        break;
1.1.1.2   root     3920:      case 0x122: case 0x126: case 0x12A: case 0x12E:
1.1       root     3921:      case 0x132: case 0x136: case 0x13A: case 0x13E:
1.1.1.4   root     3922:        SPRxPTL (hpos, value, (addr - 0x122) / 4);
1.1       root     3923:        break;
1.1.1.2   root     3924:      case 0x140: case 0x148: case 0x150: case 0x158:
1.1       root     3925:      case 0x160: case 0x168: case 0x170: case 0x178:
1.1.1.4   root     3926:        SPRxPOS (hpos, value, (addr - 0x140) / 8);
1.1       root     3927:        break;
1.1.1.2   root     3928:      case 0x142: case 0x14A: case 0x152: case 0x15A:
1.1       root     3929:      case 0x162: case 0x16A: case 0x172: case 0x17A:
1.1.1.4   root     3930:        SPRxCTL (hpos, value, (addr - 0x142) / 8);
1.1       root     3931:        break;
                   3932:      case 0x144: case 0x14C: case 0x154: case 0x15C:
                   3933:      case 0x164: case 0x16C: case 0x174: case 0x17C:
1.1.1.4   root     3934:        SPRxDATA (hpos, value, (addr - 0x144) / 8);
1.1       root     3935:        break;
1.1.1.2   root     3936:      case 0x146: case 0x14E: case 0x156: case 0x15E:
1.1       root     3937:      case 0x166: case 0x16E: case 0x176: case 0x17E:
1.1.1.4   root     3938:        SPRxDATB (hpos, value, (addr - 0x146) / 8);
1.1       root     3939:        break;
1.1.1.3   root     3940: 
                   3941:      case 0x36: JOYTEST (value); break;
1.1.1.7   root     3942:      case 0x5A: BLTCON0L (value); break;
1.1.1.3   root     3943:      case 0x5C: BLTSIZV (value); break;
                   3944:      case 0x5E: BLTSIZH (value); break;
1.1.1.4   root     3945:      case 0x1E4: DIWHIGH (hpos, value); break;
                   3946:      case 0x10C: BPLCON4 (hpos, value); break;
1.1.1.7   root     3947:      case 0x1FC: FMODE (value); break;
1.1       root     3948:     }
                   3949: }
                   3950: 
1.1.1.4   root     3951: void REGPARAM2 custom_wput (uaecptr addr, uae_u32 value)
                   3952: {
                   3953:     int hpos = current_hpos ();
1.1.1.13  root     3954:     special_mem |= S_WRITE;
                   3955: 
1.1.1.22  root     3956:     sync_copper_with_cpu (hpos, 1);
1.1.1.4   root     3957:     custom_wput_1 (hpos, addr, value);
                   3958: }
                   3959: 
                   3960: void REGPARAM2 custom_bput (uaecptr addr, uae_u32 value)
1.1       root     3961: {
1.1.1.2   root     3962:     static int warned = 0;
                   3963:     /* Is this correct now? (There are people who bput things to the upper byte of AUDxVOL). */
1.1.1.3   root     3964:     uae_u16 rval = (value << 8) | (value & 0xFF);
1.1.1.13  root     3965:     special_mem |= S_WRITE;
1.1.1.9   root     3966:     custom_wput (addr, rval);
1.1.1.2   root     3967:     if (!warned)
1.1.1.3   root     3968:        write_log ("Byte put to custom register.\n"), warned++;
1.1       root     3969: }
                   3970: 
1.1.1.3   root     3971: void REGPARAM2 custom_lput(uaecptr addr, uae_u32 value)
1.1       root     3972: {
1.1.1.13  root     3973:     special_mem |= S_WRITE;
1.1.1.9   root     3974:     custom_wput (addr & 0xfffe, value >> 16);
                   3975:     custom_wput ((addr + 2) & 0xfffe, (uae_u16)value);
1.1       root     3976: }
1.1.1.15  root     3977: 
                   3978: void custom_prepare_savestate (void)
                   3979: {
                   3980:     /* force blitter to finish, no support for saving full blitter state yet */
                   3981:     if (eventtab[ev_blitter].active) {
                   3982:        unsigned int olddmacon = dmacon;
                   3983:        dmacon |= DMA_BLITTER; /* ugh.. */
                   3984:        blitter_handler ();
                   3985:        dmacon = olddmacon;
                   3986:     }
                   3987: }
                   3988: 
                   3989: #define RB restore_u8 ()
                   3990: #define RW restore_u16 ()
                   3991: #define RL restore_u32 ()
                   3992: 
                   3993: uae_u8 *restore_custom (uae_u8 *src)
                   3994: {
                   3995:     uae_u16 dsklen, dskbytr, dskdatr;
                   3996:     int dskpt;
                   3997:     int i;
                   3998: 
                   3999:     audio_reset ();
                   4000: 
                   4001:     currprefs.chipset_mask = RL;
                   4002:     RW;                                /* 000 ? */
                   4003:     RW;                                /* 002 DMACONR */
                   4004:     RW;                                /* 004 VPOSR */
                   4005:     RW;                                /* 006 VHPOSR */
                   4006:     dskdatr = RW;              /* 008 DSKDATR */
                   4007:     RW;                                /* 00A JOY0DAT */
                   4008:     RW;                                /* 00C JOY1DAT */
                   4009:     clxdat = RW;               /* 00E CLXDAT */
                   4010:     RW;                                /* 010 ADKCONR */
                   4011:     RW;                                /* 012 POT0DAT* */
                   4012:     RW;                                /* 014 POT1DAT* */
                   4013:     RW;                                /* 016 POTINP* */
                   4014:     RW;                                /* 018 SERDATR* */
                   4015:     dskbytr = RW;              /* 01A DSKBYTR */
                   4016:     RW;                                /* 01C INTENAR */
                   4017:     RW;                                /* 01E INTREQR */
                   4018:     dskpt = RL;                        /* 020-022 DSKPT */
                   4019:     dsklen = RW;               /* 024 DSKLEN */
                   4020:     RW;                                /* 026 DSKDAT */
                   4021:     RW;                                /* 028 REFPTR */
                   4022:     lof = RW;                  /* 02A VPOSW */
                   4023:     RW;                                /* 02C VHPOSW */
                   4024:     COPCON(RW);                        /* 02E COPCON */
                   4025:     RW;                                /* 030 SERDAT* */
                   4026:     RW;                                /* 032 SERPER* */
                   4027:     POTGO(RW);                 /* 034 POTGO */
                   4028:     RW;                                /* 036 JOYTEST* */
                   4029:     RW;                                /* 038 STREQU */
                   4030:     RW;                                /* 03A STRVHBL */
                   4031:     RW;                                /* 03C STRHOR */
                   4032:     RW;                                /* 03E STRLONG */
                   4033:     BLTCON0(RW);               /* 040 BLTCON0 */
                   4034:     BLTCON1(RW);               /* 042 BLTCON1 */
                   4035:     BLTAFWM(RW);               /* 044 BLTAFWM */
                   4036:     BLTALWM(RW);               /* 046 BLTALWM */
                   4037:     BLTCPTH(RL);               /* 048-04B BLTCPT */
                   4038:     BLTBPTH(RL);               /* 04C-04F BLTBPT */
                   4039:     BLTAPTH(RL);               /* 050-053 BLTAPT */
                   4040:     BLTDPTH(RL);               /* 054-057 BLTDPT */
                   4041:     RW;                                /* 058 BLTSIZE */
                   4042:     RW;                                /* 05A BLTCON0L */
                   4043:     oldvblts = RW;             /* 05C BLTSIZV */
                   4044:     RW;                                /* 05E BLTSIZH */
                   4045:     BLTCMOD(RW);               /* 060 BLTCMOD */
                   4046:     BLTBMOD(RW);               /* 062 BLTBMOD */
                   4047:     BLTAMOD(RW);               /* 064 BLTAMOD */
                   4048:     BLTDMOD(RW);               /* 066 BLTDMOD */
                   4049:     RW;                                /* 068 ? */
                   4050:     RW;                                /* 06A ? */
                   4051:     RW;                                /* 06C ? */
                   4052:     RW;                                /* 06E ? */
                   4053:     BLTCDAT(RW);               /* 070 BLTCDAT */
                   4054:     BLTBDAT(RW);               /* 072 BLTBDAT */
                   4055:     BLTADAT(RW);               /* 074 BLTADAT */
                   4056:     RW;                                /* 076 ? */
                   4057:     RW;                                /* 078 ? */
                   4058:     RW;                                /* 07A ? */
                   4059:     RW;                                /* 07C LISAID */
                   4060:     DSKSYNC(RW);               /* 07E DSKSYNC */
                   4061:     cop1lc = RL;               /* 080/082 COP1LC */
                   4062:     cop2lc = RL;               /* 084/086 COP2LC */
                   4063:     RW;                                /* 088 ? */
                   4064:     RW;                                /* 08A ? */
                   4065:     RW;                                /* 08C ? */
                   4066:     diwstrt = RW;              /* 08E DIWSTRT */
                   4067:     diwstop = RW;              /* 090 DIWSTOP */
                   4068:     ddfstrt = RW;              /* 092 DDFSTRT */
                   4069:     ddfstop = RW;              /* 094 DDFSTOP */
                   4070:     dmacon = RW & ~(0x2000|0x4000); /* 096 DMACON */
                   4071:     CLXCON(RW);                        /* 098 CLXCON */
                   4072:     intena = RW;               /* 09A INTENA */
                   4073:     intreq = RW;               /* 09C INTREQ */
                   4074:     adkcon = RW;               /* 09E ADKCON */
                   4075:     for (i = 0; i < 8; i++)
                   4076:        bplpt[i] = RL;
                   4077:     bplcon0 = RW;              /* 100 BPLCON0 */
                   4078:     bplcon1 = RW;              /* 102 BPLCON1 */
                   4079:     bplcon2 = RW;              /* 104 BPLCON2 */
                   4080:     bplcon3 = RW;              /* 106 BPLCON3 */
                   4081:     bpl1mod = RW;              /* 108 BPL1MOD */
                   4082:     bpl2mod = RW;              /* 10A BPL2MOD */
                   4083:     bplcon4 = RW;              /* 10C BPLCON4 */
1.1.1.17  root     4084:     clxcon2 = RW;              /* 10E CLXCON2* */
1.1.1.15  root     4085:     for(i = 0; i < 8; i++)
                   4086:        RW;                     /*     BPLXDAT */
                   4087:     for(i = 0; i < 32; i++)
                   4088:        current_colors.color_regs_ecs[i] = RW; /* 180 COLORxx */
                   4089:     RW;                                /* 1C0 ? */
                   4090:     RW;                                /* 1C2 ? */
                   4091:     RW;                                /* 1C4 ? */
                   4092:     RW;                                /* 1C6 ? */
                   4093:     RW;                                /* 1C8 ? */
                   4094:     RW;                                /* 1CA ? */
                   4095:     RW;                                /* 1CC ? */
                   4096:     RW;                                /* 1CE ? */
                   4097:     RW;                                /* 1D0 ? */
                   4098:     RW;                                /* 1D2 ? */
                   4099:     RW;                                /* 1D4 ? */
                   4100:     RW;                                /* 1D6 ? */
                   4101:     RW;                                /* 1D8 ? */
                   4102:     RW;                                /* 1DA ? */
                   4103:     new_beamcon0 = RW;         /* 1DC BEAMCON0 */
                   4104:     RW;                                /* 1DE ? */
                   4105:     RW;                                /* 1E0 ? */
                   4106:     RW;                                /* 1E2 ? */
                   4107:     RW;                                /* 1E4 ? */
                   4108:     RW;                                /* 1E6 ? */
                   4109:     RW;                                /* 1E8 ? */
                   4110:     RW;                                /* 1EA ? */
                   4111:     RW;                                /* 1EC ? */
                   4112:     RW;                                /* 1EE ? */
                   4113:     RW;                                /* 1F0 ? */
                   4114:     RW;                                /* 1F2 ? */
                   4115:     RW;                                /* 1F4 ? */
                   4116:     RW;                                /* 1F6 ? */
                   4117:     RW;                                /* 1F8 ? */
                   4118:     RW;                                /* 1FA ? */
                   4119:     fmode = RW;                        /* 1FC FMODE */
                   4120:     RW;                                /* 1FE ? */
                   4121: 
                   4122:     DISK_restore_custom (dskpt, dsklen, dskdatr, dskbytr);
                   4123: 
                   4124:     return src;
                   4125: }
                   4126: 
                   4127: 
                   4128: #define SB save_u8
                   4129: #define SW save_u16
                   4130: #define SL save_u32
                   4131: 
                   4132: extern uae_u16 serper;
                   4133: 
1.1.1.21  root     4134: uae_u8 *save_custom (int *len, uae_u8 *dstptr, int full)
1.1.1.15  root     4135: {
                   4136:     uae_u8 *dstbak, *dst;
                   4137:     int i;
                   4138:     uae_u32 dskpt;
                   4139:     uae_u16 dsklen, dsksync, dskdatr, dskbytr;
                   4140: 
                   4141:     DISK_save_custom (&dskpt, &dsklen, &dsksync, &dskdatr, &dskbytr);
1.1.1.21  root     4142: 
                   4143:     if (dstptr)
                   4144:        dstbak = dst = dstptr;
                   4145:     else
                   4146:        dstbak = dst = malloc (8+256*2);
                   4147: 
1.1.1.15  root     4148:     SL (currprefs.chipset_mask);
                   4149:     SW (0);                    /* 000 ? */
                   4150:     SW (dmacon);               /* 002 DMACONR */
                   4151:     SW (VPOSR());              /* 004 VPOSR */
                   4152:     SW (VHPOSR());             /* 006 VHPOSR */
                   4153:     SW (dskdatr);              /* 008 DSKDATR */
                   4154:     SW (JOY0DAT());            /* 00A JOY0DAT */
                   4155:     SW (JOY1DAT());            /* 00C JOY1DAT */
                   4156:     SW (clxdat);               /* 00E CLXDAT */
                   4157:     SW (ADKCONR());            /* 010 ADKCONR */
                   4158:     SW (POT0DAT());            /* 012 POT0DAT */
                   4159:     SW (POT0DAT());            /* 014 POT1DAT */
                   4160:     SW (0)     ;               /* 016 POTINP * */
                   4161:     SW (0);                    /* 018 SERDATR * */
                   4162:     SW (dskbytr);              /* 01A DSKBYTR */
                   4163:     SW (INTENAR());            /* 01C INTENAR */
                   4164:     SW (INTREQR());            /* 01E INTREQR */
                   4165:     SL (dskpt);                        /* 020-023 DSKPT */
                   4166:     SW (dsklen);               /* 024 DSKLEN */
                   4167:     SW (0);                    /* 026 DSKDAT */
                   4168:     SW (0);                    /* 028 REFPTR */
                   4169:     SW (lof);                  /* 02A VPOSW */
                   4170:     SW (0);                    /* 02C VHPOSW */
                   4171:     SW (copcon);               /* 02E COPCON */
                   4172:     SW (serper);               /* 030 SERDAT * */
                   4173:     SW (serdat);               /* 032 SERPER * */
                   4174:     SW (potgo_value);          /* 034 POTGO */
                   4175:     SW (0);                    /* 036 JOYTEST * */
                   4176:     SW (0);                    /* 038 STREQU */
                   4177:     SW (0);                    /* 03A STRVBL */
                   4178:     SW (0);                    /* 03C STRHOR */
                   4179:     SW (0);                    /* 03E STRLONG */
                   4180:     SW (bltcon0);              /* 040 BLTCON0 */
                   4181:     SW (bltcon1);              /* 042 BLTCON1 */
                   4182:     SW (blt_info.bltafwm);     /* 044 BLTAFWM */
                   4183:     SW (blt_info.bltalwm);     /* 046 BLTALWM */
                   4184:     SL (bltcpt);               /* 048-04B BLTCPT */
                   4185:     SL (bltbpt);               /* 04C-04F BLTCPT */
                   4186:     SL (bltapt);               /* 050-043 BLTCPT */
                   4187:     SL (bltdpt);               /* 054-057 BLTCPT */
                   4188:     SW (0);                    /* 058 BLTSIZE */
                   4189:     SW (0);                    /* 05A BLTCON0L (use BLTCON0 instead) */
                   4190:     SW (oldvblts);             /* 05C BLTSIZV */
                   4191:     SW (blt_info.hblitsize);   /* 05E BLTSIZH */
                   4192:     SW (blt_info.bltcmod);     /* 060 BLTCMOD */
                   4193:     SW (blt_info.bltbmod);     /* 062 BLTBMOD */
                   4194:     SW (blt_info.bltamod);     /* 064 BLTAMOD */
                   4195:     SW (blt_info.bltdmod);     /* 066 BLTDMOD */
                   4196:     SW (0);                    /* 068 ? */
                   4197:     SW (0);                    /* 06A ? */
                   4198:     SW (0);                    /* 06C ? */
                   4199:     SW (0);                    /* 06E ? */
                   4200:     SW (blt_info.bltcdat);     /* 070 BLTCDAT */
                   4201:     SW (blt_info.bltbdat);     /* 072 BLTBDAT */
                   4202:     SW (blt_info.bltadat);     /* 074 BLTADAT */
                   4203:     SW (0);                    /* 076 ? */
                   4204:     SW (0);                    /* 078 ? */
                   4205:     SW (0);                    /* 07A ? */
                   4206:     SW (DENISEID());           /* 07C DENISEID/LISAID */
                   4207:     SW (dsksync);              /* 07E DSKSYNC */
                   4208:     SL (cop1lc);               /* 080-083 COP1LC */
                   4209:     SL (cop2lc);               /* 084-087 COP2LC */
                   4210:     SW (0);                    /* 088 ? */
                   4211:     SW (0);                    /* 08A ? */
                   4212:     SW (0);                    /* 08C ? */
                   4213:     SW (diwstrt);              /* 08E DIWSTRT */
                   4214:     SW (diwstop);              /* 090 DIWSTOP */
                   4215:     SW (ddfstrt);              /* 092 DDFSTRT */
                   4216:     SW (ddfstop);              /* 094 DDFSTOP */
                   4217:     SW (dmacon);               /* 096 DMACON */
                   4218:     SW (clxcon);               /* 098 CLXCON */
                   4219:     SW (intena);               /* 09A INTENA */
                   4220:     SW (intreq);               /* 09C INTREQ */
                   4221:     SW (adkcon);               /* 09E ADKCON */
                   4222:     for (i = 0; i < 8; i++)
                   4223:        SL (bplpt[i]);          /* 0E0-0FE BPLxPT */
                   4224:     SW (bplcon0);              /* 100 BPLCON0 */
                   4225:     SW (bplcon1);              /* 102 BPLCON1 */
                   4226:     SW (bplcon2);              /* 104 BPLCON2 */
                   4227:     SW (bplcon3);              /* 106 BPLCON3 */
                   4228:     SW (bpl1mod);              /* 108 BPL1MOD */
                   4229:     SW (bpl2mod);              /* 10A BPL2MOD */
                   4230:     SW (bplcon4);              /* 10C BPLCON4 */
1.1.1.17  root     4231:     SW (clxcon2);              /* 10E CLXCON2 */
1.1.1.15  root     4232:     for (i = 0;i < 8; i++)
                   4233:        SW (0);                 /* 110 BPLxDAT */
                   4234:     for ( i = 0; i < 32; i++)
                   4235:        SW (current_colors.color_regs_ecs[i]); /* 180-1BE COLORxx */
                   4236:     SW (0);                    /* 1C0 */
                   4237:     SW (0);                    /* 1C2 */
                   4238:     SW (0);                    /* 1C4 */
                   4239:     SW (0);                    /* 1C6 */
                   4240:     SW (0);                    /* 1C8 */
                   4241:     SW (0);                    /* 1CA */
                   4242:     SW (0);                    /* 1CC */
                   4243:     SW (0);                    /* 1CE */
                   4244:     SW (0);                    /* 1D0 */
                   4245:     SW (0);                    /* 1D2 */
                   4246:     SW (0);                    /* 1D4 */
                   4247:     SW (0);                    /* 1D6 */
                   4248:     SW (0);                    /* 1D8 */
                   4249:     SW (0);                    /* 1DA */
                   4250:     SW (beamcon0);             /* 1DC BEAMCON0 */
                   4251:     SW (0);                    /* 1DE */
                   4252:     SW (0);                    /* 1E0 */
                   4253:     SW (0);                    /* 1E2 */
                   4254:     SW (0);                    /* 1E4 */
                   4255:     SW (0);                    /* 1E6 */
                   4256:     SW (0);                    /* 1E8 */
                   4257:     SW (0);                    /* 1EA */
                   4258:     SW (0);                    /* 1EC */
                   4259:     SW (0);                    /* 1EE */
                   4260:     SW (0);                    /* 1F0 */
                   4261:     SW (0);                    /* 1F2 */
                   4262:     SW (0);                    /* 1F4 */
                   4263:     SW (0);                    /* 1F6 */
                   4264:     SW (0);                    /* 1F8 */
                   4265:     SW (0);                    /* 1FA */
                   4266:     SW (fmode);                        /* 1FC FMODE */
                   4267:     SW (0xffff);               /* 1FE */
                   4268: 
                   4269:     *len = dst - dstbak;
                   4270:     return dstbak;
                   4271: }
                   4272: 
                   4273: uae_u8 *restore_custom_agacolors (uae_u8 *src)
                   4274: {
                   4275:     int i;
                   4276: 
                   4277:     for (i = 0; i < 256; i++)
                   4278:        current_colors.color_regs_aga[i] = RL;
                   4279:     return src;
                   4280: }
                   4281: 
1.1.1.23! root     4282: uae_u8 *save_custom_agacolors (int *len, uae_u8 *dstptr)
1.1.1.15  root     4283: {
                   4284:     uae_u8 *dstbak, *dst;
                   4285:     int i;
                   4286: 
1.1.1.23! root     4287:     if (dstptr)
        !          4288:        dstbak = dst = dstptr;
        !          4289:     else
        !          4290:        dstbak = dst = malloc (256*4);
1.1.1.15  root     4291:     for (i = 0; i < 256; i++)
                   4292:        SL (current_colors.color_regs_aga[i]);
                   4293:     *len = dst - dstbak;
                   4294:     return dstbak;
                   4295: }
                   4296: 
1.1.1.23! root     4297: uae_u8 *restore_custom_sprite (int num, uae_u8 *src)
1.1.1.15  root     4298: {
                   4299:     spr[num].pt = RL;          /* 120-13E SPRxPT */
                   4300:     sprpos[num] = RW;          /* 1x0 SPRxPOS */
                   4301:     sprctl[num] = RW;          /* 1x2 SPRxPOS */
                   4302:     sprdata[num][0] = RW;      /* 1x4 SPRxDATA */
                   4303:     sprdatb[num][0] = RW;      /* 1x6 SPRxDATB */
                   4304:     sprdata[num][1] = RW;
                   4305:     sprdatb[num][1] = RW;
                   4306:     sprdata[num][2] = RW;
                   4307:     sprdatb[num][2] = RW;
                   4308:     sprdata[num][3] = RW;
                   4309:     sprdatb[num][3] = RW;
                   4310:     spr[num].armed = RB;
                   4311:     return src;
                   4312: }
                   4313: 
1.1.1.23! root     4314: uae_u8 *save_custom_sprite(int num, int *len)
1.1.1.15  root     4315: {
                   4316:     uae_u8 *dstbak, *dst;
                   4317: 
1.1.1.16  root     4318:     dstbak = dst = malloc (25);
1.1.1.15  root     4319:     SL (spr[num].pt);          /* 120-13E SPRxPT */
                   4320:     SW (sprpos[num]);          /* 1x0 SPRxPOS */
                   4321:     SW (sprctl[num]);          /* 1x2 SPRxPOS */
                   4322:     SW (sprdata[num][0]);      /* 1x4 SPRxDATA */
                   4323:     SW (sprdatb[num][0]);      /* 1x6 SPRxDATB */
                   4324:     SW (sprdata[num][1]);
                   4325:     SW (sprdatb[num][1]);
                   4326:     SW (sprdata[num][2]);
                   4327:     SW (sprdatb[num][2]);
                   4328:     SW (sprdata[num][3]);
                   4329:     SW (sprdatb[num][3]);
                   4330:     SB (spr[num].armed ? 1 : 0);
                   4331:     *len = dst - dstbak;
                   4332:     return dstbak;
                   4333: }
1.1.1.21  root     4334: 
                   4335: void check_prefs_changed_custom (void)
                   4336: {
                   4337:     currprefs.gfx_framerate = changed_prefs.gfx_framerate;
1.1.1.23! root     4338:     if (inputdevice_config_change_test ()) {
        !          4339:        inputdevice_copyconfig (&changed_prefs, &currprefs);
        !          4340:        inputdevice_updateconfig (&currprefs);
1.1.1.21  root     4341:     }
                   4342:     currprefs.immediate_blits = changed_prefs.immediate_blits;
                   4343:     currprefs.blits_32bit_enabled = changed_prefs.blits_32bit_enabled;
                   4344:     currprefs.collision_level = changed_prefs.collision_level;
1.1.1.23! root     4345:     if (currprefs.leds_on_screen && !changed_prefs.leds_on_screen)
        !          4346:        notice_screen_contents_lost ();
        !          4347:     currprefs.leds_on_screen = changed_prefs.leds_on_screen;
1.1.1.21  root     4348: }

unix.superglobalmegacorp.com

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