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

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

unix.superglobalmegacorp.com

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