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

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

unix.superglobalmegacorp.com

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