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

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

unix.superglobalmegacorp.com

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