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

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.4   root        6:   * Copyright 1995-1998 Bernd Schmidt
1.1.1.2   root        7:   * Copyright 1995 Alessandro Bissacco
1.1       root        8:   */
                      9: 
                     10: #include "sysconfig.h"
                     11: #include "sysdeps.h"
                     12: 
                     13: #include <ctype.h>
                     14: #include <assert.h>
                     15: 
                     16: #include "config.h"
                     17: #include "options.h"
1.1.1.3   root       18: #include "threaddep/penguin.h"
                     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 "joystick.h"
                     31: #include "audio.h"
1.1       root       32: #include "keybuf.h"
                     33: #include "serial.h"
1.1.1.2   root       34: #include "osemu.h"
1.1.1.3   root       35: #include "autoconf.h"
                     36: #include "gui.h"
                     37: #include "picasso96.h"
1.1.1.4   root       38: #include "drawing.h"
1.1.1.2   root       39: 
1.1.1.6   root       40: static unsigned int n_consecutive_skipped = 0;
                     41: static unsigned int total_skipped = 0;
                     42: 
1.1.1.3   root       43: #define SPRITE_COLLISIONS
1.1.1.2   root       44: 
1.1.1.3   root       45: /* Mouse and joystick emulation */
1.1.1.2   root       46: 
1.1.1.3   root       47: int buttonstate[3];
                     48: static int mouse_x, mouse_y;
                     49: int joy0button, joy1button;
                     50: unsigned int joy0dir, joy1dir;
                     51: 
                     52: /* Events */
1.1       root       53: 
1.1.1.4   root       54: unsigned long int cycles, nextevent, is_lastline;
                     55: static int rpt_did_reset;
1.1.1.2   root       56: struct ev eventtab[ev_max];
                     57: 
1.1.1.3   root       58: frame_time_t vsynctime, vsyncmintime;
                     59: 
1.1.1.4   root       60: static int vpos;
                     61: static uae_u16 lof;
                     62: static int next_lineno;
                     63: static enum nln_how nextline_how;
                     64: static int lof_changed = 0;
1.1       root       65: 
1.1.1.3   root       66: static uae_u32 sprtaba[256],sprtabb[256];
1.1.1.13! root       67: static uae_u32 sprite_ab_merge[256];
        !            68: /* Tables for collision detection.  */
        !            69: static uae_u32 sprclx[16], clxmask[16];
1.1.1.3   root       70: 
1.1.1.2   root       71: /*
                     72:  * Hardware registers of all sorts.
                     73:  */
1.1       root       74: 
1.1.1.4   root       75: static void custom_wput_1 (int, uaecptr, uae_u32) REGPARAM;
                     76: 
1.1.1.3   root       77: static uae_u16 cregs[256];
1.1       root       78: 
1.1.1.3   root       79: uae_u16 intena,intreq;
                     80: uae_u16 dmacon;
                     81: uae_u16 adkcon; /* used by audio code */
1.1       root       82: 
1.1.1.3   root       83: static uae_u32 cop1lc,cop2lc,copcon;
1.1.1.7   root       84:  
                     85: int maxhpos = MAXHPOS_PAL;
                     86: int maxvpos = MAXVPOS_PAL;
                     87: int minfirstline = MINFIRSTLINE_PAL;
                     88: int vblank_endline = VBLANK_ENDLINE_PAL;
                     89: int vblank_hz = VBLANK_HZ_PAL;
                     90: unsigned long syncbase;
                     91: static int fmode;
                     92: static unsigned int beamcon0, new_beamcon0;
                     93: static int ntscmode = 0;
                     94: 
                     95: #define MAX_SPRITES 32
1.1       root       96: 
1.1.1.2   root       97: /* This is but an educated guess. It seems to be correct, but this stuff
                     98:  * isn't documented well. */
1.1.1.3   root       99: enum sprstate { SPR_stop, SPR_restart, SPR_waiting_start, SPR_waiting_stop };
1.1.1.10  root      100: 
                    101: struct sprite {
                    102:     uaecptr pt;
                    103:     int on;
                    104:     int xpos;
                    105:     int vstart;
                    106:     int vstop;
                    107:     int armed;
                    108:     enum sprstate state;
                    109: };
                    110: 
                    111: static struct sprite spr[8];
                    112: 
                    113: static int sprite_vblank_endline = VBLANK_ENDLINE_NTSC + 2;
1.1       root      114: 
1.1.1.7   root      115: static unsigned int sprdata[MAX_SPRITES], sprdatb[MAX_SPRITES], sprctl[MAX_SPRITES], sprpos[MAX_SPRITES];
1.1.1.10  root      116: static int sprite_last_drawn_at[MAX_SPRITES];
1.1.1.7   root      117: static int last_sprite_point, nr_armed;
                    118: 
1.1.1.6   root      119: static uae_u32 bpl1dat, bpl2dat, bpl3dat, bpl4dat, bpl5dat, bpl6dat, bpl7dat, bpl8dat;
                    120: static uae_s16 bpl1mod, bpl2mod;
1.1       root      121: 
1.1.1.3   root      122: static uaecptr bplpt[8];
1.1.1.10  root      123: uae_u8 *real_bplpt[8];
1.1       root      124: 
                    125: /*static int blitcount[256];  blitter debug */
                    126: 
1.1.1.2   root      127: static struct color_entry current_colors;
1.1.1.6   root      128: static unsigned int bplcon0, bplcon1, bplcon2, bplcon3, bplcon4;
1.1.1.3   root      129: static int nr_planes_from_bplcon0, corrected_nr_planes_from_bplcon0;
1.1.1.4   root      130: static unsigned int diwstrt, diwstop, diwhigh;
                    131: static int diwhigh_written;
                    132: static unsigned int ddfstrt, ddfstop;
1.1.1.7   root      133: 
1.1.1.4   root      134: /* The display and data fetch windows */
1.1       root      135: 
1.1.1.4   root      136: enum diw_states
                    137: {
                    138:     DIW_waiting_start, DIW_waiting_stop
                    139: };
1.1       root      140: 
1.1.1.13! root      141: static int plffirstline, plflastline;
        !           142: static int plfstrt, plfstop;
        !           143: static int last_diw_pix_hpos, last_ddf_pix_hpos, last_decide_line_hpos;
        !           144: static int last_fetch_hpos, last_sprite_hpos;
1.1.1.6   root      145: int diwfirstword, diwlastword;
1.1.1.4   root      146: static enum diw_states diwstate, hdiwstate;
1.1       root      147: 
1.1.1.4   root      148: /* Sprite collisions */
                    149: uae_u16 clxdat, clxcon;
                    150: int clx_sprmask;
                    151: 
                    152: enum copper_states {
                    153:     COP_stop,
1.1.1.10  root      154:     COP_read1, COP_read2,
1.1.1.4   root      155:     COP_bltwait,
1.1.1.13! root      156:     COP_wait,
        !           157:     COP_wait1
1.1.1.4   root      158: };
                    159: 
                    160: struct copper {
                    161:     /* The current instruction words.  */
                    162:     unsigned int i1, i2;
                    163:     enum copper_states state;
                    164:     /* Instruction pointer.  */
                    165:     uaecptr ip;
1.1.1.10  root      166:     int hpos, vpos;
1.1.1.4   root      167:     unsigned int ignore_next;
1.1.1.10  root      168:     int vcmp, hcmp;
1.1.1.4   root      169: };
                    170: 
                    171: static struct copper cop_state;
1.1.1.10  root      172: static int copper_enabled_thisline;
                    173: static int cop_min_waittime;
1.1       root      174: 
                    175: /*
                    176:  * Statistics
                    177:  */
                    178: 
1.1.1.2   root      179: /* Used also by bebox.cpp */
1.1.1.6   root      180: unsigned long int msecs = 0, frametime = 0, lastframetime = 0, timeframes = 0;
1.1       root      181: static unsigned long int seconds_base;
                    182: int bogusframe;
1.1.1.12  root      183: int n_frames;
1.1.1.4   root      184: 
                    185: static int current_change_set;
                    186: 
                    187: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
                    188: /* sam: Those arrays uses around 7Mb of BSS... That seems  */
                    189: /* too much for AmigaDOS (uae crashes as soon as one loads */
                    190: /* it. So I use a different strategy here (realloc the     */
                    191: /* arrays when needed. That strategy might be usefull for  */
                    192: /* computer with low memory.                               */
1.1.1.13! root      193: struct sprite_entry  *sprite_entries[2];
1.1.1.4   root      194: struct color_change *color_changes[2];
1.1.1.13! root      195: static int max_sprite_entry = 400;
        !           196: static int delta_sprite_entry = 0;
1.1.1.4   root      197: static int max_color_change = 400;
                    198: static int delta_color_change = 0;
                    199: #else
1.1.1.13! root      200: struct sprite_entry sprite_entries[2][MAX_SPR_PIXELS / 16];
1.1.1.4   root      201: struct color_change color_changes[2][MAX_REG_CHANGE];
                    202: #endif
                    203: 
1.1.1.7   root      204: struct decision line_decisions[2 * (MAXVPOS + 1) + 1];
                    205: struct draw_info line_drawinfo[2][2 * (MAXVPOS + 1) + 1];
                    206: struct color_entry color_tables[2][(MAXVPOS + 1) * 2];
1.1.1.4   root      207: 
1.1.1.13! root      208: static int next_sprite_entry = 0;
        !           209: static int prev_next_sprite_entry;
        !           210: static int next_sprite_forced = 1;
        !           211: 
        !           212: struct sprite_entry *curr_sprite_entries, *prev_sprite_entries;
1.1.1.4   root      213: struct color_change *curr_color_changes, *prev_color_changes;
                    214: struct draw_info *curr_drawinfo, *prev_drawinfo;
                    215: struct color_entry *curr_color_tables, *prev_color_tables;
                    216: 
1.1.1.13! root      217: static int next_color_change;
1.1.1.4   root      218: static int next_color_entry, remembered_color_entry;
                    219: static int color_src_match, color_dest_match, color_compare_result;
                    220: 
                    221: /* These few are only needed during/at the end of the scanline, and don't
                    222:  * have to be remembered. */
1.1.1.13! root      223: static int decided_bpl1mod, decided_bpl2mod, decided_nr_planes;
1.1.1.5   root      224: 
1.1.1.13! root      225: static uae_u32 thisline_changed;
1.1.1.4   root      226: 
                    227: #ifdef SMART_UPDATE
1.1.1.5   root      228: #define MARK_LINE_CHANGED do { thisline_changed = 1; } while (0)
1.1.1.4   root      229: #else
1.1.1.5   root      230: #define MARK_LINE_CHANGED do { ; } while (0)
1.1.1.4   root      231: #endif
                    232: 
                    233: static struct decision thisline_decision;
1.1.1.13! root      234: static int modulos_added, plane_decided, color_decided;
        !           235: static int passed_plfstop, fetch_cycle;
        !           236: 
        !           237: enum fetchstate {
        !           238:     fetch_not_started,
        !           239:     fetch_started,
        !           240:     fetch_was_plane0
        !           241: } fetch_state;
1.1.1.4   root      242: 
1.1       root      243: /*
                    244:  * helper functions
                    245:  */
                    246: 
1.1.1.4   root      247: int rpt_available = 0;
1.1.1.3   root      248: 
1.1.1.4   root      249: void reset_frame_rate_hack (void)
                    250: {
                    251:     if (currprefs.m68k_speed != -1)
                    252:        return;
                    253: 
                    254:     if (! rpt_available) {
                    255:        currprefs.m68k_speed = 0;
                    256:        return;
                    257:     }
1.1.1.3   root      258: 
1.1.1.4   root      259:     rpt_did_reset = 1;
                    260:     is_lastline = 0;
                    261:     vsyncmintime = read_processor_time() + vsynctime;
                    262:     write_log ("Resetting frame rate hack\n");
                    263: }
1.1       root      264: 
1.1.1.3   root      265: void check_prefs_changed_custom (void)
                    266: {
1.1.1.7   root      267:     currprefs.gfx_framerate = changed_prefs.gfx_framerate;
1.1.1.3   root      268:     /* Not really the right place... */
1.1.1.6   root      269:     if (currprefs.jport0 != changed_prefs.jport0
                    270:        || currprefs.jport1 != changed_prefs.jport1) {
                    271:        currprefs.jport0 = changed_prefs.jport0;
                    272:        currprefs.jport1 = changed_prefs.jport1;
1.1.1.3   root      273:        joystick_setting_changed ();
1.1       root      274:     }
1.1.1.3   root      275:     currprefs.immediate_blits = changed_prefs.immediate_blits;
                    276:     currprefs.blits_32bit_enabled = changed_prefs.blits_32bit_enabled;
                    277:        
1.1       root      278: }
                    279: 
1.1.1.8   root      280: STATIC_INLINE void setclr (uae_u16 *p, uae_u16 val)
1.1       root      281: {
1.1.1.6   root      282:     if (val & 0x8000)
1.1       root      283:        *p |= val & 0x7FFF;
1.1.1.6   root      284:     else
1.1       root      285:        *p &= ~val;
                    286: }
                    287: 
1.1.1.3   root      288: __inline__ int current_hpos (void)
1.1       root      289: {
                    290:     return cycles - eventtab[ev_hsync].oldcycles;
                    291: }
                    292: 
1.1.1.8   root      293: STATIC_INLINE uae_u8 *pfield_xlateptr (uaecptr plpt, int bytecount)
1.1.1.2   root      294: {
1.1.1.4   root      295:     if (!chipmem_bank.check (plpt, bytecount)) {
1.1.1.2   root      296:        static int count = 0;
1.1.1.3   root      297:        if (!count)
                    298:            count++, write_log ("Warning: Bad playfield pointer\n");
1.1.1.2   root      299:        return NULL;
                    300:     }
1.1.1.4   root      301:     return chipmem_bank.xlateaddr (plpt);
1.1.1.2   root      302: }
                    303: 
1.1.1.8   root      304: STATIC_INLINE void docols (struct color_entry *colentry)
1.1.1.3   root      305: {
                    306:     int i;
1.1.1.11  root      307: 
                    308:     if (currprefs.chipset_mask & CSMASK_AGA) {
                    309:         for (i = 0; i < 256; i++) {
                    310:            int v = color_reg_get (colentry, i);
                    311:            if(v < 0 || v > 16777215)
                    312:                continue;
                    313:            colentry->acolors[i] = CONVERT_RGB (v);
                    314:        }
                    315:     } else {
                    316:         for (i = 0; i < 32; i++) {
                    317:            int v = color_reg_get (colentry, i);
                    318:            if (v < 0 || v > 4095)
                    319:                continue;
                    320:            colentry->acolors[i] = xcolors[v];
                    321:        }
1.1.1.3   root      322:     }
                    323: }
                    324: 
                    325: void notice_new_xcolors (void)
                    326: {
                    327:     int i;
                    328: 
                    329:     docols(&current_colors);
1.1.1.4   root      330: /*    docols(&colors_for_drawing);*/
1.1.1.7   root      331:     for (i = 0; i < (MAXVPOS + 1)*2; i++) {
1.1.1.3   root      332:        docols(color_tables[0]+i);
                    333:        docols(color_tables[1]+i);
                    334:     }
                    335: }
                    336: 
1.1.1.4   root      337: static void do_sprites (int currvp, int currhp);
1.1.1.2   root      338: 
                    339: static void remember_ctable (void)
                    340: {
                    341:     if (remembered_color_entry == -1) {
                    342:        /* The colors changed since we last recorded a color map. Record a
                    343:         * new one. */
1.1.1.11  root      344:        color_reg_cpy (curr_color_tables + next_color_entry, &current_colors);
1.1.1.2   root      345:        remembered_color_entry = next_color_entry++;
                    346:     }
                    347:     thisline_decision.ctable = remembered_color_entry;
                    348:     if (color_src_match == -1 || color_dest_match != remembered_color_entry
                    349:        || line_decisions[next_lineno].ctable != color_src_match)
                    350:     {
                    351:        /* The remembered comparison didn't help us - need to compare again. */
                    352:        int oldctable = line_decisions[next_lineno].ctable;
                    353:        int changed = 0;
                    354: 
1.1.1.3   root      355:        if (oldctable == -1) {
1.1.1.2   root      356:            changed = 1;
                    357:            color_src_match = color_dest_match = -1;
                    358:        } else {
1.1.1.11  root      359:            color_compare_result = color_reg_cmp (&prev_color_tables[oldctable], &current_colors) != 0;
1.1.1.3   root      360:            if (color_compare_result)
                    361:                changed = 1;
                    362:            color_src_match = oldctable;
1.1.1.2   root      363:            color_dest_match = remembered_color_entry;
1.1.1.3   root      364:        }
1.1.1.5   root      365:        thisline_changed |= changed;
1.1.1.3   root      366:     } else {
                    367:        /* We know the result of the comparison */
                    368:        if (color_compare_result)
1.1.1.5   root      369:            thisline_changed = 1;
1.1.1.3   root      370:     }
                    371: }
                    372: 
                    373: static void remember_ctable_for_border (void)
                    374: {
                    375:     remember_ctable ();
1.1.1.2   root      376: }
                    377: 
1.1.1.3   root      378: /* Called to determine the state of the horizontal display window state
                    379:  * machine at the current position. It might have changed since we last
                    380:  * checked.  */
1.1.1.4   root      381: static void decide_diw (int hpos)
1.1.1.2   root      382: {
1.1.1.13! root      383:     int pix_hpos = coord_diw_to_window_x (hpos * 2);
1.1.1.3   root      384:     if (hdiwstate == DIW_waiting_start && thisline_decision.diwfirstword == -1
1.1.1.9   root      385:        && pix_hpos >= diwfirstword && last_diw_pix_hpos < diwfirstword)
1.1.1.3   root      386:     {
1.1.1.13! root      387:        thisline_decision.diwfirstword = diwfirstword < 0 ? 0 : diwfirstword;
1.1.1.3   root      388:        hdiwstate = DIW_waiting_stop;
1.1.1.2   root      389:        thisline_decision.diwlastword = -1;
                    390:     }
1.1.1.3   root      391:     if (hdiwstate == DIW_waiting_stop && thisline_decision.diwlastword == -1
1.1.1.9   root      392:        && pix_hpos >= diwlastword && last_diw_pix_hpos < diwlastword)
1.1.1.3   root      393:     {
1.1.1.13! root      394:        thisline_decision.diwlastword = diwlastword < 0 ? 0 : diwlastword;
1.1.1.3   root      395:        hdiwstate = DIW_waiting_start;
1.1.1.2   root      396:     }
1.1.1.9   root      397:     last_diw_pix_hpos = pix_hpos;
1.1.1.2   root      398: }
                    399: 
1.1.1.13! root      400: /* The HRM says 0xD8, but that can't work... */
        !           401: #define HARD_DDF_STOP (0xD4)
1.1.1.2   root      402: 
1.1.1.13! root      403: static void finish_playfield_line (void)
        !           404: {
1.1.1.2   root      405:     /* The latter condition might be able to happen in interlaced frames. */
                    406:     if (vpos >= minfirstline && (thisframe_first_drawn_line == -1 || vpos < thisframe_first_drawn_line))
                    407:        thisframe_first_drawn_line = vpos;
                    408:     thisframe_last_drawn_line = vpos;
                    409: 
1.1.1.13! root      410:     if (dmaen (DMA_BITPLANE))
        !           411:        switch (nr_planes_from_bplcon0) {
        !           412:        case 8: bplpt[7] += bpl2mod;
        !           413:        case 7: bplpt[6] += bpl1mod;
        !           414:        case 6: bplpt[5] += bpl2mod;
        !           415:        case 5: bplpt[4] += bpl1mod;
        !           416:        case 4: bplpt[3] += bpl2mod;
        !           417:        case 3: bplpt[2] += bpl1mod;
        !           418:        case 2: bplpt[1] += bpl2mod;
        !           419:        case 1: bplpt[0] += bpl1mod;
        !           420:        }
1.1.1.2   root      421: 
                    422:     /* These are for comparison. */
                    423:     thisline_decision.bplcon0 = bplcon0;
                    424:     thisline_decision.bplcon2 = bplcon2;
                    425:     thisline_decision.bplcon4 = bplcon4;
1.1.1.11  root      426:     thisline_decision.fmode = fmode;
1.1.1.2   root      427: 
                    428: #ifdef SMART_UPDATE
1.1.1.13! root      429:     if (line_decisions[next_lineno].plflinelen != thisline_decision.plflinelen
        !           430:        || line_decisions[next_lineno].plfleft != thisline_decision.plfleft
1.1.1.2   root      431:        || line_decisions[next_lineno].bplcon0 != thisline_decision.bplcon0
                    432:        || line_decisions[next_lineno].bplcon2 != thisline_decision.bplcon2
                    433:        || line_decisions[next_lineno].bplcon4 != thisline_decision.bplcon4
1.1.1.11  root      434:        || line_decisions[next_lineno].fmode != thisline_decision.fmode
1.1.1.2   root      435:        )
                    436: #endif /* SMART_UPDATE */
1.1.1.5   root      437:        thisline_changed = 1;
1.1.1.2   root      438: }
                    439: 
1.1.1.13! root      440: static int estimated_last_fetch_cycle;
1.1.1.4   root      441: 
1.1.1.13! root      442: static void estimate_last_fetch_cycle (int hpos)
1.1.1.2   root      443: {
1.1.1.13! root      444:     if (! passed_plfstop) {
        !           445:        int stop = plfstop < hpos || plfstop > HARD_DDF_STOP ? HARD_DDF_STOP : plfstop;
        !           446:        /* We know that fetching is up-to-date up until hpos, so we can use fetch_cycle.  */
        !           447:        int fetch_cycle_at_stop = fetch_cycle + (stop - hpos);
        !           448:        int starting_last_block_at = (fetch_cycle_at_stop + 7) & ~7;
        !           449: 
        !           450:        estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + 8;
        !           451:     } else {
        !           452:        int starting_last_block_at = (fetch_cycle + 7) & ~7;
        !           453:        if (passed_plfstop == 2)
        !           454:            starting_last_block_at -= 8;
        !           455: 
        !           456:        estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + 8;
        !           457:     }
1.1.1.4   root      458: }
                    459: 
1.1.1.13! root      460: static uae_u32 outword[8];
        !           461: static int out_nbits, out_offs;
        !           462: static uae_u32 todisplay[8];
        !           463: 
        !           464: static uae_u32 fetched[8];
        !           465: 
        !           466: /* Expansions from bplcon0/bplcon1.  */
        !           467: static int toscr_res, toscr_delay1, toscr_delay2, toscr_nr_planes;
        !           468: 
        !           469: /* The number of bits left from the last fetched words.  */
        !           470: static int toscr_nbits;
        !           471: 
        !           472: STATIC_INLINE void maybe_first_bpl1dat (int hpos)
