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

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

unix.superglobalmegacorp.com

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