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

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

unix.superglobalmegacorp.com

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