1.1.1.4   root      473: {
1.1.1.13! root      474:     if (thisline_decision.plfleft == -1)
        !           475:        thisline_decision.plfleft = hpos;
        !           476: }
1.1.1.9   root      477: 
1.1.1.13! root      478: STATIC_INLINE void move_fetched (int hpos)
        !           479: {
        !           480: }
1.1.1.9   root      481: 
1.1.1.13! root      482: STATIC_INLINE void fetch (int nr)
        !           483: {
        !           484:     if (nr < toscr_nr_planes) {
        !           485:        fetched[nr] = chipmem_wget (bplpt[nr]);
        !           486:        bplpt[nr] += 2;
1.1.1.4   root      487:     }
1.1.1.13! root      488: }
        !           489: 
        !           490: /* Expand bplcon0/bplcon1 into the toscr_xxx variables.  */
        !           491: static void compute_toscr_delay (void)
        !           492: {
        !           493:     int delay1 = (bplcon1 & 0x0f) | ((bplcon1 & 0x0c00) >> 6);
        !           494:     int delay2 = ((bplcon1 >> 4) & 0x0f) | (((bplcon1 >> 4) & 0x0c00) >> 6);
        !           495:     int delaymask;
        !           496: 
        !           497:     toscr_res = GET_RES (bplcon0);
        !           498:     delaymask = ((16 << fetchmode) - 1) >> toscr_res;
        !           499: 
        !           500:     toscr_delay1 = (delay1 & delaymask) << toscr_res;
        !           501:     toscr_delay2 = (delay2 & delaymask) << toscr_res;
        !           502: 
        !           503:     toscr_nr_planes = GET_PLANES (bplcon0);
        !           504: }
        !           505: 
        !           506: static void clear_fetchbuffer (uae_u32 *ptr, int nwords)
        !           507: {
        !           508:     int i;
        !           509: 
        !           510:     if (! thisline_changed)
        !           511:        for (i = 0; i < nwords; i++)
        !           512:            if (ptr[i]) {
        !           513:                thisline_changed = 1;
        !           514:                break;
1.1.1.4   root      515:            }
1.1.1.13! root      516: 
        !           517:     memset (ptr, 0, nwords * 4);
        !           518: }
        !           519: 
        !           520: static void update_toscr_planes (void)
        !           521: {
        !           522:     if (toscr_nr_planes > thisline_decision.nr_planes) {
        !           523:        int j;
        !           524:        for (j = thisline_decision.nr_planes; j < toscr_nr_planes; j++)
        !           525:            clear_fetchbuffer ((uae_u32 *)(line_data[next_lineno] + 2 * MAX_WORDS_PER_LINE * j), out_offs);
        !           526: #if 0
        !           527:        if (thisline_decision.nr_planes > 0)
        !           528:            printf ("Planes from %d to %d\n", thisline_decision.nr_planes, toscr_nr_planes);
        !           529: #endif
        !           530:        thisline_decision.nr_planes = toscr_nr_planes;
1.1.1.4   root      531:     }
                    532: }
1.1.1.2   root      533: 
1.1.1.13! root      534: static void toscr_1 (int nbits)
1.1.1.7   root      535: {
1.1.1.13! root      536:     int delay1 = toscr_delay1;
        !           537:     int delay2 = toscr_delay2;
        !           538:     int i;
        !           539:     uae_u32 mask = 0xFFFF >> (16 - nbits);
        !           540: 
        !           541:     for (i = 0; i < toscr_nr_planes; i += 2) {
        !           542:        outword[i] <<= nbits;
        !           543:        outword[i] |= (todisplay[i] >> (16 - nbits + delay1)) & mask;
        !           544:        todisplay[i] <<= nbits;
        !           545:     }
        !           546:     for (i = 1; i < toscr_nr_planes; i += 2) {
        !           547:        outword[i] <<= nbits;
        !           548:        outword[i] |= (todisplay[i] >> (16 - nbits + delay2)) & mask;
        !           549:        todisplay[i] <<= nbits;
        !           550:     }
        !           551:     out_nbits += nbits;
        !           552:     if (out_nbits == 32) {
        !           553:        uae_u8 *dataptr = line_data[next_lineno] + out_offs * 4;
        !           554:        /* Don't use toscr_nr_planes here; if the plane count drops during the
        !           555:           line we still want the data to be correct for the full number of planes
        !           556:           over the full width of the line.  */
        !           557:        for (i = 0; i < thisline_decision.nr_planes; i++) {
        !           558:            uae_u32 *dataptr32 = (uae_u32 *)dataptr;
        !           559:            if (*dataptr32 != outword[i])
        !           560:                thisline_changed = 1;
        !           561:            *dataptr32 = outword[i];
        !           562:            dataptr += MAX_WORDS_PER_LINE * 2;
        !           563:        }
        !           564:        out_offs++;
        !           565:        out_nbits = 0;
        !           566:     }
1.1.1.7   root      567: }
                    568: 
1.1.1.13! root      569: static void toscr (int nbits)
1.1.1.4   root      570: {
1.1.1.13! root      571:     int t;
        !           572:     if (nbits > 16) {
        !           573:        toscr (16);
        !           574:        nbits -= 16;
1.1.1.2   root      575:     }
1.1.1.3   root      576: 
1.1.1.13! root      577:     t = 32 - out_nbits;
        !           578:     if (t < nbits) {
        !           579:        toscr_1 (t);
        !           580:        nbits -= t;
        !           581:     }
        !           582:     toscr_1 (nbits);
        !           583: }
        !           584:  
        !           585: static int flush_plane_data (void)
        !           586: {
        !           587:     int i = 0;
1.1.1.4   root      588: 
1.1.1.13! root      589:     if (out_nbits <= 16) {
        !           590:        i += 16;
        !           591:        toscr_1 (16);
        !           592:     }
        !           593:     if (out_nbits != 0) {
        !           594:        i += 32 - out_nbits;
        !           595:        toscr_1 (32 - out_nbits);
1.1.1.4   root      596:     }
1.1.1.13! root      597:     i += 32;
        !           598:     toscr_1 (16);
        !           599:     toscr_1 (16);
1.1.1.10  root      600: 
1.1.1.13! root      601:     return i >> (1 + toscr_res);
        !           602: }
        !           603: 
        !           604: /* The usual inlining tricks - don't touch unless you know what you are doing.  */
        !           605: STATIC_INLINE void long_fetch (int plane, int nwords, int weird_number_of_bits)
        !           606: {
        !           607:     uae_u16 *real_pt = (uae_u16 *)pfield_xlateptr (bplpt[plane], nwords * 2);
        !           608:     int delay = ((plane & 1) ?  toscr_delay2 : toscr_delay1);
        !           609:     int i;
        !           610:     int tmp_nbits = out_nbits;
        !           611:     uae_u32 shiftbuffer = todisplay[plane];
        !           612:     uae_u32 outval = outword[plane];
        !           613:     uae_u32 fetchval = fetched[plane];
        !           614:     uae_u32 *dataptr = (uae_u32 *)(line_data[next_lineno] + 2 * plane * MAX_WORDS_PER_LINE + 4 * out_offs);
        !           615: 
        !           616:     bplpt[plane] += nwords * 2;
        !           617: 
        !           618:     if (real_pt == 0)
        !           619:        /* @@@ Don't do this, fall back on chipmem_wget instead.  */
1.1.1.4   root      620:        return;
                    621: 
1.1.1.13! root      622:     if (thisline_decision.plfleft == -1) {
        !           623:        nwords--;
        !           624:        fetchval = do_get_mem_word (real_pt);
        !           625:        real_pt += 2;
1.1.1.2   root      626:     }
                    627: 
1.1.1.13! root      628:     while (nwords > 0) {
        !           629:        int bits_left = 32 - tmp_nbits;
        !           630: 
        !           631:        shiftbuffer |= fetchval;
        !           632: 
        !           633:        if (weird_number_of_bits && bits_left < 16) {
        !           634:            outval <<= bits_left;
        !           635:            outval |= (shiftbuffer >> (16 + delay - bits_left)) & (0xFFFF >> (16 - bits_left));
        !           636:            shiftbuffer <<= bits_left;
        !           637:            thisline_changed |= *dataptr ^ outval;
        !           638:            *dataptr++ = outval;
        !           639: 
        !           640:            tmp_nbits = 16 - bits_left;
        !           641:            outval = (shiftbuffer >> (16 + delay - tmp_nbits)) & (0xFFFF >> (16 - tmp_nbits));
        !           642:            shiftbuffer <<= tmp_nbits;
        !           643:        } else {
        !           644:            outval <<= 16;
        !           645:            outval |= (shiftbuffer >> delay) & 0xFFFF;
        !           646:            shiftbuffer <<= 16;
        !           647:            tmp_nbits += 16;
        !           648:            if (tmp_nbits == 32) {
        !           649:                thisline_changed |= *dataptr ^ outval;
        !           650:                *dataptr++ = outval;
        !           651:                tmp_nbits = 0;
        !           652:            }
        !           653:        }
        !           654: 
        !           655:        fetchval = do_get_mem_word (real_pt);
1.1.1.2   root      656: 
1.1.1.13! root      657:        nwords--;
        !           658:        real_pt++;
        !           659:     }
        !           660:     fetched[plane] = fetchval;
        !           661:     todisplay[plane] = shiftbuffer;
        !           662:     outword[plane] = outval;
1.1.1.2   root      663: }
                    664: 
1.1.1.13! root      665: static void long_fetch_0 (int hpos, int nwords) { long_fetch (hpos, nwords, 0); }
        !           666: static void long_fetch_1 (int hpos, int nwords) { long_fetch (hpos, nwords, 1); }
        !           667: 
        !           668: static void do_long_fetch (int hpos, int nwords)
1.1.1.2   root      669: {
1.1.1.13! root      670:     int i;
1.1.1.2   root      671: 
1.1.1.13! root      672:     if (out_nbits & 15) {
        !           673:        for (i = 0; i < toscr_nr_planes; i++)
        !           674:            long_fetch_1 (i, nwords);
        !           675:     } else {
        !           676:        for (i = 0; i < toscr_nr_planes; i++)
        !           677:            long_fetch_0 (i, nwords);
1.1.1.2   root      678:     }
1.1.1.13! root      679: 
        !           680:     if (thisline_decision.plfleft == -1)
        !           681:        nwords--;
        !           682: 
        !           683:     out_nbits += 16 * nwords;
        !           684:     out_offs += out_nbits >> 5;
        !           685:     out_nbits &= 31;
        !           686: }
        !           687: 
        !           688: //#define SPEEDUP
        !           689: 
        !           690: STATIC_INLINE int one_fetch_cycle (int i, int ddfstop_to_test, int unit, int unit_mask, int dma)
        !           691: {
        !           692:     if (! passed_plfstop && i == ddfstop_to_test)
        !           693:        passed_plfstop = 1;
        !           694: 
        !           695:     if ((fetch_cycle & 7) == 0) {
        !           696:        if (passed_plfstop == 2) {
        !           697:            passed_plfstop = 3;
        !           698: 
        !           699:            i += flush_plane_data ();
        !           700: 
        !           701:            thisline_decision.plfright = i;
        !           702:            thisline_decision.plflinelen = out_offs;
        !           703:            thisline_decision.bplres = toscr_res;
        !           704: 
        !           705:            finish_playfield_line ();
        !           706:            return 1;
        !           707:        }
        !           708:        if (passed_plfstop)
        !           709:            passed_plfstop++;
1.1.1.2   root      710:     }
1.1.1.13! root      711:     if (dma) {
        !           712:        int masked_cycle = fetch_cycle & unit_mask;
1.1.1.2   root      713: 
1.1.1.13! root      714:        switch (masked_cycle) {
        !           715:        case 0: fetch (7 >> toscr_res); break;
        !           716:        case 1: fetch (3 >> toscr_res); break;
        !           717:        case 2: fetch (5 >> toscr_res); break;
        !           718:        case 3: fetch (1 >> toscr_res); break;
        !           719:        case 4: fetch (6); break;
        !           720:        case 5: fetch (2); break;
        !           721:        case 6: fetch (4); break;
        !           722:        case 7: fetch (0); break;
        !           723:        }
        !           724:        if (masked_cycle == unit_mask && toscr_nr_planes > 0)
        !           725:            fetch_state = fetch_was_plane0;
1.1.1.2   root      726:     }
1.1.1.13! root      727:     fetch_cycle++;
        !           728:     toscr_nbits += 2 << toscr_res;
        !           729:     return 0;
        !           730: }
1.1.1.3   root      731: 
1.1.1.13! root      732: STATIC_INLINE void beginning_of_unit_block (int pos, int dma)
        !           733: {
        !           734:     int i;
        !           735:     if (toscr_nbits > 0 && thisline_decision.plfleft != -1)
        !           736:        toscr (toscr_nbits);
        !           737:     toscr_nbits = 0;
        !           738: 
        !           739:     for (i = 0; i < 8; i++)
        !           740:        todisplay[i] |= fetched[i];
        !           741: 
        !           742:     maybe_first_bpl1dat (pos);
        !           743: }
        !           744: 
        !           745: STATIC_INLINE void update_fetch (int until)
        !           746: {
        !           747:     int unit, unit_mask;
        !           748:     int pos;
        !           749:     int dma = dmaen (DMA_BITPLANE);
        !           750: 
        !           751:     int ddfstop_to_test;
        !           752: 
        !           753:     if (framecnt != 0 || passed_plfstop == 3)
1.1.1.2   root      754:        return;
1.1.1.13! root      755: 
        !           756:     /* We need an explicit test against HARD_DDF_STOP here to guard against
        !           757:        programs that move the DDFSTOP before our current position before we
        !           758:        reach it.  */
        !           759:     ddfstop_to_test = HARD_DDF_STOP;
        !           760:     if (ddfstop >= last_fetch_hpos && ddfstop < HARD_DDF_STOP)
        !           761:        ddfstop_to_test = ddfstop;
        !           762: 
        !           763:     compute_toscr_delay ();
        !           764:     update_toscr_planes ();
        !           765: 
        !           766:     unit = 8 >> toscr_res;
        !           767:     unit_mask = unit - 1;
        !           768: 
        !           769:     /* @@@ This needs updating for different FMODEs in AGA.  */
        !           770: 
        !           771:     pos = last_fetch_hpos;
        !           772: 
        !           773:     /* First, finish one fetch block if we already started one.  */
        !           774:     for (; ; pos++) {
        !           775:        if (pos == until)
        !           776:            goto out;
        !           777: 
        !           778:        if ((fetch_cycle & 7) == 0)
        !           779:            break;
        !           780: 
        !           781:        if (fetch_state == fetch_was_plane0)
        !           782:            beginning_of_unit_block (pos, dma);
        !           783:        fetch_state = fetch_started;
        !           784: 
        !           785:        if (one_fetch_cycle (pos, ddfstop_to_test, unit, unit_mask, dma))
        !           786:            return;
1.1.1.2   root      787:     }
                    788: 
1.1.1.13! root      789:     /* Now, our position is aligned to the fetch block boundaries.  */
        !           790: 
        !           791: #ifdef SPEEDUP
        !           792:     /* Unrolled version of the for loop below.  */
        !           793:     if (! passed_plfstop && toscr_nr_planes == thisline_decision.nr_planes) {
        !           794:        int stop = until < ddfstop_to_test + 0 * unit_mask ? until : ddfstop_to_test + 0 * unit_mask;
        !           795:        int count = stop - pos;
        !           796: 
        !           797:        if (count >= unit) {
        !           798:            if (toscr_nbits > 0 && thisline_decision.plfleft != -1)
        !           799:                toscr (toscr_nbits);
        !           800:            toscr_nbits = 0;
        !           801: 
        !           802:            if (fetch_state == fetch_was_plane0)
        !           803:                beginning_of_unit_block (pos, dma);
        !           804: 
        !           805:            do_long_fetch (pos, count >> (3 - toscr_res));
        !           806:            
        !           807:            if (toscr_nr_planes > 0)
        !           808:                maybe_first_bpl1dat (pos + unit);
        !           809: 
        !           810:            count &= ~unit_mask;
        !           811:            if (pos <= ddfstop_to_test && pos + count > ddfstop_to_test)
        !           812:                passed_plfstop = 1;
        !           813: 
        !           814:            pos += count;
        !           815:            fetch_cycle += count;
        !           816:            fetch_state = fetch_was_plane0;
        !           817:            if (pos == until)
        !           818:                return;
        !           819:        }
1.1.1.2   root      820:     }
                    821: #endif
1.1.1.13! root      822:     /* We enter this with I aligned to unit cycles (i.e. (fetch_cycle & unit_mask) == 0.  */
        !           823:     for (; pos < until; pos++) {
        !           824:        if (fetch_state == fetch_was_plane0)
        !           825:            beginning_of_unit_block (pos, dma);
        !           826:        fetch_state = fetch_started;
        !           827: 
        !           828:        if (one_fetch_cycle (pos, ddfstop_to_test, unit, unit_mask, dma))
        !           829:            return;
        !           830:     }
        !           831: 
        !           832:   out:
        !           833:     if (thisline_decision.plfleft != -1 && toscr_nbits > 0) {
        !           834:        toscr (toscr_nbits);
        !           835:     }
        !           836:     toscr_nbits = 0;
1.1.1.2   root      837: }
                    838: 
1.1.1.13! root      839: STATIC_INLINE void decide_fetch (int hpos)
        !           840: {
        !           841:     if (fetch_state != fetch_not_started && hpos > last_fetch_hpos)
        !           842:        update_fetch (hpos);
        !           843:     last_fetch_hpos = hpos;
        !           844: }
        !           845: 
        !           846: /* This function is responsible for turning on datafetch if necessary.  */
1.1.1.8   root      847: STATIC_INLINE void decide_line (int hpos)
1.1.1.2   root      848: {
1.1.1.13! root      849:     if (fetch_state != fetch_not_started)
        !           850:        return;
        !           851: 
        !           852:     /* Test if we passed the start of the DDF window.  */
        !           853:     if (last_decide_line_hpos < plfstrt && hpos >= plfstrt) {
        !           854:        /* First, take care of the vertical DIW.  Surprisingly enough, this seems to be
        !           855:           correct here - putting this into decide_diw() results in garbage.  */
        !           856:        if (diwstate == DIW_waiting_start && vpos == plffirstline) {
        !           857:            diwstate = DIW_waiting_stop;
        !           858:        }
        !           859:        if (diwstate == DIW_waiting_stop && vpos == plflastline) {
        !           860:            diwstate = DIW_waiting_start;
        !           861:        }
        !           862: 
        !           863:        if (diwstate == DIW_waiting_stop) {
        !           864:            fetch_state = fetch_started;
        !           865:            fetch_cycle = 0;
        !           866:            last_fetch_hpos = plfstrt;
        !           867:            out_nbits = 0;
        !           868:            out_offs = 0;
        !           869:            toscr_nbits = 0;
        !           870: 
        !           871:            compute_toscr_delay ();
        !           872: 
        !           873:            /* If someone already wrote BPL1DAT, clear the area between that point and
        !           874:               the real fetch start.  */
        !           875:            if (thisline_decision.plfleft != -1) {
        !           876:                out_nbits = (plfstrt - thisline_decision.plfleft) << (1 + toscr_res);
        !           877:                out_offs = out_nbits >> 5;
        !           878:                out_nbits &= 31;
        !           879:            }
        !           880:            update_toscr_planes ();
        !           881: 
        !           882:            estimate_last_fetch_cycle (plfstrt);
        !           883:            last_decide_line_hpos = hpos;
        !           884:            do_sprites (vpos, plfstrt);
        !           885:            return;
        !           886:        }
        !           887:     }
        !           888: 
        !           889:     if (last_decide_line_hpos < 0x34)
        !           890:        do_sprites (vpos, hpos);
        !           891: 
        !           892:     last_decide_line_hpos = hpos;
1.1.1.2   root      893: }
                    894: 
1.1.1.3   root      895: /* Called when a color is about to be changed (write to a color register),
                    896:  * but the new color has not been entered into the table yet. */
1.1.1.4   root      897: static void record_color_change (int hpos, int regno, unsigned long value)
1.1.1.3   root      898: {
                    899:     /* Early positions don't appear on-screen. */
1.1.1.4   root      900:     if (framecnt != 0 || vpos < minfirstline || hpos < 0x18
1.1.1.3   root      901:        /*|| currprefs.emul_accuracy == 0*/)
                    902:        return;
                    903: 
1.1.1.4   root      904:     decide_diw (hpos);
                    905:     decide_line (hpos);
1.1.1.3   root      906: 
1.1.1.13! root      907:     if (thisline_decision.ctable == -1)
        !           908:        remember_ctable ();
1.1.1.3   root      909: 
                    910: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
1.1.1.4   root      911:     if (next_color_change >= max_color_change) {
1.1.1.3   root      912:        ++delta_color_change;
                    913:        return;
                    914:     }
                    915: #endif
1.1.1.4   root      916:     curr_color_changes[next_color_change].linepos = hpos;
1.1.1.3   root      917:     curr_color_changes[next_color_change].regno = regno;
                    918:     curr_color_changes[next_color_change++].value = value;
                    919: }
                    920: 
1.1.1.13! root      921: /* Sprite-to-sprite collisions are taken care of in record_sprite.  This one does
        !           922:    playfield/sprite collisions.
        !           923:    That's the theory.  In practice this doesn't work yet.  I also suspect this code
        !           924:    is way too slow.  */
        !           925: static void do_sprite_collisions (void)
