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

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

unix.superglobalmegacorp.com

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