1.1.1.2   root      926: {
1.1.1.13! root      927:     int nr_sprites = curr_drawinfo[next_lineno].nr_sprites;
        !           928:     int first = curr_drawinfo[next_lineno].first_sprite_entry;
        !           929:     int i;
        !           930:     unsigned int collision_mask = clxmask[clxcon >> 12];
        !           931:     int plf_first_pixel = thisline_decision.plfleft * 2 + DIW_DDF_OFFSET;
1.1.1.2   root      932: 
1.1.1.13! root      933:     for (i = 0; i < nr_sprites; i++) {
        !           934:        struct sprite_entry *e = curr_sprite_entries + first + i;
        !           935:        int j;
        !           936:        int minpos = e->pos;
        !           937:        int maxpos = e->max;
        !           938: 
        !           939:        if (maxpos > thisline_decision.diwlastword)
        !           940:            maxpos = thisline_decision.diwlastword;
        !           941:        if (maxpos > thisline_decision.plfright * 2 + DIW_DDF_OFFSET)
        !           942:            maxpos = thisline_decision.plfright * 2 + DIW_DDF_OFFSET;
        !           943:        if (minpos < thisline_decision.diwfirstword)
        !           944:            minpos = thisline_decision.diwfirstword;
        !           945:        if (minpos < plf_first_pixel)
        !           946:            minpos = plf_first_pixel;
        !           947: 
        !           948:        for (j = minpos; j < maxpos; j++) {
        !           949:            int sprpix = spixels[e->first_pixel + j - e->pos] & collision_mask;
        !           950:            int k;
1.1.1.2   root      951: 
1.1.1.13! root      952:            if (sprpix == 0)
        !           953:                continue;
1.1.1.2   root      954: 
1.1.1.13! root      955:            sprpix = sprite_ab_merge[sprpix & 255] | (sprite_ab_merge[sprpix >> 8] << 2);
        !           956:            sprpix <<= 1;
1.1.1.2   root      957: 
1.1.1.13! root      958:            /* Loop over number of playfields.  */
        !           959:            for (k = 0; k < 2; k++) {
        !           960:                int l;
        !           961:                int match = 1;
        !           962: 
        !           963:                for (l = k; match && l < 6; l += 2)
        !           964:                    if (clxcon & (64 << l)) {
        !           965:                        int t = 0;
        !           966:                        if (l < thisline_decision.nr_planes) {
        !           967:                            int offs = j - plf_first_pixel;
        !           968:                            uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + 2 * l * MAX_WORDS_PER_LINE);
        !           969:                            uae_u32 word = ldata[offs >> 5];
        !           970:                            t = (word >> (31 - (offs & 31))) & 1;
        !           971:                        }
        !           972:                        if (t != ((clxcon >> l) & 1))
        !           973:                            match = 0;
        !           974:                    }
        !           975:                if (match)
        !           976:                    clxdat |= sprpix;
        !           977:                sprpix <<= 4;
        !           978:            }
1.1.1.2   root      979:        }
                    980:     }
                    981: }
                    982: 
1.1.1.13! root      983: /* DATAB contains the sprite data; 16 pixels in two-bit packets.  Bits 0/1
        !           984:    determine the color of the leftmost pixel, bits 2/3 the color of the next
        !           985:    etc.
        !           986:    This function assumes that for all sprites in a given line, SPRXP either
        !           987:    stays equal or increases between successive calls.  */
        !           988: static void record_sprite (int line, int num, int sprxp, uae_u32 datab, unsigned int ctl)
1.1.1.2   root      989: {
1.1.1.13! root      990:     struct sprite_entry *e = curr_sprite_entries + next_sprite_entry;
        !           991:     int i;
        !           992:     int word_offs;
        !           993:     uae_u16 *buf;
        !           994:     uae_u32 collision_mask;
        !           995:     int collision_enabled;
        !           996: 
        !           997:     if (currprefs.gfx_lores == 0)
        !           998:        sprxp >>= 1;
        !           999: 
        !          1000:     /* Try to coalesce entries if they aren't too far apart.  */
        !          1001:     if (! next_sprite_forced && e[-1].max + 16 >= sprxp)
        !          1002:        e--;
        !          1003:     else {
        !          1004:        next_sprite_entry++;
        !          1005:        e->pos = sprxp;
        !          1006:        e->has_attached = 0;
        !          1007:     }
        !          1008:     if (sprxp < e->pos)
        !          1009:        abort ();
        !          1010:     e->max = sprxp + 16;
        !          1011:     e[1].first_pixel = e->first_pixel + ((e->max - e->pos + 3) & ~3);
        !          1012:     next_sprite_forced = 0;
        !          1013: 
        !          1014:     collision_mask = clxmask[clxcon >> 12];
        !          1015:     word_offs = e->first_pixel + sprxp - e->pos;
        !          1016:     buf = spixels + word_offs;
        !          1017:     while (datab) {
        !          1018:        unsigned int tmp = *buf;
        !          1019:        unsigned int col = (datab & 3) << (2 * num);
        !          1020:        tmp |= col;
        !          1021:        *buf++ = tmp;
        !          1022:        datab >>= 2;
        !          1023:        tmp &= collision_mask;
        !          1024:        if (tmp) {
        !          1025:            unsigned int shrunk_tmp = sprite_ab_merge[tmp & 255] | (sprite_ab_merge[tmp >> 8] << 2);
        !          1026:            clxdat |= sprclx[shrunk_tmp];
1.1.1.2   root     1027:        }
                   1028:     }
                   1029: 
1.1.1.13! root     1030:     /* We have 8 bits per pixel in spixstate, two for every sprite pair.  The
        !          1031:        low order bit records whether the attach bit was set for this pair.  */
        !          1032: 
        !          1033:     if (ctl & (num << 7) & 0x80) {
        !          1034:        uae_u32 state = 0x01010101 << (num - 1);
        !          1035:        uae_u32 *stbuf = spixstate.words + (word_offs >> 2);
        !          1036:        uae_u8 *stb1 = spixstate.bytes + word_offs;     
        !          1037:        stb1[0] |= state;
        !          1038:        stb1[1] |= state;
        !          1039:        stb1[2] |= state;
        !          1040:        stb1[3] |= state;
        !          1041:        stb1[4] |= state;
        !          1042:        stb1[5] |= state;
        !          1043:        stb1[6] |= state;
        !          1044:        stb1[7] |= state;
        !          1045:        stb1[8] |= state;
        !          1046:        stb1[9] |= state;
        !          1047:        stb1[10] |= state;
        !          1048:        stb1[11] |= state;
        !          1049:        stb1[12] |= state;
        !          1050:        stb1[13] |= state;
        !          1051:        stb1[14] |= state;
        !          1052:        stb1[15] |= state;
        !          1053:        e->has_attached = 1;
1.1.1.3   root     1054:     }
                   1055: }
1.1.1.2   root     1056: 
1.1.1.4   root     1057: static void decide_sprites (int hpos)
1.1.1.3   root     1058: {
1.1.1.7   root     1059:     int nrs[MAX_SPRITES], posns[MAX_SPRITES];
                   1060:     int count, i;
1.1.1.13! root     1061:     int point = coord_hw_to_window_x (hpos * 2);
1.1.1.2   root     1062: 
1.1.1.4   root     1063:     if (framecnt != 0 || hpos < 0x14 || nr_armed == 0 || point == last_sprite_point)
1.1.1.2   root     1064:        return;
                   1065: 
1.1.1.4   root     1066:     decide_diw (hpos);
                   1067:     decide_line (hpos);
1.1.1.3   root     1068: 
1.1.1.13! root     1069: #if 0
        !          1070:     /* This tries to detect whether the line is border, but that doesn't work, it's too early.  */
        !          1071:     if (thisline_decision.plfleft == -1)
1.1.1.2   root     1072:        return;
1.1.1.13! root     1073: #endif
1.1.1.3   root     1074:     count = 0;
                   1075:     for (i = 0; i < 8; i++) {
1.1.1.10  root     1076:        int sprxp = spr[i].xpos;
1.1.1.3   root     1077:        int j, bestp;
1.1.1.2   root     1078: 
1.1.1.13! root     1079:        if (! spr[i].armed || sprxp < 0 || sprxp <= last_sprite_point || sprxp > point)
1.1.1.3   root     1080:            continue;
                   1081:        if ((thisline_decision.diwfirstword >= 0 && sprxp + sprite_width < thisline_decision.diwfirstword)
                   1082:            || (thisline_decision.diwlastword >= 0 && sprxp > thisline_decision.diwlastword))
                   1083:            continue;
1.1.1.2   root     1084: 
1.1.1.13! root     1085:        /* Sort the sprites in order of ascending X position before recording them.  */
1.1.1.3   root     1086:        for (bestp = 0; bestp < count; bestp++) {
                   1087:            if (posns[bestp] > sprxp)
                   1088:                break;
                   1089:            if (posns[bestp] == sprxp && nrs[bestp] < i)
                   1090:                break;
                   1091:        }
                   1092:        for (j = count; j > bestp; j--) {
                   1093:            posns[j] = posns[j-1];
                   1094:            nrs[j] = nrs[j-1];
                   1095:        }
                   1096:        posns[j] = sprxp;
                   1097:        nrs[j] = i;
                   1098:        count++;
                   1099:     }
1.1.1.13! root     1100:     for (i = 0; i < count; i++) {
        !          1101:        int nr = nrs[i];    
        !          1102:        unsigned int data = sprdata[nr];
        !          1103:        unsigned int datb = sprdatb[nr];
        !          1104:        uae_u32 datab = ((sprtaba[data & 0xFF] << 16) | sprtaba[data >> 8]
        !          1105:                         | (sprtabb[datb & 0xFF] << 16) | sprtabb[datb >> 8]);
        !          1106:        record_sprite (next_lineno, nr, spr[nr].xpos, datab, sprctl[nr]);
        !          1107:     }
1.1.1.3   root     1108:     last_sprite_point = point;
1.1.1.2   root     1109: }
                   1110: 
1.1.1.13! root     1111: STATIC_INLINE int sprites_differ (struct draw_info *dip, struct draw_info *dip_old)
        !          1112: {
        !          1113:     struct sprite_entry *this_first = curr_sprite_entries + dip->first_sprite_entry;
        !          1114:     struct sprite_entry *this_last = curr_sprite_entries + dip->last_sprite_entry;
        !          1115:     struct sprite_entry *prev_first = prev_sprite_entries + dip_old->first_sprite_entry;
        !          1116:     int npixels;
        !          1117:     int i;
        !          1118: 
        !          1119:     if (dip->nr_sprites != dip_old->nr_sprites)
        !          1120:        return 1;
        !          1121:     
        !          1122:     if (dip->nr_sprites == 0)
        !          1123:        return 0;
        !          1124: 
        !          1125:     for (i = 0; i < dip->nr_sprites; i++)
        !          1126:        if (this_first[i].pos != prev_first[i].pos
        !          1127:            || this_first[i].max != prev_first[i].max
        !          1128:            || this_first[i].has_attached != prev_first[i].has_attached)
        !          1129:            return 1;
        !          1130: 
        !          1131:     npixels = this_last->first_pixel + (this_last->max - this_last->pos) - this_first->first_pixel;
        !          1132:     if (memcmp (spixels + this_first->first_pixel, spixels + prev_first->first_pixel,
        !          1133:                npixels * sizeof (uae_u16)) != 0)
        !          1134:        return 1;
        !          1135:     if (memcmp (spixstate.bytes + this_first->first_pixel, spixstate.bytes + prev_first->first_pixel, npixels) != 0)
        !          1136:        return 1;
        !          1137:     return 0;
        !          1138: }
        !          1139: 
        !          1140: STATIC_INLINE int color_changes_differ (struct draw_info *dip, struct draw_info *dip_old)
        !          1141: {
        !          1142:     if (dip->nr_color_changes != dip_old->nr_color_changes)
        !          1143:        return 1;
        !          1144:     
        !          1145:     if (dip->nr_color_changes == 0)
        !          1146:        return 0;
        !          1147:     if (memcmp (curr_color_changes + dip->first_color_change,
        !          1148:                prev_color_changes + dip_old->first_color_change,
        !          1149:                dip->nr_color_changes * sizeof *curr_color_changes) != 0)
        !          1150:        return 1;
        !          1151:     return 0;
        !          1152: }
        !          1153: 
1.1.1.3   root     1154: /* End of a horizontal scan line. Finish off all decisions that were not
                   1155:  * made yet. */
1.1.1.2   root     1156: static void finish_decisions (void)
                   1157: {
                   1158:     struct draw_info *dip;
                   1159:     struct draw_info *dip_old;
                   1160:     struct decision *dp;
                   1161:     int changed;
1.1.1.4   root     1162:     int hpos = current_hpos ();
1.1.1.2   root     1163: 
                   1164:     if (framecnt != 0)
                   1165:        return;
                   1166: 
1.1.1.4   root     1167:     decide_diw (hpos);
1.1.1.13! root     1168:     decide_line (hpos);
        !          1169:     decide_fetch (hpos);
        !          1170: 
        !          1171:     if (thisline_decision.plfleft != -1 && thisline_decision.plflinelen == -1) {
        !          1172:        if (fetch_state != fetch_not_started)
        !          1173:            abort ();
        !          1174:        thisline_decision.plfright = thisline_decision.plfleft;
        !          1175:        thisline_decision.plflinelen = 0;
        !          1176:        thisline_decision.bplres = RES_LORES;
        !          1177:     }
1.1.1.3   root     1178: 
                   1179:     /* Large DIWSTOP values can cause the stop position never to be
                   1180:      * reached, so the state machine always stays in the same state and
                   1181:      * there's a more-or-less full-screen DIW. */
1.1.1.13! root     1182:     if (hdiwstate == DIW_waiting_stop || thisline_decision.diwlastword > max_diwlastword)
1.1.1.3   root     1183:        thisline_decision.diwlastword = max_diwlastword;
                   1184: 
1.1.1.13! root     1185:     if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
        !          1186:        MARK_LINE_CHANGED;
        !          1187:     if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword)
        !          1188:        MARK_LINE_CHANGED;
1.1.1.2   root     1189: 
                   1190:     dip = curr_drawinfo + next_lineno;
                   1191:     dip_old = prev_drawinfo + next_lineno;
                   1192:     dp = line_decisions + next_lineno;
1.1.1.5   root     1193:     changed = thisline_changed;
1.1.1.2   root     1194: 
1.1.1.13! root     1195:     if (thisline_decision.plfleft != -1) {
        !          1196:        record_diw_line (thisline_decision.diwfirstword, thisline_decision.diwlastword);
1.1.1.2   root     1197: 
1.1.1.4   root     1198:        decide_sprites (hpos);
1.1.1.2   root     1199:     }
                   1200: 
1.1.1.13! root     1201:     dip->last_sprite_entry = next_sprite_entry;
1.1.1.2   root     1202:     dip->last_color_change = next_color_change;
1.1.1.3   root     1203: 
                   1204:     if (thisline_decision.ctable == -1) {
1.1.1.13! root     1205:        if (thisline_decision.plfleft == -1)
1.1.1.3   root     1206:            remember_ctable_for_border ();
1.1.1.13! root     1207:        else
        !          1208:            remember_ctable ();
1.1.1.3   root     1209:     }
1.1.1.2   root     1210: 
                   1211:     dip->nr_color_changes = next_color_change - dip->first_color_change;
1.1.1.13! root     1212:     dip->nr_sprites = next_sprite_entry - dip->first_sprite_entry;
1.1.1.2   root     1213: 
1.1.1.13! root     1214:     if (thisline_decision.plfleft != line_decisions[next_lineno].plfleft)
1.1.1.2   root     1215:        changed = 1;
1.1.1.13! root     1216:     if (! changed && color_changes_differ (dip, dip_old))
1.1.1.2   root     1217:        changed = 1;
1.1.1.13! root     1218:     if (!changed && thisline_decision.plfleft != -1 && sprites_differ (dip, dip_old))
1.1.1.10  root     1219:        changed = 1;
1.1.1.2   root     1220: 
                   1221:     if (changed) {
1.1.1.5   root     1222:        thisline_changed = 1;
1.1.1.2   root     1223:        *dp = thisline_decision;
                   1224:     } else
                   1225:        /* The only one that may differ: */
                   1226:        dp->ctable = thisline_decision.ctable;
                   1227: }
                   1228: 
1.1.1.3   root     1229: /* Set the state of all decisions to "undecided" for a new scanline. */
1.1.1.2   root     1230: static void reset_decisions (void)
                   1231: {
                   1232:     if (framecnt != 0)
                   1233:        return;
1.1.1.13! root     1234: 
        !          1235:     thisline_decision.nr_planes = 0;
        !          1236: 
1.1.1.2   root     1237:     decided_bpl1mod = bpl1mod;
                   1238:     decided_bpl2mod = bpl2mod;
                   1239: 
1.1.1.10  root     1240:     thisline_decision.plfleft = -1;
1.1.1.13! root     1241:     thisline_decision.plflinelen = -1;
1.1.1.10  root     1242: 
1.1.1.7   root     1243:     /* decided_res shouldn't be touched before it's initialized by decide_line(). */
1.1.1.2   root     1244:     thisline_decision.diwfirstword = -1;
                   1245:     thisline_decision.diwlastword = -2;
1.1.1.3   root     1246:     if (hdiwstate == DIW_waiting_stop) {
1.1.1.13! root     1247:        thisline_decision.diwfirstword = 0;
1.1.1.3   root     1248:        if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
1.1.1.5   root     1249:            MARK_LINE_CHANGED;
1.1.1.3   root     1250:     }
1.1.1.2   root     1251:     thisline_decision.ctable = -1;
                   1252: 
1.1.1.5   root     1253:     thisline_changed = 0;
1.1.1.2   root     1254:     curr_drawinfo[next_lineno].first_color_change = next_color_change;
1.1.1.13! root     1255:     curr_drawinfo[next_lineno].first_sprite_entry = next_sprite_entry;
        !          1256:     next_sprite_forced = 1;
1.1.1.2   root     1257: 
1.1.1.3   root     1258:     /* memset(sprite_last_drawn_at, 0, sizeof sprite_last_drawn_at); */
                   1259:     last_sprite_point = 0;
1.1.1.2   root     1260:     modulos_added = 0;
                   1261:     plane_decided = 0;
                   1262:     color_decided = 0;
1.1.1.13! root     1263:     fetch_state = fetch_not_started;
        !          1264:     passed_plfstop = 0;
        !          1265: 
        !          1266:     memset (todisplay, 0, sizeof todisplay);
        !          1267:     memset (fetched, 0, sizeof fetched);
        !          1268:     memset (outword, 0, sizeof outword);
1.1.1.9   root     1269: 
1.1.1.13! root     1270:     last_decide_line_hpos = -1;
1.1.1.9   root     1271:     last_diw_pix_hpos = -1;
                   1272:     last_ddf_pix_hpos = -1;
1.1.1.13! root     1273:     last_sprite_hpos = -1;
        !          1274:     last_fetch_hpos = -1;
1.1.1.2   root     1275: }
                   1276: 
1.1.1.7   root     1277: /* set PAL or NTSC timing variables */
                   1278: 
                   1279: static void init_hz (void)
                   1280: {
                   1281:     int isntsc;
                   1282: 
                   1283:     beamcon0 = new_beamcon0;
                   1284: 
                   1285:     isntsc = beamcon0 & 0x20 ? 0 : 1;
                   1286:     if (!isntsc) {
                   1287:        maxvpos = MAXVPOS_PAL;
                   1288:        maxhpos = MAXHPOS_PAL;
                   1289:        minfirstline = MINFIRSTLINE_PAL;
                   1290:        vblank_endline = VBLANK_ENDLINE_PAL;
                   1291:        vblank_hz = VBLANK_HZ_PAL;
                   1292:     } else {
                   1293:        maxvpos = MAXVPOS_NTSC;
                   1294:        maxhpos = MAXHPOS_NTSC;
                   1295:        minfirstline = MINFIRSTLINE_NTSC;
                   1296:        vblank_endline = VBLANK_ENDLINE_NTSC;
                   1297:        vblank_hz = VBLANK_HZ_NTSC;
                   1298:     }
                   1299:     vsynctime = syncbase / vblank_hz;
                   1300: 
                   1301:     write_log ("Using %s timing\n", isntsc ? "NTSC" : "PAL");
                   1302: }
                   1303: 
1.1.1.13! root     1304: #if 0
1.1.1.11  root     1305: void expand_fetchmodes (int fmode, int bplcon0)
1.1.1.2   root     1306: {
1.1.1.11  root     1307:     int res;
                   1308: 
                   1309:     if (bplcon0 & 0x8000)
                   1310:        res = 1;
                   1311:     else if (bplcon0 & 0x0040)
                   1312:        res = 2;
                   1313:     else
                   1314:        res = 0;
                   1315:     switch (fmode & 3) {
1.1.1.13! root     1316:     case 3:
        !          1317:       fetchmode = 2;
        !          1318:       switch (res) {
        !          1319:       case 2: prefetch = 1<<3; fetchsize = 1<<3; fetchstart_shift = 3; break;
        !          1320:       case 1: prefetch = 1<<3; fetchsize = 1<<4; fetchstart_shift = 4; break;
        !          1321:       case 0: prefetch = 1<<3; fetchsize = 1<<5; fetchstart_shift = 5; break;
        !          1322:       }
        !          1323:       break;
        !          1324:     case 2:
        !          1325:     case 1:
        !          1326:       fetchmode = 1;
        !          1327:       switch (res) {
        !          1328:       case 2: prefetch = 1<<2; fetchsize = 1<<3; fetchstart_shift = 2; break;
        !          1329:       case 1: prefetch = 1<<3; fetchsize = 1<<3; fetchstart_shift = 3; break;
        !          1330:       case 0: prefetch = 1<<3; fetchsize = 1<<4; fetchstart_shift = 4; break;
        !          1331:       }
        !          1332:       break;
        !          1333:     case 0:
        !          1334:       fetchmode = 0;
        !          1335:       switch (res) {
        !          1336:       case 2: prefetch = 1<<1; fetchsize = 1<<3; fetchstart_shift = 1; break;
        !          1337:       case 1: prefetch = 1<<2; fetchsize = 1<<3; fetchstart_shift = 2; break;
        !          1338:       case 0: prefetch = 1<<3; fetchsize = 1<<3; fetchstart_shift = 3; break;
        !          1339:       }
        !          1340:       break;
        !          1341:     }
1.1.1.11  root     1342:     fetchstart = 1 << fetchstart_shift;
                   1343: }
1.1.1.13! root     1344: #endif
1.1.1.7   root     1345: 
1.1.1.11  root     1346: static void calcdiw (void)
                   1347: {
                   1348:     int fetch;
1.1.1.4   root     1349:     int hstrt = diwstrt & 0xFF;
                   1350:     int hstop = diwstop & 0xFF;
                   1351:     int vstrt = diwstrt >> 8;
                   1352:     int vstop = diwstop >> 8;
                   1353: 
                   1354:     if (diwhigh_written) {
                   1355:        hstrt |= ((diwhigh >> 5) & 1) << 8;
                   1356:        hstop |= ((diwhigh >> 13) & 1) << 8;
                   1357:        vstrt |= (diwhigh & 7) << 8;
                   1358:        vstop |= ((diwhigh >> 8) & 7) << 8;
                   1359:     } else {
                   1360:        hstop += 0x100;
                   1361:        if ((vstop & 0x80) == 0)
                   1362:            vstop |= 0x100;
                   1363:     }
                   1364: 
1.1.1.13! root     1365:     diwfirstword = coord_diw_to_window_x (hstrt);
        !          1366:     diwlastword = coord_diw_to_window_x (hstop);
1.1.1.2   root     1367:     if (diwfirstword < 0)
                   1368:        diwfirstword = 0;
1.1.1.3   root     1369: 
1.1.1.4   root     1370:     plffirstline = vstrt;
                   1371:     plflastline = vstop;
                   1372: 
1.1       root     1373: #if 0
                   1374:     /* This happens far too often. */
                   1375:     if (plffirstline < minfirstline) {
                   1376:        fprintf(stderr, "Warning: Playfield begins before line %d!\n", minfirstline);
                   1377:        plffirstline = minfirstline;
                   1378:     }
                   1379: #endif
1.1.1.4   root     1380: 
1.1       root     1381: #if 0 /* Turrican does this */
                   1382:     if (plflastline > 313) {
1.1.1.4   root     1383:        fprintf (stderr, "Warning: Playfield out of range!\n");
1.1       root     1384:        plflastline = 313;
                   1385:     }
                   1386: #endif
1.1.1.2   root     1387:     plfstrt = ddfstrt;
                   1388:     plfstop = ddfstop;
1.1.1.13! root     1389:     if (plfstrt < 0x18)
        !          1390:        plfstrt = 0x18;
1.1       root     1391: }
                   1392: 
1.1.1.4   root     1393: /* Mousehack stuff */
1.1.1.2   root     1394: 
1.1.1.4   root     1395: #define defstepx (1<<16)
                   1396: #define defstepy (1<<16)
                   1397: #define defxoffs 0
                   1398: #define defyoffs 0
1.1.1.3   root     1399: 
1.1.1.4   root     1400: static const int docal = 60, xcaloff = 40, ycaloff = 20;
                   1401: static const int calweight = 3;
                   1402: static int lastsampledmx, lastsampledmy;
                   1403: static int lastspr0x,lastspr0y,lastdiffx,lastdiffy,spr0pos,spr0ctl;
                   1404: static int mstepx,mstepy,xoffs=defxoffs,yoffs=defyoffs;
                   1405: static int sprvbfl;
1.1.1.2   root     1406: 
1.1.1.4   root     1407: int lastmx, lastmy;
                   1408: int newmousecounters;
                   1409: int ievent_alive = 0;
1.1       root     1410: 
1.1.1.4   root     1411: static enum { unknown_mouse, normal_mouse, dont_care_mouse, follow_mouse } mousestate;
1.1       root     1412: 
1.1.1.4   root     1413: static void mousehack_setdontcare (void)
1.1       root     1414: {
1.1.1.4   root     1415:     if (mousestate == dont_care_mouse)
1.1.1.2   root     1416:        return;
                   1417: 
1.1.1.3   root     1418:     write_log ("Don't care mouse mode set\n");
                   1419:     mousestate = dont_care_mouse;
                   1420:     lastspr0x = lastmx; lastspr0y = lastmy;
                   1421:     mstepx = defstepx; mstepy = defstepy;
                   1422: }
                   1423: 
1.1.1.4   root     1424: static void mousehack_setfollow (void)
1.1.1.3   root     1425: {
1.1.1.4   root     1426:     if (mousestate == follow_mouse)
                   1427:        return;
                   1428: 
1.1.1.3   root     1429:     write_log ("Follow sprite mode set\n");
                   1430:     mousestate = follow_mouse;
                   1431:     lastdiffx = lastdiffy = 0;
                   1432:     sprvbfl = 0;
1.1.1.4   root     1433:     spr0ctl = spr0pos = 0;
1.1.1.3   root     1434:     mstepx = defstepx; mstepy = defstepy;
                   1435: }
                   1436: 
1.1.1.7   root     1437: static uae_u32 mousehack_helper (void)
1.1.1.3   root     1438: {
                   1439:     int mousexpos, mouseypos;
                   1440: 
                   1441: #ifdef PICASSO96
                   1442:     if (picasso_on) {
1.1.1.4   root     1443:        mousexpos = lastmx - picasso96_state.XOffset;
                   1444:        mouseypos = lastmy - picasso96_state.YOffset;
1.1.1.3   root     1445:     } else
                   1446: #endif
                   1447:     {
                   1448:        if (lastmy >= gfxvidinfo.height)
1.1.1.4   root     1449:            lastmy = gfxvidinfo.height - 1;
                   1450:        mouseypos = coord_native_to_amiga_y (lastmy) << 1;
                   1451:        mousexpos = coord_native_to_amiga_x (lastmx);
1.1.1.3   root     1452:     }
                   1453: 
                   1454:     switch (m68k_dreg (regs, 0)) {
                   1455:      case 0:
                   1456:        return ievent_alive ? -1 : needmousehack ();
                   1457:      case 1:
                   1458:        ievent_alive = 10;
                   1459:        return mousexpos;
                   1460:      case 2:
                   1461:        return mouseypos;
                   1462:     }
                   1463:     return 0;
                   1464: }
                   1465: 
1.1.1.4   root     1466: void togglemouse (void)
1.1.1.3   root     1467: {
1.1.1.4   root     1468:     switch (mousestate) {
                   1469:      case dont_care_mouse: mousehack_setfollow (); break;
                   1470:      case follow_mouse: mousehack_setdontcare (); break;
1.1.1.3   root     1471:      default: break; /* Nnnnnghh! */
                   1472:     }
                   1473: }
                   1474: 
1.1.1.8   root     1475: STATIC_INLINE int adjust (int val)
1.1.1.3   root     1476: {
1.1.1.4   root     1477:     if (val > 127)
1.1.1.3   root     1478:        return 127;
1.1.1.4   root     1479:     else if (val < -127)
1.1.1.3   root     1480:        return -127;
                   1481:     return val;
                   1482: }
                   1483: 
1.1.1.4   root     1484: static void do_mouse_hack (void)
1.1.1.3   root     1485: {
                   1486:     int spr0x = ((spr0pos & 0xff) << 2) | ((spr0ctl & 1) << 1);
                   1487:     int spr0y = ((spr0pos >> 8) | ((spr0ctl & 4) << 6)) << 1;
                   1488:     int diffx, diffy;
                   1489: 
                   1490:     if (ievent_alive > 0) {
                   1491:        mouse_x = mouse_y = 0;
                   1492:        return;
                   1493:     }
                   1494:     switch (mousestate) {
1.1.1.11  root     1495:     case normal_mouse:
1.1.1.3   root     1496:        diffx = lastmx - lastsampledmx;
                   1497:        diffy = lastmy - lastsampledmy;
                   1498:        if (!newmousecounters) {
                   1499:            if (diffx > 127) diffx = 127;
                   1500:            if (diffx < -127) diffx = -127;
                   1501:            mouse_x += diffx;
                   1502:            if (diffy > 127) diffy = 127;
                   1503:            if (diffy < -127) diffy = -127;
                   1504:            mouse_y += diffy;
                   1505:        }
                   1506:        lastsampledmx += diffx; lastsampledmy += diffy;
                   1507:        break;
                   1508: 
1.1.1.11  root     1509:     case dont_care_mouse:
1.1.1.4   root     1510:        diffx = adjust (((lastmx - lastspr0x) * mstepx) >> 16);
                   1511:        diffy = adjust (((lastmy - lastspr0y) * mstepy) >> 16);
                   1512:        lastspr0x = lastmx; lastspr0y = lastmy;
                   1513:        mouse_x += diffx; mouse_y += diffy;
1.1.1.3   root     1514:        break;
                   1515: 
1.1.1.11  root     1516:     case follow_mouse:
1.1.1.4   root     1517:        if (sprvbfl && sprvbfl-- > 1) {
1.1.1.3   root     1518:            int mousexpos, mouseypos;
                   1519: 
1.1.1.4   root     1520:            if ((lastdiffx > docal || lastdiffx < -docal)
                   1521:                && lastspr0x != spr0x
                   1522:                && spr0x > plfstrt*4 + 34 + xcaloff
                   1523:                && spr0x < plfstop*4 - xcaloff)
1.1.1.3   root     1524:            {
                   1525:                int val = (lastdiffx << 16) / (spr0x - lastspr0x);
1.1.1.4   root     1526:                if (val >= 0x8000)
                   1527:                    mstepx = (mstepx * (calweight - 1) + val) / calweight;
1.1.1.3   root     1528:            }
1.1.1.4   root     1529:            if ((lastdiffy > docal || lastdiffy < -docal)
                   1530:                && lastspr0y != spr0y
                   1531:                && spr0y > plffirstline + ycaloff
                   1532:                && spr0y < plflastline - ycaloff)
1.1.1.3   root     1533:            {
1.1.1.4   root     1534:                int val = (lastdiffy << 16) / (spr0y - lastspr0y);
                   1535:                if (val >= 0x8000)
                   1536:                    mstepy = (mstepy * (calweight - 1) + val) / calweight;
1.1.1.3   root     1537:            }
                   1538:            if (lastmy >= gfxvidinfo.height)
                   1539:                lastmy = gfxvidinfo.height-1;
1.1.1.4   root     1540:            mouseypos = coord_native_to_amiga_y (lastmy) << 1;
                   1541:            mousexpos = coord_native_to_amiga_x (lastmx);
1.1.1.3   root     1542:            diffx = adjust ((((mousexpos + xoffs - spr0x) & ~1) * mstepx) >> 16);
                   1543:            diffy = adjust ((((mouseypos + yoffs - spr0y) & ~1) * mstepy) >> 16);
1.1.1.4   root     1544:            lastspr0x = spr0x; lastspr0y = spr0y;
                   1545:            lastdiffx = diffx; lastdiffy = diffy;
                   1546:            mouse_x += diffx; mouse_y += diffy;
1.1.1.3   root     1547:        }
                   1548:        break;
1.1.1.4   root     1549:        
1.1.1.11  root     1550:     default:
1.1.1.4   root     1551:        abort ();
1.1.1.3   root     1552:     }
                   1553: }
                   1554: 
1.1.1.7   root     1555: static int timehack_alive = 0;
                   1556: 
                   1557: static uae_u32 timehack_helper (void)
                   1558: {
                   1559: #ifdef HAVE_GETTIMEOFDAY
                   1560:     struct timeval tv;
                   1561:     if (m68k_dreg (regs, 0) == 0)
                   1562:        return timehack_alive;
                   1563: 
                   1564:     timehack_alive = 10;
                   1565: 
                   1566:     gettimeofday (&tv, NULL);
                   1567:     put_long (m68k_areg (regs, 0), tv.tv_sec - (((365 * 8 + 2) * 24 - 2) * 60 * 60));
                   1568:     put_long (m68k_areg (regs, 0) + 4, tv.tv_usec);
                   1569:     return 0;
                   1570: #else
                   1571:     return 2;
                   1572: #endif
                   1573: }
                   1574: 
1.1.1.3   root     1575:  /*
1.1       root     1576:   * register functions
                   1577:   */
1.1.1.8   root     1578: STATIC_INLINE uae_u16 DENISEID (void)
1.1.1.7   root     1579: {
                   1580:     if (currprefs.chipset_mask & CSMASK_AGA)
                   1581:        return 0xF8;
                   1582:     if (currprefs.chipset_mask & CSMASK_ECS_DENISE)
                   1583:        return 0xFC;
                   1584:     return 0xFFFF;
                   1585: }
1.1.1.8   root     1586: STATIC_INLINE uae_u16 DMACONR (void)
1.1       root     1587: {
                   1588:     return (dmacon | (bltstate==BLT_done ? 0 : 0x4000)
                   1589:            | (blt_info.blitzero ? 0x2000 : 0));
                   1590: }
1.1.1.8   root     1591: STATIC_INLINE uae_u16 INTENAR (void)
1.1.1.4   root     1592: {
                   1593:     return intena;
                   1594: }
                   1595: uae_u16 INTREQR (void)
1.1       root     1596: {
1.1.1.9   root     1597:     return intreq /* | (currprefs.use_serial ? 0x0001 : 0) */;
1.1       root     1598: }
1.1.1.8   root     1599: STATIC_INLINE uae_u16 ADKCONR (void)
1.1.1.4   root     1600: {
                   1601:     return adkcon;
                   1602: }
1.1.1.8   root     1603: STATIC_INLINE uae_u16 VPOSR (void)
1.1       root     1604: {
1.1.1.7   root     1605:     unsigned int csbit = ntscmode ? 0x1000 : 0;
                   1606:     csbit |= (currprefs.chipset_mask & CSMASK_AGA) ? 0x2300 : 0;
                   1607:     csbit |= (currprefs.chipset_mask & CSMASK_ECS_AGNUS) ? 0x2000 : 0;
                   1608:     return (vpos >> 8) | lof | csbit;
1.1       root     1609: }
1.1.1.4   root     1610: static void VPOSW (uae_u16 v)
1.1.1.2   root     1611: {
                   1612:     if (lof != (v & 0x8000))
                   1613:        lof_changed = 1;
                   1614:     lof = v & 0x8000;
1.1.1.3   root     1615:     /*
                   1616:      * This register is much more fun on a real Amiga. You can program
                   1617:      * refresh rates with it ;) But I won't emulate this...
                   1618:      */
1.1.1.2   root     1619: }
1.1       root     1620: 
1.1.1.8   root     1621: STATIC_INLINE uae_u16 VHPOSR (void)
1.1.1.4   root     1622: {
1.1.1.13! root     1623:     return (vpos << 8) | current_hpos ();
1.1.1.4   root     1624: }
                   1625: 
1.1.1.8   root     1626: STATIC_INLINE void COP1LCH (uae_u16 v) { cop1lc = (cop1lc & 0xffff) | ((uae_u32)v << 16); }
                   1627: STATIC_INLINE void COP1LCL (uae_u16 v) { cop1lc = (cop1lc & ~0xffff) | (v & 0xfffe); }
                   1628: STATIC_INLINE void COP2LCH (uae_u16 v) { cop2lc = (cop2lc & 0xffff) | ((uae_u32)v << 16); }
                   1629: STATIC_INLINE void COP2LCL (uae_u16 v) { cop2lc = (cop2lc & ~0xffff) | (v & 0xfffe); }
1.1.1.4   root     1630: 
1.1.1.9   root     1631: static void start_copper (void)
1.1.1.4   root     1632: {
1.1.1.10  root     1633:     int was_active = eventtab[ev_copper].active;
                   1634:     eventtab[ev_copper].active = 0;
                   1635:     if (was_active)
                   1636:        events_schedule ();
                   1637: 
1.1.1.4   root     1638:     cop_state.ignore_next = 0;
                   1639:     cop_state.state = COP_read1;
                   1640:     cop_state.vpos = vpos;
                   1641:     cop_state.hpos = current_hpos () & ~1;
1.1.1.9   root     1642: 
1.1.1.10  root     1643:     if (dmaen (DMA_COPPER)) {
                   1644:        copper_enabled_thisline = 1;
1.1.1.13! root     1645:        set_special (SPCFLAG_COPPER);
1.1.1.10  root     1646:     }
1.1.1.9   root     1647: }
                   1648: 
                   1649: static void COPJMP1 (uae_u16 a)
                   1650: {
                   1651:     cop_state.ip = cop1lc;
                   1652:     start_copper ();
1.1.1.4   root     1653: }
                   1654: 
                   1655: static void COPJMP2 (uae_u16 a)
                   1656: {
                   1657:     cop_state.ip = cop2lc;
1.1.1.9   root     1658:     start_copper ();
1.1.1.4   root     1659: }
                   1660: 
1.1.1.8   root     1661: STATIC_INLINE void COPCON (uae_u16 a)
1.1.1.4   root     1662: {
                   1663:     copcon = a;
1.1       root     1664: }
1.1.1.4   root     1665: 
1.1.1.13! root     1666: static void DMACON (int hpos, uae_u16 v)
1.1       root     1667: {
                   1668:     int i, need_resched = 0;
                   1669: 
1.1.1.3   root     1670:     uae_u16 oldcon = dmacon;
                   1671: 
1.1.1.13! root     1672:     decide_line (hpos);
        !          1673:     decide_fetch (hpos);
        !          1674: 
        !          1675:     setclr (&dmacon, v);
        !          1676:     dmacon &= 0x1FFF;
1.1.1.3   root     1677: 
                   1678:     /* FIXME? Maybe we need to think a bit more about the master DMA enable
1.1       root     1679:      * bit in these cases. */
1.1.1.10  root     1680:     if ((dmacon & DMA_COPPER) != (oldcon & DMA_COPPER)) {
                   1681:        if (eventtab[ev_copper].active)
                   1682:            need_resched = 1;
                   1683:        eventtab[ev_copper].active = 0;
                   1684:     }
1.1.1.3   root     1685:     if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) {
1.1.1.4   root     1686:        cop_state.ip = cop1lc;
                   1687:        cop_state.ignore_next = 0;
                   1688:        cop_state.state = COP_read1;
                   1689:        cop_state.vpos = vpos;
1.1.1.13! root     1690:        cop_state.hpos = hpos & ~1;
1.1.1.10  root     1691:        copper_enabled_thisline = 1;
1.1.1.13! root     1692:        set_special (SPCFLAG_COPPER);
1.1       root     1693:     }
1.1.1.9   root     1694:     if (! (dmacon & DMA_COPPER)) {
1.1.1.10  root     1695:        copper_enabled_thisline = 0;
1.1.1.13! root     1696:        unset_special (SPCFLAG_COPPER);
1.1.1.9   root     1697:        cop_state.state = COP_stop;
                   1698:     }
                   1699: 
1.1       root     1700:     if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done) {
                   1701:        static int count = 0;
                   1702:        if (!count) {
                   1703:            count = 1;
1.1.1.3   root     1704:            write_log ("warning: program is doing blitpri hacks.\n");
1.1       root     1705:        }
1.1.1.13! root     1706:        set_special (SPCFLAG_BLTNASTY);
1.1       root     1707:     }
1.1.1.10  root     1708:     if ((dmacon & (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER)) != (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER))
1.1.1.13! root     1709:        unset_special (SPCFLAG_BLTNASTY);
1.1.1.4   root     1710: 
                   1711:     update_audio ();
                   1712: 
1.1       root     1713:     for (i = 0; i < 4; i++) {
                   1714:        struct audio_channel_data *cdp = audio_channel + i;
1.1.1.3   root     1715: 
1.1       root     1716:        cdp->dmaen = (dmacon & 0x200) && (dmacon & (1<<i));
                   1717:        if (cdp->dmaen) {
                   1718:            if (cdp->state == 0) {
                   1719:                cdp->state = 1;
                   1720:                cdp->pt = cdp->lc;
                   1721:                cdp->wper = cdp->per;
                   1722:                cdp->wlen = cdp->len;
                   1723:                cdp->data_written = 2;
1.1.1.4   root     1724:                cdp->evtime = eventtab[ev_hsync].evtime - cycles;
1.1       root     1725:            }
                   1726:        } else {
                   1727:            if (cdp->state == 1 || cdp->state == 5) {
                   1728:                cdp->state = 0;
1.1.1.7   root     1729:                cdp->last_sample = 0;
1.1       root     1730:                cdp->current_sample = 0;
                   1731:            }
                   1732:        }
                   1733:     }
1.1.1.4   root     1734: 
1.1       root     1735:     if (need_resched)
                   1736:        events_schedule();
                   1737: }
1.1.1.2   root     1738: 
1.1.1.3   root     1739: /*static int trace_intena = 0;*/
1.1.1.2   root     1740: 
1.1.1.8   root     1741: STATIC_INLINE void INTENA (uae_u16 v)
1.1.1.2   root     1742: {
1.1.1.3   root     1743: /*    if (trace_intena)
1.1.1.4   root     1744:        fprintf (stderr, "INTENA: %04x\n", v);*/
1.1.1.13! root     1745:     setclr (&intena,v);
        !          1746:     set_special (SPCFLAG_INT);
1.1.1.2   root     1747: }
1.1.1.3   root     1748: void INTREQ (uae_u16 v)
1.1       root     1749: {
1.1.1.3   root     1750:     setclr(&intreq,v);
1.1.1.13! root     1751:     set_special (SPCFLAG_INT);
        !          1752:     if ((v & 0x8800) == 0x0800)
1.1.1.4   root     1753:        serdat &= 0xbfff;
1.1.1.3   root     1754: }
1.1       root     1755: 
1.1.1.3   root     1756: static void ADKCON (uae_u16 v)
                   1757: {
                   1758:     unsigned long t;
1.1.1.4   root     1759: 
                   1760:     update_audio ();
                   1761: 
1.1.1.3   root     1762:     setclr (&adkcon,v);
                   1763:     t = adkcon | (adkcon >> 4);
                   1764:     audio_channel[0].adk_mask = (((t >> 0) & 1) - 1);
                   1765:     audio_channel[1].adk_mask = (((t >> 1) & 1) - 1);
                   1766:     audio_channel[2].adk_mask = (((t >> 2) & 1) - 1);
                   1767:     audio_channel[3].adk_mask = (((t >> 3) & 1) - 1);
                   1768: }
1.1       root     1769: 
1.1.1.7   root     1770: static void BEAMCON0 (uae_u16 v)
                   1771: {
                   1772:     new_beamcon0 = v & 0x20;
                   1773: }
                   1774: 
1.1.1.4   root     1775: static void BPLPTH (int hpos, uae_u16 v, int num)
1.1.1.3   root     1776: {
1.1.1.4   root     1777:     decide_line (hpos);
1.1.1.13! root     1778:     decide_fetch (hpos);
1.1.1.4   root     1779:     bplpt[num] = (bplpt[num] & 0xffff) | ((uae_u32)v << 16);
1.1.1.3   root     1780: }
1.1.1.4   root     1781: static void BPLPTL (int hpos, uae_u16 v, int num)
1.1.1.3   root     1782: {
1.1.1.4   root     1783:     decide_line (hpos);
1.1.1.13! root     1784:     decide_fetch (hpos);
1.1.1.4   root     1785:     bplpt[num] = (bplpt[num] & ~0xffff) | (v & 0xfffe);
1.1.1.3   root     1786: }
1.1       root     1787: 
1.1.1.4   root     1788: static void BPLCON0 (int hpos, uae_u16 v)
1.1       root     1789: {
1.1.1.7   root     1790:     if (! (currprefs.chipset_mask & CSMASK_AGA)) {
                   1791:        v &= 0xFF0E;
                   1792:        /* The Sanity WOC demo needs this at one place (at the end of the "Party Effect")
                   1793:         * Disable bitplane DMA if someone tries to do more than 4 Hires bitplanes. */
                   1794:        if ((v & 0xF000) > 0xC000)
                   1795:            v &= 0xFFF;
                   1796:        /* Don't want 7 lores planes either. */
                   1797:        if ((v & 0x8000) == 0 && (v & 0x7000) == 0x7000)
                   1798:            v &= 0xEFFF;
                   1799:     }
1.1.1.2   root     1800:     if (bplcon0 == v)
1.1       root     1801:        return;
1.1.1.13! root     1802: 
1.1.1.4   root     1803:     decide_line (hpos);
1.1.1.13! root     1804:     decide_fetch (hpos);
        !          1805: 
1.1.1.9   root     1806:     /* if ((bplcon0 ^ v) & 0x8000)*/
                   1807:        calcdiw ();
1.1.1.2   root     1808:     bplcon0 = v;
1.1.1.6   root     1809:     nr_planes_from_bplcon0 = GET_PLANES (v);
1.1.1.7   root     1810: 
                   1811:     if (currprefs.chipset_mask & CSMASK_AGA)
                   1812:        /* It's not clear how the copper timings are affected by the number
                   1813:         * of bitplanes on AGA machines */
                   1814:        corrected_nr_planes_from_bplcon0 = 4;
                   1815:     else
                   1816:        corrected_nr_planes_from_bplcon0 = nr_planes_from_bplcon0 << (bplcon0 & 0x8000 ? 1 : 0);
1.1       root     1817: }
1.1.1.9   root     1818: 
1.1.1.8   root     1819: STATIC_INLINE void BPLCON1 (int hpos, uae_u16 v)
1.1       root     1820: {
1.1.1.2   root     1821:     if (bplcon1 == v)
1.1       root     1822:        return;
1.1.1.13! root     1823:     decide_line (hpos);
        !          1824:     decide_fetch (hpos);
1.1.1.2   root     1825:     bplcon1 = v;
1.1       root     1826: }
1.1.1.8   root     1827: STATIC_INLINE void BPLCON2 (int hpos, uae_u16 v)
1.1       root     1828: {
1.1.1.7   root     1829:     if (bplcon2 == v)
                   1830:        return;
                   1831:     decide_line (hpos);
1.1.1.2   root     1832:     bplcon2 = v;
1.1       root     1833: }
1.1.1.8   root     1834: STATIC_INLINE void BPLCON3 (int hpos, uae_u16 v)
1.1       root     1835: {
1.1.1.7   root     1836:     if (bplcon3 == v)
                   1837:        return;
                   1838:     decide_line (hpos);
1.1.1.3   root     1839:     bplcon3 = v;
1.1       root     1840: }
1.1.1.8   root     1841: STATIC_INLINE void BPLCON4 (int hpos, uae_u16 v)
1.1       root     1842: {
1.1.1.7   root     1843:     if (! (currprefs.chipset_mask & CSMASK_AGA))
                   1844:        return;
                   1845:     if (bplcon4 == v)
                   1846:        return;
                   1847:     decide_line (hpos);
1.1.1.3   root     1848:     bplcon4 = v;
1.1       root     1849: }
                   1850: 
1.1.1.4   root     1851: static void BPL1MOD (int hpos, uae_u16 v)
1.1       root     1852: {
                   1853:     v &= ~1;
1.1.1.3   root     1854:     if ((uae_s16)bpl1mod == (uae_s16)v)
1.1       root     1855:        return;
1.1.1.13! root     1856:     decide_line (hpos);
        !          1857:     decide_fetch (hpos);
1.1       root     1858:     bpl1mod = v;
                   1859: }
1.1.1.2   root     1860: 
1.1.1.4   root     1861: static void BPL2MOD (int hpos, uae_u16 v)
1.1.1.3   root     1862: {
1.1       root     1863:     v &= ~1;
1.1.1.3   root     1864:     if ((uae_s16)bpl2mod == (uae_s16)v)
1.1       root     1865:        return;
1.1.1.13! root     1866:     decide_line (hpos);
        !          1867:     decide_fetch (hpos);
1.1       root     1868:     bpl2mod = v;
                   1869: }
                   1870: 
1.1.1.13! root     1871: STATIC_INLINE void BPL1DAT (int hpos, uae_u16 v)
1.1.1.10  root     1872: {
1.1.1.13! root     1873:     decide_line (hpos);
1.1.1.10  root     1874:     bpl1dat = v;
1.1.1.13! root     1875: 
        !          1876:     {
        !          1877:        static int count = 0;
        !          1878:        if (count++ > 1000) {
        !          1879:            count = 0;
        !          1880:            printf ("BPL1DAT %d\n", hpos);
        !          1881:        }
        !          1882:     }
        !          1883:     
        !          1884:     maybe_first_bpl1dat (hpos);
1.1.1.10  root     1885: }
1.1.1.2   root     1886: /* We could do as well without those... */
1.1.1.8   root     1887: STATIC_INLINE void BPL2DAT (uae_u16 v) { bpl2dat = v; }
                   1888: STATIC_INLINE void BPL3DAT (uae_u16 v) { bpl3dat = v; }
                   1889: STATIC_INLINE void BPL4DAT (uae_u16 v) { bpl4dat = v; }
                   1890: STATIC_INLINE void BPL5DAT (uae_u16 v) { bpl5dat = v; }
                   1891: STATIC_INLINE void BPL6DAT (uae_u16 v) { bpl6dat = v; }
                   1892: STATIC_INLINE void BPL7DAT (uae_u16 v) { bpl7dat = v; }
                   1893: STATIC_INLINE void BPL8DAT (uae_u16 v) { bpl8dat = v; }
1.1       root     1894: 
1.1.1.4   root     1895: static void DIWSTRT (int hpos, uae_u16 v)
1.1       root     1896: {
1.1.1.4   root     1897:     if (diwstrt == v && ! diwhigh_written)
1.1       root     1898:        return;
1.1.1.4   root     1899:     decide_line (hpos);
                   1900:     diwhigh_written = 0;
1.1.1.3   root     1901:     diwstrt = v;
1.1.1.4   root     1902:     calcdiw ();
1.1       root     1903: }
1.1.1.4   root     1904: 
                   1905: static void DIWSTOP (int hpos, uae_u16 v)
1.1       root     1906: {
1.1.1.4   root     1907:     if (diwstop == v && ! diwhigh_written)
1.1       root     1908:        return;
1.1.1.4   root     1909:     decide_line (hpos);
                   1910:     diwhigh_written = 0;
1.1.1.3   root     1911:     diwstop = v;
1.1.1.4   root     1912:     calcdiw ();
                   1913: }
                   1914: 
                   1915: static void DIWHIGH (int hpos, uae_u16 v)
                   1916: {
1.1.1.7   root     1917:     if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE))
                   1918:        return;
1.1.1.4   root     1919:     if (diwhigh_written && diwhigh == v)
                   1920:        return;
                   1921:     decide_line (hpos);
                   1922:     diwhigh_written = 1;
                   1923:     diwhigh = v;
                   1924:     calcdiw ();
1.1       root     1925: }
1.1.1.4   root     1926: 
                   1927: static void DDFSTRT (int hpos, uae_u16 v)
1.1.1.3   root     1928: {
1.1.1.11  root     1929:     v &= 0xFC;
1.1.1.2   root     1930:     if (ddfstrt == v)
1.1       root     1931:        return;
1.1.1.4   root     1932:     decide_line (hpos);
1.1.1.3   root     1933:     ddfstrt = v;
1.1.1.4   root     1934:     calcdiw ();
1.1.1.13! root     1935:     if (ddfstop > 0xD4 && (ddfstrt & 4) == 4)
        !          1936:        printf ("WARNING! Very strange DDF values.\n");
1.1       root     1937: }
1.1.1.4   root     1938: static void DDFSTOP (int hpos, uae_u16 v)
1.1.1.3   root     1939: {
1.1.1.11  root     1940:     v &= 0xFC;
1.1.1.2   root     1941:     if (ddfstop == v)
1.1       root     1942:        return;
1.1.1.4   root     1943:     decide_line (hpos);
1.1.1.13! root     1944:     decide_fetch (hpos);
1.1.1.2   root     1945:     ddfstop = v;
1.1.1.4   root     1946:     calcdiw ();
1.1.1.13! root     1947:     if (fetch_state != fetch_not_started)
        !          1948:        estimate_last_fetch_cycle (hpos);
        !          1949:     if (ddfstop > 0xD4 && (ddfstrt & 4) == 4)
        !          1950:        printf ("WARNING! Very strange DDF values.\n");
1.1       root     1951: }
                   1952: 
1.1.1.7   root     1953: static void FMODE (uae_u16 v)
                   1954: {
                   1955:     if (! (currprefs.chipset_mask & CSMASK_AGA))
                   1956:        return;
1.1.1.13! root     1957: 
1.1.1.7   root     1958:     fmode = v;
                   1959:     calcdiw ();
                   1960: }
                   1961: 
1.1.1.4   root     1962: static void BLTADAT (uae_u16 v)
1.1       root     1963: {
1.1.1.13! root     1964:     maybe_blit ();
1.1.1.2   root     1965: 
                   1966:     blt_info.bltadat = v;
1.1       root     1967: }
1.1.1.2   root     1968: /*
                   1969:  * "Loading data shifts it immediately" says the HRM. Well, that may
                   1970:  * be true for BLTBDAT, but not for BLTADAT - it appears the A data must be
                   1971:  * loaded for every word so that AFWM and ALWM can be applied.
                   1972:  */
1.1.1.4   root     1973: static void BLTBDAT (uae_u16 v)
1.1       root     1974: {
1.1.1.13! root     1975:     maybe_blit ();
1.1.1.2   root     1976: 
                   1977:     if (bltcon1 & 2)
                   1978:        blt_info.bltbhold = v << (bltcon1 >> 12);
                   1979:     else
                   1980:        blt_info.bltbhold = v >> (bltcon1 >> 12);
                   1981:     blt_info.bltbdat = v;
1.1       root     1982: }
1.1.1.4   root     1983: static void BLTCDAT (uae_u16 v) { maybe_blit (); blt_info.bltcdat = v; }
1.1       root     1984: 
1.1.1.4   root     1985: static void BLTAMOD (uae_u16 v) { maybe_blit (); blt_info.bltamod = (uae_s16)(v & 0xFFFE); }
                   1986: static void BLTBMOD (uae_u16 v) { maybe_blit (); blt_info.bltbmod = (uae_s16)(v & 0xFFFE); }
                   1987: static void BLTCMOD (uae_u16 v) { maybe_blit (); blt_info.bltcmod = (uae_s16)(v & 0xFFFE); }
                   1988: static void BLTDMOD (uae_u16 v) { maybe_blit (); blt_info.bltdmod = (uae_s16)(v & 0xFFFE); }
1.1       root     1989: 
1.1.1.4   root     1990: static void BLTCON0 (uae_u16 v) { maybe_blit (); bltcon0 = v; blinea_shift = v >> 12; }
1.1.1.3   root     1991: /* The next category is "Most useless hardware register".
1.1       root     1992:  * And the winner is... */
1.1.1.7   root     1993: static void BLTCON0L (uae_u16 v)
                   1994: {
                   1995:     if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
                   1996:        return;
                   1997:     maybe_blit (); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF);
                   1998: }
1.1.1.4   root     1999: static void BLTCON1 (uae_u16 v) { maybe_blit (); bltcon1 = v; }
                   2000: 
                   2001: static void BLTAFWM (uae_u16 v) { maybe_blit (); blt_info.bltafwm = v; }
                   2002: static void BLTALWM (uae_u16 v) { maybe_blit (); blt_info.bltalwm = v; }
1.1       root     2003: 
1.1.1.4   root     2004: static void BLTAPTH (uae_u16 v) { maybe_blit (); bltapt = (bltapt & 0xffff) | ((uae_u32)v << 16); }
                   2005: static void BLTAPTL (uae_u16 v) { maybe_blit (); bltapt = (bltapt & ~0xffff) | (v & 0xFFFE); }
                   2006: static void BLTBPTH (uae_u16 v) { maybe_blit (); bltbpt = (bltbpt & 0xffff) | ((uae_u32)v << 16); }
                   2007: static void BLTBPTL (uae_u16 v) { maybe_blit (); bltbpt = (bltbpt & ~0xffff) | (v & 0xFFFE); }
                   2008: static void BLTCPTH (uae_u16 v) { maybe_blit (); bltcpt = (bltcpt & 0xffff) | ((uae_u32)v << 16); }
                   2009: static void BLTCPTL (uae_u16 v) { maybe_blit (); bltcpt = (bltcpt & ~0xffff) | (v & 0xFFFE); }
                   2010: static void BLTDPTH (uae_u16 v) { maybe_blit (); bltdpt = (bltdpt & 0xffff) | ((uae_u32)v << 16); }
                   2011: static void BLTDPTL (uae_u16 v) { maybe_blit (); bltdpt = (bltdpt & ~0xffff) | (v & 0xFFFE); }
1.1       root     2012: 
1.1.1.4   root     2013: static void BLTSIZE (uae_u16 v)
1.1       root     2014: {
                   2015:     bltsize = v;
1.1.1.3   root     2016: 
1.1.1.4   root     2017:     maybe_blit ();
1.1       root     2018: 
                   2019:     blt_info.vblitsize = bltsize >> 6;
                   2020:     blt_info.hblitsize = bltsize & 0x3F;
                   2021:     if (!blt_info.vblitsize) blt_info.vblitsize = 1024;
                   2022:     if (!blt_info.hblitsize) blt_info.hblitsize = 64;
1.1.1.3   root     2023: 
                   2024:     bltstate = BLT_init;
1.1.1.4   root     2025:     do_blitter ();
1.1       root     2026: }
1.1.1.4   root     2027: 
                   2028: static void BLTSIZV (uae_u16 v)
1.1       root     2029: {
1.1.1.7   root     2030:     if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
                   2031:        return;
1.1.1.4   root     2032:     maybe_blit ();
1.1       root     2033:     oldvblts = v & 0x7FFF;
                   2034: }
1.1.1.4   root     2035: 
                   2036: static void BLTSIZH (uae_u16 v)
1.1       root     2037: {
1.1.1.7   root     2038:     if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
                   2039:        return;
1.1.1.4   root     2040:     maybe_blit ();
1.1       root     2041:     blt_info.hblitsize = v & 0x7FF;
                   2042:     blt_info.vblitsize = oldvblts;
                   2043:     if (!blt_info.vblitsize) blt_info.vblitsize = 32768;
                   2044:     if (!blt_info.hblitsize) blt_info.hblitsize = 0x800;
1.1.1.2   root     2045:     bltstate = BLT_init;
1.1.1.5   root     2046:     do_blitter ();
1.1       root     2047: }
1.1.1.4   root     2048: 
1.1.1.8   root     2049: STATIC_INLINE void SPRxCTL_1 (uae_u16 v, int num)
1.1       root     2050: {
1.1.1.2   root     2051:     int sprxp;
                   2052:     sprctl[num] = v;
1.1.1.10  root     2053:     nr_armed -= spr[num].armed;
                   2054:     spr[num].armed = 0;
1.1.1.3   root     2055:     if (sprpos[num] == 0 && v == 0) {
1.1.1.10  root     2056:        spr[num].state = SPR_stop;
                   2057:        spr[num].on = 0;
1.1.1.3   root     2058:     } else
1.1.1.10  root     2059:        spr[num].state = SPR_waiting_start;
1.1.1.2   root     2060: 
1.1.1.13! root     2061:     sprxp = coord_hw_to_window_x ((sprpos[num] & 0xFF) * 2 + (v & 1) + DIW_DDF_OFFSET);
1.1.1.10  root     2062:     spr[num].xpos = sprxp;
                   2063:     spr[num].vstart = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100);
                   2064:     spr[num].vstop = (sprctl[num] >> 8) | ((sprctl[num] << 7) & 0x100);
1.1.1.2   root     2065: }
1.1.1.8   root     2066: STATIC_INLINE void SPRxPOS_1 (uae_u16 v, int num)
1.1.1.2   root     2067: {
                   2068:     int sprxp;
                   2069:     sprpos[num] = v;
1.1.1.13! root     2070:     sprxp = coord_hw_to_window_x ((v & 0xFF) * 2 + (sprctl[num] & 1) + DIW_DDF_OFFSET);
1.1.1.10  root     2071:     spr[num].xpos = sprxp;
                   2072:     spr[num].vstart = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100);
1.1.1.2   root     2073: }
1.1.1.8   root     2074: STATIC_INLINE void SPRxDATA_1 (uae_u16 v, int num)
1.1.1.2   root     2075: {
                   2076:     sprdata[num] = v;
1.1.1.10  root     2077:     nr_armed += 1 - spr[num].armed;
                   2078:     spr[num].armed = 1;
1.1.1.2   root     2079: }
1.1.1.8   root     2080: STATIC_INLINE void SPRxDATB_1 (uae_u16 v, int num)
1.1.1.2   root     2081: {
                   2082:     sprdatb[num] = v;
                   2083: }
1.1.1.4   root     2084: static void SPRxDATA (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxDATA_1 (v, num); }
                   2085: static void SPRxDATB (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxDATB_1 (v, num); }
                   2086: static void SPRxCTL (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxCTL_1 (v, num); }
                   2087: static void SPRxPOS (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxPOS_1 (v, num); }
                   2088: static void SPRxPTH (int hpos, uae_u16 v, int num)
1.1       root     2089: {
1.1.1.4   root     2090:     decide_sprites (hpos);
1.1.1.10  root     2091:     spr[num].pt &= 0xffff;
                   2092:     spr[num].pt |= (uae_u32)v << 16;
1.1.1.3   root     2093: 
1.1.1.10  root     2094:     if (spr[num].state == SPR_stop || vpos < sprite_vblank_endline)
                   2095:        spr[num].state = SPR_restart;
                   2096:     spr[num].on = 1;
1.1       root     2097: }
1.1.1.4   root     2098: static void SPRxPTL (int hpos, uae_u16 v, int num)
1.1       root     2099: {
1.1.1.4   root     2100:     decide_sprites (hpos);
1.1.1.10  root     2101:     spr[num].pt &= ~0xffff;
                   2102:     spr[num].pt |= v;
1.1       root     2103: 
1.1.1.10  root     2104:     if (spr[num].state == SPR_stop || vpos < sprite_vblank_endline)
                   2105:        spr[num].state = SPR_restart;
                   2106:     spr[num].on = 1;
1.1.1.3   root     2107: }
1.1.1.4   root     2108: static void CLXCON (uae_u16 v)
1.1.1.3   root     2109: {
                   2110:     clxcon = v;
                   2111:     clx_sprmask = (((v >> 15) << 7) | ((v >> 14) << 5) | ((v >> 13) << 3) | ((v >> 12) << 1) | 0x55);
                   2112: }
1.1.1.4   root     2113: static uae_u16 CLXDAT (void)
1.1.1.3   root     2114: {
                   2115:     uae_u16 v = clxdat;
                   2116:     clxdat = 0;
                   2117:     return v;
                   2118: }
1.1.1.11  root     2119: 
1.1.1.13! root     2120: static uae_u16 COLOR_READ (int num)
1.1       root     2121: {
1.1.1.13! root     2122:     int cr, cg, cb, colreg;
        !          2123:     uae_u16 cval;
        !          2124: 
        !          2125:     if (!(currprefs.chipset_mask & CSMASK_AGA) || !(bplcon2 & 0x0100))
        !          2126:        return 0xffff;
        !          2127: 
        !          2128:     colreg = ((bplcon3 >> 13) & 7) * 32 + num;
        !          2129:     cr = current_colors.color_regs_aga[colreg] >> 16;
        !          2130:     cg = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF;
        !          2131:     cb = current_colors.color_regs_aga[colreg] & 0xFF;
        !          2132:     if (bplcon3 & 0x200)
        !          2133:        cval = ((cr & 15) << 12) | ((cg & 15) << 4) | ((cb & 15) << 0);
        !          2134:     else
        !          2135:        cval = ((cr >> 4) << 12) | ((cg >> 4) << 4) | ((cb >> 4) << 0);
        !          2136:     return cval;
        !          2137: }
1.1.1.3   root     2138: 
1.1.1.13! root     2139: static void COLOR_WRITE (int hpos, uae_u16 v, int num)
        !          2140: {
1.1       root     2141:     v &= 0xFFF;
1.1.1.11  root     2142:     if (currprefs.chipset_mask & CSMASK_AGA) {
1.1.1.4   root     2143:        int r,g,b;
                   2144:        int cr,cg,cb;
                   2145:        int colreg;
1.1.1.3   root     2146:        uae_u32 cval;
1.1.1.4   root     2147: 
1.1.1.11  root     2148:        /* writing is disabled when RDRAM=1 */
1.1.1.13! root     2149:        if (bplcon2 & 0x0100)
        !          2150:            return;
1.1.1.11  root     2151: 
1.1.1.2   root     2152:        colreg = ((bplcon3 >> 13) & 7) * 32 + num;
1.1       root     2153:        r = (v & 0xF00) >> 8;
                   2154:        g = (v & 0xF0) >> 4;
                   2155:        b = (v & 0xF) >> 0;
1.1.1.11  root     2156:        cr = current_colors.color_regs_aga[colreg] >> 16;
                   2157:        cg = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF;
                   2158:        cb = current_colors.color_regs_aga[colreg] & 0xFF;
1.1       root     2159: 
1.1.1.2   root     2160:        if (bplcon3 & 0x200) {
1.1       root     2161:            cr &= 0xF0; cr |= r;
                   2162:            cg &= 0xF0; cg |= g;
                   2163:            cb &= 0xF0; cb |= b;
                   2164:        } else {
                   2165:            cr = r + (r << 4);
                   2166:            cg = g + (g << 4);
                   2167:            cb = b + (b << 4);
                   2168:        }
                   2169:        cval = (cr << 16) | (cg << 8) | cb;
1.1.1.11  root     2170:        if (cval == current_colors.color_regs_aga[colreg])
1.1       root     2171:            return;
1.1.1.5   root     2172: 
                   2173:        /* Call this with the old table still intact. */
1.1.1.11  root     2174:        record_color_change (hpos, colreg, cval);
1.1.1.5   root     2175:        remembered_color_entry = -1;
1.1.1.11  root     2176:        current_colors.color_regs_aga[colreg] = cval;
                   2177:        current_colors.acolors[colreg] = CONVERT_RGB (cval);
                   2178:    } else {
                   2179:        if (current_colors.color_regs_ecs[num] == v)
1.1       root     2180:            return;
1.1.1.2   root     2181:        /* Call this with the old table still intact. */
1.1.1.4   root     2182:        record_color_change (hpos, num, v);
1.1.1.2   root     2183:        remembered_color_entry = -1;
1.1.1.11  root     2184:        current_colors.color_regs_ecs[num] = v;
1.1.1.2   root     2185:        current_colors.acolors[num] = xcolors[v];
1.1       root     2186:     }
                   2187: }
1.1.1.3   root     2188: 
                   2189: static uae_u16 potgo_value;
                   2190: 
1.1.1.4   root     2191: static void POTGO (uae_u16 v)
1.1       root     2192: {
1.1.1.3   root     2193:     potgo_value = v;
                   2194: }
                   2195: 
1.1.1.4   root     2196: static uae_u16 POTGOR (void)
1.1.1.3   root     2197: {
1.1.1.11  root     2198:     uae_u16 v = (potgo_value | (potgo_value >> 1)) & 0x5500;
                   2199: 
                   2200:     v |= (~potgo_value & 0xAA00) >> 1;
1.1.1.3   root     2201: 
1.1.1.6   root     2202:     if (JSEM_ISMOUSE (0, &currprefs)) {
1.1.1.3   root     2203:        if (buttonstate[2])
                   2204:            v &= 0xFBFF;
                   2205: 
                   2206:        if (buttonstate[1])
                   2207:            v &= 0xFEFF;
1.1.1.6   root     2208:     } else if (JSEM_ISJOY0 (0, &currprefs) || JSEM_ISJOY1 (0, &currprefs)) {
1.1.1.3   root     2209:        if (joy0button & 2) v &= 0xfbff;
                   2210:        if (joy0button & 4) v &= 0xfeff;
                   2211:     }
                   2212: 
1.1.1.6   root     2213:     if (JSEM_ISJOY0 (1, &currprefs) || JSEM_ISJOY1 (1, &currprefs)) {
1.1.1.3   root     2214:        if (joy1button & 2) v &= 0xbfff;
                   2215:        if (joy1button & 4) v &= 0xefff;
                   2216:     }
1.1       root     2217: 
                   2218:     return v;
                   2219: }
1.1.1.4   root     2220: 
                   2221: static uae_u16 POT0DAT (void)
1.1       root     2222: {
1.1.1.3   root     2223:     static uae_u16 cnt = 0;
1.1.1.6   root     2224:     if (JSEM_ISMOUSE (0, &currprefs)) {
1.1.1.3   root     2225:        if (buttonstate[2])
                   2226:            cnt = ((cnt + 1) & 0xFF) | (cnt & 0xFF00);
                   2227:        if (buttonstate[1])
                   2228:            cnt += 0x100;
                   2229:     }
                   2230: 
1.1       root     2231:     return cnt;
                   2232: }
1.1.1.4   root     2233: static uae_u16 JOY0DAT (void)
1.1       root     2234: {
1.1.1.6   root     2235:     if (JSEM_ISMOUSE (0, &currprefs)) {
1.1.1.4   root     2236:        do_mouse_hack ();
1.1.1.3   root     2237:        return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8);
                   2238:     }
1.1       root     2239:     return joy0dir;
                   2240: }
1.1.1.4   root     2241: static uae_u16 JOY1DAT (void)
1.1       root     2242: {
1.1.1.6   root     2243:     if (JSEM_ISMOUSE (1, &currprefs)) {
1.1.1.4   root     2244:        do_mouse_hack ();
1.1.1.3   root     2245:        return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8);
                   2246:     }
                   2247:     return joy1dir;
1.1       root     2248: }
1.1.1.4   root     2249: static void JOYTEST (uae_u16 v)
1.1       root     2250: {
1.1.1.6   root     2251:     if (JSEM_ISMOUSE (0, &currprefs)) {
1.1.1.3   root     2252:        mouse_x = v & 0xFC;
                   2253:        mouse_y = (v >> 8) & 0xFC;
1.1       root     2254:     }
                   2255: }
                   2256: 
1.1.1.4   root     2257: /* Determine which cycles are available for the copper in a display
                   2258:  * with a agiven number of planes.  */
                   2259: static int cycles_for_plane[9][8] = {
                   2260:     { 0, -1, 0, -1, 0, -1, 0, -1 },
                   2261:     { 0, -1, 0, -1, 0, -1, 0, -1 },
                   2262:     { 0, -1, 0, -1, 0, -1, 0, -1 },
                   2263:     { 0, -1, 0, -1, 0, -1, 0, -1 },
                   2264:     { 0, -1, 0, -1, 0, -1, 0, -1 },
1.1.1.13! root     2265:     { 0, -1, 0, -1, 0, -1, 1, -1 }, /* */
1.1.1.4   root     2266:     { 0, -1, 1, -1, 0, -1, 1, -1 },
                   2267:     { 1, -1, 1, -1, 1, -1, 1, -1 },
                   2268:     { 1, -1, 1, -1, 1, -1, 1, -1 }
                   2269: };
1.1.1.2   root     2270: 
1.1.1.4   root     2271: static unsigned int waitmasktab[256];
1.1.1.2   root     2272: 
1.1.1.13! root     2273: STATIC_INLINE int copper_cant_read (int hpos, int planes)
1.1       root     2274: {
1.1.1.4   root     2275:     int t;
1.1.1.2   root     2276: 
1.1.1.9   root     2277:     /* @@@ */
1.1.1.13! root     2278:     if (hpos >= (maxhpos & ~1))
1.1.1.2   root     2279:        return 1;
1.1.1.3   root     2280: 
1.1.1.7   root     2281:     if (currprefs.chipset_mask & CSMASK_AGA)
                   2282:        /* FIXME */
                   2283:        return 0;
                   2284: 
1.1.1.13! root     2285:     if (fetch_state == fetch_not_started || passed_plfstop == 3
        !          2286:        || hpos > estimated_last_fetch_cycle)
1.1.1.4   root     2287:        return 0;
1.1.1.3   root     2288: 
1.1.1.13! root     2289:     t = cycles_for_plane[planes][(hpos + fetch_cycle - last_fetch_hpos) & 7];
1.1.1.4   root     2290: #if 0
                   2291:     if (t == -1)
                   2292:        abort ();
                   2293: #endif
                   2294:     return t;
1.1.1.2   root     2295: }
                   2296: 
1.1.1.10  root     2297: STATIC_INLINE int dangerous_reg (int reg)
                   2298: {
                   2299:     /* Safe:
                   2300:      * Bitplane pointers, control registers, modulos and data.
                   2301:      * Sprite pointers, control registers, and data.
                   2302:      * Color registers.  */
                   2303:     if (reg >= 0xE0 && reg < 0x1C0)
                   2304:        return 0;
                   2305:     return 1;
                   2306: }
                   2307: 
1.1.1.13! root     2308: #define FAST_COPPER 0
        !          2309: 
1.1.1.9   root     2310: static void update_copper (int until_hpos)
1.1.1.2   root     2311: {
1.1.1.10  root     2312:     int vp = vpos & (((cop_state.i2 >> 8) & 0x7F) | 0x80);
1.1.1.4   root     2313:     int c_hpos = cop_state.hpos;
1.1.1.2   root     2314: 
1.1.1.10  root     2315:     if (eventtab[ev_copper].active)
                   2316:        abort ();
                   2317: 
                   2318:     if (cop_state.state == COP_wait && vp < cop_state.vcmp)
                   2319:        abort ();
                   2320: 
                   2321:     until_hpos &= ~1;
                   2322: 
                   2323:     if (until_hpos > (maxhpos & ~1))
                   2324:        until_hpos = maxhpos & ~1;
1.1.1.3   root     2325: 
1.1.1.13! root     2326:     until_hpos += 2;
1.1.1.4   root     2327:     for (;;) {
1.1.1.10  root     2328:        int old_hpos = c_hpos;
                   2329:        int hp;
                   2330: 
1.1.1.13! root     2331:        if (c_hpos >= until_hpos)
1.1.1.3   root     2332:            break;
                   2333: 
1.1.1.13! root     2334:        /* So we know about the fetch state.  */
1.1.1.9   root     2335:        decide_line (c_hpos);
1.1.1.3   root     2336: 
1.1.1.10  root     2337:        c_hpos += 2;
1.1.1.13! root     2338:        if (copper_cant_read (old_hpos, corrected_nr_planes_from_bplcon0))
1.1.1.10  root     2339:            continue;
1.1.1.3   root     2340: 
1.1.1.10  root     2341:        switch (cop_state.state) {
1.1.1.9   root     2342:        case COP_read1:
                   2343:            cop_state.i1 = chipmem_bank.wget (cop_state.ip);
                   2344:            cop_state.ip += 2;
                   2345:            cop_state.state = COP_read2;
                   2346:            break;
                   2347: 
                   2348:        case COP_read2:
                   2349:            cop_state.i2 = chipmem_bank.wget (cop_state.ip);
                   2350:            cop_state.ip += 2;
1.1.1.10  root     2351:            cop_state.state = COP_read1;
1.1.1.9   root     2352:            if (cop_state.ignore_next) {
                   2353:                cop_state.ignore_next = 0;
                   2354:                break;
                   2355:            }
                   2356:            /* Perform moves immediately.  */
                   2357:            if ((cop_state.i1 & 1) == 0) {
1.1.1.11  root     2358:                unsigned int address = cop_state.i1 & 0x1FE;
                   2359:                if (address < (copcon & 2 ? ((currprefs.chipset_mask & CSMASK_AGA) ? 0 : 0x40u) : 0x80u)) {
1.1.1.10  root     2360:                    cop_state.state = COP_stop; 
                   2361:                    copper_enabled_thisline = 0;
1.1.1.13! root     2362:                    unset_special (SPCFLAG_COPPER);
1.1.1.10  root     2363:                    goto out;
1.1.1.4   root     2364:                }
1.1.1.13! root     2365:                if (address == 0x88) {
1.1.1.4   root     2366:                    cop_state.ip = cop1lc;
1.1.1.13! root     2367:                } else if (address == 0x8A) {
1.1.1.4   root     2368:                    cop_state.ip = cop2lc;
1.1.1.13! root     2369:                } else
1.1.1.11  root     2370:                    custom_wput_1 (old_hpos, address, cop_state.i2);
1.1.1.10  root     2371:                /* That could have turned off the copper...  */
                   2372:                if (! copper_enabled_thisline)
                   2373:                    goto out;
1.1.1.9   root     2374:                break;
1.1.1.3   root     2375:            }
1.1.1.2   root     2376: 
1.1.1.10  root     2377:            cop_state.vcmp = (cop_state.i1 & (cop_state.i2 | 0x8000)) >> 8;
1.1.1.9   root     2378:            cop_state.hcmp = (cop_state.i1 & cop_state.i2 & 0xFE);
                   2379:            if ((cop_state.i2 & 1) == 1) {
                   2380:                /* Skip instruction.  */
1.1.1.13! root     2381:                vp = vpos & (((cop_state.i2 >> 8) & 0x7F) | 0x80);
        !          2382:                hp = old_hpos & (cop_state.i2 & 0xFE);
        !          2383: 
1.1.1.9   root     2384:                if ((vp > cop_state.vcmp || (vp == cop_state.vcmp && hp >= cop_state.hcmp))
                   2385:                    && ((cop_state.i2 & 0x8000) != 0 || ! (DMACONR() & 0x4000)))
                   2386:                    cop_state.ignore_next = 1;
1.1.1.2   root     2387:                break;
1.1.1.4   root     2388:            }
1.1.1.9   root     2389:            cop_state.state = COP_wait;
1.1.1.13! root     2390: 
        !          2391:            vp = vpos & (((cop_state.i2 >> 8) & 0x7F) | 0x80);
        !          2392:            hp = old_hpos & (cop_state.i2 & 0xFE);
        !          2393: 
1.1.1.9   root     2394:            if (cop_state.i1 == 0xFFFF && cop_state.i2 == 0xFFFE) {
                   2395:                cop_state.state = COP_stop;
1.1.1.10  root     2396:                copper_enabled_thisline = 0;
1.1.1.13! root     2397:                unset_special (SPCFLAG_COPPER);
1.1.1.10  root     2398:                goto out;
1.1.1.2   root     2399:            }
1.1.1.9   root     2400:            if (vp < cop_state.vcmp) {
1.1.1.10  root     2401:                copper_enabled_thisline = 0;
1.1.1.13! root     2402:                unset_special (SPCFLAG_COPPER);
1.1.1.10  root     2403:                goto out;
1.1.1.2   root     2404:            }
1.1.1.10  root     2405:            if (vp > cop_state.vcmp)
1.1.1.9   root     2406:                break;
                   2407: 
1.1.1.10  root     2408:            /* Only enable shortcuts if there's no masking going on.  */
1.1.1.13! root     2409:            if (FAST_COPPER && (cop_state.i2 & 0xFE) == 0xFE) {
        !          2410:                /* Compute cycles remaining until c_hpos is past until_hpos
        !          2411:                   (i.e. until we'd normally break out of the loop).  */
1.1.1.10  root     2412:                int time_remaining = until_hpos - c_hpos;
                   2413: 
1.1.1.13! root     2414:                if (time_remaining < 0)
        !          2415:                    abort ();
        !          2416: 
        !          2417:                /* Compute minimum number of cycles to wait once the copper is at c_hpos.  */
        !          2418:                cop_min_waittime = cop_state.hcmp - hp - 2;
        !          2419: 
        !          2420:                if (cop_min_waittime <= 0)
1.1.1.10  root     2421:                    break;
1.1.1.13! root     2422: 
        !          2423:                /* Does this still leave us before until_hpos?  */
        !          2424:                if (cop_min_waittime <= time_remaining) {
1.1.1.10  root     2425:                    c_hpos += cop_min_waittime;
                   2426:                    break;
                   2427:                }
1.1.1.13! root     2428: 
        !          2429:                /* This wait will use up all the time up to until_hpos, and then some.  */
1.1.1.10  root     2430:                c_hpos += time_remaining;
                   2431:                cop_min_waittime -= time_remaining;
1.1.1.13! root     2432: 
1.1.1.10  root     2433:                if (cop_min_waittime >= 8) {
1.1.1.13! root     2434:                    unset_special (SPCFLAG_COPPER);
1.1.1.10  root     2435:                    eventtab[ev_copper].active = 1;
                   2436:                    eventtab[ev_copper].oldcycles = cycles;
                   2437:                    eventtab[ev_copper].evtime = cycles + cop_min_waittime;
1.1.1.13! root     2438:                    /* until_hpos is larger than hpos; add a correction for this adjustment.  */
        !          2439:                    cop_min_waittime -= 2;
1.1.1.10  root     2440:                    events_schedule ();
                   2441:                    goto out;
                   2442:                }
                   2443:            }
                   2444:            break;
                   2445: 
                   2446:        case COP_wait:
                   2447:            if (vp < cop_state.vcmp)
                   2448:                abort ();
                   2449: 
1.1.1.13! root     2450:            hp = old_hpos & (cop_state.i2 & 0xFE);
1.1.1.9   root     2451:            if (vp == cop_state.vcmp && hp < cop_state.hcmp)
1.1.1.4   root     2452:                break;
1.1.1.10  root     2453: 
                   2454:            /* Now we know that the comparisons were successful.  We might still
                   2455:               have to wait for the blitter though.  */
                   2456:            if ((cop_state.i2 & 0x8000) == 0 && (DMACONR() & 0x4000)) {
1.1.1.9   root     2457:                /* We need to wait for the blitter.  */
1.1.1.4   root     2458:                cop_state.state = COP_bltwait;
1.1.1.10  root     2459:                copper_enabled_thisline = 0;
1.1.1.13! root     2460:                unset_special (SPCFLAG_COPPER);
1.1.1.10  root     2461:                goto out;
1.1.1.2   root     2462:            }
1.1.1.10  root     2463: 
1.1.1.13! root     2464:            cop_state.state = COP_wait1;
        !          2465:            break;
        !          2466: 
        !          2467:        case COP_wait1:
1.1.1.10  root     2468:            cop_state.state = COP_read1;
1.1.1.4   root     2469:            break;
1.1.1.2   root     2470: 
1.1.1.13! root     2471:        default:
1.1.1.10  root     2472:            abort ();
1.1       root     2473:        }
1.1.1.4   root     2474:     }
1.1.1.10  root     2475: 
                   2476:   out:
1.1.1.4   root     2477:     cop_state.hpos = c_hpos;
1.1.1.13! root     2478: #if FAST_COPPER
1.1.1.10  root     2479:     /* The future, Conan?  */
                   2480:     if (cop_state.state == COP_read1 || cop_state.state == COP_read2) {
                   2481:        int ip = cop_state.ip;
                   2482:        int word = cop_state.i1;
1.1.1.13! root     2483:        int cycle_count;
1.1.1.10  root     2484: 
                   2485:        if (eventtab[ev_copper].active /* || ! (regs.spcflags & SPCFLAG_COPPER) */)
                   2486:            abort ();
                   2487: 
                   2488:        if (cop_state.state == COP_read2) {
                   2489:            ip += 2;
                   2490:            c_hpos += 2;
                   2491:            goto inner;
                   2492:        }
                   2493:        while (c_hpos < (maxhpos & ~1)) {
                   2494:            word = chipmem_bank.wget (ip);
                   2495:            ip += 4;
                   2496:            c_hpos += 4;
                   2497:          inner:
                   2498:            if ((word & 1) || dangerous_reg (word))
                   2499:                break;
                   2500:        }
1.1.1.13! root     2501:        cycle_count = c_hpos - cop_state.hpos;
        !          2502:        if (cycle_count >= 8) {
        !          2503:            unset_special (SPCFLAG_COPPER);
1.1.1.10  root     2504:            eventtab[ev_copper].active = 1;
                   2505:            eventtab[ev_copper].oldcycles = cycles;
1.1.1.13! root     2506:            eventtab[ev_copper].evtime = cycles + cycle_count;
1.1.1.10  root     2507:            events_schedule ();
                   2508:        }
                   2509:     }
                   2510: #endif
1.1       root     2511: }
                   2512: 
1.1.1.9   root     2513: static void compute_spcflag_copper (void)
1.1       root     2514: {
1.1.1.10  root     2515:     copper_enabled_thisline = 0;
1.1.1.13! root     2516:     unset_special (SPCFLAG_COPPER);
1.1.1.10  root     2517:     if (! dmaen (DMA_COPPER) || cop_state.state == COP_stop || cop_state.state == COP_bltwait)
                   2518:        return;
                   2519: 
                   2520:     if (cop_state.state == COP_wait) {
                   2521:        int vp = vpos & (((cop_state.i2 >> 8) & 0x7F) | 0x80);
                   2522: 
                   2523:        if (vp < cop_state.vcmp)
                   2524:            return;
                   2525:        copper_enabled_thisline = 1;
                   2526: 
1.1.1.13! root     2527:        if (FAST_COPPER && vp == cop_state.vcmp) {
        !          2528:            int hp = cop_state.hpos & (cop_state.i2 & 0xFE);
        !          2529:            cop_min_waittime = cop_state.hcmp - hp - 2;
1.1.1.10  root     2530: 
                   2531:            /* If possible, compute a minimum waiting time, and set the event
                   2532:               timer if it's sufficiently large to be worthwhile.  */
                   2533:            if ((cop_state.i2 & 0xFE) == 0xFE && cop_min_waittime >= 8) {
                   2534:                eventtab[ev_copper].active = 1;
                   2535:                eventtab[ev_copper].oldcycles = cycles;
                   2536:                eventtab[ev_copper].evtime = cycles + cop_min_waittime;
                   2537:                events_schedule ();
                   2538:                return;
                   2539:            }
                   2540:        }
                   2541:     }
                   2542: 
                   2543:     copper_enabled_thisline = 1;
1.1.1.13! root     2544:     set_special (SPCFLAG_COPPER);
1.1.1.10  root     2545: }
                   2546: 
                   2547: static void copper_handler (void)
                   2548: {
                   2549:     /* This will take effect immediately, within the same cycle.  */
1.1.1.13! root     2550:     set_special (SPCFLAG_COPPER);
1.1.1.10  root     2551: 
                   2552:     if (! copper_enabled_thisline)
                   2553:        abort ();
                   2554: 
                   2555:     if (cop_state.state == COP_wait) {
                   2556:        cop_state.hpos += cop_min_waittime;
                   2557:        if (cop_state.hpos > current_hpos ())
                   2558:            abort ();
                   2559:     }
                   2560: 
                   2561:     eventtab[ev_copper].active = 0;
1.1.1.3   root     2562: }
1.1.1.2   root     2563: 
1.1.1.4   root     2564: void blitter_done_notify (void)
1.1       root     2565: {
1.1.1.4   root     2566:     if (cop_state.state != COP_bltwait)
                   2567:        return;
1.1.1.10  root     2568: 
                   2569:     copper_enabled_thisline = 1;
1.1.1.13! root     2570:     set_special (SPCFLAG_COPPER);
1.1.1.9   root     2571:     cop_state.state = COP_wait;
1.1.1.2   root     2572: }
                   2573: 
1.1.1.9   root     2574: void do_copper (void)
1.1.1.2   root     2575: {
1.1.1.4   root     2576:     int hpos = current_hpos ();
                   2577:     update_copper (hpos);
1.1.1.2   root     2578: }
                   2579: 
1.1.1.13! root     2580: static void sync_copper_with_cpu (int hpos)
        !          2581: {
        !          2582:     /* Need to let the copper advance to the current position, but only if it
        !          2583:        isn't in a waiting state.  */
        !          2584:     if (eventtab[ev_copper].active) {
        !          2585:        if (cop_state.state != COP_wait) {
        !          2586:            eventtab[ev_copper].active = 0;
        !          2587:            events_schedule ();
        !          2588:            set_special (SPCFLAG_COPPER);
        !          2589:        }
        !          2590:     }
        !          2591:     if (copper_enabled_thisline && ! eventtab[ev_copper].active)
        !          2592:        update_copper (hpos);
        !          2593: }
        !          2594: 
        !          2595: static void do_sprites (int currvp, int hpos)
1.1.1.4   root     2596: {
                   2597:     int i;
1.1.1.13! root     2598:     int maxspr, minspr;
1.1.1.2   root     2599: 
1.1.1.4   root     2600:     /* I don't know whether this is right. Some programs write the sprite pointers
1.1.1.13! root     2601:      * directly at the start of the copper list. With the test against currvp, the
1.1.1.4   root     2602:      * first two words of data are read on the second line in the frame. The problem
                   2603:      * occurs when the program jumps to another copperlist a few lines further down
                   2604:      * which _also_ writes the sprite pointer registers. This means that a) writing
                   2605:      * to the sprite pointers sets the state to SPR_restart; or b) that sprite DMA
                   2606:      * is disabled until the end of the vertical blanking interval. The HRM
                   2607:      * isn't clear - it says that the vertical sprite position can be set to any
                   2608:      * value, but this wouldn't be the first mistake... */
                   2609:     /* Update: I modified one of the programs to write the sprite pointers the
                   2610:      * second time only _after_ the VBlank interval, and it showed the same behaviour
                   2611:      * as it did unmodified under UAE with the above check. This indicates that the
                   2612:      * solution below is correct. */
1.1.1.9   root     2613:     /* Another update: seems like we have to use the NTSC value here (see Sanity Turmoil
                   2614:      * demo).  */
1.1.1.10  root     2615:     /* Maximum for Sanity Turmoil: 27.
                   2616:        Minimum for Sanity Arte: 22.  */
                   2617:     if (currvp < sprite_vblank_endline)
1.1.1.4   root     2618:        return;
1.1.1.3   root     2619: 
1.1.1.4   root     2620:     /* The graph in the HRM, p. 195 seems to indicate that sprite 0 is
                   2621:      * fetched at cycle 0x14 and thus can't be disabled by bitplane DMA. */
1.1.1.13! root     2622:     maxspr = hpos / 4 - 0x14 / 4;
        !          2623:     minspr = last_sprite_hpos / 4 - 0x14 / 4;
        !          2624: 
        !          2625:     if (minspr > 8 || maxspr < 0)
1.1.1.4   root     2626:        return;
1.1.1.13! root     2627: 
1.1.1.4   root     2628:     if (maxspr > 8)
                   2629:        maxspr = 8;
1.1.1.13! root     2630:     if (minspr < 0)
        !          2631:         minspr = 0;
1.1.1.2   root     2632: 
1.1.1.13! root     2633:     for (i = minspr; i < maxspr; i++) {
1.1.1.4   root     2634:        int fetch = 0;
1.1.1.2   root     2635: 
1.1.1.10  root     2636:        if (spr[i].on == 0)
1.1.1.4   root     2637:            continue;
1.1.1.2   root     2638: 
1.1.1.10  root     2639:        if (spr[i].state == SPR_restart) {
1.1.1.4   root     2640:            fetch = 2;
1.1.1.10  root     2641:            spr[i].on = 1;
                   2642:        } else if ((spr[i].state == SPR_waiting_start && spr[i].vstart == vpos) || spr[i].state == SPR_waiting_stop) {
1.1.1.4   root     2643:            fetch = 1;
1.1.1.10  root     2644:            spr[i].state = SPR_waiting_stop;
1.1.1.2   root     2645:        }
1.1.1.10  root     2646:        if ((spr[i].state == SPR_waiting_stop || spr[i].state == SPR_waiting_start) && spr[i].vstop == vpos) {
1.1.1.4   root     2647:            fetch = 2;
1.1.1.10  root     2648:            spr[i].state = SPR_waiting_start;
1.1.1.2   root     2649:        }
1.1.1.3   root     2650: 
1.1.1.9   root     2651:        if (fetch && dmaen (DMA_SPRITE)) {
1.1.1.10  root     2652:            uae_u16 data1 = chipmem_bank.wget (spr[i].pt);
                   2653:            uae_u16 data2 = chipmem_bank.wget (spr[i].pt + 2);
                   2654:            spr[i].pt += 4;
1.1.1.3   root     2655: 
1.1.1.4   root     2656:            if (fetch == 1) {
                   2657:                /* Hack for X mouse auto-calibration */
                   2658:                if (i == 0 && !sprvbfl && ((sprpos[0] & 0xff) << 2) > 2 * DISPLAY_LEFT_SHIFT) {
1.1.1.9   root     2659:                    spr0ctl = sprctl[0];
                   2660:                    spr0pos = sprpos[0];
                   2661:                    sprvbfl = 2;
1.1.1.3   root     2662:                }
1.1.1.9   root     2663:                SPRxDATB_1 (data2, i);
                   2664:                SPRxDATA_1 (data1, i);
1.1.1.4   root     2665:            } else {
1.1.1.9   root     2666:                SPRxPOS_1 (data1, i);
                   2667:                SPRxCTL_1 (data2, i);
1.1.1.3   root     2668:            }
1.1       root     2669:        }
                   2670:     }
1.1.1.13! root     2671:     last_sprite_hpos = hpos;
1.1       root     2672: }
                   2673: 
1.1.1.4   root     2674: static void init_sprites (void)
1.1       root     2675: {
1.1.1.4   root     2676:     int i;
1.1.1.2   root     2677: 
1.1.1.4   root     2678:     for (i = 0; i < 8; i++) {
                   2679:        /* ???? */
1.1.1.10  root     2680:        spr[i].state = SPR_stop;
                   2681:        spr[i].on = 0;
1.1.1.4   root     2682:     }
1.1.1.2   root     2683: 
1.1.1.4   root     2684:     memset (sprpos, 0, sizeof sprpos);
                   2685:     memset (sprctl, 0, sizeof sprctl);
                   2686: }
1.1.1.2   root     2687: 
1.1.1.3   root     2688: static void adjust_array_sizes (void)
1.1.1.2   root     2689: {
                   2690: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
1.1.1.13! root     2691:     if (delta_sprite_entry) {
1.1.1.3   root     2692:        void *p1,*p2;
1.1.1.13! root     2693:        int mcc = max_sprite_entry + 50 + delta_sprite_entry;
        !          2694:        delta_sprite_entry = 0;
        !          2695:        p1 = realloc (sprite_entries[0], mcc * sizeof (struct sprite_entry));
        !          2696:        p2 = realloc (sprite_entries[1], mcc * sizeof (struct sprite_entry));
        !          2697:        if (p1) sprite_entries[0] = p1;
        !          2698:        if (p2) sprite_entries[1] = p2;
1.1.1.3   root     2699:        if (p1 && p2) {
1.1.1.13! root     2700:            fprintf (stderr, "new max_sprite_entry=%d\n",mcc);
        !          2701:            max_sprite_entry = mcc;
1.1.1.2   root     2702:        }
                   2703:     }
1.1.1.3   root     2704:     if (delta_color_change) {
                   2705:        void *p1,*p2;
                   2706:        int mcc = max_color_change + 200 + delta_color_change;
                   2707:        delta_color_change = 0;
                   2708:        p1 = realloc (color_changes[0], mcc * sizeof (struct color_change));
                   2709:        p2 = realloc (color_changes[1], mcc * sizeof (struct color_change));
                   2710:        if (p1) color_changes[0] = p1;
                   2711:        if (p2) color_changes[1] = p2;
                   2712:        if (p1 && p2) {
                   2713:            fprintf (stderr, "new max_color_change=%d\n",mcc);
1.1.1.2   root     2714:            max_color_change = mcc;
1.1.1.3   root     2715:        }
                   2716:     }
1.1.1.2   root     2717: #endif
1.1.1.3   root     2718: }
                   2719: 
1.1.1.4   root     2720: static void init_hardware_frame (void)
1.1.1.3   root     2721: {
1.1.1.4   root     2722:     next_lineno = 0;
                   2723:     nextline_how = nln_normal;
                   2724:     diwstate = DIW_waiting_start;
                   2725:     hdiwstate = DIW_waiting_start;
                   2726: }
1.1.1.2   root     2727: 
1.1.1.4   root     2728: void init_hardware_for_drawing_frame (void)
                   2729: {
1.1.1.3   root     2730:     adjust_array_sizes ();
                   2731: 
1.1.1.13! root     2732:     /* Avoid this code in the first frame after a customreset.  */
        !          2733:     if (prev_sprite_entries) {
        !          2734:        int first_pixel = prev_sprite_entries[0].first_pixel;
        !          2735:        int npixels = prev_sprite_entries[prev_next_sprite_entry].first_pixel - first_pixel;
        !          2736:        memset (spixels + first_pixel, 0, npixels * sizeof *spixels);
        !          2737:        memset (spixstate.bytes + first_pixel, 0, npixels * sizeof *spixstate.bytes);
        !          2738:     }
        !          2739:     prev_next_sprite_entry = next_sprite_entry;
1.1.1.3   root     2740: 
1.1.1.13! root     2741:     next_color_change = 0;
        !          2742:     next_sprite_entry = 0;
1.1.1.2   root     2743:     next_color_entry = 0;
                   2744:     remembered_color_entry = -1;
1.1.1.13! root     2745: 
        !          2746:     prev_sprite_entries = sprite_entries[current_change_set];
        !          2747:     curr_sprite_entries = sprite_entries[current_change_set ^ 1];
1.1.1.2   root     2748:     prev_color_changes = color_changes[current_change_set];
                   2749:     curr_color_changes = color_changes[current_change_set ^ 1];
                   2750:     prev_color_tables = color_tables[current_change_set];
                   2751:     curr_color_tables = color_tables[current_change_set ^ 1];
1.1.1.3   root     2752: 
1.1.1.2   root     2753:     prev_drawinfo = line_drawinfo[current_change_set];
1.1.1.4   root     2754:     curr_drawinfo = line_drawinfo[current_change_set ^ 1];
                   2755:     current_change_set ^= 1;
1.1.1.3   root     2756: 
1.1.1.4   root     2757:     color_src_match = color_dest_match = -1;
1.1.1.13! root     2758: 
        !          2759:     /* Use both halves of the array in alternating fashion.  */
        !          2760:     curr_sprite_entries[0].first_pixel = current_change_set * MAX_SPR_PIXELS;
        !          2761:     next_sprite_forced = 1;
1.1.1.3   root     2762: }
                   2763: 
1.1.1.2   root     2764: static void vsync_handler (void)
1.1       root     2765: {
1.1.1.12  root     2766:     n_frames++;
                   2767: 
1.1.1.4   root     2768:     if (currprefs.m68k_speed == -1) {
                   2769:        frame_time_t curr_time = read_processor_time ();
1.1.1.3   root     2770:        vsyncmintime += vsynctime;
                   2771:        /* @@@ Mathias? How do you think we should do this? */
                   2772:        /* If we are too far behind, or we just did a reset, adjust the
                   2773:         * needed time. */
1.1.1.4   root     2774:        if ((long int)(curr_time - vsyncmintime) > 0 || rpt_did_reset)
1.1.1.3   root     2775:            vsyncmintime = curr_time + vsynctime;
1.1.1.4   root     2776:        rpt_did_reset = 0;
1.1.1.3   root     2777:     }
1.1.1.4   root     2778: 
1.1.1.3   root     2779:     handle_events ();
1.1       root     2780: 
1.1.1.3   root     2781:     getjoystate (0, &joy0dir, &joy0button);
                   2782:     getjoystate (1, &joy1dir, &joy1button);
1.1       root     2783: 
1.1.1.4   root     2784:     INTREQ (0x8020);
1.1.1.3   root     2785:     if (bplcon0 & 4)
1.1.1.2   root     2786:        lof ^= 0x8000;
1.1.1.3   root     2787: 
1.1.1.4   root     2788:     vsync_handle_redraw (lof, lof_changed);
                   2789:     if (quit_program > 0)
1.1.1.3   root     2790:        return;
                   2791: 
1.1.1.4   root     2792:     {
1.1.1.3   root     2793:        static int cnt = 0;
                   2794:        if (cnt == 0) {
                   2795:            /* resolution_check_change (); */
                   2796:            DISK_check_change ();
                   2797:            cnt = 5;
                   2798:        }
                   2799:        cnt--;
1.1.1.2   root     2800:     }
1.1.1.3   root     2801: 
1.1.1.7   root     2802:     /* For now, let's only allow this to change at vsync time.  It gets too
                   2803:      * hairy otherwise.  */
                   2804:     if (beamcon0 != new_beamcon0)
                   2805:        init_hz ();
                   2806: 
1.1.1.2   root     2807:     lof_changed = 0;
1.1.1.3   root     2808: 
1.1.1.4   root     2809:     cop_state.ip = cop1lc;
                   2810:     cop_state.state = COP_read1;
                   2811:     cop_state.vpos = 0;
                   2812:     cop_state.hpos = 0;
                   2813:     cop_state.ignore_next = 0;
                   2814: 
                   2815:     init_hardware_frame ();
                   2816: 
1.1       root     2817: #ifdef HAVE_GETTIMEOFDAY
                   2818:     {
                   2819:        struct timeval tv;
                   2820:        unsigned long int newtime;
1.1.1.3   root     2821: 
1.1.1.9   root     2822:        gettimeofday (&tv,NULL);
1.1       root     2823:        newtime = (tv.tv_sec-seconds_base) * 1000 + tv.tv_usec / 1000;
1.1.1.3   root     2824: 
                   2825:        if (!bogusframe) {
1.1.1.6   root     2826:            lastframetime = newtime - msecs;
                   2827: 
                   2828: #if 0 /* This doesn't appear to work too well yet... later.  */
                   2829:            if (n_consecutive_skipped > currprefs.sound_pri_cutoff
                   2830:                || lastframetime < currprefs.sound_pri_time)
                   2831:            {
                   2832:                n_consecutive_skipped = 0;
                   2833:                clear_inhibit_frame (IHF_SOUNDADJUST);
                   2834:            } else {
                   2835:                n_consecutive_skipped++;
                   2836:                set_inhibit_frame (IHF_SOUNDADJUST);
                   2837:                total_skipped++;
                   2838:            }
                   2839: #endif
                   2840: 
                   2841:            frametime += lastframetime;
1.1       root     2842:            timeframes++;
1.1.1.6   root     2843: 
                   2844:            if ((timeframes & 127) == 0)
                   2845:                gui_fps (1000 * timeframes / frametime);
1.1       root     2846:        }
                   2847:        msecs = newtime;
                   2848:        bogusframe = 0;
                   2849:     }
                   2850: #endif
1.1.1.3   root     2851:     if (ievent_alive > 0)
                   2852:        ievent_alive--;
1.1.1.7   root     2853:     if (timehack_alive > 0)
                   2854:        timehack_alive--;
1.1       root     2855:     CIA_vsync_handler();
                   2856: }
                   2857: 
1.1.1.4   root     2858: static void hsync_handler (void)
1.1       root     2859: {
1.1.1.10  root     2860:     int copper_was_active = eventtab[ev_copper].active;
                   2861:     if (copper_was_active) {
                   2862:        /* Could happen if horizontal wait position is too large.  */
                   2863:        eventtab[ev_copper].active = 0;
1.1.1.13! root     2864:        /* If this was a sequence of moves, we have to call update_copper if
        !          2865:           we don't want to lose them.  */
        !          2866:        if (cop_state.state != COP_wait) {
1.1.1.10  root     2867:            copper_was_active = 0;
1.1.1.13! root     2868:            set_special (SPCFLAG_COPPER);
        !          2869:        }
1.1.1.10  root     2870:     }
                   2871:     if (copper_enabled_thisline && ! copper_was_active)
                   2872:        update_copper (maxhpos);
                   2873: 
1.1.1.2   root     2874:     finish_decisions ();
1.1.1.13! root     2875:     if (currprefs.collision_level > 1)
        !          2876:        do_sprite_collisions ();
1.1.1.2   root     2877: 
1.1.1.5   root     2878:     hsync_record_line_state (next_lineno, nextline_how, thisline_changed);
1.1       root     2879: 
                   2880:     eventtab[ev_hsync].evtime += cycles - eventtab[ev_hsync].oldcycles;
                   2881:     eventtab[ev_hsync].oldcycles = cycles;
1.1.1.8   root     2882:     CIA_hsync_handler ();
1.1.1.11  root     2883:     DISK_update ();
1.1.1.3   root     2884: 
                   2885:     if (currprefs.produce_sound > 0) {
1.1       root     2886:        int nr;
1.1.1.4   root     2887: 
                   2888:        update_audio ();
                   2889: 
1.1       root     2890:        /* Sound data is fetched at the beginning of each line */
                   2891:        for (nr = 0; nr < 4; nr++) {
                   2892:            struct audio_channel_data *cdp = audio_channel + nr;
1.1.1.3   root     2893: 
1.1       root     2894:            if (cdp->data_written == 2) {
                   2895:                cdp->data_written = 0;
                   2896:                cdp->nextdat = chipmem_bank.wget(cdp->pt);
                   2897:                cdp->pt += 2;
                   2898:                if (cdp->state == 2 || cdp->state == 3) {
                   2899:                    if (cdp->wlen == 1) {
                   2900:                        cdp->pt = cdp->lc;
                   2901:                        cdp->wlen = cdp->len;
                   2902:                        cdp->intreq2 = 1;
                   2903:                    } else
                   2904:                        cdp->wlen--;
                   2905:                }
                   2906:            }
                   2907:        }
                   2908:     }
1.1.1.4   root     2909: 
                   2910:     hardware_line_completed (next_lineno);
                   2911: 
1.1       root     2912:     if (++vpos == (maxvpos + (lof != 0))) {
                   2913:        vpos = 0;
                   2914:        vsync_handler();
                   2915:     }
1.1.1.2   root     2916: 
1.1.1.4   root     2917:     is_lastline = vpos + 1 == maxvpos + (lof != 0) && currprefs.m68k_speed == -1 && ! rpt_did_reset;
1.1.1.3   root     2918: 
1.1.1.4   root     2919:     if ((bplcon0 & 4) && currprefs.gfx_linedbl)
                   2920:        notice_interlace_seen ();
1.1.1.2   root     2921: 
                   2922:     if (framecnt == 0) {
1.1.1.4   root     2923:        int lineno = vpos;
                   2924:        nextline_how = nln_normal;
1.1.1.3   root     2925:        if (currprefs.gfx_linedbl) {
1.1       root     2926:            lineno *= 2;
1.1.1.5   root     2927:            nextline_how = currprefs.gfx_linedbl == 1 ? nln_doubled : nln_nblack;
1.1.1.2   root     2928:            if (bplcon0 & 4) {
                   2929:                if (!lof) {
                   2930:                    lineno++;
1.1.1.4   root     2931:                    nextline_how = nln_lower;
1.1.1.2   root     2932:                } else {
1.1.1.4   root     2933:                    nextline_how = nln_upper;
1.1.1.2   root     2934:                }
1.1       root     2935:            }
                   2936:        }
                   2937:        next_lineno = lineno;
1.1.1.2   root     2938:        reset_decisions ();
1.1       root     2939:     }
1.1.1.3   root     2940:     if (uae_int_requested) {
                   2941:        set_uae_int_flag ();
                   2942:        INTREQ (0xA000);
                   2943:     }
1.1.1.9   root     2944:     /* See if there's a chance of a copper wait ending this line.  */
                   2945:     cop_state.hpos = 0;
                   2946:     compute_spcflag_copper ();
1.1.1.3   root     2947: }
                   2948: 
                   2949: static void init_eventtab (void)
                   2950: {
                   2951:     int i;
                   2952: 
                   2953:     for(i = 0; i < ev_max; i++) {
                   2954:        eventtab[i].active = 0;
                   2955:        eventtab[i].oldcycles = 0;
                   2956:     }
1.1.1.4   root     2957: 
1.1.1.3   root     2958:     eventtab[ev_cia].handler = CIA_handler;
                   2959:     eventtab[ev_hsync].handler = hsync_handler;
                   2960:     eventtab[ev_hsync].evtime = maxhpos + cycles;
                   2961:     eventtab[ev_hsync].active = 1;
                   2962: 
1.1.1.10  root     2963:     eventtab[ev_copper].handler = copper_handler;
                   2964:     eventtab[ev_copper].active = 0;
1.1.1.3   root     2965:     eventtab[ev_blitter].handler = blitter_handler;
                   2966:     eventtab[ev_blitter].active = 0;
1.1.1.11  root     2967:     eventtab[ev_disk].handler = DISK_handler;
                   2968:     eventtab[ev_disk].active = 0;
1.1.1.4   root     2969: 
1.1.1.3   root     2970:     events_schedule ();
1.1       root     2971: }
                   2972: 
1.1.1.3   root     2973: void customreset (void)
1.1       root     2974: {
1.1.1.4   root     2975:     int i;
1.1.1.11  root     2976:     int zero = 0;
1.1       root     2977: #ifdef HAVE_GETTIMEOFDAY
                   2978:     struct timeval tv;
                   2979: #endif
1.1.1.2   root     2980: 
1.1.1.12  root     2981:     if ((currprefs.chipset_mask & CSMASK_AGA) == 0) {
1.1.1.11  root     2982:        for (i = 0; i < 32; i++) {
                   2983:            current_colors.color_regs_ecs[i] = 0;
                   2984:            current_colors.acolors[i] = xcolors[0];
                   2985:        }
                   2986:     } else {
                   2987:         for (i = 0; i < 256; i++) {
                   2988:            current_colors.color_regs_aga[i] = 0;
                   2989:            current_colors.acolors[i] = CONVERT_RGB (zero);
                   2990:        }
1.1.1.9   root     2991:     }
1.1.1.3   root     2992: 
1.1.1.12  root     2993:     n_frames = 0;
                   2994: 
1.1.1.3   root     2995:     expamem_reset ();
1.1.1.4   root     2996: 
1.1.1.12  root     2997:     DISK_reset ();
1.1.1.3   root     2998:     CIA_reset ();
                   2999:     cycles = 0;
1.1.1.13! root     3000:     unset_special (~(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE));
1.1.1.3   root     3001: 
1.1.1.2   root     3002:     vpos = 0;
1.1       root     3003:     lof = 0;
1.1.1.3   root     3004: 
1.1.1.4   root     3005:     if (needmousehack ()) {
1.1.1.3   root     3006: #if 0
1.1.1.4   root     3007:        mousehack_setfollow();
1.1.1.3   root     3008: #else
1.1.1.4   root     3009:        mousehack_setdontcare();
1.1.1.3   root     3010: #endif
1.1       root     3011:     } else {
                   3012:        mousestate = normal_mouse;
                   3013:     }
1.1.1.3   root     3014:     ievent_alive = 0;
1.1.1.7   root     3015:     timehack_alive = 0;
1.1.1.3   root     3016: 
                   3017:     clx_sprmask = 0xFF;
                   3018:     clxdat = 0;
                   3019: 
1.1.1.13! root     3020:     curr_sprite_entries = 0;
        !          3021:     prev_sprite_entries = 0;
        !          3022:     sprite_entries[0][0].first_pixel = 0;
        !          3023:     sprite_entries[1][0].first_pixel = MAX_SPR_PIXELS;
        !          3024:     sprite_entries[0][1].first_pixel = 0;
        !          3025:     sprite_entries[1][1].first_pixel = MAX_SPR_PIXELS;
        !          3026:     memset (spixels, 0, sizeof spixels);
        !          3027:     memset (&spixstate, 0, sizeof spixstate);
        !          3028:     
1.1.1.10  root     3029:     /* Clear the armed flags of all sprites.  */
                   3030:     memset (spr, 0, sizeof spr);
1.1.1.3   root     3031:     nr_armed = 0;
1.1       root     3032: 
                   3033:     dmacon = intena = 0;
                   3034:     bltstate = BLT_done;
1.1.1.4   root     3035:     cop_state.state = COP_stop;
1.1.1.2   root     3036:     diwstate = DIW_waiting_start;
1.1.1.3   root     3037:     hdiwstate = DIW_waiting_start;
1.1       root     3038:     copcon = 0;
1.1.1.11  root     3039:     DSKLEN (0, 0);
1.1       root     3040:     cycles = 0;
1.1.1.3   root     3041: 
1.1.1.2   root     3042:     bplcon4 = 0x11; /* Get AGA chipset into ECS compatibility mode */
                   3043:     bplcon3 = 0xC00;
1.1       root     3044: 
1.1.1.7   root     3045:     new_beamcon0 = ntscmode ? 0x00 : 0x20;
                   3046:     init_hz ();
                   3047: 
                   3048:     audio_reset ();
                   3049: 
1.1.1.3   root     3050:     init_eventtab ();
1.1.1.2   root     3051: 
1.1.1.3   root     3052:     init_sprites ();
                   3053: 
1.1.1.2   root     3054:     init_hardware_frame ();
1.1.1.4   root     3055:     reset_drawing ();
                   3056: 
1.1.1.2   root     3057:     reset_decisions ();
1.1.1.3   root     3058: 
1.1       root     3059: #ifdef HAVE_GETTIMEOFDAY
1.1.1.4   root     3060:     gettimeofday (&tv, NULL);
1.1       root     3061:     seconds_base = tv.tv_sec;
                   3062:     bogusframe = 1;
                   3063: #endif
                   3064: }
                   3065: 
1.1.1.3   root     3066: void dumpcustom (void)
1.1       root     3067: {
1.1.1.6   root     3068:     write_log ("DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR(),
                   3069:               (unsigned int)intena, (unsigned int)intreq, (unsigned int)vpos, (unsigned int)current_hpos());
                   3070:     write_log ("COP1LC: %08lx, COP2LC: %08lx\n", (unsigned long)cop1lc, (unsigned long)cop2lc);
1.1.1.13! root     3071:     write_log ("DIWSTRT: %04x DIWSTOP: %04x DDFSTRT: %04x DDFSTOP: %04x\n",
        !          3072:               (unsigned int)diwstrt, (unsigned int)diwstop, (unsigned int)ddfstrt, (unsigned int)ddfstop);
1.1.1.3   root     3073:     if (timeframes) {
1.1.1.6   root     3074:        write_log ("Average frame time: %d ms [frames: %d time: %d]\n",
                   3075:                   frametime / timeframes, timeframes, frametime);
                   3076:        if (total_skipped)
                   3077:            write_log ("Skipped frames: %d\n", total_skipped);
1.1       root     3078:     }
1.1.1.3   root     3079:     dump_audio_bench ();
1.1.1.4   root     3080:     /*for (i=0; i<256; i++) if (blitcount[i]) fprintf (stderr, "minterm %x = %d\n",i,blitcount[i]);  blitter debug */
1.1       root     3081: }
                   3082: 
1.1.1.3   root     3083: int intlev (void)
1.1       root     3084: {
1.1.1.3   root     3085:     uae_u16 imask = intreq & intena;
1.1       root     3086:     if (imask && (intena & 0x4000)){
                   3087:        if (imask & 0x2000) return 6;
                   3088:        if (imask & 0x1800) return 5;
                   3089:        if (imask & 0x0780) return 4;
                   3090:        if (imask & 0x0070) return 3;
                   3091:        if (imask & 0x0008) return 2;
                   3092:        if (imask & 0x0007) return 1;
                   3093:     }
                   3094:     return -1;
                   3095: }
                   3096: 
1.1.1.4   root     3097: static void gen_custom_tables (void)
                   3098: {
                   3099:     int i;
                   3100:     for (i = 0; i < 256; i++) {
                   3101:        unsigned int j;
                   3102:        sprtaba[i] = ((((i >> 7) & 1) << 0)
                   3103:                      | (((i >> 6) & 1) << 2)
                   3104:                      | (((i >> 5) & 1) << 4)
                   3105:                      | (((i >> 4) & 1) << 6)
                   3106:                      | (((i >> 3) & 1) << 8)
                   3107:                      | (((i >> 2) & 1) << 10)
                   3108:                      | (((i >> 1) & 1) << 12)
                   3109:                      | (((i >> 0) & 1) << 14));
                   3110:        sprtabb[i] = sprtaba[i] * 2;
1.1.1.13! root     3111:        sprite_ab_merge[i] = (((i & 15) ? 1 : 0)
        !          3112:                              | ((i & 240) ? 2 : 0));
        !          3113:        
1.1.1.4   root     3114:        for (j = 0; j < 511; j = (j << 1) | 1)
                   3115:            if ((i & ~j) == 0)
                   3116:                waitmasktab[i] = ~j;
                   3117:     }
1.1.1.13! root     3118:     for (i = 0; i < 16; i++) {
        !          3119:        clxmask[i] = (((i & 1) ? 0xF : 0x3)
        !          3120:                      | ((i & 2) ? 0xF0 : 0x30)
        !          3121:                      | ((i & 4) ? 0xF00 : 0x300)
        !          3122:                      | ((i & 8) ? 0xF000 : 0x3000));
        !          3123:        sprclx[i] = (((i & 0x3) == 0x3 ? 1 : 0)
        !          3124:                     | ((i & 0x5) == 0x5 ? 2 : 0)
        !          3125:                     | ((i & 0x9) == 0x9 ? 4 : 0)
        !          3126:                     | ((i & 0x6) == 0x6 ? 8 : 0)
        !          3127:                     | ((i & 0xA) == 0xA ? 16 : 0)
        !          3128:                     | ((i & 0xC) == 0xC ? 32 : 0)) << 9;
        !          3129:     }
1.1.1.4   root     3130: }
                   3131: 
1.1.1.3   root     3132: void custom_init (void)
1.1       root     3133: {
1.1.1.7   root     3134:     uaecptr pos;
                   3135: 
1.1.1.4   root     3136: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
1.1       root     3137:     int num;
1.1.1.2   root     3138: 
1.1.1.4   root     3139:     for (num = 0; num < 2; num++) {
1.1.1.13! root     3140:        sprite_entries[num] = xmalloc (max_sprite_entry * sizeof (struct sprite_entry));
1.1.1.4   root     3141:        color_changes[num] = xmalloc (max_color_change * sizeof (struct color_change));
1.1.1.2   root     3142:     }
                   3143: #endif
1.1.1.3   root     3144: 
1.1.1.7   root     3145:     pos = here ();
                   3146: 
                   3147:     org (0xF0FF70);
                   3148:     calltrap (deftrap (mousehack_helper));
                   3149:     dw (RTS);
                   3150: 
                   3151:     org (0xF0FFA0);
                   3152:     calltrap (deftrap (timehack_helper));
                   3153:     dw (RTS);
                   3154: 
                   3155:     org (pos);
                   3156: 
1.1.1.4   root     3157:     gen_custom_tables ();
                   3158:     build_blitfilltable ();
                   3159: 
                   3160:     drawing_init ();
                   3161: 
                   3162:     mousestate = unknown_mouse;
                   3163: 
                   3164:     if (needmousehack ())
                   3165:        mousehack_setfollow();
1.1       root     3166: }
                   3167: 
                   3168: /* Custom chip memory bank */
                   3169: 
1.1.1.4   root     3170: static uae_u32 custom_lget (uaecptr) REGPARAM;
                   3171: static uae_u32 custom_wget (uaecptr) REGPARAM;
                   3172: static uae_u32 custom_bget (uaecptr) REGPARAM;
                   3173: static void custom_lput (uaecptr, uae_u32) REGPARAM;
                   3174: static void custom_wput (uaecptr, uae_u32) REGPARAM;
                   3175: static void custom_bput (uaecptr, uae_u32) REGPARAM;
1.1       root     3176: 
                   3177: addrbank custom_bank = {
                   3178:     custom_lget, custom_wget, custom_bget,
                   3179:     custom_lput, custom_wput, custom_bput,
                   3180:     default_xlate, default_check
                   3181: };
                   3182: 
1.1.1.13! root     3183: STATIC_INLINE uae_u32 REGPARAM2 custom_wget_1 (uaecptr addr)
1.1       root     3184: {
1.1.1.13! root     3185:     special_mem |= S_READ;
1.1.1.4   root     3186:     switch (addr & 0x1FE) {
1.1.1.13! root     3187:      case 0x002: return DMACONR ();
        !          3188:      case 0x004: return VPOSR ();
        !          3189:      case 0x006: return VHPOSR ();
        !          3190: 
        !          3191:      case 0x008: return DSKDATR (current_hpos ());
        !          3192: 
        !          3193:      case 0x00A: return JOY0DAT ();
        !          3194:      case 0x00C: return JOY1DAT ();
        !          3195:      case 0x00E: return CLXDAT ();
        !          3196:      case 0x010: return ADKCONR ();
        !          3197: 
        !          3198:      case 0x012: return POT0DAT ();
        !          3199:      case 0x016: return POTGOR ();
        !          3200:      case 0x018: return SERDATR ();
        !          3201:      case 0x01A: return DSKBYTR (current_hpos ());
        !          3202:      case 0x01C: return INTENAR ();
        !          3203:      case 0x01E: return INTREQR ();
        !          3204:      case 0x07C: return DENISEID ();
        !          3205: 
        !          3206:      case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
        !          3207:      case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
        !          3208:      case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
        !          3209:      case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
        !          3210:      case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
        !          3211:      case 0x1BC: case 0x1BE:
        !          3212:        return COLOR_READ ((addr & 0x3E) / 2);
        !          3213:        break;
        !          3214: 
1.1       root     3215:      default:
1.1.1.13! root     3216:        custom_wput (addr, 0);
1.1       root     3217:        return 0xffff;
                   3218:     }
                   3219: }
                   3220: 
1.1.1.13! root     3221: uae_u32 REGPARAM2 custom_wget (uaecptr addr)
        !          3222: {
        !          3223:     sync_copper_with_cpu (current_hpos ());
        !          3224:     return custom_wget_1 (addr);
        !          3225: }
        !          3226: 
1.1.1.3   root     3227: uae_u32 REGPARAM2 custom_bget (uaecptr addr)
1.1       root     3228: {
1.1.1.13! root     3229:     special_mem |= S_READ;
        !          3230:     return custom_wget (addr & 0xfffe) >> (addr & 1 ? 0 : 8);
1.1       root     3231: }
                   3232: 
1.1.1.3   root     3233: uae_u32 REGPARAM2 custom_lget (uaecptr addr)
1.1       root     3234: {
1.1.1.13! root     3235:     special_mem |= S_READ;
        !          3236:     return ((uae_u32)custom_wget (addr & 0xfffe) << 16) | custom_wget ((addr + 2) & 0xfffe);
1.1       root     3237: }
                   3238: 
1.1.1.4   root     3239: void REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value)
1.1       root     3240: {
                   3241:     addr &= 0x1FE;
1.1.1.3   root     3242:     switch (addr) {
                   3243:      case 0x020: DSKPTH (value); break;
                   3244:      case 0x022: DSKPTL (value); break;
1.1.1.13! root     3245:      case 0x024: DSKLEN (value, hpos); break;
1.1.1.3   root     3246:      case 0x026: DSKDAT (value); break;
                   3247: 
                   3248:      case 0x02A: VPOSW (value); break;
                   3249:      case 0x2E:  COPCON (value); break;
                   3250:      case 0x030: SERDAT (value); break;
                   3251:      case 0x032: SERPER (value); break;
                   3252:      case 0x34: POTGO (value); break;
                   3253:      case 0x040: BLTCON0 (value); break;
                   3254:      case 0x042: BLTCON1 (value); break;
                   3255: 
                   3256:      case 0x044: BLTAFWM (value); break;
                   3257:      case 0x046: BLTALWM (value); break;
                   3258: 
                   3259:      case 0x050: BLTAPTH (value); break;
                   3260:      case 0x052: BLTAPTL (value); break;
                   3261:      case 0x04C: BLTBPTH (value); break;
                   3262:      case 0x04E: BLTBPTL (value); break;
                   3263:      case 0x048: BLTCPTH (value); break;
                   3264:      case 0x04A: BLTCPTL (value); break;
                   3265:      case 0x054: BLTDPTH (value); break;
                   3266:      case 0x056: BLTDPTL (value); break;
                   3267: 
                   3268:      case 0x058: BLTSIZE (value); break;
                   3269: 
                   3270:      case 0x064: BLTAMOD (value); break;
                   3271:      case 0x062: BLTBMOD (value); break;
                   3272:      case 0x060: BLTCMOD (value); break;
                   3273:      case 0x066: BLTDMOD (value); break;
                   3274: 
                   3275:      case 0x070: BLTCDAT (value); break;
                   3276:      case 0x072: BLTBDAT (value); break;
                   3277:      case 0x074: BLTADAT (value); break;
                   3278: 
                   3279:      case 0x07E: DSKSYNC (value); break;
                   3280: 
                   3281:      case 0x080: COP1LCH (value); break;
                   3282:      case 0x082: COP1LCL (value); break;
                   3283:      case 0x084: COP2LCH (value); break;
                   3284:      case 0x086: COP2LCL (value); break;
                   3285: 
                   3286:      case 0x088: COPJMP1 (value); break;
                   3287:      case 0x08A: COPJMP2 (value); break;
                   3288: 
1.1.1.4   root     3289:      case 0x08E: DIWSTRT (hpos, value); break;
                   3290:      case 0x090: DIWSTOP (hpos, value); break;
                   3291:      case 0x092: DDFSTRT (hpos, value); break;
                   3292:      case 0x094: DDFSTOP (hpos, value); break;
1.1.1.3   root     3293: 
1.1.1.13! root     3294:      case 0x096: DMACON (hpos, value); break;
1.1.1.3   root     3295:      case 0x098: CLXCON (value); break;
                   3296:      case 0x09A: INTENA (value); break;
                   3297:      case 0x09C: INTREQ (value); break;
                   3298:      case 0x09E: ADKCON (value); break;
                   3299: 
                   3300:      case 0x0A0: AUDxLCH (0, value); break;
                   3301:      case 0x0A2: AUDxLCL (0, value); break;
                   3302:      case 0x0A4: AUDxLEN (0, value); break;
                   3303:      case 0x0A6: AUDxPER (0, value); break;
                   3304:      case 0x0A8: AUDxVOL (0, value); break;
                   3305:      case 0x0AA: AUDxDAT (0, value); break;
                   3306: 
                   3307:      case 0x0B0: AUDxLCH (1, value); break;
                   3308:      case 0x0B2: AUDxLCL (1, value); break;
                   3309:      case 0x0B4: AUDxLEN (1, value); break;
                   3310:      case 0x0B6: AUDxPER (1, value); break;
                   3311:      case 0x0B8: AUDxVOL (1, value); break;
                   3312:      case 0x0BA: AUDxDAT (1, value); break;
                   3313: 
                   3314:      case 0x0C0: AUDxLCH (2, value); break;
                   3315:      case 0x0C2: AUDxLCL (2, value); break;
                   3316:      case 0x0C4: AUDxLEN (2, value); break;
                   3317:      case 0x0C6: AUDxPER (2, value); break;
                   3318:      case 0x0C8: AUDxVOL (2, value); break;
                   3319:      case 0x0CA: AUDxDAT (2, value); break;
                   3320: 
                   3321:      case 0x0D0: AUDxLCH (3, value); break;
                   3322:      case 0x0D2: AUDxLCL (3, value); break;
                   3323:      case 0x0D4: AUDxLEN (3, value); break;
                   3324:      case 0x0D6: AUDxPER (3, value); break;
                   3325:      case 0x0D8: AUDxVOL (3, value); break;
                   3326:      case 0x0DA: AUDxDAT (3, value); break;
                   3327: 
1.1.1.4   root     3328:      case 0x0E0: BPLPTH (hpos, value, 0); break;
                   3329:      case 0x0E2: BPLPTL (hpos, value, 0); break;
                   3330:      case 0x0E4: BPLPTH (hpos, value, 1); break;
                   3331:      case 0x0E6: BPLPTL (hpos, value, 1); break;
                   3332:      case 0x0E8: BPLPTH (hpos, value, 2); break;
                   3333:      case 0x0EA: BPLPTL (hpos, value, 2); break;
                   3334:      case 0x0EC: BPLPTH (hpos, value, 3); break;
                   3335:      case 0x0EE: BPLPTL (hpos, value, 3); break;
                   3336:      case 0x0F0: BPLPTH (hpos, value, 4); break;
                   3337:      case 0x0F2: BPLPTL (hpos, value, 4); break;
                   3338:      case 0x0F4: BPLPTH (hpos, value, 5); break;
                   3339:      case 0x0F6: BPLPTL (hpos, value, 5); break;
1.1.1.6   root     3340:      case 0x0F8: BPLPTH (hpos, value, 6); break;
                   3341:      case 0x0FA: BPLPTL (hpos, value, 6); break;
                   3342:      case 0x0FC: BPLPTH (hpos, value, 7); break;
                   3343:      case 0x0FE: BPLPTL (hpos, value, 7); break;
1.1.1.4   root     3344: 
                   3345:      case 0x100: BPLCON0 (hpos, value); break;
                   3346:      case 0x102: BPLCON1 (hpos, value); break;
                   3347:      case 0x104: BPLCON2 (hpos, value); break;
                   3348:      case 0x106: BPLCON3 (hpos, value); break;
1.1.1.3   root     3349: 
1.1.1.4   root     3350:      case 0x108: BPL1MOD (hpos, value); break;
                   3351:      case 0x10A: BPL2MOD (hpos, value); break;
1.1.1.3   root     3352: 
1.1.1.13! root     3353:      case 0x110: BPL1DAT (hpos, value); break;
1.1.1.3   root     3354:      case 0x112: BPL2DAT (value); break;
                   3355:      case 0x114: BPL3DAT (value); break;
                   3356:      case 0x116: BPL4DAT (value); break;
                   3357:      case 0x118: BPL5DAT (value); break;
                   3358:      case 0x11A: BPL6DAT (value); break;
1.1.1.6   root     3359:      case 0x11C: BPL7DAT (value); break;
                   3360:      case 0x11E: BPL8DAT (value); break;
1.1       root     3361: 
                   3362:      case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
                   3363:      case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
                   3364:      case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
                   3365:      case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
                   3366:      case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
1.1.1.2   root     3367:      case 0x1BC: case 0x1BE:
1.1.1.13! root     3368:        COLOR_WRITE (hpos, value & 0xFFF, (addr & 0x3E) / 2);
1.1.1.2   root     3369:        break;
                   3370:      case 0x120: case 0x124: case 0x128: case 0x12C:
1.1       root     3371:      case 0x130: case 0x134: case 0x138: case 0x13C:
1.1.1.4   root     3372:        SPRxPTH (hpos, value, (addr - 0x120) / 4);
1.1       root     3373:        break;
1.1.1.2   root     3374:      case 0x122: case 0x126: case 0x12A: case 0x12E:
1.1       root     3375:      case 0x132: case 0x136: case 0x13A: case 0x13E:
1.1.1.4   root     3376:        SPRxPTL (hpos, value, (addr - 0x122) / 4);
1.1       root     3377:        break;
1.1.1.2   root     3378:      case 0x140: case 0x148: case 0x150: case 0x158:
1.1       root     3379:      case 0x160: case 0x168: case 0x170: case 0x178:
1.1.1.4   root     3380:        SPRxPOS (hpos, value, (addr - 0x140) / 8);
1.1       root     3381:        break;
1.1.1.2   root     3382:      case 0x142: case 0x14A: case 0x152: case 0x15A:
1.1       root     3383:      case 0x162: case 0x16A: case 0x172: case 0x17A:
1.1.1.4   root     3384:        SPRxCTL (hpos, value, (addr - 0x142) / 8);
1.1       root     3385:        break;
                   3386:      case 0x144: case 0x14C: case 0x154: case 0x15C:
                   3387:      case 0x164: case 0x16C: case 0x174: case 0x17C:
1.1.1.4   root     3388:        SPRxDATA (hpos, value, (addr - 0x144) / 8);
1.1       root     3389:        break;
1.1.1.2   root     3390:      case 0x146: case 0x14E: case 0x156: case 0x15E:
1.1       root     3391:      case 0x166: case 0x16E: case 0x176: case 0x17E:
1.1.1.4   root     3392:        SPRxDATB (hpos, value, (addr - 0x146) / 8);
1.1       root     3393:        break;
1.1.1.3   root     3394: 
                   3395:      case 0x36: JOYTEST (value); break;
1.1.1.7   root     3396:      case 0x5A: BLTCON0L (value); break;
1.1.1.3   root     3397:      case 0x5C: BLTSIZV (value); break;
                   3398:      case 0x5E: BLTSIZH (value); break;
1.1.1.4   root     3399:      case 0x1E4: DIWHIGH (hpos, value); break;
                   3400:      case 0x10C: BPLCON4 (hpos, value); break;
1.1.1.7   root     3401:      case 0x1FC: FMODE (value); break;
1.1       root     3402:     }
                   3403: }
                   3404: 
1.1.1.4   root     3405: void REGPARAM2 custom_wput (uaecptr addr, uae_u32 value)
                   3406: {
                   3407:     int hpos = current_hpos ();
1.1.1.13! root     3408:     special_mem |= S_WRITE;
        !          3409: 
        !          3410:     sync_copper_with_cpu (hpos);
1.1.1.4   root     3411:     custom_wput_1 (hpos, addr, value);
                   3412: }
                   3413: 
                   3414: void REGPARAM2 custom_bput (uaecptr addr, uae_u32 value)
1.1       root     3415: {
1.1.1.2   root     3416:     static int warned = 0;
                   3417:     /* Is this correct now? (There are people who bput things to the upper byte of AUDxVOL). */
1.1.1.3   root     3418:     uae_u16 rval = (value << 8) | (value & 0xFF);
1.1.1.13! root     3419:     special_mem |= S_WRITE;
1.1.1.9   root     3420:     custom_wput (addr, rval);
1.1.1.2   root     3421:     if (!warned)
1.1.1.3   root     3422:        write_log ("Byte put to custom register.\n"), warned++;
1.1       root     3423: }
                   3424: 
1.1.1.3   root     3425: void REGPARAM2 custom_lput(uaecptr addr, uae_u32 value)
1.1       root     3426: {
1.1.1.13! root     3427:     special_mem |= S_WRITE;
1.1.1.9   root     3428:     custom_wput (addr & 0xfffe, value >> 16);
                   3429:     custom_wput ((addr + 2) & 0xfffe, (uae_u16)value);
1.1       root     3430: }

unix.superglobalmegacorp.com

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