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

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.2   root        6:   * Copyright 1995, 1996, 1997 Bernd Schmidt
                      7:   * Copyright 1995 Alessandro Bissacco
1.1       root        8:   */
                      9: 
1.1.1.3 ! root       10:  /*
        !            11:   * This file should be split into two parts. There are two concepts of a
        !            12:   * "frame" here: a hardware frame which emulates the display hardware of
        !            13:   * the A500, and a "drawing" frame, which renders data on the screen. You
        !            14:   * can have multiple hardware frames for one drawing frame, or completely
        !            15:   * inhibit drawing while hardware frames continue to be emulated. There
        !            16:   * should be a separate file "drawing.c" or something.
        !            17:   */
1.1       root       18: #include "sysconfig.h"
                     19: #include "sysdeps.h"
                     20: 
                     21: #include <ctype.h>
                     22: #include <assert.h>
                     23: 
                     24: #include "config.h"
                     25: #include "options.h"
1.1.1.3 ! root       26: #include "threaddep/penguin.h"
        !            27: #include "uae.h"
        !            28: #include "gensound.h"
        !            29: #include "sounddep/sound.h"
1.1       root       30: #include "events.h"
                     31: #include "memory.h"
                     32: #include "custom.h"
1.1.1.2   root       33: #include "readcpu.h"
1.1       root       34: #include "newcpu.h"
                     35: #include "cia.h"
                     36: #include "disk.h"
                     37: #include "blitter.h"
                     38: #include "xwin.h"
1.1.1.3 ! root       39: #include "joystick.h"
        !            40: #include "audio.h"
1.1       root       41: #include "keybuf.h"
                     42: #include "serial.h"
1.1.1.2   root       43: #include "osemu.h"
1.1.1.3 ! root       44: #include "autoconf.h"
        !            45: #include "gui.h"
        !            46: #include "picasso96.h"
        !            47: #include "p2c.h"
1.1.1.2   root       48: 
                     49: #ifdef X86_ASSEMBLY
                     50: #define LORES_HACK
                     51: #endif
1.1.1.3 ! root       52: #define SPRITE_COLLISIONS
1.1.1.2   root       53: 
                     54: /*
                     55:  * Several people have tried this define, with not much success. Turning on
                     56:  * AGA garbles the screen. A place you could start looking is the calcdiw()
                     57:  * function - the AGA timing parameters are different, and apparently I
                     58:  * haven't figured out the correct formula yet. Pity, the current one looks
                     59:  * logical.
1.1.1.3 ! root       60:  *
1.1.1.2   root       61:  * @@@ Probably won't compile in this version.
                     62:  */
1.1       root       63: 
                     64: /* #define EMULATE_AGA */
                     65: 
                     66: #ifndef EMULATE_AGA
                     67: #define AGA_CHIPSET 0
                     68: #else
                     69: #define AGA_CHIPSET 1
                     70: #endif
                     71: 
                     72: #define SMART_UPDATE 1
                     73: 
1.1.1.2   root       74: #ifdef SUPPORT_PENGUINS
                     75: #undef SMART_UPDATE
1.1.1.3 ! root       76: #define SMART_UPDATE 1
1.1.1.2   root       77: #endif
                     78: 
                     79: #if AGA_CHIPSET == 1
1.1       root       80: #define MAX_PLANES 8
1.1.1.2   root       81: #else
                     82: #define MAX_PLANES 6
                     83: #endif
                     84: 
                     85: /* Fetched data spends 9 lores pixels somewhere in the chips before it appears
                     86:  * on-screen. We don't emulate this. Instead, we cheat with the copper to
                     87:  * compensate (much easier that way). */
                     88: #define COPPER_MAGIC_FUDGE -9
                     89: /* We ignore that many lores pixels at the start of the display. These are
                     90:  * invisible anyway due to hardware DDF limits. */
                     91: #define DISPLAY_LEFT_SHIFT 0x38
                     92: static int lores_factor, lores_shift, sprite_width;
                     93: 
                     94: #define PIXEL_XPOS(HPOS) (((HPOS)*2 - DISPLAY_LEFT_SHIFT) << lores_shift)
1.1       root       95: 
1.1.1.2   root       96: /* @@@ Is maxhpos + 4 - 1 correct? (4 less isn't enough) */
                     97: #define max_diwlastword (PIXEL_XPOS(maxhpos + 4 -1))
1.1       root       98: 
1.1.1.3 ! root       99: /* Mouse and joystick emulation */
1.1.1.2   root      100: 
1.1       root      101: #define defstepx (1<<16)
                    102: #define defstepy (1<<16)
                    103: #define defxoffs 0
                    104: #define defyoffs 0
                    105: 
                    106: static const int docal = 60, xcaloff = 40, ycaloff = 20;
                    107: static const int calweight = 3;
                    108: static int lastsampledmx, lastsampledmy;
                    109: 
1.1.1.3 ! root      110: int buttonstate[3];
        !           111: int lastmx, lastmy;
        !           112: int newmousecounters;
        !           113: int ievent_alive = 0;
        !           114: 
        !           115: static enum { normal_mouse, dont_care_mouse, follow_mouse } mousestate;
        !           116: 
        !           117: static int mouse_x, mouse_y;
        !           118: int joy0button, joy1button;
        !           119: unsigned int joy0dir, joy1dir;
        !           120: static int lastspr0x,lastspr0y,lastdiffx,lastdiffy,spr0pos,spr0ctl;
        !           121: static int mstepx,mstepy,xoffs=defxoffs,yoffs=defyoffs;
        !           122: static int sprvbfl;
        !           123: 
        !           124: /* Video buffer description structure. Filled in by the graphics system
        !           125:  * dependent code. */
        !           126: 
        !           127: struct vidbuf_description gfxvidinfo;
        !           128: 
        !           129: /* Events */
1.1       root      130: 
1.1.1.3 ! root      131: unsigned long int cycles, nextevent, is_lastline, did_reset;
1.1.1.2   root      132: struct ev eventtab[ev_max];
                    133: 
1.1.1.3 ! root      134: frame_time_t vsynctime, vsyncmintime;
        !           135: 
1.1       root      136: int vpos;
1.1.1.3 ! root      137: uae_u16 lof;
1.1.1.2   root      138: static int lof_changed = 0, interlace_seen = 0;
1.1       root      139: 
1.1.1.2   root      140: static int copper_waiting_for_blitter, copper_active;
                    141: static const int dskdelay = 2; /* FIXME: ??? */
1.1       root      142: 
1.1.1.2   root      143: static int dblpf_ind1[256], dblpf_ind2[256], dblpf_2nd1[256], dblpf_2nd2[256];
                    144: static int dblpf_aga1[256], dblpf_aga2[256], linear_map_256[256], lots_of_twos[256];
1.1       root      145: 
1.1.1.2   root      146: static int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 };
1.1       root      147: 
1.1.1.3 ! root      148: /* Big lookup tables for planar to chunky conversion. */
        !           149: 
        !           150: uae_u32 hirestab_h[256][2];
        !           151: uae_u32 lorestab_h[256][4];
        !           152: 
        !           153: uae_u32 hirestab_l[256][1];
        !           154: uae_u32 lorestab_l[256][2];
        !           155: 
        !           156: static uae_u32 sprtaba[256],sprtabb[256];
        !           157: static uae_u32 clxtab[256];
        !           158: 
        !           159: /* The color lookup table. */
        !           160: 
        !           161: xcolnr xcolors[4096];
        !           162: 
1.1.1.2   root      163: /*
                    164:  * Hardware registers of all sorts.
                    165:  */
1.1       root      166: 
                    167: static int fmode;
                    168: 
1.1.1.3 ! root      169: static uae_u16 cregs[256];
1.1       root      170: 
1.1.1.3 ! root      171: uae_u16 intena,intreq;
        !           172: uae_u16 dmacon;
        !           173: uae_u16 adkcon; /* used by audio code */
1.1       root      174: 
1.1.1.3 ! root      175: static uae_u32 cop1lc,cop2lc,copcon;
1.1       root      176: 
1.1.1.2   root      177: /* This is but an educated guess. It seems to be correct, but this stuff
                    178:  * isn't documented well. */
1.1.1.3 ! root      179: enum sprstate { SPR_stop, SPR_restart, SPR_waiting_start, SPR_waiting_stop };
        !           180: static enum sprstate sprst[8];
        !           181: static int spron[8];
        !           182: static uaecptr sprpt[8];
1.1.1.2   root      183: static int sprxpos[8], sprvstart[8], sprvstop[8];
1.1       root      184: 
1.1.1.3 ! root      185: static uae_u32 bpl1dat,bpl2dat,bpl3dat,bpl4dat,bpl5dat,bpl6dat,bpl7dat,bpl8dat;
        !           186: static uae_s16 bpl1mod,bpl2mod;
1.1       root      187: 
1.1.1.3 ! root      188: static uaecptr bplpt[8];
1.1.1.2   root      189: #ifndef SMART_UPDATE
                    190: static char *real_bplpt[8];
                    191: #endif
1.1       root      192: 
                    193: /*static int blitcount[256];  blitter debug */
                    194: 
1.1.1.2   root      195: struct color_entry {
1.1       root      196: #if AGA_CHIPSET == 0
1.1.1.2   root      197:     /* X86.S expects this at the start of the structure. */
                    198:     xcolnr acolors[32];
1.1.1.3 ! root      199:     uae_u16 color_regs[32];
1.1       root      200: #else
1.1.1.3 ! root      201:     uae_u32 color_regs[256];
1.1       root      202: #endif
                    203: };
                    204: 
1.1.1.2   root      205: static struct color_entry current_colors;
                    206: struct color_entry colors_for_drawing;
                    207: static unsigned int bplcon0,bplcon1,bplcon2,bplcon3,bplcon4;
1.1.1.3 ! root      208: static int nr_planes_from_bplcon0, corrected_nr_planes_from_bplcon0;
1.1.1.2   root      209: static unsigned int diwstrt,diwstop,ddfstrt,ddfstop;
                    210: static unsigned int sprdata[8], sprdatb[8], sprctl[8], sprpos[8];
                    211: static int sprarmed[8], sprite_last_drawn_at[8];
1.1.1.3 ! root      212: static int last_sprite_point, nr_armed;
        !           213: static uae_u16 clxdat, clxcon;
        !           214: static int clx_sprmask;
        !           215: static uae_u32 dskpt;
        !           216: static uae_u16 dsklen,dsksync;
1.1       root      217: 
1.1.1.3 ! root      218: static uae_u32 coplc;
1.1.1.2   root      219: static unsigned int copi1,copi2;
1.1       root      220: 
1.1.1.2   root      221: static enum copper_states {
                    222:     COP_stop, COP_read, COP_do_read, COP_read_ignore, COP_do_read_ignore, COP_wait, COP_morewait, COP_move, COP_skip
1.1       root      223: } copstate;
1.1.1.2   root      224: /* The time the copper needs for one cycle depends on bitplane DMA. Whenever
                    225:  * possible, we calculate a fixed value and store it here. */
                    226: static int copper_cycle_time;
1.1       root      227: 
                    228: static int dsklength;
                    229: 
1.1.1.2   root      230: static int plffirstline,plflastline,plfstrt,plfstop,plflinelen;
                    231: static int diwfirstword,diwlastword;
1.1.1.3 ! root      232: static enum { DIW_waiting_start, DIW_waiting_stop } diwstate, hdiwstate;
1.1       root      233: 
                    234: int dskdmaen; /* used in cia.c */
                    235: 
1.1.1.2   root      236: /* 880 isn't a magic number, it's a safe number with some padding at the end.
                    237:  * This used to be 1000, but that's excessive. (840 is too low). I'm too lazy
                    238:  * to figure out the exact space needed. */
1.1       root      239: union {
                    240:     /* Let's try to align this thing. */
                    241:     double uupzuq;
                    242:     long int cruxmedo;
1.1.1.2   root      243:     unsigned char apixels[880];
1.1       root      244: } pixdata;
                    245: 
1.1.1.3 ! root      246: uae_u32 ham_linebuf[880];
        !           247: uae_u32 aga_linebuf[880], *aga_lbufptr;
1.1       root      248: 
                    249: char *xlinebuffer;
1.1.1.2   root      250: int next_lineno;
                    251: static int nln_how;
                    252: 
                    253: static int *amiga2aspect_line_map, *native2amiga_line_map;
1.1.1.3 ! root      254: static char *row_map[2049];
1.1.1.2   root      255: static int max_drawn_amiga_line;
1.1       root      256: 
                    257: /*
                    258:  * Statistics
                    259:  */
                    260: 
1.1.1.2   root      261: /* Used also by bebox.cpp */
                    262: unsigned long int msecs = 0, frametime = 0, timeframes = 0;
1.1       root      263: static unsigned long int seconds_base;
                    264: int bogusframe;
                    265: 
                    266: /*
                    267:  * helper functions
                    268:  */
                    269: 
1.1.1.3 ! root      270: int picasso_requested_on;
        !           271: int picasso_on;
        !           272: 
        !           273: uae_sem_t frame_sem, gui_sem, ihf_sem;
        !           274: volatile int frame_do_semup;
        !           275: volatile int inhibit_frame;
        !           276: 
1.1       root      277: static int framecnt = 0;
1.1.1.3 ! root      278: static int frame_redraw_necessary;
1.1       root      279: 
1.1.1.3 ! root      280: static __inline__ void count_frame (void)
1.1       root      281: {
1.1.1.3 ! root      282:     framecnt++;
        !           283:     if (framecnt >= currprefs.framerate)
        !           284:        framecnt = 0;
        !           285: }
        !           286: 
        !           287: void check_prefs_changed_custom (void)
        !           288: {
        !           289:     currprefs.framerate = changed_prefs.framerate;
        !           290:     /* Not really the right place... */
        !           291:     if (currprefs.fake_joystick != changed_prefs.fake_joystick) {      
        !           292:        currprefs.fake_joystick = changed_prefs.fake_joystick;
        !           293:        joystick_setting_changed ();
1.1       root      294:     }
1.1.1.3 ! root      295:     currprefs.immediate_blits = changed_prefs.immediate_blits;
        !           296:     currprefs.blits_32bit_enabled = changed_prefs.blits_32bit_enabled;
        !           297:        
1.1       root      298: }
                    299: 
1.1.1.3 ! root      300: static __inline__ void setclr (uae_u16 *p, uae_u16 val)
1.1       root      301: {
                    302:     if (val & 0x8000) {
                    303:        *p |= val & 0x7FFF;
                    304:     } else {
                    305:        *p &= ~val;
                    306:     }
                    307: }
                    308: 
1.1.1.3 ! root      309: __inline__ int current_hpos (void)
1.1       root      310: {
                    311:     return cycles - eventtab[ev_hsync].oldcycles;
                    312: }
                    313: 
1.1.1.3 ! root      314: static __inline__ uae_u8 *pfield_xlateptr (uaecptr plpt, int bytecount)
1.1.1.2   root      315: {
                    316:     if (!chipmem_bank.check(plpt,bytecount)) {
                    317:        static int count = 0;
1.1.1.3 ! root      318:        if (!count)
        !           319:            count++, write_log ("Warning: Bad playfield pointer\n");
1.1.1.2   root      320:        return NULL;
                    321:     }
                    322:     return chipmem_bank.xlateaddr(plpt);
                    323: }
                    324: 
                    325: static void calculate_copper_cycle_time (void)
1.1       root      326: {
1.1.1.2   root      327:     if (diwstate == DIW_waiting_start || !dmaen (DMA_BITPLANE)) {
                    328:        copper_cycle_time = 2;
                    329:        return;
                    330:     }
1.1.1.3 ! root      331:     copper_cycle_time = corrected_nr_planes_from_bplcon0 <= 4 ? 2 : -1;
1.1.1.2   root      332: }
                    333: 
                    334: /* line_draw_funcs: pfield_do_linetoscr, pfield_do_fill_line, decode_ham6 */
                    335: typedef void (*line_draw_func)(int, int);
                    336: 
                    337: #define LINE_UNDECIDED 1
                    338: #define LINE_DECIDED 2
                    339: #define LINE_DECIDED_DOUBLE 3
                    340: #define LINE_AS_PREVIOUS 4
                    341: #define LINE_BORDER_NEXT 5
                    342: #define LINE_BORDER_PREV 6
                    343: #define LINE_DONE 7
                    344: #define LINE_DONE_AS_PREVIOUS 8
                    345: #define LINE_REMEMBERED_AS_PREVIOUS 9
                    346: 
                    347: static char *line_drawn;
                    348: static char linestate[(maxvpos + 1)*2 + 1];
                    349: 
                    350: static int min_diwstart, max_diwstop, prev_x_adjust, linetoscr_x_adjust, linetoscr_right_x;
1.1.1.3 ! root      351: static int linetoscr_x_adjust_bytes;
1.1.1.2   root      352: static int thisframe_y_adjust, prev_y_adjust, thisframe_first_drawn_line, thisframe_last_drawn_line;
                    353: static int thisframe_y_adjust_real, max_ypos_thisframe, min_ypos_for_screen;
1.1.1.3 ! root      354: static int extra_y_adjust;
1.1.1.2   root      355: 
1.1.1.3 ! root      356: static uae_u8 line_data[(maxvpos+1) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2];
1.1.1.2   root      357: 
                    358: /*
                    359:  * The idea behind this code is that at some point during each horizontal
                    360:  * line, we decide how to draw this line. There are many more-or-less
                    361:  * independent decisions, each of which can be taken at a different horizontal
                    362:  * position.
1.1.1.3 ! root      363:  * Sprites, color changes and bitplane delay changes are handled specially:
        !           364:  * There isn't a single decision, but a list of structures containing
1.1.1.2   root      365:  * information on how to draw the line.
                    366:  */
                    367: 
                    368: struct color_change {
                    369:     int linepos;
                    370:     int regno;
                    371:     unsigned long value;
                    372: };
                    373: 
                    374: struct sprite_draw {
                    375:     int linepos;
                    376:     int num;
                    377:     int ctl;
1.1.1.3 ! root      378:     uae_u32 datab;
1.1.1.2   root      379: };
                    380: 
                    381: struct delay_change {
                    382:     int linepos;
                    383:     unsigned int value;
                    384: };
                    385: 
                    386: /* Way too much... */
                    387: #define MAX_REG_CHANGE ((maxvpos+1) * 2 * maxhpos)
                    388: static int current_change_set;
                    389: 
                    390: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
1.1.1.3 ! root      391: /* sam: Those arrays uses around 7Mb of BSS... That seems  */
1.1.1.2   root      392: /* too much for AmigaDOS (uae crashes as soon as one loads */
                    393: /* it. So I use a different strategy here (realloc the     */
                    394: /* arrays when needed. That strategy might be usefull for  */
                    395: /* computer with low memory.                               */
                    396: static struct sprite_draw  *sprite_positions[2];
1.1.1.3 ! root      397: static int max_sprite_draw    = 400;
        !           398: static int delta_sprite_draw  = 0;
1.1.1.2   root      399: static struct color_change *color_changes[2];
1.1.1.3 ! root      400: static int max_color_change   = 400;
        !           401: static int delta_color_change = 0;
        !           402: static struct delay_change *delay_changes;
        !           403: static int max_delay_change = 100;
        !           404: static int delta_delay_change = 0;
1.1.1.2   root      405: #else
                    406: static struct sprite_draw sprite_positions[2][MAX_REG_CHANGE];
                    407: static struct color_change color_changes[2][MAX_REG_CHANGE];
1.1.1.3 ! root      408: /* We don't remember those across frames, that would be too much effort.
1.1.1.2   root      409:  * We simply redraw the line whenever we see one of these. */
                    410: static struct delay_change delay_changes[MAX_REG_CHANGE];
1.1.1.3 ! root      411: #endif
1.1.1.2   root      412: static struct sprite_draw *curr_sprite_positions, *prev_sprite_positions;
                    413: static struct color_change *curr_color_changes, *prev_color_changes;
                    414: 
                    415: static int next_color_change, next_sprite_draw, next_delay_change;
                    416: 
                    417: static struct color_entry color_tables[2][(maxvpos+1) * 2];
                    418: static struct color_entry *curr_color_tables, *prev_color_tables;
                    419: static int next_color_entry, remembered_color_entry, drawing_color_matches;
                    420: static enum { color_match_acolors, color_match_full } color_match_type;
1.1.1.3 ! root      421: static int color_src_match, color_dest_match, color_compare_result;
1.1.1.2   root      422: 
                    423: static int last_redraw_point;
                    424: 
                    425: static int first_drawn_line, last_drawn_line;
                    426: static int first_block_line, last_block_line;
                    427: 
1.1.1.3 ! root      428: static __inline__ void docols(struct color_entry *colentry)
        !           429: {
        !           430: #if AGA_CHIPSET == 0
        !           431:     int i;
        !           432:     for (i = 0; i < 32; i++) {
        !           433:        int v = colentry->color_regs[i];
        !           434:        if (v < 0 || v > 4095)
        !           435:          continue;
        !           436:        colentry->acolors[i] = xcolors[v];
        !           437:     }
        !           438: #endif
        !           439: }
        !           440: 
        !           441: void notice_new_xcolors (void)
        !           442: {
        !           443:     int i;
        !           444: 
        !           445:     docols(&current_colors);
        !           446:     docols(&colors_for_drawing);
        !           447:     for (i = 0; i < (maxvpos+1)*2; i++) {
        !           448:        docols(color_tables[0]+i);
        !           449:        docols(color_tables[1]+i);
        !           450:     }
        !           451: }
        !           452: 
        !           453: void notice_screen_contents_lost (void)
        !           454: {
        !           455:     frame_redraw_necessary = 2;
        !           456: }
        !           457: 
1.1.1.2   root      458: static void init_regchanges (void)
                    459: {
                    460:     size_t i;
                    461: 
                    462:     next_color_change = 0;
                    463:     next_sprite_draw = 0;
                    464:     current_change_set = 0;
                    465:     for (i = 0; i < sizeof linestate / sizeof *linestate; i++)
                    466:        linestate[i] = LINE_UNDECIDED;
                    467: }
                    468: 
                    469: /* struct decision contains things we save across drawing frames for
                    470:  * comparison (smart update stuff). */
                    471: struct decision {
                    472:     unsigned long color0;
                    473:     int which;
                    474:     int plfstrt, plflinelen;
                    475:     int diwfirstword, diwlastword;
                    476:     int ctable;
                    477: 
1.1.1.3 ! root      478:     uae_u16 bplcon0, bplcon1, bplcon2;
1.1.1.2   root      479: #if 0 /* We don't need this. */
1.1.1.3 ! root      480:     uae_u16 bplcon3;
1.1.1.2   root      481: #endif
                    482: #if AGA_CHIPSET == 1
1.1.1.3 ! root      483:     uae_u16 bplcon4;
1.1.1.2   root      484: #endif
                    485: };
                    486: 
                    487: /* Anything related to changes in hw registers during the DDF for one
                    488:  * line. */
                    489: struct draw_info {
                    490:     int first_sprite_draw, last_sprite_draw;
                    491:     int first_color_change, last_color_change;
                    492:     int first_delay_change, last_delay_change;
                    493:     int nr_color_changes, nr_sprites;
                    494: };
                    495: 
                    496: /* These few are only needed during/at the end of the scanline, and don't
                    497:  * have to be remembered. */
                    498: static int decided_bpl1mod, decided_bpl2mod, decided_nr_planes, decided_hires;
                    499: 
                    500: /* These are generated by the drawing code from the line_decisions array for
                    501:  * each line that needs to be drawn. */
                    502: static int bplehb, bplham, bpldualpf, bpldualpfpri, bplplanecnt, bplhires;
                    503: static int bpldelay1, bpldelay2;
                    504: static int plfpri[3];
                    505: 
                    506: static struct decision line_decisions[2 * (maxvpos+1) + 1];
                    507: static struct draw_info line_drawinfo[2][2 * (maxvpos+1) + 1];
                    508: static struct draw_info *curr_drawinfo, *prev_drawinfo;
                    509: static struct decision *dp_for_drawing;
                    510: static struct draw_info *dip_for_drawing;
                    511: 
1.1.1.3 ! root      512: static char line_changed[2 * (maxvpos+1)];
1.1.1.2   root      513: 
                    514: #ifdef SMART_UPDATE
                    515: #define MARK_LINE_CHANGED(l) do { line_changed[l] = 1; } while (0)
                    516: #else
                    517: #define MARK_LINE_CHANGED(l) do { } while (0)
                    518: #endif
                    519: 
                    520: static struct decision thisline_decision;
                    521: static int modulos_added, plane_decided, color_decided, very_broken_program;
                    522: 
                    523: static void do_sprites(int currvp, int currhp);
                    524: 
                    525: static void remember_ctable (void)
                    526: {
                    527:     if (remembered_color_entry == -1) {
                    528:        /* The colors changed since we last recorded a color map. Record a
                    529:         * new one. */
                    530:        memcpy (curr_color_tables + next_color_entry, &current_colors, sizeof current_colors);
                    531:        remembered_color_entry = next_color_entry++;
                    532:     }
                    533:     thisline_decision.ctable = remembered_color_entry;
                    534:     if (color_src_match == -1 || color_dest_match != remembered_color_entry
                    535:        || line_decisions[next_lineno].ctable != color_src_match)
                    536:     {
                    537:        /* The remembered comparison didn't help us - need to compare again. */
                    538:        int oldctable = line_decisions[next_lineno].ctable;
                    539:        int changed = 0;
                    540: 
1.1.1.3 ! root      541:        if (oldctable == -1) {
1.1.1.2   root      542:            changed = 1;
                    543:            color_src_match = color_dest_match = -1;
                    544:        } else {
1.1.1.3 ! root      545:            color_compare_result = memcmp (&prev_color_tables[oldctable].color_regs,
        !           546:                                           &current_colors.color_regs,
        !           547:                                           sizeof current_colors.color_regs) != 0;
        !           548:            if (color_compare_result)
        !           549:                changed = 1;
        !           550:            color_src_match = oldctable;
1.1.1.2   root      551:            color_dest_match = remembered_color_entry;
1.1.1.3 ! root      552:        }
        !           553:        if (changed) {
        !           554:            line_changed[next_lineno] = 1;
        !           555:        }
        !           556:     } else {
        !           557:        /* We know the result of the comparison */
        !           558:        if (color_compare_result)
        !           559:            line_changed[next_lineno] = 1;
        !           560:     }
        !           561: }
        !           562: 
        !           563: static void remember_ctable_for_border (void)
        !           564: {
        !           565:     remember_ctable ();
        !           566: #if 0
        !           567:     if (remembered_color_entry == -1) {
        !           568:        /* The colors changed since we last recorded a color map. Record a
        !           569:         * new one. */
        !           570:        memcpy (curr_color_tables + next_color_entry, &current_colors, sizeof current_colors);
        !           571:        remembered_color_entry = next_color_entry++;
        !           572:     }
        !           573:     thisline_decision.ctable = remembered_color_entry;
        !           574:     if (color_src_match == -1 || color_dest_match != remembered_color_entry
        !           575:        || line_decisions[next_lineno].ctable != color_src_match)
        !           576:     {
        !           577:        /* The remembered comparison didn't help us - need to compare again. */
        !           578:        int oldctable = line_decisions[next_lineno].ctable;
        !           579:        int changed = 0;
        !           580: 
        !           581:        if (oldctable == -1) {
        !           582:            changed = 1;
        !           583:            color_src_match = color_dest_match = -1;
        !           584:        } else {
        !           585:            color_compare_result = memcmp (&prev_color_tables[oldctable].color_regs,
        !           586:                                           &current_colors.color_regs,
        !           587:                                           sizeof current_colors.color_regs) != 0;
        !           588:            if (color_compare_result)
        !           589:                changed = 1;
1.1.1.2   root      590:            color_src_match = oldctable;
1.1.1.3 ! root      591:            color_dest_match = remembered_color_entry;
        !           592:        }
        !           593:        if (changed) {
        !           594:            line_changed[next_lineno] = 1;
1.1.1.2   root      595:        }
1.1.1.3 ! root      596:     } else {
        !           597:        /* We know the result of the comparison */
        !           598:        if (color_compare_result)
        !           599:            line_changed[next_lineno] = 1;
1.1.1.2   root      600:     }
1.1.1.3 ! root      601: #endif
1.1.1.2   root      602: }
                    603: 
1.1.1.3 ! root      604: /* Called to determine the state of the horizontal display window state
        !           605:  * machine at the current position. It might have changed since we last
        !           606:  * checked.  */
1.1.1.2   root      607: static void decide_diw (void)
                    608: {
1.1.1.3 ! root      609:     if (hdiwstate == DIW_waiting_start && thisline_decision.diwfirstword == -1
        !           610:        && PIXEL_XPOS (current_hpos ()) >= diwfirstword)
        !           611:     {
1.1.1.2   root      612:        thisline_decision.diwfirstword = diwfirstword;
1.1.1.3 ! root      613:        hdiwstate = DIW_waiting_stop;
1.1.1.2   root      614:        /* Decide playfield delays only at DIW start, because they don't matter before and
                    615:         * some programs change them after DDF start but before DIW start. */
                    616:        thisline_decision.bplcon1 = bplcon1;
                    617:        if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
                    618:            MARK_LINE_CHANGED (next_lineno);
                    619:        thisline_decision.diwlastword = -1;
                    620:     }
1.1.1.3 ! root      621:     if (hdiwstate == DIW_waiting_stop && thisline_decision.diwlastword == -1
        !           622:        && PIXEL_XPOS (current_hpos ()) >= diwlastword)
        !           623:     {
1.1.1.2   root      624:        thisline_decision.diwlastword = diwlastword;
1.1.1.3 ! root      625:        hdiwstate = DIW_waiting_start;
1.1.1.2   root      626:        if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword)
                    627:            MARK_LINE_CHANGED (next_lineno);
                    628:     }
                    629: }
                    630: 
1.1.1.3 ! root      631: /* Called when we know that the line is not in the border and we want to it.
        !           632:  * The data fetch starting position and length are passed as parameters. */
1.1.1.2   root      633: static __inline__ void decide_as_playfield (int startpos, int len)
                    634: {
                    635:     thisline_decision.which = 1;
                    636: 
                    637:     /* The latter condition might be able to happen in interlaced frames. */
                    638:     if (vpos >= minfirstline && (thisframe_first_drawn_line == -1 || vpos < thisframe_first_drawn_line))
                    639:        thisframe_first_drawn_line = vpos;
                    640:     thisframe_last_drawn_line = vpos;
                    641: 
                    642:     thisline_decision.plfstrt = startpos;
                    643:     thisline_decision.plflinelen = len;
                    644: 
                    645:     /* These are for comparison. */
                    646:     thisline_decision.bplcon0 = bplcon0;
                    647:     thisline_decision.bplcon2 = bplcon2;
                    648: #if AGA_CHIPSET == 1
                    649:     thisline_decision.bplcon4 = bplcon4;
                    650: #endif
                    651: 
                    652: #ifdef SMART_UPDATE
                    653:     if (line_decisions[next_lineno].plfstrt != thisline_decision.plfstrt
                    654:        || line_decisions[next_lineno].plflinelen != thisline_decision.plflinelen
                    655:        || line_decisions[next_lineno].bplcon0 != thisline_decision.bplcon0
                    656:        || line_decisions[next_lineno].bplcon2 != thisline_decision.bplcon2
                    657: #if AGA_CHIPSET == 1
                    658:        || line_decisions[next_lineno].bplcon4 != thisline_decision.bplcon4
                    659: #endif
                    660:        )
                    661: #endif /* SMART_UPDATE */
                    662:        line_changed[next_lineno] = 1;
                    663: }
                    664: 
1.1.1.3 ! root      665: /* Called when we already decided whether the line is playfield or border,
        !           666:  * but are no longer sure that this was such a good idea. This can make a
        !           667:  * difference only for very badly written software. */
1.1.1.2   root      668: static __inline__ void post_decide_line (void)
                    669: {
                    670:     static int warned = 0;
                    671:     int tmp;
                    672: 
                    673:     if (thisline_decision.which == 1 && current_hpos () < thisline_decision.plfstrt + thisline_decision.plflinelen
                    674:        && ((bplcon0 & 0x7000) == 0 || !dmaen (DMA_BITPLANE)))
                    675:     {
                    676:        /* This is getting gross... */
                    677:        thisline_decision.plflinelen = current_hpos() - thisline_decision.plfstrt;
                    678:        thisline_decision.plflinelen &= 7;
                    679:        if (thisline_decision.plflinelen == 0)
                    680:            thisline_decision.which = -1;
                    681:        /* ... especially THIS! */
                    682:        modulos_added = 1;
                    683:        return;
                    684:     }
1.1.1.3 ! root      685: 
1.1.1.2   root      686:     if (thisline_decision.which != -1 || diwstate == DIW_waiting_start || (bplcon0 & 0x7000) == 0
                    687:        || !dmaen (DMA_BITPLANE) || current_hpos () >= thisline_decision.plfstrt + thisline_decision.plflinelen)
                    688:        return;
                    689: #if 0 /* Can't warn because Kickstart 1.3 does it at reset time ;-) */
                    690:     if (!warned) {
1.1.1.3 ! root      691:        write_log ("That program you are running is _really_ broken.\n");
1.1.1.2   root      692:        warned = 1;
                    693:     }
                    694: #endif
                    695: 
                    696:     decided_hires = (bplcon0 & 0x8000) == 0x8000;
1.1.1.3 ! root      697:     decided_nr_planes = nr_planes_from_bplcon0;
1.1.1.2   root      698: 
                    699:     /* Magic 12, Ray of Hope 2 demo does ugly things. Looks great from the
                    700:      * outside, rotten inside. */
                    701:     if (decided_hires) {
                    702:        tmp = current_hpos () & ~3;
                    703:        very_broken_program = current_hpos () & 3;
                    704:     } else {
                    705:        tmp = current_hpos () & ~7;
                    706:        very_broken_program = current_hpos () & 7;
                    707:     }
                    708:     MARK_LINE_CHANGED (next_lineno); /* Play safe. */
                    709:     decide_as_playfield (tmp, plflinelen + plfstrt - tmp);
                    710: }
                    711: 
                    712: static void decide_line_1 (void)
                    713: {
                    714:     do_sprites(vpos, current_hpos ());
                    715: 
                    716:     /* Surprisingly enough, this seems to be correct here - putting this into
                    717:      * decide_diw() results in garbage. */
                    718:     if (diwstate == DIW_waiting_start && vpos == plffirstline) {
                    719:        diwstate = DIW_waiting_stop;
                    720:        calculate_copper_cycle_time ();
                    721:     }
                    722:     if (diwstate == DIW_waiting_stop && vpos == plflastline) {
                    723:        diwstate = DIW_waiting_start;
                    724:        calculate_copper_cycle_time ();
                    725:     }
                    726: 
                    727:     if (framecnt != 0) {
                    728: /*     thisline_decision.which = -2; This doesn't do anything but hurt, I think. */
                    729:        return;
                    730:     }
1.1.1.3 ! root      731: 
        !           732:     if (!dmaen(DMA_BITPLANE) || diwstate == DIW_waiting_start || nr_planes_from_bplcon0 == 0) {
1.1.1.2   root      733:        /* We don't want to draw this one. */
                    734:        thisline_decision.which = -1;
1.1.1.3 ! root      735:        thisline_decision.plfstrt = plfstrt;
        !           736:        thisline_decision.plflinelen = plflinelen;
1.1.1.2   root      737:        return;
                    738:     }
                    739: 
                    740:     decided_hires = (bplcon0 & 0x8000) == 0x8000;
1.1.1.3 ! root      741:     decided_nr_planes = nr_planes_from_bplcon0;
1.1.1.2   root      742: #if 0
1.1.1.3 ! root      743:     /* The blitter gets slower if there's high bitplane activity.
1.1.1.2   root      744:      * @@@ but the values must be different. FIXME */
                    745:     if (bltstate != BLT_done
                    746:        && ((decided_hires && decided_nr_planes > 2)
                    747:            || (!decided_hires && decided_nr_planes > 4)))
                    748:     {
                    749:        int pl = decided_nr_planes;
                    750:        unsigned int n = (eventtab[ev_blitter].evtime-cycles);
                    751:        if (n > plflinelen)
                    752:            n = plflinelen;
                    753:        n >>= 1;
                    754:        if (decided_hires)
                    755:            pl <<= 1;
                    756:        if (pl == 8)
                    757:            eventtab[ev_blitter].evtime += plflinelen;
                    758:        else if (pl == 6)
                    759:            eventtab[ev_blitter].evtime += n*2;
                    760:        else if (pl == 5)
                    761:            eventtab[ev_blitter].evtime += n*3/2;
                    762:        events_schedule();
                    763:     }
                    764: #endif
                    765:     decide_as_playfield (plfstrt, plflinelen);
                    766: }
                    767: 
1.1.1.3 ! root      768: /* Main entry point for deciding how to draw a line. May either do
        !           769:  * nothing, decide the line as border, or decide the line as playfield. */
1.1.1.2   root      770: static __inline__ void decide_line (void)
                    771: {
                    772:     if (thisline_decision.which == 0 && current_hpos() >= plfstrt)
                    773:        decide_line_1 ();
                    774: }
                    775: 
1.1.1.3 ! root      776: /* Called when a color is about to be changed (write to a color register),
        !           777:  * but the new color has not been entered into the table yet. */
        !           778: static void record_color_change (int regno, unsigned long value)
        !           779: {
        !           780:     /* Early positions don't appear on-screen. */
        !           781:     if (framecnt != 0 || vpos < minfirstline || current_hpos () < 0x18
        !           782:        /*|| currprefs.emul_accuracy == 0*/)
        !           783:        return;
        !           784: 
        !           785:     decide_diw ();
        !           786:     decide_line ();
        !           787: 
        !           788:     /* See if we can record the color table, but have not done so yet.
        !           789:      * @@@ There might be a minimal performance loss in case someone changes
        !           790:      * a color exactly at the start of the DIW. I don't think it can actually
        !           791:      * fail to work even in this case, but I'm not 100% sure.
        !           792:      * @@@ There might be a slightly larger performance loss if we're drawing
        !           793:      * this line as border... especially if there are changes in colors != 0
        !           794:      * we might end up setting line_changed for no reason. FIXME */
        !           795:     if (thisline_decision.diwfirstword >= 0
        !           796:        && thisline_decision.which != 0)
        !           797:     {
        !           798:        if (thisline_decision.ctable == -1)
        !           799:            remember_ctable ();
        !           800:     }
        !           801: 
        !           802:     /* Changes outside the DIW can be ignored if the modified color is not the
        !           803:      * background color, or if the accuracy is < 2. */
        !           804:     if ((regno != 0 || currprefs.emul_accuracy < 2)
        !           805:        && (diwstate == DIW_waiting_start || thisline_decision.diwfirstword < 0
        !           806:            || thisline_decision.diwlastword >= 0
        !           807:            || thisline_decision.which == 0
        !           808:            || (thisline_decision.which == 1 && current_hpos() >= thisline_decision.plfstrt + thisline_decision.plflinelen)))
        !           809:        return;
        !           810: 
        !           811:     /* If the border is changed the first time before the DIW, record the
        !           812:      * original starting border value. */
        !           813:     if (regno == 0 && thisline_decision.color0 == 0xFFFFFFFFul && thisline_decision.diwfirstword < 0) {
        !           814:        thisline_decision.color0 = current_colors.color_regs[0];
        !           815:        if (line_decisions[next_lineno].color0 != value)
        !           816:            line_changed[next_lineno] = 1;
        !           817:     }
        !           818:     /* Anything else gets recorded in the color_changes table. */
        !           819: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
        !           820:     if(next_color_change >= max_color_change) {
        !           821:        ++delta_color_change;
        !           822:        return;
        !           823:     }
        !           824: #endif
        !           825:     curr_color_changes[next_color_change].linepos = current_hpos ();
        !           826:     curr_color_changes[next_color_change].regno = regno;
        !           827:     curr_color_changes[next_color_change++].value = value;
        !           828: }
        !           829: 
        !           830: /* Stupid hack to get some Sanity demos working. */
1.1.1.2   root      831: static void decide_delay (void)
                    832: {
                    833:     static int warned;
                    834: 
                    835:     /* Don't do anything if we're outside the DIW. */
                    836:     if (thisline_decision.diwfirstword == -1 || thisline_decision.diwlastword > 0)
                    837:        return;
                    838:     decide_line ();
                    839:     /* Half-hearted attempt to get things right even when post_decide_line() changes
                    840:      * the decision afterwards. */
                    841:     if (thisline_decision.which != 1) {
                    842:        thisline_decision.bplcon1 = bplcon1;
                    843:        return;
                    844:     }
                    845:     /* @@@ Could check here for DDF stopping earlier than DIW */
1.1.1.3 ! root      846: 
        !           847: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
        !           848:     if(next_delay_change >= max_delay_change) {
        !           849:        ++delta_delay_change;
        !           850:        return;
        !           851:     }
        !           852: #endif
1.1.1.2   root      853:     delay_changes[next_delay_change].linepos = current_hpos ();
                    854:     delay_changes[next_delay_change++].value = bplcon1;
                    855:     if (!warned) {
                    856:        warned = 1;
1.1.1.3 ! root      857:        write_log ("Program is torturing BPLCON1.\n");
1.1.1.2   root      858:     }
                    859: }
                    860: 
                    861: /*
                    862:  * The decision which bitplane pointers to use is not taken at plfstrt, since
                    863:  * data fetch does not start for all planes at this point. Therefore, we wait
                    864:  * for the end of the ddf area or the first write to any of the bitplane
                    865:  * pointer registers, whichever comes last, before we decide which plane pointers
                    866:  * to use.
                    867:  * Call decide_line() before this function.
                    868:  */
                    869: static void decide_plane (void)
                    870: {
                    871:     int i, bytecount;
                    872: 
                    873:     if (framecnt != 0 || plane_decided)
                    874:        return;
                    875: 
                    876:     if (decided_nr_planes == -1 /* Still undecided */
                    877:        || current_hpos () < thisline_decision.plfstrt + thisline_decision.plflinelen)
                    878:        return;
                    879: 
                    880:     plane_decided = 1;
                    881: 
                    882:     bytecount = plflinelen / (decided_hires ? 4 : 8) * 2;
                    883: 
                    884:     if (bytecount > MAX_WORDS_PER_LINE * 2) {
                    885:        /* Can't happen. */
                    886:        static int warned = 0;
                    887:        if (!warned)
1.1.1.3 ! root      888:            write_log ("Mysterious bug in decide_plane(). Please report.\n");
1.1.1.2   root      889:        bytecount = 0;
                    890:     }
                    891:     if (!very_broken_program) {
1.1.1.3 ! root      892:        uae_u8 *dataptr = line_data[next_lineno];
1.1.1.2   root      893:        for (i = 0; i < decided_nr_planes; i++, dataptr += MAX_WORDS_PER_LINE*2) {
1.1.1.3 ! root      894:            uaecptr pt = bplpt[i];
        !           895:            uae_u8 *real_ptr = pfield_xlateptr(pt, bytecount);
1.1.1.2   root      896:            if (real_ptr == NULL)
                    897:                real_ptr = pfield_xlateptr(0, 0);
                    898: #ifdef SMART_UPDATE
1.1.1.3 ! root      899: #if 1
        !           900:            if (line_changed[next_lineno])
1.1.1.2   root      901:                memcpy (dataptr, real_ptr, bytecount);
1.1.1.3 ! root      902:            else
        !           903: #endif
        !           904:                line_changed[next_lineno] |= memcmpy (dataptr, real_ptr, bytecount);
1.1.1.2   root      905: #else
                    906:            real_bplpt[i] = real_ptr;
                    907: #endif
                    908:        }
1.1       root      909:     } else {
1.1.1.3 ! root      910:        uae_u8 *dataptr = line_data[next_lineno];
1.1.1.2   root      911:        for (i = 0; i < decided_nr_planes; i++, dataptr += MAX_WORDS_PER_LINE*2) {
1.1.1.3 ! root      912:            uaecptr pt = bplpt[i];
        !           913:            uae_u8 *real_ptr;
        !           914: 
1.1.1.2   root      915:            if (decided_hires) {
                    916:                switch (i) {
                    917:                 case 3: pt -= 2;
                    918:                 case 2: pt -= (very_broken_program >= 3 ? 2 : 0); break;
                    919:                 case 1: pt -= (very_broken_program >= 2 ? 2 : 0); break;
                    920:                 case 0: break;
                    921:                }
                    922:            } else {
                    923:                switch (i) {
                    924:                 case 5: pt -= (very_broken_program >= 3 ? 2 : 0); break;
                    925:                 case 4: pt -= (very_broken_program >= 7 ? 2 : 0); break;
                    926:                 case 3: pt -= (very_broken_program >= 2 ? 2 : 0); break;
                    927:                 case 2: pt -= (very_broken_program >= 6 ? 2 : 0); break;
                    928:                 case 1: pt -= (very_broken_program >= 4 ? 2 : 0); break;
                    929:                 case 0: break;
                    930:                }
                    931:            }
                    932:            real_ptr = pfield_xlateptr(pt, bytecount);
                    933:            if (real_ptr == NULL)
                    934:                real_ptr = pfield_xlateptr(0, 0);
                    935: #ifdef SMART_UPDATE
                    936:            if (!line_changed[next_lineno])
                    937:                line_changed[next_lineno] |= memcmpy (dataptr, real_ptr, bytecount);
                    938:            else
                    939:                memcpy (dataptr, real_ptr, bytecount);
                    940: #else
                    941:            real_bplpt[i] = real_ptr;
                    942: #endif
                    943:        }
                    944:     }
                    945: }
                    946: 
                    947: /*
                    948:  * Called from the BPLxMOD routines, after a new value has been written.
                    949:  * This routine decides whether the new value is already relevant for the
                    950:  * current line.
                    951:  */
                    952: static void decide_modulos (void)
                    953: {
                    954:     /* All this effort just for the Sanity WOC demo... */
                    955:     decide_line ();
                    956:     if (decided_nr_planes != -1 && current_hpos() >= thisline_decision.plfstrt + thisline_decision.plflinelen)
                    957:        return;
                    958:     decided_bpl1mod = bpl1mod;
                    959:     decided_bpl2mod = bpl2mod;
                    960: }
                    961: 
                    962: /*
1.1.1.3 ! root      963:  * Add the modulos to the bitplane pointers if data fetch is already
        !           964:  * finished for the current line.
        !           965:  * Call decide_plane() before calling this, so that we won't use the
        !           966:  * new values of the plane pointers for the current line.
1.1.1.2   root      967:  */
                    968: static void do_modulos (void)
                    969: {
                    970:     /* decided_nr_planes is != -1 if this line should be drawn by the
1.1.1.3 ! root      971:      * display hardware, regardless of whether it fits on the emulated screen.
1.1.1.2   root      972:      */
                    973:     if (decided_nr_planes != -1 && plane_decided && !modulos_added
                    974:        && current_hpos() >= thisline_decision.plfstrt + thisline_decision.plflinelen)
                    975:     {
                    976:        int bytecount = thisline_decision.plflinelen / (decided_hires ? 4 : 8) * 2;
                    977:        int add1 = bytecount + decided_bpl1mod;
                    978:        int add2 = bytecount + decided_bpl2mod;
                    979: 
                    980:        if (!very_broken_program) {
                    981:            switch (decided_nr_planes) {
                    982:             case 8: bplpt[7] += add2;
                    983:             case 7: bplpt[6] += add1;
                    984:             case 6: bplpt[5] += add2;
                    985:             case 5: bplpt[4] += add1;
                    986:             case 4: bplpt[3] += add2;
                    987:             case 3: bplpt[2] += add1;
                    988:             case 2: bplpt[1] += add2;
                    989:             case 1: bplpt[0] += add1;
                    990:            }
1.1.1.3 ! root      991:        } else if (decided_hires) { /* @@@ used to be bplhires which is clearly wrong */
1.1.1.2   root      992:            switch (decided_nr_planes) {
                    993:             case 8: bplpt[7] += add2;
                    994:             case 7: bplpt[6] += add1;
                    995:             case 6: bplpt[5] += add2;
                    996:             case 5: bplpt[4] += add1;
                    997:             case 4: bplpt[3] += add2 - 2;
                    998:             case 3: bplpt[2] += add1 - (very_broken_program >= 3 ? 2 : 0);
                    999:             case 2: bplpt[1] += add2 - (very_broken_program >= 2 ? 2 : 0);
                   1000:             case 1: bplpt[0] += add1;
1.1.1.3 ! root     1001:            }
1.1.1.2   root     1002:        } else {
                   1003:            switch (decided_nr_planes) {
                   1004:             case 8: bplpt[7] += add2;
                   1005:             case 7: bplpt[6] += add1;
                   1006:             case 6: bplpt[5] += add2 - (very_broken_program >= 3 ? 2 : 0);
                   1007:             case 5: bplpt[4] += add1 - (very_broken_program >= 7 ? 2 : 0);
                   1008:             case 4: bplpt[3] += add2 - (very_broken_program >= 2 ? 2 : 0);
                   1009:             case 3: bplpt[2] += add1 - (very_broken_program >= 6 ? 2 : 0);
                   1010:             case 2: bplpt[1] += add2 - (very_broken_program >= 4 ? 2 : 0);
                   1011:             case 1: bplpt[0] += add1;
1.1.1.3 ! root     1012:            }
1.1.1.2   root     1013:        }
                   1014: 
                   1015:        modulos_added = 1;
                   1016:     }
                   1017: }
                   1018: 
1.1.1.3 ! root     1019: static __inline__ void record_sprite (int spr, int sprxp)
1.1.1.2   root     1020: {
1.1.1.3 ! root     1021:     int pos = next_sprite_draw;
        !          1022:     unsigned int data, datb;
1.1.1.2   root     1023: 
1.1.1.3 ! root     1024: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
        !          1025:     if(pos >= max_sprite_draw) {
        !          1026:        ++delta_sprite_draw;
1.1.1.2   root     1027:        return;
1.1.1.3 ! root     1028:     }
        !          1029: #endif
        !          1030:     data = sprdata[spr];
        !          1031:     datb = sprdatb[spr];
1.1.1.2   root     1032: 
1.1.1.3 ! root     1033:     /* XXX FIXME, this isn't very clever, but it might do */
        !          1034:     for (;;) {
        !          1035:        if (pos == curr_drawinfo[next_lineno].first_sprite_draw)
        !          1036:            break;
        !          1037:        if (curr_sprite_positions[pos-1].linepos < sprxp)
        !          1038:            break;
        !          1039:        if (curr_sprite_positions[pos-1].linepos == sprxp
        !          1040:            && curr_sprite_positions[pos-1].num > spr)
        !          1041:            break;
        !          1042:        printf("Foo\n");
        !          1043:        pos--;
        !          1044:     }
        !          1045:     if (pos != next_sprite_draw) {
        !          1046:        int pos2 = next_sprite_draw;
        !          1047:        while (pos2 != pos) {
        !          1048:            curr_sprite_positions[pos2] = curr_sprite_positions[pos2-1];
        !          1049:            pos2--;
        !          1050:        }
        !          1051:     }
        !          1052:     curr_sprite_positions[pos].linepos = sprxp;
        !          1053:     curr_sprite_positions[pos].num = spr;
        !          1054:     curr_sprite_positions[pos].ctl = sprctl[spr];
        !          1055:     curr_sprite_positions[pos].datab = ((sprtaba[data & 0xFF] << 16) | sprtaba[data >> 8]
        !          1056:                                        | (sprtabb[datb & 0xFF] << 16) | sprtabb[datb >> 8]);
        !          1057:     next_sprite_draw++;
        !          1058: }
1.1.1.2   root     1059: 
1.1.1.3 ! root     1060: static void decide_sprites (void)
        !          1061: {
        !          1062:     int nrs[8], posns[8], count, i;
        !          1063:     int point = PIXEL_XPOS (current_hpos ());
1.1.1.2   root     1064: 
1.1.1.3 ! root     1065:     if (framecnt != 0 || current_hpos() < 0x14 || nr_armed == 0 || point == last_sprite_point)
1.1.1.2   root     1066:        return;
                   1067: 
1.1.1.3 ! root     1068:     decide_diw ();
        !          1069:     decide_line ();
        !          1070: 
        !          1071:     if (thisline_decision.which != 1)
1.1.1.2   root     1072:        return;
                   1073: 
1.1.1.3 ! root     1074:     count = 0;
        !          1075:     for (i = 0; i < 8; i++) {
        !          1076:        int sprxp = sprxpos[i];
        !          1077:        int j, bestp;
1.1.1.2   root     1078: 
1.1.1.3 ! root     1079:        if (!sprarmed[i] || sprxp < 0 || sprxp > point || last_sprite_point >= sprxp)
        !          1080:            continue;
        !          1081:        if ((thisline_decision.diwfirstword >= 0 && sprxp + sprite_width < thisline_decision.diwfirstword)
        !          1082:            || (thisline_decision.diwlastword >= 0 && sprxp > thisline_decision.diwlastword))
        !          1083:            continue;
1.1.1.2   root     1084: 
1.1.1.3 ! root     1085:        for (bestp = 0; bestp < count; bestp++) {
        !          1086:            if (posns[bestp] > sprxp)
        !          1087:                break;
        !          1088:            if (posns[bestp] == sprxp && nrs[bestp] < i)
        !          1089:                break;
        !          1090:        }
        !          1091:        for (j = count; j > bestp; j--) {
        !          1092:            posns[j] = posns[j-1];
        !          1093:            nrs[j] = nrs[j-1];
        !          1094:        }
        !          1095:        posns[j] = sprxp;
        !          1096:        nrs[j] = i;
        !          1097:        count++;
        !          1098:     }
        !          1099:     for (i = 0; i < count; i++)
        !          1100:        record_sprite(nrs[i], posns[i]);
        !          1101:     last_sprite_point = point;
1.1.1.2   root     1102: }
                   1103: 
1.1.1.3 ! root     1104: /* End of a horizontal scan line. Finish off all decisions that were not
        !          1105:  * made yet. */
1.1.1.2   root     1106: static void finish_decisions (void)
                   1107: {
                   1108:     struct draw_info *dip;
                   1109:     struct draw_info *dip_old;
                   1110:     struct decision *dp;
                   1111:     int changed;
                   1112: 
                   1113:     if (framecnt != 0)
                   1114:        return;
                   1115: 
                   1116:     decide_diw ();
                   1117:     if (thisline_decision.which == 0)
                   1118:        decide_line_1 ();
1.1.1.3 ! root     1119: 
        !          1120:     /* Large DIWSTOP values can cause the stop position never to be
        !          1121:      * reached, so the state machine always stays in the same state and
        !          1122:      * there's a more-or-less full-screen DIW. */
        !          1123:     if (hdiwstate == DIW_waiting_stop) {
        !          1124:        thisline_decision.diwlastword = max_diwlastword;
        !          1125:        if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword)
        !          1126:            MARK_LINE_CHANGED (next_lineno);
        !          1127:     }
        !          1128: 
1.1.1.2   root     1129:     if (line_decisions[next_lineno].which != thisline_decision.which)
                   1130:        line_changed[next_lineno] = 1;
                   1131:     decide_plane ();
                   1132: 
                   1133:     dip = curr_drawinfo + next_lineno;
                   1134:     dip_old = prev_drawinfo + next_lineno;
                   1135:     dp = line_decisions + next_lineno;
                   1136:     changed = line_changed[next_lineno];
                   1137: 
                   1138:     if (thisline_decision.which == 1) {
                   1139:        if (diwlastword > max_diwstop)
                   1140:            max_diwstop = diwlastword;
                   1141:        if (diwfirstword < min_diwstart)
                   1142:            min_diwstart = diwfirstword;
                   1143: 
1.1.1.3 ! root     1144:        decide_sprites();
        !          1145: 
1.1.1.2   root     1146:        if (thisline_decision.bplcon1 != line_decisions[next_lineno].bplcon1)
                   1147:            changed = 1;
                   1148:     }
                   1149: 
                   1150:     dip->last_color_change = next_color_change;
                   1151:     dip->last_delay_change = next_delay_change;
                   1152:     dip->last_sprite_draw = next_sprite_draw;
1.1.1.3 ! root     1153: 
        !          1154:     if (thisline_decision.ctable == -1) {
        !          1155:        if (thisline_decision.which == 1)
        !          1156:            remember_ctable ();
        !          1157:        else
        !          1158:            remember_ctable_for_border ();
        !          1159:     }
1.1.1.2   root     1160:     if (thisline_decision.which == -1 && thisline_decision.color0 == 0xFFFFFFFFul)
                   1161:        thisline_decision.color0 = current_colors.color_regs[0];
                   1162: 
                   1163:     dip->nr_color_changes = next_color_change - dip->first_color_change;
                   1164:     dip->nr_sprites = next_sprite_draw - dip->first_sprite_draw;
                   1165: 
                   1166:     if (dip->first_delay_change != dip->last_delay_change)
                   1167:        changed = 1;
                   1168:     if (!changed
                   1169:        && (dip->nr_color_changes != dip_old->nr_color_changes
1.1.1.3 ! root     1170:            || (dip->nr_color_changes > 0
        !          1171:                && memcmp (curr_color_changes + dip->first_color_change,
        !          1172:                           prev_color_changes + dip_old->first_color_change,
        !          1173:                           dip->nr_color_changes * sizeof *curr_color_changes) != 0)))
1.1.1.2   root     1174:        changed = 1;
                   1175:     if (!changed && thisline_decision.which == 1
                   1176:        && (dip->nr_sprites != dip_old->nr_sprites
                   1177:            || (dip->nr_sprites > 0
1.1.1.3 ! root     1178:                && memcmp (curr_sprite_positions + dip->first_sprite_draw,
        !          1179:                           prev_sprite_positions + dip_old->first_sprite_draw,
        !          1180:                           dip->nr_sprites * sizeof *curr_sprite_positions) != 0)))
1.1.1.2   root     1181:        changed = 1;
                   1182: 
                   1183:     if (changed) {
                   1184:        line_changed[next_lineno] = 1;
                   1185:        *dp = thisline_decision;
                   1186:     } else
                   1187:        /* The only one that may differ: */
                   1188:        dp->ctable = thisline_decision.ctable;
                   1189: }
                   1190: 
1.1.1.3 ! root     1191: /* Set the state of all decisions to "undecided" for a new scanline. */
1.1.1.2   root     1192: static void reset_decisions (void)
                   1193: {
                   1194:     if (framecnt != 0)
                   1195:        return;
                   1196:     thisline_decision.which = 0;
                   1197:     decided_bpl1mod = bpl1mod;
                   1198:     decided_bpl2mod = bpl2mod;
                   1199:     decided_nr_planes = -1;
                   1200: 
                   1201:     /* decided_hires shouldn't be touched before it's initialized by decide_line(). */
                   1202:     thisline_decision.diwfirstword = -1;
                   1203:     thisline_decision.diwlastword = -2;
1.1.1.3 ! root     1204:     if (hdiwstate == DIW_waiting_stop) {
        !          1205:        thisline_decision.diwfirstword = PIXEL_XPOS (DISPLAY_LEFT_SHIFT/2);
        !          1206:        if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
        !          1207:            MARK_LINE_CHANGED (next_lineno);
        !          1208:     }
1.1.1.2   root     1209:     thisline_decision.ctable = -1;
                   1210:     thisline_decision.color0 = 0xFFFFFFFFul;
                   1211: 
                   1212:     line_changed[next_lineno] = 0;
                   1213:     curr_drawinfo[next_lineno].first_color_change = next_color_change;
                   1214:     curr_drawinfo[next_lineno].first_delay_change = next_delay_change;
                   1215:     curr_drawinfo[next_lineno].first_sprite_draw = next_sprite_draw;
                   1216: 
1.1.1.3 ! root     1217:     /* memset(sprite_last_drawn_at, 0, sizeof sprite_last_drawn_at); */
        !          1218:     last_sprite_point = 0;
1.1.1.2   root     1219:     modulos_added = 0;
                   1220:     plane_decided = 0;
                   1221:     color_decided = 0;
                   1222:     very_broken_program = 0;
                   1223: }
                   1224: 
1.1.1.3 ! root     1225: /* Initialize the decision array, once before the emulator really starts. */
1.1.1.2   root     1226: static void init_decisions (void)
                   1227: {
                   1228:     size_t i;
                   1229:     for (i = 0; i < sizeof line_decisions / sizeof *line_decisions; i++) {
                   1230:        line_decisions[i].which = -2;
1.1       root     1231:     }
1.1.1.2   root     1232: }
                   1233: 
1.1.1.3 ! root     1234: /* Calculate display window and data fetch values from the corresponding
        !          1235:  * hardware registers. */
1.1.1.2   root     1236: static void calcdiw (void)
                   1237: {
                   1238:     diwfirstword = ((diwstrt & 0xFF) - DISPLAY_LEFT_SHIFT - 1) << lores_shift;
                   1239:     diwlastword  = ((diwstop & 0xFF) + 0x100 - DISPLAY_LEFT_SHIFT - 1) << lores_shift;
                   1240: 
                   1241:     if (diwlastword > max_diwlastword)
                   1242:        diwlastword = max_diwlastword;
                   1243:     if (diwfirstword < 0)
                   1244:        diwfirstword = 0;
                   1245:     if (diwlastword < 0)
                   1246:        diwlastword = 0;
1.1.1.3 ! root     1247: 
1.1.1.2   root     1248:     plffirstline = diwstrt >> 8;
                   1249:     plflastline = diwstop >> 8;
1.1       root     1250: #if 0
                   1251:     /* This happens far too often. */
                   1252:     if (plffirstline < minfirstline) {
                   1253:        fprintf(stderr, "Warning: Playfield begins before line %d!\n", minfirstline);
                   1254:        plffirstline = minfirstline;
                   1255:     }
                   1256: #endif
                   1257:     if ((plflastline & 0x80) == 0) plflastline |= 0x100;
                   1258: #if 0 /* Turrican does this */
                   1259:     if (plflastline > 313) {
                   1260:        fprintf(stderr, "Warning: Playfield out of range!\n");
                   1261:        plflastline = 313;
                   1262:     }
                   1263: #endif
1.1.1.2   root     1264:     plfstrt = ddfstrt;
                   1265:     plfstop = ddfstop;
1.1       root     1266:     if (plfstrt < 0x18) plfstrt = 0x18;
1.1.1.3 ! root     1267:     if (plfstop < 0x18) plfstop = 0x18;
1.1       root     1268:     if (plfstop > 0xD8) plfstop = 0xD8;
                   1269:     if (plfstrt > plfstop) plfstrt = plfstop;
                   1270: 
                   1271:     /* ! If the masking operation is changed, the pfield_doline code could break
                   1272:      * on some systems (alignment) */
                   1273:     /* This actually seems to be correct now, at least the non-AGA stuff... */
                   1274:     plfstrt &= ~3;
                   1275:     plfstop &= ~3;
1.1.1.2   root     1276:     /* @@@ Start looking for AGA bugs here... (or maybe even in the above masking ops) */
1.1       root     1277:     if ((fmode & 3) == 0)
                   1278:        plflinelen = (plfstop-plfstrt+15) & ~7;
                   1279:     else if ((fmode & 3) == 3)
                   1280:        plflinelen = (plfstop-plfstrt+63) & ~31;
                   1281:     else
                   1282:        plflinelen = (plfstop-plfstrt+31) & ~15;
                   1283: }
                   1284: 
                   1285: /*
                   1286:  * Screen update macros/functions
                   1287:  */
                   1288: 
1.1.1.3 ! root     1289: static unsigned int ham_lastcolor;
        !          1290: 
        !          1291: static void init_ham_decoding(int first)
        !          1292: {
        !          1293:     int pix = dp_for_drawing->diwfirstword;
        !          1294:     ham_lastcolor = colors_for_drawing.color_regs[0];
        !          1295:     while (pix < first) {
        !          1296:        int pv = pixdata.apixels[pix];
        !          1297:        switch(pv & 0x30) {
        !          1298:         case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break;
        !          1299:         case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
        !          1300:         case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
        !          1301:         case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
        !          1302:        }
        !          1303:        pix++;
        !          1304:     }
        !          1305: }
        !          1306: 
        !          1307: static void decode_ham6 (int pix, int stoppos)
        !          1308: {
        !          1309:     uae_u32 *buf = ham_linebuf;
1.1       root     1310: 
                   1311:     if (!bplham || bplplanecnt != 6)
                   1312:        return;
1.1.1.3 ! root     1313: 
1.1.1.2   root     1314:     if (stoppos > dp_for_drawing->diwlastword)
                   1315:        stoppos = dp_for_drawing->diwlastword;
                   1316:     if (pix < dp_for_drawing->diwfirstword) {
1.1.1.3 ! root     1317:        ham_lastcolor = colors_for_drawing.color_regs[0];
1.1.1.2   root     1318:        pix = dp_for_drawing->diwfirstword;
                   1319:     }
                   1320: #ifdef LORES_HACK
1.1.1.3 ! root     1321:     if (currprefs.gfx_lores == 2)
1.1.1.2   root     1322:        pix <<= 1, stoppos <<= 1;
                   1323: #endif
                   1324:     while (pix < stoppos) {
1.1       root     1325:        int pv = pixdata.apixels[pix];
                   1326:        switch(pv & 0x30) {
1.1.1.3 ! root     1327:         case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break;
        !          1328:         case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
        !          1329:         case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
        !          1330:         case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
1.1       root     1331:        }
                   1332: 
1.1.1.3 ! root     1333:        buf[pix++] = ham_lastcolor;
        !          1334:     }
1.1       root     1335: }
1.1.1.2   root     1336: #if 0
1.1       root     1337: static void decode_ham_aga (int pix, int stoppos)
                   1338: {
1.1.1.3 ! root     1339:     static uae_u32 lastcolor;
        !          1340:     uae_u32 *buf = ham_linebuf;
1.1       root     1341: 
                   1342:     if (!bplham || (bplplanecnt != 6 && bplplanecnt != 8))
                   1343:        return;
1.1.1.3 ! root     1344: 
1.1.1.2   root     1345:     if (pix <= dp_for_drawing->diwfirstword) {
                   1346:        pix = dp_for_drawing->diwfirstword;
                   1347:        lastcolor = colors_for_drawing.color_regs[0];
1.1       root     1348:     }
                   1349: 
1.1.1.2   root     1350:     if (dp_for_drawing->bplplanecnt == 6) {
1.1       root     1351:        /* HAM 6 */
1.1.1.2   root     1352:        while (pix < dp_for_drawing->diwlastword && pix < stoppos) {
1.1       root     1353:            int pv = pixdata.apixels[pix];
                   1354:            switch(pv & 0x30) {
1.1.1.2   root     1355:             case 0x00: lastcolor = colors_for_drawing.color_regs[pv]; break;
1.1       root     1356:             case 0x10: lastcolor &= 0xFFFF00; lastcolor |= (pv & 0xF)*0x11; break;
                   1357:             case 0x20: lastcolor &= 0x00FFFF; lastcolor |= (pv & 0xF)*0x11 << 16; break;
                   1358:             case 0x30: lastcolor &= 0xFF00FF; lastcolor |= (pv & 0xF)*0x11 << 8; break;
1.1.1.3 ! root     1359:            }
1.1       root     1360:            buf[pix++] = lastcolor;
                   1361:        }
1.1.1.2   root     1362:     } else if (dp_for_drawing->bplplanecnt == 8) {
1.1       root     1363:        /* HAM 8 */
1.1.1.2   root     1364:        while (pix < dp_for_drawing->diwlastword && pix < stoppos) {
1.1       root     1365:            int pv = pixdata.apixels[pix];
                   1366:            switch(pv & 0x3) {
1.1.1.2   root     1367:             case 0x0: lastcolor = colors_for_drawing.color_regs[pv >> 2]; break;
1.1       root     1368:             case 0x1: lastcolor &= 0xFFFF03; lastcolor |= (pv & 0xFC); break;
                   1369:             case 0x2: lastcolor &= 0x03FFFF; lastcolor |= (pv & 0xFC) << 16; break;
                   1370:             case 0x3: lastcolor &= 0xFF03FF; lastcolor |= (pv & 0xFC) << 8; break;
                   1371:            }
                   1372:            buf[pix++] = lastcolor;
                   1373:        }
                   1374:     }
                   1375: }
1.1.1.2   root     1376: #endif
1.1       root     1377: 
1.1.1.2   root     1378: #if AGA_CHIPSET != 0
1.1       root     1379: /* WARNING: Not too much of this will work correctly yet. */
                   1380: 
                   1381: static void pfield_linetoscr_aga(int pix, int stoppos)
                   1382: {
1.1.1.3 ! root     1383:     uae_u32 *buf = aga_lbufptr;
1.1       root     1384:     int i;
1.1.1.3 ! root     1385:     int xor = (uae_u8)(bplcon4 >> 8);
1.1       root     1386:     int oldpix = pix; \
                   1387: 
                   1388:     buf -= pix; \
                   1389: 
                   1390:     for (i = 0; i < stoppos; i++)
                   1391:        pixdata.apixels[i] ^= xor;
1.1.1.3 ! root     1392: 
1.1       root     1393:     while (pix < diwfirstword && pix < stoppos) {
1.1.1.2   root     1394:        buf[pix++] = colors_for_drawing.color_regs[0];
1.1       root     1395:     }
                   1396:     if (bplham) {
                   1397:        while (pix < diwlastword && pix < stoppos) {
1.1.1.3 ! root     1398:            uae_u32 d = ham_linebuf[pix];
1.1       root     1399:            buf[pix] = d;
                   1400:            pix++;
                   1401:        }
                   1402:     } else if (bpldualpf) {
                   1403:        /* Dual playfield */
                   1404:        int *lookup = bpldualpfpri ? dblpf_aga2 : dblpf_aga1;
                   1405:        int *lookup_no = bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1;
                   1406:        while (pix < diwlastword && pix < stoppos) {
                   1407:            int pixcol = pixdata.apixels[pix];
                   1408:            int pfno = lookup_no[pixcol];
1.1.1.3 ! root     1409: 
1.1       root     1410:            if (spixstate[pix]) {
1.1.1.3 ! root     1411:                buf[pix] = colors_for_drawing.color_regs[pixcol];
1.1       root     1412:            } else {
                   1413:                int val = lookup[pixdata.apixels[pix]];
1.1.1.3 ! root     1414:                if (pfno == 2)
1.1.1.2   root     1415:                    val += dblpfofs[(bplcon2 >> 10) & 7];
                   1416:                buf[pix] = colors_for_drawing.color_regs[val];
1.1       root     1417:            }
                   1418:            pix++;
                   1419:        }
                   1420:     } else if (bplehb) {
                   1421:        while (pix < diwlastword && pix < stoppos) {
1.1.1.3 ! root     1422:            int pixcol = pixdata.apixels[pix];
        !          1423:            uae_u32 d = colors_for_drawing.color_regs[pixcol];
1.1       root     1424:            /* What about sprites? */
                   1425:            if (pixcol & 0x20)
                   1426:                d = (d & 0x777777) >> 1;
                   1427:            buf[pix] = d;
                   1428:            pix++;
                   1429:        }
                   1430:     } else {
                   1431:        while (pix < diwlastword && pix < stoppos) {
                   1432:            int pixcol = pixdata.apixels[pix];
1.1.1.2   root     1433:            buf[pix] = colors_for_drawing.color_regs[pixcol];
1.1       root     1434:            pix++;
                   1435:        }
                   1436:     }
                   1437:     while (pix < stoppos) {
1.1.1.2   root     1438:        buf[pix++] = colors_for_drawing.color_regs[0];
1.1       root     1439:     }
                   1440:     aga_lbufptr += pix - oldpix;
                   1441: }
                   1442: 
                   1443: static void aga_translate32(int start, int stop)
                   1444: {
1.1.1.3 ! root     1445:     memcpy (((uae_u32 *)xlinebuffer) + start, aga_linebuf + start, 4*(stop-start));
1.1       root     1446: }
                   1447: 
                   1448: static void aga_translate16(int start, int stop)
                   1449: {
                   1450:     int i;
                   1451:     for (i = start; i < stop; i++) {
1.1.1.3 ! root     1452:        uae_u32 d = aga_linebuf[i];
        !          1453:        uae_u16 v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12);
        !          1454:        ((uae_u16 *)xlinebuffer)[i] = xcolors[v];
1.1       root     1455:     }
                   1456: }
                   1457: 
                   1458: static void aga_translate8(int start, int stop)
                   1459: {
                   1460:     int i;
                   1461:     for (i = start; i < stop; i++) {
1.1.1.3 ! root     1462:        uae_u32 d = aga_linebuf[i];
        !          1463:        uae_u16 v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12);
        !          1464:        ((uae_u8 *)xlinebuffer)[i] = xcolors[v];
1.1       root     1465:     }
                   1466: }
1.1.1.2   root     1467: #endif
1.1       root     1468: 
1.1.1.2   root     1469: static int linetoscr_double_offset;
1.1       root     1470: 
1.1.1.3 ! root     1471: #define LINE_TO_SCR(NAME, TYPE, DO_DOUBLE, CONVERT) \
1.1.1.2   root     1472: static void NAME(int pix, int lframe_end, int diw_end, int stoppos) \
                   1473: { \
                   1474:     TYPE *buf = ((TYPE *)xlinebuffer); \
                   1475:     int oldpix = pix; \
                   1476:     /* These are different for register-allocation purposes. */ \
                   1477:     TYPE d1, d2; \
                   1478:     int offset; \
                   1479: \
                   1480:     if (DO_DOUBLE) offset = linetoscr_double_offset / sizeof(TYPE); \
                   1481: \
1.1.1.3 ! root     1482:     d1 = CONVERT(colors_for_drawing.acolors[0]); \
1.1.1.2   root     1483:     while (pix < lframe_end) { \
                   1484:        buf[pix] = d1; if (DO_DOUBLE) buf[pix+offset] = d1; \
                   1485:        pix++; \
                   1486:     } \
                   1487:     if (bplham && bplplanecnt == 6) { \
                   1488:        /* HAM 6 */ \
                   1489:        while (pix < diw_end) { \
1.1.1.3 ! root     1490:            TYPE d = CONVERT(xcolors[ham_linebuf[pix]]); \
1.1.1.2   root     1491:            buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
                   1492:            pix++; \
                   1493:        } \
                   1494:     } else if (bpldualpf) { \
                   1495:        /* Dual playfield */ \
                   1496:        int *lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; \
                   1497:        while (pix < diw_end) { \
                   1498:            int pixcol = pixdata.apixels[pix]; \
                   1499:            TYPE d; \
1.1.1.3 ! root     1500:            d = CONVERT(colors_for_drawing.acolors[lookup[pixcol]]); \
1.1.1.2   root     1501:            buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
                   1502:            pix++; \
                   1503:        } \
                   1504:     } else if (bplehb) { \
                   1505:        while (pix < diw_end) { \
                   1506:            int p = pixdata.apixels[pix]; \
1.1.1.3 ! root     1507:            TYPE d = CONVERT (colors_for_drawing.acolors[p]); \
        !          1508:            if (p >= 32) d = CONVERT(xcolors[(colors_for_drawing.color_regs[p-32] >> 1) & 0x777]); \
1.1.1.2   root     1509:            buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
                   1510:            pix++; \
                   1511:        } \
                   1512:     } else { \
                   1513:        while (pix < diw_end) { \
1.1.1.3 ! root     1514:            TYPE d = CONVERT (colors_for_drawing.acolors[pixdata.apixels[pix]]); \
1.1.1.2   root     1515:            buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
                   1516:            pix++; \
                   1517:        } \
                   1518:     } \
1.1.1.3 ! root     1519:     d2 = CONVERT (colors_for_drawing.acolors[0]); \
1.1.1.2   root     1520:     while (pix < stoppos) { \
                   1521:        buf[pix] = d2; if (DO_DOUBLE) buf[pix+offset] = d2; \
                   1522:        pix++; \
                   1523:     } \
                   1524: }
1.1       root     1525: 
1.1.1.3 ! root     1526: #define FILL_LINE(NAME, TYPE, CONVERT) \
1.1.1.2   root     1527: static void NAME(char *buf, int start, int stop) \
1.1       root     1528: { \
                   1529:     TYPE *b = (TYPE *)buf; \
                   1530:     int i;\
1.1.1.2   root     1531:     xcolnr col = colors_for_drawing.acolors[0]; \
                   1532:     for (i = start; i < stop; i++) \
1.1.1.3 ! root     1533:        b[i] = CONVERT (col); \
        !          1534: }
        !          1535: 
        !          1536: LINE_TO_SCR(pfield_linetoscr_8, uae_u8, 0,)
        !          1537: LINE_TO_SCR(pfield_linetoscr_16, uae_u16, 0,)
        !          1538: LINE_TO_SCR(pfield_linetoscr_32, uae_u32, 0,)
        !          1539: LINE_TO_SCR(pfield_linetoscr_8_double_slow, uae_u8, 1,)
        !          1540: LINE_TO_SCR(pfield_linetoscr_16_double_slow, uae_u16, 1,)
        !          1541: LINE_TO_SCR(pfield_linetoscr_32_double_slow, uae_u32, 1,)
        !          1542: 
        !          1543: FILL_LINE(fill_line_8, uae_u8,)
        !          1544: FILL_LINE(fill_line_16, uae_u16,)
        !          1545: FILL_LINE(fill_line_32, uae_u32,)
        !          1546: 
        !          1547: #ifdef HAVE_UAE_U24
        !          1548: LINE_TO_SCR(pfield_linetoscr_24, uae_u24, 0, uae24_convert)
        !          1549: LINE_TO_SCR(pfield_linetoscr_24_double_slow, uae_u24, 1, uae24_convert)
        !          1550: FILL_LINE(fill_line_24, uae_u24, uae24_convert)
        !          1551: #else
        !          1552: /* Dummy versions */
        !          1553: static void pfield_linetoscr_24 (int pix, int lframe_end, int diw_end, int stoppos)
        !          1554: {
        !          1555: }
        !          1556: static void pfield_linetoscr_24_double_slow (int pix, int lframe_end, int diw_end, int stoppos)
        !          1557: {
        !          1558: }
        !          1559: static void fill_line_24 (char *buf, int start, int stop)
        !          1560: {
        !          1561: }
        !          1562: #endif
        !          1563: 
        !          1564: static __inline__ void fill_line_full (void)
        !          1565: {
        !          1566:     switch (gfxvidinfo.pixbytes) {
        !          1567:      case 1: fill_line_8(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
        !          1568:      case 2: fill_line_16(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
        !          1569:      case 3: fill_line_24(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
        !          1570:      case 4: fill_line_32(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
        !          1571:     }
1.1       root     1572: }
                   1573: 
1.1.1.3 ! root     1574: #define fill_line fill_line_full
1.1       root     1575: 
                   1576: #define pfield_linetoscr_full8 pfield_linetoscr_8
                   1577: #define pfield_linetoscr_full16 pfield_linetoscr_16
1.1.1.3 ! root     1578: #define pfield_linetoscr_full24 pfield_linetoscr_24
1.1       root     1579: #define pfield_linetoscr_full32 pfield_linetoscr_32
                   1580: 
                   1581: #define pfield_linetoscr_full8_double pfield_linetoscr_8_double_slow
                   1582: #define pfield_linetoscr_full16_double pfield_linetoscr_16_double_slow
1.1.1.3 ! root     1583: #define pfield_linetoscr_full24_double pfield_linetoscr_24_double_slow
1.1       root     1584: #define pfield_linetoscr_full32_double pfield_linetoscr_32_double_slow
                   1585: 
                   1586: #if 1 && defined(X86_ASSEMBLY)
1.1.1.3 ! root     1587: /* This version of fill_line is probably a win on all machines, but for
        !          1588:  * now I'm cautious */
        !          1589: #undef fill_line
        !          1590: static __inline__ void fill_line (void)
        !          1591: {
        !          1592:     int shift;
        !          1593:     int nints, nrem;
        !          1594:     int *start;
        !          1595:     xcolnr val;
        !          1596: 
        !          1597: #ifdef HAVE_UAE_U24
        !          1598:     if (gfxvidinfo.pixbytes == 3) {
        !          1599:        fill_line_24 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width);
        !          1600:        return;
        !          1601:     }
        !          1602: #endif
        !          1603:     
        !          1604:     shift = 0;
        !          1605:     if (gfxvidinfo.pixbytes == 2)
        !          1606:        shift = 1;
        !          1607:     if (gfxvidinfo.pixbytes == 4)
        !          1608:        shift = 2;
        !          1609: 
        !          1610:     nints = gfxvidinfo.width >> (2-shift);
        !          1611:     nrem = nints & 7;
        !          1612:     nints &= ~7;
        !          1613:     start = (int *)(((char *)xlinebuffer) + (linetoscr_x_adjust << shift));
        !          1614:     val = colors_for_drawing.acolors[0];
        !          1615:     for (; nints > 0; nints -= 8, start+=8) {
        !          1616:        *start = val;
        !          1617:        *(start+1) = val;
        !          1618:        *(start+2) = val;
        !          1619:        *(start+3) = val;
        !          1620:        *(start+4) = val;
        !          1621:        *(start+5) = val;
        !          1622:        *(start+6) = val;
        !          1623:        *(start+7) = val;
        !          1624:     }
        !          1625: 
        !          1626:     switch (nrem) {
        !          1627:      case 7:
        !          1628:        *start++ = val;
        !          1629:      case 6:
        !          1630:        *start++ = val;
        !          1631:      case 5:
        !          1632:        *start++ = val;
        !          1633:      case 4:
        !          1634:        *start++ = val;
        !          1635:      case 3:
        !          1636:        *start++ = val;
        !          1637:      case 2:
        !          1638:        *start++ = val;
        !          1639:      case 1:
        !          1640:        *start = val;
        !          1641:     }
        !          1642: }
        !          1643: 
1.1       root     1644: #undef pfield_linetoscr_full8
1.1.1.2   root     1645: /* The types are lies, of course. */
                   1646: extern void pfield_linetoscr_normal_asm8(void) __asm__("pfield_linetoscr_normal_asm8");
                   1647: extern void pfield_linetoscr_ehb_asm8(void) __asm__("pfield_linetoscr_ehb_asm8");
                   1648: extern void pfield_linetoscr_ham6_asm8(void) __asm__("pfield_linetoscr_ham6_asm8");
                   1649: extern void pfield_linetoscr_dualpf_asm8(void) __asm__("pfield_linetoscr_dualpf_asm8");
                   1650: extern void pfield_linetoscr_hdouble_asm8(void) __asm__("pfield_linetoscr_hdouble_asm8");
1.1.1.3 ! root     1651: extern void pfield_linetoscr_hdouble_dpf_asm8(void) __asm__("pfield_linetoscr_hdouble_dpf_asm8");
        !          1652: extern void pfield_linetoscr_hdouble_ehb_asm8(void) __asm__("pfield_linetoscr_hdouble_ehb_asm8");
1.1.1.2   root     1653: extern void pfield_linetoscr_asm8(void (*)(void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm8");
                   1654: 
                   1655: static void pfield_linetoscr_full8(int pix, int lframe_end, int diw_end, int stoppos)
                   1656: {
                   1657:     int lframe_end_1, diw_end_1;
                   1658: 
                   1659:     lframe_end_1 = pix + ((lframe_end - pix) & ~3);
                   1660:     diw_end_1 = stoppos - ((stoppos - diw_end) & ~3);
                   1661: 
                   1662:     if (bplham && bplplanecnt == 6) {
                   1663:        pfield_linetoscr_asm8(pfield_linetoscr_ham6_asm8, pix, lframe_end_1, diw_end_1, stoppos);
                   1664:     } else if (bpldualpf) {
1.1.1.3 ! root     1665: #ifdef LORES_HACK
        !          1666:        if (currprefs.gfx_lores == 2)
        !          1667:            pfield_linetoscr_asm8(pfield_linetoscr_hdouble_dpf_asm8, pix, lframe_end_1, diw_end_1, stoppos,
        !          1668:                                   bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
        !          1669:        else
        !          1670: #endif
        !          1671:            pfield_linetoscr_asm8(pfield_linetoscr_dualpf_asm8, pix, lframe_end_1, diw_end_1, stoppos,
        !          1672:                                  bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
1.1.1.2   root     1673:     } else if (bplehb) {
                   1674: #ifdef LORES_HACK
1.1.1.3 ! root     1675:        if (currprefs.gfx_lores == 2)
        !          1676:            pfield_linetoscr_asm8(pfield_linetoscr_hdouble_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos);
        !          1677:        else
1.1.1.2   root     1678: #endif
1.1.1.3 ! root     1679:            pfield_linetoscr_asm8(pfield_linetoscr_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos);
1.1.1.2   root     1680:     } else {
1.1.1.3 ! root     1681: #ifdef LORES_HACK
        !          1682:        if (currprefs.gfx_lores == 2)
        !          1683:            pfield_linetoscr_asm8(pfield_linetoscr_hdouble_asm8, pix, lframe_end_1, diw_end_1, stoppos);
        !          1684:        else
        !          1685: #endif
        !          1686:            pfield_linetoscr_asm8(pfield_linetoscr_normal_asm8, pix, lframe_end_1, diw_end_1, stoppos);
1.1.1.2   root     1687:     }
1.1.1.3 ! root     1688: 
1.1.1.2   root     1689:     /* The assembly functions work on aligned data, so we may have to do some
                   1690:      * additional work at the edges. */
                   1691:     if (lframe_end != lframe_end_1) {
                   1692:        int i, c = colors_for_drawing.acolors[0];
                   1693:        for (i = lframe_end_1; i < lframe_end; i++)
                   1694:            xlinebuffer[i] = c;
                   1695:     }
                   1696:     if (diw_end != diw_end_1) {
                   1697:        int i, c = colors_for_drawing.acolors[0];
                   1698:        for (i = diw_end; i < diw_end_1; i++)
                   1699:            xlinebuffer[i] = c;
                   1700:     }
                   1701: }
                   1702: 
1.1       root     1703: #undef pfield_linetoscr_full16
1.1.1.2   root     1704: extern void pfield_linetoscr_normal_asm16(void) __asm__("pfield_linetoscr_normal_asm16");
                   1705: extern void pfield_linetoscr_ehb_asm16(void) __asm__("pfield_linetoscr_ehb_asm16");
                   1706: extern void pfield_linetoscr_ham6_asm16(void) __asm__("pfield_linetoscr_ham6_asm16");
                   1707: extern void pfield_linetoscr_dualpf_asm16(void) __asm__("pfield_linetoscr_dualpf_asm16");
                   1708: extern void pfield_linetoscr_hdouble_asm16(void) __asm__("pfield_linetoscr_hdouble_asm16");
1.1.1.3 ! root     1709: extern void pfield_linetoscr_hdouble_dpf_asm16(void) __asm__("pfield_linetoscr_hdouble_dpf_asm16");
        !          1710: extern void pfield_linetoscr_hdouble_ehb_asm16(void) __asm__("pfield_linetoscr_hdouble_ehb_asm16");
1.1.1.2   root     1711: extern void pfield_linetoscr_asm16(void (*)(void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm16");
                   1712: 
                   1713: static void pfield_linetoscr_full16(int pix, int lframe_end, int diw_end, int stoppos)
                   1714: {
                   1715:     int lframe_end_1, diw_end_1;
                   1716: 
                   1717:     lframe_end_1 = pix + ((lframe_end - pix) & ~3);
                   1718:     diw_end_1 = stoppos - ((stoppos - diw_end) & ~3);
                   1719: 
                   1720:     if (bplham && bplplanecnt == 6) {
                   1721:        pfield_linetoscr_asm16(pfield_linetoscr_ham6_asm16, pix, lframe_end_1, diw_end_1, stoppos);
                   1722:     } else if (bpldualpf) {
1.1.1.3 ! root     1723: #ifdef LORES_HACK
        !          1724:        if (currprefs.gfx_lores == 2)
        !          1725:            pfield_linetoscr_asm16(pfield_linetoscr_hdouble_dpf_asm16, pix, lframe_end_1, diw_end_1, stoppos,
        !          1726:                                   bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
        !          1727:        else
        !          1728: #endif
        !          1729:            pfield_linetoscr_asm16(pfield_linetoscr_dualpf_asm16, pix, lframe_end_1, diw_end_1, stoppos,
        !          1730:                                   bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
1.1.1.2   root     1731:     } else if (bplehb) {
                   1732: #ifdef LORES_HACK
1.1.1.3 ! root     1733:        if (currprefs.gfx_lores == 2)
        !          1734:            pfield_linetoscr_asm16(pfield_linetoscr_hdouble_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos);
        !          1735:        else
1.1.1.2   root     1736: #endif
1.1.1.3 ! root     1737:            pfield_linetoscr_asm16(pfield_linetoscr_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos);
1.1.1.2   root     1738:     } else {
1.1.1.3 ! root     1739: #ifdef LORES_HACK
        !          1740:        if (currprefs.gfx_lores == 2)
        !          1741:            pfield_linetoscr_asm16(pfield_linetoscr_hdouble_asm16, pix, lframe_end_1, diw_end_1, stoppos);
        !          1742:        else
        !          1743: #endif
        !          1744:            pfield_linetoscr_asm16(pfield_linetoscr_normal_asm16, pix, lframe_end_1, diw_end_1, stoppos);
1.1.1.2   root     1745:     }
                   1746: 
                   1747:     /* The assembly functions work on aligned data, so we may have to do some
                   1748:      * additional work at the edges. */
                   1749:     if (lframe_end != lframe_end_1) {
                   1750:        int i, c = colors_for_drawing.acolors[0];
                   1751:        for (i = lframe_end_1; i < lframe_end; i++)
1.1.1.3 ! root     1752:            ((uae_u16 *)xlinebuffer)[i] = c;
1.1.1.2   root     1753:     }
                   1754:     if (diw_end != diw_end_1) {
                   1755:        int i, c = colors_for_drawing.acolors[0];
                   1756:        for (i = diw_end; i < diw_end_1; i++)
1.1.1.3 ! root     1757:            ((uae_u16 *)xlinebuffer)[i] = c;
1.1.1.2   root     1758:     }
                   1759: }
                   1760: 
                   1761: #ifndef NO_DOUBLING_LINETOSCR
                   1762: #define NO_DOUBLING_LINETOSCR
                   1763: #endif
                   1764: 
                   1765: #endif
                   1766: 
                   1767: #ifdef NO_DOUBLING_LINETOSCR
1.1       root     1768: #undef pfield_linetoscr_full8_double
                   1769: #undef pfield_linetoscr_full16_double
1.1.1.2   root     1770: static void pfield_linetoscr_full8_double(int start, int lframe_end, int diw_end, int stop)
1.1       root     1771: {
                   1772:     char *oldxlb = (char *)xlinebuffer;
1.1.1.2   root     1773:     pfield_linetoscr_full8(start, lframe_end, diw_end, stop);
                   1774:     xlinebuffer = oldxlb + linetoscr_double_offset;
                   1775:     pfield_linetoscr_full8(start, lframe_end, diw_end, stop);
1.1       root     1776: }
1.1.1.2   root     1777: static void pfield_linetoscr_full16_double(int start, int lframe_end, int diw_end, int stop)
1.1       root     1778: {
                   1779:     char *oldxlb = (char *)xlinebuffer;
1.1.1.2   root     1780:     pfield_linetoscr_full16(start, lframe_end, diw_end, stop);
                   1781:     xlinebuffer = oldxlb + linetoscr_double_offset;
                   1782:     pfield_linetoscr_full16(start, lframe_end, diw_end, stop);
1.1       root     1783: }
                   1784: #endif
                   1785: 
1.1.1.2   root     1786: static int linetoscr_diw_end, linetoscr_diw_start;
                   1787: 
1.1.1.3 ! root     1788: /* Initialize the variables necessary for drawing a line.
        !          1789:  * This involves setting up start/stop positions and display window
        !          1790:  * borders. Also, since the drawing code may not fully overwrite all
        !          1791:  * releveant areas in the pixdata.apixels array for speed reasons, parts of
        !          1792:  * it must possibly be cleared here. */
1.1.1.2   root     1793: static void pfield_init_linetoscr (void)
                   1794: {
                   1795:     int ddf_left, ddf_right;
                   1796:     int mindelay = bpldelay1, maxdelay = bpldelay2;
                   1797:     if (bpldelay1 > bpldelay2)
                   1798:        maxdelay = bpldelay1, mindelay = bpldelay2;
                   1799: 
                   1800:     linetoscr_diw_start = dp_for_drawing->diwfirstword;
                   1801:     linetoscr_diw_end = dp_for_drawing->diwlastword;
                   1802: 
                   1803:     /* We should really look at DDF also when calculating max_diwstop/min_diwstrt,
                   1804:      * so that centering works better, but I'm afraid that might cost too many
1.1.1.3 ! root     1805:      * cycles. Plus it's dangerous, see the code below that handles the case
1.1.1.2   root     1806:      * with sprites. */
                   1807:     if (dip_for_drawing->nr_sprites == 0) {
                   1808:        int hiresadjust = bplhires ? 4 : 8;
                   1809:        ddf_left = ((dp_for_drawing->plfstrt + hiresadjust)*2 + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift;
                   1810:        ddf_right = ((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2 + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift;
1.1.1.3 ! root     1811: 
1.1.1.2   root     1812:        if (linetoscr_diw_start < ddf_left)
                   1813:            linetoscr_diw_start = ddf_left;
                   1814:        if (linetoscr_diw_end > ddf_right)
                   1815:            linetoscr_diw_end = ddf_right;
                   1816: 
                   1817:        if (mindelay != maxdelay) {
                   1818:            /* Raahh...
                   1819:             * We just clear the maximum amount of space that may need to be
                   1820:             * cleared. We could do this exactly, but it would come out slower
                   1821:             * because of the overhead. */
                   1822:            int strt = ddf_left;
1.1.1.3 ! root     1823:            if (currprefs.gfx_lores == 2) {
        !          1824:                fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_left>>1), 15);
        !          1825:                fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_right>>1) - 15, 15);
        !          1826:            } else if (currprefs.gfx_lores) {
1.1.1.2   root     1827:                fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 15);
                   1828:                fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 15, 15);
                   1829:            } else {
                   1830:                fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 30);
                   1831:                fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 30, 30);
                   1832:            }
                   1833:        }
                   1834:     } else {
                   1835:        int hiresadjust = bplhires ? 4 : 8;
                   1836:        /* We swap mindelay and maxdelay here to get rid of the mindelay != maxdelay check.
                   1837:         * Since we have to do a memset anyway (because there may be sprites),
                   1838:         * we might as well clear all at once. */
                   1839:        ddf_left = ((dp_for_drawing->plfstrt + hiresadjust)*2 + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift;
                   1840:        ddf_right = ((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2 + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift;
                   1841:        if (linetoscr_diw_start < ddf_left) {
                   1842:            int strt = linetoscr_diw_start;
                   1843:            int stop = ddf_left;
                   1844: #ifdef LORES_HACK
1.1.1.3 ! root     1845:            if (currprefs.gfx_lores == 2)
1.1.1.2   root     1846:                strt >>= 1, stop >>= 1;
                   1847: #endif
                   1848:            if (strt < stop)
                   1849:                fuzzy_memset (pixdata.apixels, 0, strt, stop - strt);
                   1850:        }
                   1851: 
                   1852:        if (linetoscr_diw_end > ddf_right) {
                   1853:            int strt = ddf_right;
                   1854:            int stop = linetoscr_diw_end;
                   1855: #ifdef LORES_HACK
1.1.1.3 ! root     1856:            if (currprefs.gfx_lores == 2)
1.1.1.2   root     1857:                strt >>= 1, stop >>= 1;
                   1858: #endif
                   1859:            if (strt < stop)
                   1860:                fuzzy_memset (pixdata.apixels, 0, strt, stop - strt);
                   1861:        }
                   1862:     }
                   1863:     /* Perverse cases happen. */
                   1864:     if (linetoscr_diw_end < linetoscr_diw_start)
                   1865:        linetoscr_diw_end = linetoscr_diw_start;
                   1866: }
                   1867: 
1.1       root     1868: static void pfield_do_linetoscr(int start, int stop)
                   1869: {
1.1.1.2   root     1870:     int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end;
                   1871: 
                   1872:     if (stop > linetoscr_right_x)
                   1873:        stop = linetoscr_right_x;
                   1874:     if (start < linetoscr_x_adjust)
                   1875:        start = linetoscr_x_adjust;
1.1.1.3 ! root     1876: 
1.1.1.2   root     1877:     if (lframe_end < start)
                   1878:        lframe_end = start;
                   1879:     if (diw_end > stop)
                   1880:        diw_end = stop;
                   1881: 
1.1       root     1882:     if (start >= stop)
                   1883:        return;
                   1884: 
                   1885: #if AGA_CHIPSET == 0
1.1.1.2   root     1886:     if (start == linetoscr_x_adjust && stop == linetoscr_right_x) {
1.1       root     1887:        switch (gfxvidinfo.pixbytes) {
1.1.1.2   root     1888:         case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break;
                   1889:         case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break;
1.1.1.3 ! root     1890:         case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break;
1.1.1.2   root     1891:         case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break;
1.1       root     1892:        }
                   1893:     } else {
                   1894:        switch (gfxvidinfo.pixbytes) {
1.1.1.2   root     1895:         case 1: pfield_linetoscr_8 (start, lframe_end, diw_end, stop); break;
                   1896:         case 2: pfield_linetoscr_16 (start, lframe_end, diw_end, stop); break;
1.1.1.3 ! root     1897:         case 3: pfield_linetoscr_24 (start, lframe_end, diw_end, stop); break;
1.1.1.2   root     1898:         case 4: pfield_linetoscr_32 (start, lframe_end, diw_end, stop); break;
1.1       root     1899:        }
                   1900:     }
                   1901: #else
1.1.1.2   root     1902:     pfield_linetoscr_aga(start, lframe_end, diw_end, stop);
1.1       root     1903: #endif
                   1904: }
                   1905: 
1.1.1.2   root     1906: static void pfield_do_fill_line(int start, int stop)
1.1       root     1907: {
1.1.1.2   root     1908:     if (stop > linetoscr_right_x)
                   1909:        stop = linetoscr_right_x;
                   1910:     if (start < linetoscr_x_adjust)
                   1911:        start = linetoscr_x_adjust;
                   1912: 
                   1913:     if (start >= stop)
                   1914:        return;
                   1915: 
                   1916:     switch (gfxvidinfo.pixbytes) {
                   1917:      case 1: fill_line_8 (xlinebuffer, start, stop); break;
                   1918:      case 2: fill_line_16 (xlinebuffer, start, stop); break;
1.1.1.3 ! root     1919:      case 3: fill_line_24 (xlinebuffer, start, stop); break;
1.1.1.2   root     1920:      case 4: fill_line_32 (xlinebuffer, start, stop); break;
1.1       root     1921:     }
1.1.1.2   root     1922: }
                   1923: 
                   1924: static void pfield_do_linetoscr_full(int double_line)
                   1925: {
1.1.1.3 ! root     1926:     int start = linetoscr_x_adjust, stop = start + gfxvidinfo.width;
1.1.1.2   root     1927:     int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end;
                   1928:     if (lframe_end < start)
                   1929:        lframe_end = start;
                   1930:     if (diw_end > stop)
                   1931:        diw_end = stop;
1.1       root     1932: 
                   1933: #if AGA_CHIPSET == 0
                   1934:     if (double_line) {
                   1935:        switch (gfxvidinfo.pixbytes) {
1.1.1.2   root     1936:         case 1: pfield_linetoscr_full8_double (start, lframe_end, diw_end, stop); break;
                   1937:         case 2: pfield_linetoscr_full16_double (start, lframe_end, diw_end, stop); break;
1.1.1.3 ! root     1938:         case 3: pfield_linetoscr_full24_double (start, lframe_end, diw_end, stop); break;
1.1.1.2   root     1939:         case 4: pfield_linetoscr_full32_double (start, lframe_end, diw_end, stop); break;
1.1       root     1940:        }
1.1.1.3 ! root     1941:     } else
1.1       root     1942:        switch (gfxvidinfo.pixbytes) {
1.1.1.2   root     1943:         case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break;
                   1944:         case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break;
1.1.1.3 ! root     1945:         case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break;
1.1.1.2   root     1946:         case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break;
1.1       root     1947:        }
                   1948: #else
1.1.1.2   root     1949:     pfield_linetoscr_aga(start, lframe_end, diw_end, stop);
1.1       root     1950: #endif
                   1951: }
                   1952: 
1.1.1.3 ! root     1953: /* Mouse stuff */
        !          1954: static void setdontcare(void)
        !          1955: {
        !          1956:     write_log ("Don't care mouse mode set\n");
        !          1957:     mousestate = dont_care_mouse;
        !          1958:     lastspr0x = lastmx; lastspr0y = lastmy;
        !          1959:     mstepx = defstepx; mstepy = defstepy;
        !          1960: }
        !          1961: 
        !          1962: static void setfollow(void)
        !          1963: {
        !          1964:     write_log ("Follow sprite mode set\n");
        !          1965:     mousestate = follow_mouse;
        !          1966:     lastdiffx = lastdiffy = 0;
        !          1967:     sprvbfl = 0;
        !          1968:     spr0ctl=spr0pos = 0;
        !          1969:     mstepx = defstepx; mstepy = defstepy;
        !          1970: }
        !          1971: 
        !          1972: uae_u32 mousehack_helper (void)
        !          1973: {
        !          1974:     int mousexpos, mouseypos;
        !          1975: 
        !          1976: #ifdef PICASSO96
        !          1977:     if (picasso_on) {
        !          1978:        mousexpos = lastmx + picasso96_state.XOffset;
        !          1979:        mouseypos = lastmy + picasso96_state.YOffset;
        !          1980:     } else
        !          1981: #endif
        !          1982:     {
        !          1983:        mousexpos = lastmx + linetoscr_x_adjust;
        !          1984:        if (lastmy >= gfxvidinfo.height)
        !          1985:            lastmy = gfxvidinfo.height-1;
        !          1986:        mouseypos = native2amiga_line_map[lastmy] + thisframe_y_adjust - minfirstline;
        !          1987:        mouseypos <<= 1;
        !          1988:        mousexpos <<= (1-lores_shift);
        !          1989:        mousexpos += 2*DISPLAY_LEFT_SHIFT;
        !          1990:     }
        !          1991: 
        !          1992:     switch (m68k_dreg (regs, 0)) {
        !          1993:      case 0:
        !          1994:        return ievent_alive ? -1 : needmousehack ();
        !          1995:      case 1:
        !          1996:        ievent_alive = 10;
        !          1997:        return mousexpos;
        !          1998:      case 2:
        !          1999:        return mouseypos;
        !          2000:     }
        !          2001:     return 0;
        !          2002: }
        !          2003: 
        !          2004: void togglemouse(void)
        !          2005: {
        !          2006:     switch(mousestate) {
        !          2007:      case dont_care_mouse: setfollow(); break;
        !          2008:      case follow_mouse: setdontcare(); break;
        !          2009:      default: break; /* Nnnnnghh! */
        !          2010:     }
        !          2011: }
        !          2012: 
        !          2013: static __inline__ int adjust(int val)
        !          2014: {
        !          2015:     if (val>127)
        !          2016:        return 127;
        !          2017:     else if (val<-127)
        !          2018:        return -127;
        !          2019:     return val;
        !          2020: }
        !          2021: 
        !          2022: static void do_mouse_hack(void)
        !          2023: {
        !          2024:     int spr0x = ((spr0pos & 0xff) << 2) | ((spr0ctl & 1) << 1);
        !          2025:     int spr0y = ((spr0pos >> 8) | ((spr0ctl & 4) << 6)) << 1;
        !          2026:     int diffx, diffy;
        !          2027: 
        !          2028:     if (ievent_alive > 0) {
        !          2029:        mouse_x = mouse_y = 0;
        !          2030:        return;
        !          2031:     }
        !          2032:     switch (mousestate) {
        !          2033:      case normal_mouse:
        !          2034:        diffx = lastmx - lastsampledmx;
        !          2035:        diffy = lastmy - lastsampledmy;
        !          2036:        if (!newmousecounters) {
        !          2037:            if (diffx > 127) diffx = 127;
        !          2038:            if (diffx < -127) diffx = -127;
        !          2039:            mouse_x += diffx;
        !          2040:            if (diffy > 127) diffy = 127;
        !          2041:            if (diffy < -127) diffy = -127;
        !          2042:            mouse_y += diffy;
        !          2043:        }
        !          2044:        lastsampledmx += diffx; lastsampledmy += diffy;
        !          2045:        break;
        !          2046: 
        !          2047:      case dont_care_mouse:
        !          2048:        diffx = adjust (((lastmx-lastspr0x) * mstepx) >> 16);
        !          2049:        diffy = adjust (((lastmy-lastspr0y) * mstepy) >> 16);
        !          2050:        lastspr0x=lastmx; lastspr0y=lastmy;
        !          2051:        mouse_x+=diffx; mouse_y+=diffy;
        !          2052:        break;
        !          2053: 
        !          2054:      case follow_mouse:
        !          2055:        if (sprvbfl && sprvbfl-- >1) {
        !          2056:            int mousexpos, mouseypos;
        !          2057: 
        !          2058:            if ((lastdiffx > docal || lastdiffx < -docal) && lastspr0x != spr0x
        !          2059:                && spr0x > plfstrt*4 + 34 + xcaloff && spr0x < plfstop*4 - xcaloff)
        !          2060:            {
        !          2061:                int val = (lastdiffx << 16) / (spr0x - lastspr0x);
        !          2062:                if (val>=0x8000) mstepx=(mstepx*(calweight-1)+val)/calweight;
        !          2063:            }
        !          2064:            if ((lastdiffy > docal || lastdiffy < -docal) && lastspr0y != spr0y
        !          2065:                && spr0y>plffirstline+ycaloff && spr0y<plflastline-ycaloff)
        !          2066:            {
        !          2067:                int val = (lastdiffy<<16) / (spr0y-lastspr0y);
        !          2068:                if (val>=0x8000) mstepy=(mstepy*(calweight-1)+val)/calweight;
        !          2069:            }
        !          2070:            mousexpos = lastmx + linetoscr_x_adjust;
        !          2071:            if (lastmy >= gfxvidinfo.height)
        !          2072:                lastmy = gfxvidinfo.height-1;
        !          2073:            mouseypos = native2amiga_line_map[lastmy] + thisframe_y_adjust - minfirstline;
        !          2074:            mouseypos <<= 1;
        !          2075:            mousexpos <<= (1-lores_shift);
        !          2076:            mousexpos += 2*DISPLAY_LEFT_SHIFT;
        !          2077:            diffx = adjust ((((mousexpos + xoffs - spr0x) & ~1) * mstepx) >> 16);
        !          2078:            diffy = adjust ((((mouseypos + yoffs - spr0y) & ~1) * mstepy) >> 16);
        !          2079:            lastspr0x=spr0x; lastspr0y=spr0y;
        !          2080:            lastdiffx=diffx; lastdiffy=diffy;
        !          2081:            mouse_x+=diffx; mouse_y+=diffy;
        !          2082:        }
        !          2083:        break;
        !          2084:     }
        !          2085: }
        !          2086: 
        !          2087:  /*
1.1       root     2088:   * register functions
                   2089:   */
                   2090: 
1.1.1.3 ! root     2091: __inline__ uae_u16 DMACONR(void)
1.1       root     2092: {
                   2093:     return (dmacon | (bltstate==BLT_done ? 0 : 0x4000)
                   2094:            | (blt_info.blitzero ? 0x2000 : 0));
                   2095: }
1.1.1.3 ! root     2096: static __inline__ uae_u16 INTENAR(void) { return intena; }
        !          2097: uae_u16 INTREQR(void)
1.1       root     2098: {
1.1.1.3 ! root     2099:     return intreq | (currprefs.use_serial ? 0x0001 : 0);
1.1       root     2100: }
1.1.1.3 ! root     2101: static __inline__ uae_u16 ADKCONR(void) { return adkcon; }
        !          2102: static __inline__ uae_u16 VPOSR(void)
1.1       root     2103: {
                   2104: #if AGA_CHIPSET == 1
                   2105:     return (vpos >> 8) | lof | 0x2300;
                   2106: #elif defined (ECS_AGNUS)
                   2107:     return (vpos >> 8) | lof | 0x2000;
                   2108: #else
                   2109:     return (vpos >> 8) | lof;
                   2110: #endif
                   2111: }
1.1.1.3 ! root     2112: static void  VPOSW(uae_u16 v)
1.1.1.2   root     2113: {
                   2114:     if (lof != (v & 0x8000))
                   2115:        lof_changed = 1;
                   2116:     lof = v & 0x8000;
1.1.1.3 ! root     2117:     /*
        !          2118:      * This register is much more fun on a real Amiga. You can program
        !          2119:      * refresh rates with it ;) But I won't emulate this...
        !          2120:      */
1.1.1.2   root     2121: }
1.1.1.3 ! root     2122: static __inline__ uae_u16 VHPOSR(void) { return (vpos << 8) | current_hpos(); }
1.1       root     2123: 
1.1.1.3 ! root     2124: static __inline__ void COP1LCH(uae_u16 v) { cop1lc = (cop1lc & 0xffff) | ((uae_u32)v << 16); }
        !          2125: static __inline__ void COP1LCL(uae_u16 v) { cop1lc = (cop1lc & ~0xffff) | (v & 0xfffe); }
        !          2126: static __inline__ void COP2LCH(uae_u16 v) { cop2lc = (cop2lc & 0xffff) | ((uae_u32)v << 16); }
        !          2127: static __inline__ void COP2LCL(uae_u16 v) { cop2lc = (cop2lc & ~0xffff) | (v & 0xfffe); }
1.1       root     2128: 
1.1.1.3 ! root     2129: static void  COPJMP1(uae_u16 a)
1.1       root     2130: {
1.1.1.3 ! root     2131:     coplc = cop1lc; copstate = COP_read;
1.1       root     2132:     eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles;
                   2133:     eventtab[ev_copper].evtime = 4 + cycles; events_schedule();
                   2134:     copper_active = 1;
1.1.1.2   root     2135:     copper_waiting_for_blitter = 0;
1.1       root     2136: }
1.1.1.3 ! root     2137: static void  COPJMP2(uae_u16 a)
1.1       root     2138: {
1.1.1.3 ! root     2139:     coplc = cop2lc; copstate = COP_read;
1.1       root     2140:     eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles;
                   2141:     eventtab[ev_copper].evtime = 4 + cycles; events_schedule();
                   2142:     copper_active = 1;
1.1.1.2   root     2143:     copper_waiting_for_blitter = 0;
1.1       root     2144: }
1.1.1.3 ! root     2145: static __inline__ void COPCON(uae_u16 a) { copcon = a; }
        !          2146: static void  DMACON(uae_u16 v)
1.1       root     2147: {
                   2148:     int i, need_resched = 0;
                   2149: 
1.1.1.3 ! root     2150:     uae_u16 oldcon = dmacon;
        !          2151: 
1.1.1.2   root     2152:     decide_line();
1.1       root     2153:     setclr(&dmacon,v); dmacon &= 0x1FFF;
1.1.1.3 ! root     2154:     /* ??? post_decide_line (); */
        !          2155: 
        !          2156:     /* FIXME? Maybe we need to think a bit more about the master DMA enable
1.1       root     2157:      * bit in these cases. */
1.1.1.3 ! root     2158:     if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) {
1.1       root     2159:        COPJMP1(0);
                   2160:     }
                   2161:     if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done) {
                   2162:        static int count = 0;
                   2163:        if (!count) {
                   2164:            count = 1;
1.1.1.3 ! root     2165:            write_log ("warning: program is doing blitpri hacks.\n");
1.1       root     2166:        }
                   2167:        regs.spcflags |= SPCFLAG_BLTNASTY;
                   2168:     }
                   2169: #ifndef DONT_WANT_SOUND
                   2170:     for (i = 0; i < 4; i++) {
                   2171:        struct audio_channel_data *cdp = audio_channel + i;
1.1.1.3 ! root     2172: 
1.1       root     2173:        cdp->dmaen = (dmacon & 0x200) && (dmacon & (1<<i));
                   2174:        if (cdp->dmaen) {
                   2175:            if (cdp->state == 0) {
                   2176:                cdp->state = 1;
                   2177:                cdp->pt = cdp->lc;
                   2178:                cdp->wper = cdp->per;
                   2179:                cdp->wlen = cdp->len;
                   2180:                cdp->data_written = 2;
                   2181:                eventtab[ev_aud0 + i].oldcycles = eventtab[ev_hsync].oldcycles;
                   2182:                eventtab[ev_aud0 + i].evtime = eventtab[ev_hsync].evtime;
                   2183:                eventtab[ev_aud0 + i].active = 1;
                   2184:                need_resched = 1; /* not _really_ necessary here, but... */
                   2185:            }
                   2186:        } else {
                   2187:            if (cdp->state == 1 || cdp->state == 5) {
                   2188:                cdp->state = 0;
                   2189:                cdp->current_sample = 0;
                   2190:                eventtab[ev_aud0 + i].active = 0;
                   2191:                need_resched = 1;
                   2192:            }
                   2193:        }
                   2194:     }
                   2195: #endif
1.1.1.2   root     2196:     calculate_copper_cycle_time ();
1.1       root     2197:     if (copper_active && !eventtab[ev_copper].active) {
                   2198:        eventtab[ev_copper].active = 1;
                   2199:        eventtab[ev_copper].oldcycles = cycles;
                   2200:        eventtab[ev_copper].evtime = 1 + cycles;
                   2201:        need_resched = 1;
                   2202:     }
                   2203:     if (need_resched)
                   2204:        events_schedule();
                   2205: }
1.1.1.2   root     2206: 
1.1.1.3 ! root     2207: /*static int trace_intena = 0;*/
1.1.1.2   root     2208: 
1.1.1.3 ! root     2209: static __inline__ void INTENA (uae_u16 v)
1.1.1.2   root     2210: {
1.1.1.3 ! root     2211: /*    if (trace_intena)
        !          2212:        fprintf(stderr, "INTENA: %04x\n", v);*/
        !          2213:     setclr(&intena,v); regs.spcflags |= SPCFLAG_INT;
1.1.1.2   root     2214: }
1.1.1.3 ! root     2215: void INTREQ (uae_u16 v)
1.1       root     2216: {
1.1.1.3 ! root     2217:     setclr(&intreq,v);
        !          2218:     regs.spcflags |= SPCFLAG_INT;
        !          2219:     if ((v&0x8800)==0x0800) serdat&=0xbfff;
        !          2220: }
1.1       root     2221: 
1.1.1.3 ! root     2222: static void ADKCON (uae_u16 v)
        !          2223: {
        !          2224:     unsigned long t;
        !          2225:     setclr (&adkcon,v);
        !          2226:     t = adkcon | (adkcon >> 4);
        !          2227:     audio_channel[0].adk_mask = (((t >> 0) & 1) - 1);
        !          2228:     audio_channel[1].adk_mask = (((t >> 1) & 1) - 1);
        !          2229:     audio_channel[2].adk_mask = (((t >> 2) & 1) - 1);
        !          2230:     audio_channel[3].adk_mask = (((t >> 3) & 1) - 1);
        !          2231: }
1.1       root     2232: 
1.1.1.3 ! root     2233: static void BPLPTH (uae_u16 v, int num)
        !          2234: {
        !          2235:   decide_line ();
        !          2236:   decide_plane();
        !          2237:   do_modulos();
        !          2238:   bplpt[num] = (bplpt[num] & 0xffff) | ((uae_u32)v << 16);
        !          2239: }
        !          2240: static void BPLPTL (uae_u16 v, int num)
        !          2241: {
        !          2242:   decide_line ();
        !          2243:   decide_plane();
        !          2244:   do_modulos();
        !          2245:   bplpt[num] = (bplpt[num] & ~0xffff) | (v & 0xfffe);
        !          2246: }
1.1       root     2247: 
1.1.1.3 ! root     2248: static void BPLCON0 (uae_u16 v)
1.1       root     2249: {
1.1.1.2   root     2250: #if AGA_CHIPSET == 0
                   2251:     v &= 0xFF0E;
                   2252:     /* The Sanity WOC demo needs this at one place (at the end of the "Party Effect")
                   2253:      * Disable bitplane DMA if someone tries to do more than 4 Hires bitplanes. */
                   2254:     if ((v & 0xF000) > 0xC000)
                   2255:        v &= 0xFFF;
                   2256:     /* Don't want 7 lores planes either. */
                   2257:     if ((v & 0x8000) == 0 && (v & 0x7000) == 0x7000)
                   2258:        v &= 0xEFFF;
                   2259: #endif
                   2260:     if (bplcon0 == v)
1.1       root     2261:        return;
1.1.1.2   root     2262:     decide_line ();
                   2263:     bplcon0 = v;
1.1.1.3 ! root     2264:     nr_planes_from_bplcon0 = (bplcon0 >> 12) & 7;
        !          2265:     corrected_nr_planes_from_bplcon0 = ((bplcon0 >> 12) & 7) << (bplcon0 & 0x8000 ? 1 : 0);
1.1.1.2   root     2266:     post_decide_line ();
                   2267:     calculate_copper_cycle_time ();
                   2268: #if 0
1.1       root     2269:     calcdiw(); /* This should go away. */
1.1.1.2   root     2270: #endif
1.1       root     2271: }
1.1.1.3 ! root     2272: static __inline__ void BPLCON1 (uae_u16 v)
1.1       root     2273: {
1.1.1.2   root     2274:     if (bplcon1 == v)
1.1       root     2275:        return;
1.1.1.2   root     2276:     decide_diw ();
                   2277:     bplcon1 = v;
                   2278:     decide_delay ();
1.1       root     2279: }
1.1.1.3 ! root     2280: static __inline__ void BPLCON2 (uae_u16 v)
1.1       root     2281: {
1.1.1.2   root     2282:     if (bplcon2 != v)
                   2283:        decide_line ();
                   2284:     bplcon2 = v;
1.1       root     2285: }
1.1.1.3 ! root     2286: static __inline__ void BPLCON3 (uae_u16 v)
1.1       root     2287: {
1.1.1.2   root     2288:     if (bplcon3 != v)
                   2289:        decide_line ();
1.1.1.3 ! root     2290:     bplcon3 = v;
1.1       root     2291: }
1.1.1.3 ! root     2292: static __inline__ void BPLCON4 (uae_u16 v)
1.1       root     2293: {
1.1.1.2   root     2294:     if (bplcon4 != v)
                   2295:        decide_line ();
1.1.1.3 ! root     2296:     bplcon4 = v;
1.1       root     2297: }
                   2298: 
1.1.1.3 ! root     2299: static void BPL1MOD (uae_u16 v)
1.1       root     2300: {
                   2301:     v &= ~1;
1.1.1.3 ! root     2302:     if ((uae_s16)bpl1mod == (uae_s16)v)
1.1       root     2303:        return;
                   2304:     bpl1mod = v;
1.1.1.2   root     2305:     decide_modulos ();
1.1       root     2306: }
1.1.1.2   root     2307: 
1.1.1.3 ! root     2308: static void BPL2MOD (uae_u16 v)
        !          2309: {
1.1       root     2310:     v &= ~1;
1.1.1.3 ! root     2311:     if ((uae_s16)bpl2mod == (uae_s16)v)
1.1       root     2312:        return;
                   2313:     bpl2mod = v;
1.1.1.2   root     2314:     decide_modulos();
1.1       root     2315: }
                   2316: 
1.1.1.2   root     2317: /* We could do as well without those... */
1.1.1.3 ! root     2318: static __inline__ void BPL1DAT (uae_u16 v) { bpl1dat = v; }
        !          2319: static __inline__ void BPL2DAT (uae_u16 v) { bpl2dat = v; }
        !          2320: static __inline__ void BPL3DAT (uae_u16 v) { bpl3dat = v; }
        !          2321: static __inline__ void BPL4DAT (uae_u16 v) { bpl4dat = v; }
        !          2322: static __inline__ void BPL5DAT (uae_u16 v) { bpl5dat = v; }
        !          2323: static __inline__ void BPL6DAT (uae_u16 v) { bpl6dat = v; }
1.1       root     2324: 
1.1.1.3 ! root     2325: static void DIWSTRT (uae_u16 v)
1.1       root     2326: {
1.1.1.2   root     2327:     if (diwstrt == v)
1.1       root     2328:        return;
1.1.1.2   root     2329:     decide_line ();
1.1.1.3 ! root     2330:     diwstrt = v;
1.1       root     2331:     calcdiw();
                   2332: }
1.1.1.3 ! root     2333: static void DIWSTOP (uae_u16 v)
1.1       root     2334: {
1.1.1.2   root     2335:     if (diwstop == v)
1.1       root     2336:        return;
1.1.1.3 ! root     2337:     diwstop = v;
1.1       root     2338:     calcdiw();
                   2339: }
1.1.1.3 ! root     2340: static void DDFSTRT (uae_u16 v)
        !          2341: {
1.1.1.2   root     2342:     v &= 0xFF;
                   2343:     if (ddfstrt == v)
1.1       root     2344:        return;
1.1.1.2   root     2345:     decide_line ();
1.1.1.3 ! root     2346:     ddfstrt = v;
1.1       root     2347:     calcdiw();
                   2348: }
1.1.1.3 ! root     2349: static void DDFSTOP (uae_u16 v)
        !          2350: {
1.1.1.2   root     2351:     v &= 0xFF;
                   2352:     if (ddfstop == v)
1.1       root     2353:        return;
1.1.1.2   root     2354:     decide_line ();
                   2355:     ddfstop = v;
1.1       root     2356:     calcdiw();
                   2357: }
                   2358: 
1.1.1.3 ! root     2359: static void  BLTADAT(uae_u16 v)
1.1       root     2360: {
1.1.1.2   root     2361:     maybe_blit();
                   2362: 
                   2363:     blt_info.bltadat = v;
1.1       root     2364: }
1.1.1.2   root     2365: /*
                   2366:  * "Loading data shifts it immediately" says the HRM. Well, that may
                   2367:  * be true for BLTBDAT, but not for BLTADAT - it appears the A data must be
                   2368:  * loaded for every word so that AFWM and ALWM can be applied.
                   2369:  */
1.1.1.3 ! root     2370: static void  BLTBDAT(uae_u16 v)
1.1       root     2371: {
1.1.1.3 ! root     2372:     maybe_blit();
1.1.1.2   root     2373: 
                   2374:     if (bltcon1 & 2)
                   2375:        blt_info.bltbhold = v << (bltcon1 >> 12);
                   2376:     else
                   2377:        blt_info.bltbhold = v >> (bltcon1 >> 12);
                   2378:     blt_info.bltbdat = v;
1.1       root     2379: }
1.1.1.3 ! root     2380: static void BLTCDAT(uae_u16 v) { maybe_blit(); blt_info.bltcdat = v; }
1.1       root     2381: 
1.1.1.3 ! root     2382: static void BLTAMOD(uae_u16 v) { maybe_blit(); blt_info.bltamod = (uae_s16)(v & 0xFFFE); }
        !          2383: static void BLTBMOD(uae_u16 v) { maybe_blit(); blt_info.bltbmod = (uae_s16)(v & 0xFFFE); }
        !          2384: static void BLTCMOD(uae_u16 v) { maybe_blit(); blt_info.bltcmod = (uae_s16)(v & 0xFFFE); }
        !          2385: static void BLTDMOD(uae_u16 v) { maybe_blit(); blt_info.bltdmod = (uae_s16)(v & 0xFFFE); }
1.1       root     2386: 
1.1.1.3 ! root     2387: static void BLTCON0(uae_u16 v) { maybe_blit(); bltcon0 = v; blinea_shift = v >> 12; }
        !          2388: /* The next category is "Most useless hardware register".
1.1       root     2389:  * And the winner is... */
1.1.1.3 ! root     2390: static void BLTCON0L(uae_u16 v) { maybe_blit(); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF); }
        !          2391: static void BLTCON1(uae_u16 v) { maybe_blit(); bltcon1 = v; }
1.1       root     2392: 
1.1.1.3 ! root     2393: static void BLTAFWM(uae_u16 v) { maybe_blit(); blt_info.bltafwm = v; }
        !          2394: static void BLTALWM(uae_u16 v) { maybe_blit(); blt_info.bltalwm = v; }
1.1       root     2395: 
1.1.1.3 ! root     2396: static void BLTAPTH(uae_u16 v) { maybe_blit(); bltapt = (bltapt & 0xffff) | ((uae_u32)v << 16); }
        !          2397: static void BLTAPTL(uae_u16 v) { maybe_blit(); bltapt = (bltapt & ~0xffff) | (v & 0xFFFE); }
        !          2398: static void BLTBPTH(uae_u16 v) { maybe_blit(); bltbpt = (bltbpt & 0xffff) | ((uae_u32)v << 16); }
        !          2399: static void BLTBPTL(uae_u16 v) { maybe_blit(); bltbpt = (bltbpt & ~0xffff) | (v & 0xFFFE); }
        !          2400: static void BLTCPTH(uae_u16 v) { maybe_blit(); bltcpt = (bltcpt & 0xffff) | ((uae_u32)v << 16); }
        !          2401: static void BLTCPTL(uae_u16 v) { maybe_blit(); bltcpt = (bltcpt & ~0xffff) | (v & 0xFFFE); }
        !          2402: static void BLTDPTH(uae_u16 v) { maybe_blit(); bltdpt = (bltdpt & 0xffff) | ((uae_u32)v << 16); }
        !          2403: static void BLTDPTL(uae_u16 v) { maybe_blit(); bltdpt = (bltdpt & ~0xffff) | (v & 0xFFFE); }
        !          2404: static void BLTSIZE(uae_u16 v)
1.1       root     2405: {
                   2406:     bltsize = v;
1.1.1.3 ! root     2407: 
        !          2408:     maybe_blit();
1.1       root     2409: 
                   2410:     blt_info.vblitsize = bltsize >> 6;
                   2411:     blt_info.hblitsize = bltsize & 0x3F;
                   2412:     if (!blt_info.vblitsize) blt_info.vblitsize = 1024;
                   2413:     if (!blt_info.hblitsize) blt_info.hblitsize = 64;
1.1.1.3 ! root     2414: 
        !          2415:     bltstate = BLT_init;
1.1.1.2   root     2416:     do_blitter();
1.1       root     2417: }
1.1.1.3 ! root     2418: static void BLTSIZV(uae_u16 v)
1.1       root     2419: {
1.1.1.3 ! root     2420:     maybe_blit();
1.1       root     2421:     oldvblts = v & 0x7FFF;
                   2422: }
1.1.1.3 ! root     2423: static void BLTSIZH(uae_u16 v)
1.1       root     2424: {
1.1.1.2   root     2425:     maybe_blit();
1.1       root     2426:     blt_info.hblitsize = v & 0x7FF;
                   2427:     blt_info.vblitsize = oldvblts;
                   2428:     if (!blt_info.vblitsize) blt_info.vblitsize = 32768;
                   2429:     if (!blt_info.hblitsize) blt_info.hblitsize = 0x800;
1.1.1.2   root     2430:     bltstate = BLT_init;
                   2431:     do_blitter();
1.1       root     2432: }
1.1.1.3 ! root     2433: static __inline__ void SPRxCTL_1(uae_u16 v, int num)
1.1       root     2434: {
1.1.1.2   root     2435:     int sprxp;
                   2436:     sprctl[num] = v;
1.1.1.3 ! root     2437:     nr_armed -= sprarmed[num];
1.1.1.2   root     2438:     sprarmed[num] = 0;
1.1.1.3 ! root     2439:     if (sprpos[num] == 0 && v == 0) {
        !          2440:        sprst[num] = SPR_stop;
        !          2441:        spron[num] = 0;
        !          2442:     } else
        !          2443:        sprst[num] = SPR_waiting_start;
1.1.1.2   root     2444: 
                   2445:     sprxp = ((sprpos[num] & 0xFF) * 2) + (v & 1) - DISPLAY_LEFT_SHIFT;
1.1.1.3 ! root     2446:     if (!currprefs.gfx_lores)
1.1.1.2   root     2447:        sprxp *= 2;
                   2448:     sprxpos[num] = sprxp;
                   2449:     sprvstart[num] = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100);
                   2450:     sprvstop[num] = (sprctl[num] >> 8) | ((sprctl[num] << 7) & 0x100);
                   2451: }
1.1.1.3 ! root     2452: static __inline__ void SPRxPOS_1(uae_u16 v, int num)
1.1.1.2   root     2453: {
                   2454:     int sprxp;
                   2455:     sprpos[num] = v;
                   2456:     sprxp = ((v & 0xFF) * 2) + (sprctl[num] & 1) - DISPLAY_LEFT_SHIFT;
1.1.1.3 ! root     2457:     if (!currprefs.gfx_lores)
1.1.1.2   root     2458:        sprxp *= 2;
                   2459:     sprxpos[num] = sprxp;
                   2460:     sprvstart[num] = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100);
                   2461: }
1.1.1.3 ! root     2462: static __inline__ void SPRxDATA_1(uae_u16 v, int num)
1.1.1.2   root     2463: {
                   2464:     sprdata[num] = v;
1.1.1.3 ! root     2465:     nr_armed += 1 - sprarmed[num];
1.1.1.2   root     2466:     sprarmed[num] = 1;
                   2467: }
1.1.1.3 ! root     2468: static __inline__ void SPRxDATB_1(uae_u16 v, int num)
1.1.1.2   root     2469: {
                   2470:     sprdatb[num] = v;
                   2471: }
1.1.1.3 ! root     2472: static void SPRxDATA(uae_u16 v, int num) { decide_sprites (); SPRxDATA_1 (v, num); }
        !          2473: static void SPRxDATB(uae_u16 v, int num) { decide_sprites (); SPRxDATB_1 (v, num); }
        !          2474: static void SPRxCTL(uae_u16 v, int num) { decide_sprites (); SPRxCTL_1 (v, num); }
        !          2475: static void SPRxPOS(uae_u16 v, int num) { decide_sprites (); SPRxPOS_1 (v, num); }
        !          2476: static void SPRxPTH(uae_u16 v, int num)
1.1       root     2477: {
1.1.1.3 ! root     2478:     decide_line ();
        !          2479:     sprpt[num] &= 0xffff;
        !          2480:     sprpt[num] |= (uae_u32)v << 16;
        !          2481: 
        !          2482:     if (sprst[num] == SPR_stop || vpos < vblank_endline)
        !          2483:        sprst[num] = SPR_restart;
        !          2484:     spron[num] = 1;
1.1       root     2485: }
1.1.1.3 ! root     2486: static void SPRxPTL(uae_u16 v, int num)
1.1       root     2487: {
1.1.1.3 ! root     2488:     decide_line ();
        !          2489:     sprpt[num] &= ~0xffff;
1.1.1.2   root     2490:     sprpt[num] |= v;
1.1       root     2491: 
1.1.1.3 ! root     2492:     if (sprst[num] == SPR_stop || vpos < vblank_endline)
        !          2493:        sprst[num] = SPR_restart;
        !          2494:     spron[num] = 1;
        !          2495: }
        !          2496: static void CLXCON(uae_u16 v)
        !          2497: {
        !          2498:     clxcon = v;
        !          2499:     clx_sprmask = (((v >> 15) << 7) | ((v >> 14) << 5) | ((v >> 13) << 3) | ((v >> 12) << 1) | 0x55);
        !          2500: }
        !          2501: static uae_u16 CLXDAT(void)
        !          2502: {
        !          2503:     uae_u16 v = clxdat;
        !          2504:     clxdat = 0;
        !          2505:     return v;
        !          2506: }
        !          2507: static void COLOR(uae_u16 v, int num)
1.1       root     2508: {
                   2509:     int r,g,b;
                   2510:     int cr,cg,cb;
                   2511:     int colreg;
1.1.1.3 ! root     2512: 
1.1       root     2513:     v &= 0xFFF;
                   2514: #if AGA_CHIPSET == 1
                   2515:     {
1.1.1.2   root     2516:        /* XXX Broken */
1.1.1.3 ! root     2517:        uae_u32 cval;
1.1.1.2   root     2518:        colreg = ((bplcon3 >> 13) & 7) * 32 + num;
1.1       root     2519:        r = (v & 0xF00) >> 8;
                   2520:        g = (v & 0xF0) >> 4;
                   2521:        b = (v & 0xF) >> 0;
1.1.1.2   root     2522:        cr = color_regs[colreg] >> 16;
                   2523:        cg = (color_regs[colreg] >> 8) & 0xFF;
                   2524:        cb = color_regs[colreg] & 0xFF;
1.1       root     2525: 
1.1.1.2   root     2526:        if (bplcon3 & 0x200) {
1.1       root     2527:            cr &= 0xF0; cr |= r;
                   2528:            cg &= 0xF0; cg |= g;
                   2529:            cb &= 0xF0; cb |= b;
                   2530:        } else {
                   2531:            cr = r + (r << 4);
                   2532:            cg = g + (g << 4);
                   2533:            cb = b + (b << 4);
                   2534:        }
                   2535:        cval = (cr << 16) | (cg << 8) | cb;
1.1.1.2   root     2536:        if (cval == color_regs[colreg])
1.1       root     2537:            return;
1.1.1.2   root     2538:        color_regs[colreg] = cval;
1.1       root     2539:        pfield_may_need_update(1);
                   2540:     }
1.1.1.3 ! root     2541: #else
1.1       root     2542:     {
1.1.1.2   root     2543:        if (current_colors.color_regs[num] == v)
1.1       root     2544:            return;
1.1.1.2   root     2545:        /* Call this with the old table still intact. */
                   2546:        record_color_change (num, v);
                   2547:        remembered_color_entry = -1;
                   2548:        current_colors.color_regs[num] = v;
                   2549:        current_colors.acolors[num] = xcolors[v];
1.1       root     2550:     }
                   2551: #endif
                   2552: }
                   2553: 
1.1.1.3 ! root     2554: static void  DSKSYNC(uae_u16 v) { dsksync = v; }
        !          2555: static void  DSKDAT(uae_u16 v) { write_log ("DSKDAT written. Not good.\n"); }
        !          2556: static void  DSKPTH(uae_u16 v) { dskpt = (dskpt & 0xffff) | ((uae_u32)v << 16); }
        !          2557: static void  DSKPTL(uae_u16 v) { dskpt = (dskpt & ~0xffff) | (v); }
1.1       root     2558: 
1.1.1.3 ! root     2559: static void  DSKLEN(uae_u16 v)
1.1       root     2560: {
                   2561:     if (v & 0x8000) {
                   2562:        dskdmaen = dskdmaen == 1 ? 2 : 1;
1.1.1.3 ! root     2563:     } else {
1.1       root     2564:        dskdmaen = 0;
                   2565:        if (eventtab[ev_diskblk].active)
1.1.1.3 ! root     2566:            write_log ("warning: Disk DMA aborted!\n");
1.1       root     2567:        eventtab[ev_diskblk].active = 0;
                   2568:        events_schedule();
1.1.1.3 ! root     2569: 
1.1       root     2570:     }
                   2571:     dsklen = dsklength = v; dsklength &= 0x3fff;
                   2572:     if (dskdmaen == 2 && dsksync != 0x4489 && (adkcon & 0x400)) {
1.1.1.3 ! root     2573:        sprintf (warning_buffer, "Non-standard sync: %04x len: %x\n", dsksync, dsklength);
        !          2574:        write_log (warning_buffer);
1.1       root     2575:     }
                   2576:     if (dskdmaen > 1) {
                   2577:        if (dsklen & 0x4000) {
                   2578:            eventtab[ev_diskblk].active = 1;
                   2579:            eventtab[ev_diskblk].oldcycles = cycles;
                   2580:            eventtab[ev_diskblk].evtime = 40 + cycles; /* ??? */
                   2581:            events_schedule();
                   2582:        } else {
                   2583:            int result = DISK_PrepareReadMFM(dsklength, dsksync, adkcon & 0x400);
                   2584:            if (result) {
                   2585:                eventtab[ev_diskblk].active = 1;
                   2586:                eventtab[ev_diskblk].oldcycles = cycles;
                   2587:                eventtab[ev_diskblk].evtime = result + cycles;
                   2588:                events_schedule();
                   2589:            }
                   2590:        }
                   2591:     }
                   2592: }
                   2593: 
1.1.1.3 ! root     2594: static uae_u16 DSKBYTR(void)
1.1       root     2595: {
1.1.1.3 ! root     2596:     uae_u16 v = (dsklen >> 1) & 0x6000;
        !          2597:     uae_u16 mfm, byte;
1.1       root     2598:     if (DISK_GetData(&mfm, &byte))
                   2599:        v |= 0x8000;
                   2600:     v |= byte;
                   2601:     if (dsksync == mfm) v |= 0x1000;
                   2602:     return v;
                   2603: }
                   2604: 
1.1.1.3 ! root     2605: static uae_u16 DSKDATR(void)
1.1       root     2606: {
1.1.1.3 ! root     2607:     uae_u16 mfm, byte;
1.1       root     2608:     DISK_GetData(&mfm, &byte);
1.1.1.3 ! root     2609:     return mfm;
1.1       root     2610: }
1.1.1.3 ! root     2611: 
        !          2612: static uae_u16 potgo_value;
        !          2613: 
        !          2614: static void POTGO(uae_u16 v)
1.1       root     2615: {
1.1.1.3 ! root     2616:     potgo_value = v;
        !          2617: }
        !          2618: 
        !          2619: static uae_u16 POTGOR(void)
        !          2620: {
        !          2621:     uae_u16 v = (potgo_value | (potgo_value << 1)) & 0xAA00;
        !          2622:     v |= v >> 1;
        !          2623: 
        !          2624:     if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) {
        !          2625:        if (buttonstate[2])
        !          2626:            v &= 0xFBFF;
        !          2627: 
        !          2628:        if (buttonstate[1])
        !          2629:            v &= 0xFEFF;
        !          2630:     }
        !          2631:     else if (JSEM_ISJOY0(0, currprefs.fake_joystick) || JSEM_ISJOY1(0, currprefs.fake_joystick)) {
        !          2632:        if (joy0button & 2) v &= 0xfbff;
        !          2633:        if (joy0button & 4) v &= 0xfeff;
        !          2634:     }
        !          2635: 
        !          2636:     if (JSEM_ISJOY0(1, currprefs.fake_joystick) || JSEM_ISJOY1(1, currprefs.fake_joystick)) {
        !          2637:        if (joy1button & 2) v &= 0xbfff;
        !          2638:        if (joy1button & 4) v &= 0xefff;
        !          2639:     }
1.1       root     2640: 
                   2641:     return v;
                   2642: }
1.1.1.3 ! root     2643: static uae_u16 POT0DAT(void)
1.1       root     2644: {
1.1.1.3 ! root     2645:     static uae_u16 cnt = 0;
        !          2646:     if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) {
        !          2647:        if (buttonstate[2])
        !          2648:            cnt = ((cnt + 1) & 0xFF) | (cnt & 0xFF00);
        !          2649:        if (buttonstate[1])
        !          2650:            cnt += 0x100;
        !          2651:     }
        !          2652: 
1.1       root     2653:     return cnt;
                   2654: }
1.1.1.3 ! root     2655: static uae_u16 JOY0DAT(void)
1.1       root     2656: {
1.1.1.3 ! root     2657:     if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) {
        !          2658:        do_mouse_hack();
        !          2659:        return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8);
        !          2660:     }
1.1       root     2661:     return joy0dir;
                   2662: }
1.1.1.3 ! root     2663: static uae_u16 JOY1DAT(void)
1.1       root     2664: {
1.1.1.3 ! root     2665:     if (JSEM_ISMOUSE (1, currprefs.fake_joystick)) {
        !          2666:        do_mouse_hack();
        !          2667:        return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8);
        !          2668:     }
        !          2669:     return joy1dir;
1.1       root     2670: }
1.1.1.3 ! root     2671: static void JOYTEST(uae_u16 v)
1.1       root     2672: {
1.1.1.3 ! root     2673:     if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) {
        !          2674:        mouse_x = v & 0xFC;
        !          2675:        mouse_y = (v >> 8) & 0xFC;
1.1       root     2676:     }
                   2677: }
                   2678: 
1.1.1.2   root     2679: /*
                   2680:  * Here starts the copper code. It should be rewritten.
                   2681:  */
                   2682: 
1.1.1.3 ! root     2683: #define COPPER_ALTERNATIVE 1
1.1       root     2684: /*
                   2685:  * Calculate the minimum number of cycles after which the
                   2686:  * copper comparison becomes true. This is quite tricky. I hope it works.
                   2687:  */
                   2688: static int calc_copcomp_true(int currvpos, int currhpos)
1.1.1.3 ! root     2689: {
        !          2690:     uae_u16 vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
        !          2691:     uae_u16 hp = currhpos & (copi2 & 0xFE);
        !          2692:     uae_u16 vcmp = ((copi1 & (copi2 | 0x8000)) >> 8);
        !          2693:     uae_u16 hcmp = (copi1 & copi2 & 0xFE);
1.1       root     2694:     int copper_time_hpos;
                   2695:     int cycleadd = maxhpos - currhpos;
                   2696:     int coptime = 0;
1.1.1.3 ! root     2697:     int maxwait = 32767;
1.1       root     2698: 
1.1.1.3 ! root     2699: #if COPPER_ALTERNATIVE == 0
1.1.1.2   root     2700:     /* This is a kludge... the problem is that there are programs that wait for
                   2701:      * FFDDFFFE and then for a line in the second display half, and this doesn't
                   2702:      * work without this. I _think_ the reason why it works on the Amiga is that
                   2703:      * the last cycle in the line isn't available for the copper, but I'm not sure.
                   2704:      * OTOH, I'm pretty convinced that the copper timings are correct otherwise, so
                   2705:      * I added this rather than changing something else. */
                   2706:     if (hcmp == 0xDC)
                   2707:        hcmp += 2;
1.1.1.3 ! root     2708: #endif
        !          2709:     decide_line();
        !          2710:     /* Copper DMA is turned off in Hires 4 bitplane mode */
        !          2711:     if (vp == vcmp
        !          2712:        && decided_nr_planes == 4 /* -1 if before plfstrt */
        !          2713:        && decided_hires
        !          2714:        && currhpos >= thisline_decision.plfstrt
        !          2715:        && currhpos < thisline_decision.plfstrt + thisline_decision.plflinelen)
        !          2716:        coptime += thisline_decision.plfstrt + thisline_decision.plflinelen - currhpos;
        !          2717: 
1.1       root     2718:     if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000)))
1.1.1.3 ! root     2719:        return coptime;
1.1       root     2720: 
                   2721:     try_again:
                   2722: 
                   2723:     while (vp < vcmp) {
                   2724:        currvpos++;
                   2725:        if (currvpos > maxvpos + 1)
                   2726:            return -1;
                   2727:        currhpos = 0;
                   2728:        coptime += cycleadd;
                   2729:        cycleadd = maxhpos;
                   2730:        vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
                   2731:     }
1.1.1.3 ! root     2732:     if ((bplcon0 & 0xF000) == 0xC000) {
        !          2733:        if (coptime > 0)
        !          2734:            return coptime;
        !          2735:        maxwait = plfstrt - current_hpos();
        !          2736:        if (maxwait < 0)
        !          2737:            maxwait = 32767;
        !          2738:     }
1.1       root     2739:     copper_time_hpos = currhpos;
                   2740:     hp = copper_time_hpos & (copi2 & 0xFE);
1.1.1.3 ! root     2741:     if (!(vp > vcmp)) {
1.1.1.2   root     2742:        while ((int)hp < ((int)hcmp)) {
1.1       root     2743:            currhpos++;
                   2744:            /* Copper DMA is turned off in Hires 4 bitplane mode */
1.1.1.2   root     2745:            if (decided_nr_planes != 4 /* -1 if before plfstrt */
                   2746:                || !decided_hires
                   2747:                || current_hpos () >= (thisline_decision.plfstrt + thisline_decision.plflinelen))
1.1       root     2748:                copper_time_hpos++;
1.1.1.3 ! root     2749: 
1.1.1.2   root     2750:            if (currhpos > maxhpos) {
1.1       root     2751:                /* Now, what? There might be a good position on the
                   2752:                 * next line. But it can also be the FFFF FFFE
                   2753:                 * case.
                   2754:                 */
                   2755:                currhpos = 0;
                   2756:                currvpos++;
                   2757:                vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
                   2758:                goto try_again;
                   2759:            }
                   2760:            coptime++;
1.1.1.3 ! root     2761:            if (coptime >= maxwait)
        !          2762:                return coptime;
1.1       root     2763:            hp = copper_time_hpos & (copi2 & 0xFE);
                   2764:        }
                   2765:     }
1.1.1.2   root     2766:     if (coptime == 0) /* waiting for the blitter */
1.1.1.3 ! root     2767:        return 1;
1.1.1.2   root     2768: 
                   2769:     return coptime;
                   2770: }
                   2771: 
                   2772: /*
                   2773:  * Simple version of the above which only tries to get vpos correct.
                   2774:  */
                   2775: static int calc_copcomp_true_vpos(int currvpos, int currhpos)
1.1.1.3 ! root     2776: {
        !          2777:     uae_u16 vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
        !          2778:     uae_u16 hp = currhpos & (copi2 & 0xFE);
        !          2779:     uae_u16 vcmp = ((copi1 & (copi2 | 0x8000)) >> 8);
        !          2780:     uae_u16 hcmp = (copi1 & copi2 & 0xFE);
1.1.1.2   root     2781:     int copper_time_hpos;
                   2782:     int cycleadd = maxhpos - currhpos;
                   2783:     int coptime = 0;
1.1.1.3 ! root     2784: #if COPPER_ALTERNATIVE == 0
1.1.1.2   root     2785:     /* see above */
                   2786:     if (hcmp == 0xDC)
                   2787:        hcmp += 2;
1.1.1.3 ! root     2788: #endif
1.1.1.2   root     2789:     if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000)))
1.1.1.3 ! root     2790:        return 0;
1.1.1.2   root     2791: 
                   2792:     while (vp < vcmp) {
                   2793:        currvpos++;
                   2794:        if (currvpos > maxvpos + 1)
                   2795:            return -1;
                   2796:        currhpos = 0;
                   2797:        coptime += cycleadd;
                   2798:        cycleadd = maxhpos;
                   2799:        vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
                   2800:     }
                   2801:     return coptime;
                   2802: }
                   2803: 
                   2804: static enum copper_states cop_cmds[4] = { COP_move, COP_wait, COP_move, COP_skip };
                   2805: 
                   2806: /* This function is not always correct, but it's the best we can do. */
                   2807: static int copper_memory_cycles (int n)
                   2808: {
                   2809:     int current_cycle = current_hpos ();
                   2810:     int n_needed = 0;
1.1.1.3 ! root     2811:     int planes = corrected_nr_planes_from_bplcon0;
        !          2812: 
1.1.1.2   root     2813:     while (n) {
                   2814:        /* This sucks. The DIW may end vertically at exactly this point. Therefore,
                   2815:         * we must call decide_line(). If we're vertically outside the DIW,
                   2816:         * copper_cycle_time will be != -1 after this call [Sanity Interference] */
                   2817:        decide_line ();
1.1.1.3 ! root     2818: #if COPPER_ALTERNATIVE == 1
        !          2819:        if (current_cycle >= (maxhpos-3)) {
        !          2820:            n_needed += maxhpos - current_cycle;
        !          2821:            current_cycle = 0;
        !          2822:            continue;
        !          2823:        }
        !          2824: #endif
        !          2825:        if (copper_cycle_time == -1 && current_cycle >= 0x14
        !          2826:            && current_cycle >= plfstrt && current_cycle < plfstrt + plflinelen
        !          2827:            && (planes == 6 || (planes == 5 && (current_cycle % 8) < 4)))
1.1.1.2   root     2828:        {
                   2829:            n_needed += 4;
                   2830:            current_cycle += 4;
                   2831:        } else {
                   2832:            n_needed += 2;
1.1.1.3 ! root     2833:            current_cycle += 2;
1.1.1.2   root     2834:        }
1.1.1.3 ! root     2835:        if (current_cycle >= maxhpos)
        !          2836:            current_cycle -= maxhpos;
1.1.1.2   root     2837:        n--;
                   2838:     }
                   2839:     return n_needed;
                   2840: }
1.1       root     2841: 
1.1.1.2   root     2842: static __inline__ int calc_copper_cycles (int n_cycles)
                   2843: {
1.1.1.3 ! root     2844:     return /*copper_cycle_time != -1 ? copper_cycle_time * n_cycles : */copper_memory_cycles (n_cycles);
1.1       root     2845: }
                   2846: 
1.1.1.2   root     2847: static __inline__ int copper_init_read (int n_cycles)
1.1       root     2848: {
                   2849:     if (dmaen(DMA_COPPER)){
1.1.1.2   root     2850:        int t = calc_copper_cycles (n_cycles);
                   2851: 
                   2852:        eventtab[ev_copper].evtime = t + cycles;
                   2853:        return 1;
1.1       root     2854:     } else {
                   2855:        copstate = COP_read;
                   2856:        eventtab[ev_copper].active = 0;
1.1.1.2   root     2857:        return 0;
                   2858:     }
                   2859: }
                   2860: 
                   2861: static __inline__ void copper_read (void)
                   2862: {
                   2863:     int cmd;
1.1.1.3 ! root     2864: 
        !          2865:     copi1 = chipmem_bank.wget(coplc);
1.1.1.2   root     2866:     copi2 = chipmem_bank.wget(coplc+2);
                   2867:     coplc += 4;
                   2868:     eventtab[ev_copper].oldcycles = cycles;
1.1.1.3 ! root     2869: 
1.1.1.2   root     2870:     cmd = (copi1 & 1) | ((copi2 & 1) << 1);
                   2871:     copstate = cop_cmds[cmd];
                   2872:     eventtab[ev_copper].oldcycles = cycles;
                   2873: }
                   2874: 
                   2875: static __inline__ void handle_bltfinish_wait (void)
                   2876: {
                   2877:     if (bltstate == BLT_done) {
                   2878:        copstate = COP_read;
                   2879:        /* Don't need to wait. Experimental: No copper wakeup time in this case. */
                   2880:     } else {
                   2881:        eventtab[ev_copper].active = 0;
                   2882:        copstate = COP_morewait;
                   2883:        copper_waiting_for_blitter = 1;
                   2884:     }
                   2885: }
                   2886: 
                   2887: void blitter_done_notify (void)
                   2888: {
                   2889:     if (copper_waiting_for_blitter) {
                   2890:        copper_waiting_for_blitter = 0;
                   2891:        eventtab[ev_copper].active = 1;
                   2892:        eventtab[ev_copper].oldcycles = cycles;
                   2893:        eventtab[ev_copper].evtime = 1 + cycles;
                   2894:        events_schedule ();
1.1       root     2895:     }
                   2896: }
                   2897: 
1.1.1.3 ! root     2898: #if 0
        !          2899: static void do_copper_cheat(void)
        !          2900: {
        !          2901:     int coptime, t;
        !          2902:     int nmoves = 100; /*??*/
        !          2903:     int nextcycles = eventtab[ev_hsync].evtime + currprefs.copper_pos;
        !          2904: 
        !          2905:     eventtab[ev_copper].evtime = nextcycles;
        !          2906:     eventtab[ev_copper].oldcycles = cycles;
        !          2907:     nextcycles -= cycles;
        !          2908: 
        !          2909:     if (!dmaen(DMA_COPPER)) {
        !          2910:        eventtab[ev_copper].active = 0;
        !          2911:        return;
        !          2912:     }
        !          2913:     for (; nmoves; nmoves--)
        !          2914:        switch(copstate){
        !          2915:         case COP_read:
        !          2916:            copper_read ();
        !          2917:            break;
        !          2918: 
        !          2919:         case COP_read_ignore:
        !          2920:            copper_read ();
        !          2921:            copstate = COP_read;
        !          2922:            break;
        !          2923: 
        !          2924:         case COP_move:
        !          2925:            if (copi1 >= (copcon & 2 ? 0x40u : 0x80u)) {
        !          2926:                custom_bank.wput(copi1,copi2);
        !          2927:                copstate = COP_read;
        !          2928:            } else {
        !          2929:                copstate = COP_stop;
        !          2930:                eventtab[ev_copper].active = 0;
        !          2931:                copper_active = 0;
        !          2932:                return;
        !          2933:            }
        !          2934:            break;
        !          2935: 
        !          2936:         case COP_skip:
        !          2937:            copstate = COP_read;
        !          2938:            if (calc_copcomp_true(vpos, current_hpos()) == 0)
        !          2939:                copstate = COP_read_ignore;
        !          2940:            break;
        !          2941: 
        !          2942:         case COP_wait:
        !          2943:            coptime = calc_copcomp_true(vpos, current_hpos());
        !          2944:            if (coptime < 0) {
        !          2945:                copstate = COP_stop;
        !          2946:                eventtab[ev_copper].active = 0;
        !          2947:                copper_active = 0;
        !          2948:                return;
        !          2949:            }
        !          2950:            if (coptime == 0) {
        !          2951:                copper_read();
        !          2952:                if (vpos != 255)
        !          2953:                    break;
        !          2954:                eventtab[ev_copper].evtime = cycles + 6;
        !          2955:                return;
        !          2956:            }
        !          2957:            if (coptime >= nextcycles)
        !          2958:                return;
        !          2959:            if (vpos == 255)
        !          2960:                eventtab[ev_copper].evtime = cycles + coptime;
        !          2961:            /*else
        !          2962:                copstate = COP_read;*/
        !          2963:            return;
        !          2964: 
        !          2965:         case COP_stop:
        !          2966:            eventtab[ev_copper].active = 0;
        !          2967:            copper_active = 0;
        !          2968:            return;
        !          2969: 
        !          2970:         case COP_morewait:
        !          2971:         case COP_do_read:
        !          2972:         case COP_do_read_ignore:
        !          2973:            abort();
        !          2974:        }
        !          2975: }
        !          2976: #endif
        !          2977: 
1.1       root     2978: static void do_copper(void)
1.1.1.2   root     2979: {
                   2980:     int coptime, t;
                   2981:     for (;;)
                   2982:        switch(copstate){
                   2983:         case COP_read:
                   2984:            eventtab[ev_copper].oldcycles = cycles;
                   2985:            if (!copper_init_read (2))
                   2986:                return;
                   2987:            copstate = COP_do_read;
                   2988:            return;
1.1.1.3 ! root     2989: 
1.1.1.2   root     2990:         case COP_do_read:
                   2991:            copper_read ();
                   2992:            break;
                   2993: 
                   2994:         case COP_read_ignore:
                   2995:            eventtab[ev_copper].oldcycles = cycles;
                   2996:            if (!copper_init_read (2))
                   2997:                return;
                   2998:            copstate = COP_do_read_ignore;
                   2999:            return;
                   3000: 
                   3001:         case COP_do_read_ignore:
                   3002:            copper_read ();
                   3003:            copstate = COP_read;
                   3004:            break;
                   3005: 
                   3006:         case COP_move:
1.1.1.3 ! root     3007:            if (copi1 >= (copcon & 2 ? 0x40u : 0x80u)) {
1.1.1.2   root     3008:                custom_bank.wput(copi1,copi2);
                   3009:                copstate = COP_read;
                   3010:                break;
                   3011:            } else {
                   3012:                copstate = COP_stop;
                   3013:                eventtab[ev_copper].active = 0;
                   3014:                copper_active = 0;
                   3015:            }
                   3016:            return;
                   3017: 
                   3018:         case COP_skip:
                   3019:            copstate = COP_read;
                   3020:            if (calc_copcomp_true(vpos, current_hpos()) == 0)
                   3021:                copstate = COP_read_ignore;
                   3022:            break;
                   3023: 
                   3024:         case COP_wait:
                   3025:            /* Recognize blitter wait statements. This is a speed optimization
                   3026:             * only.*/
                   3027:            if (copi1 == 1 && copi2 == 0) {
                   3028:                handle_bltfinish_wait ();
                   3029:                if (!eventtab[ev_copper].active)
                   3030:                    return;
                   3031:                break;
                   3032:            }
                   3033:            coptime = calc_copcomp_true_vpos(vpos, current_hpos());
                   3034:            if (coptime > 0) {
                   3035:                copstate = COP_morewait;
                   3036:                eventtab[ev_copper].oldcycles = cycles;
                   3037:                eventtab[ev_copper].evtime = coptime + cycles;
                   3038:                return;
                   3039:            }
                   3040:            coptime = calc_copcomp_true(vpos, current_hpos());
                   3041:            if (coptime < 0) {
                   3042:                copstate = COP_stop;
                   3043:                eventtab[ev_copper].active = 0;
                   3044:                copper_active = 0;
                   3045:                return;
                   3046:            }
                   3047:            if (coptime) {
                   3048:                copstate = COP_morewait;
                   3049:                eventtab[ev_copper].evtime = coptime + cycles;
                   3050:                return;
                   3051:            }
                   3052:            copstate = COP_read;
                   3053:            /* Experimental: no copper wakeup time in this case. The HRM says
                   3054:             * nothing about this. */
                   3055:            break;
                   3056: 
                   3057:         case COP_morewait:
                   3058:            coptime = calc_copcomp_true(vpos, current_hpos());
                   3059:            if (coptime < 0) {
                   3060:                copstate = COP_stop;
                   3061:                eventtab[ev_copper].active = 0;
                   3062:                copper_active = 0;
                   3063:                return;
                   3064:            }
                   3065:            if (coptime) {
                   3066:                eventtab[ev_copper].evtime = coptime + cycles;
                   3067:                return;
                   3068:            }
                   3069:            /* Copper wakeup time: 1 memory cycle, plus 2 for the next read */
                   3070:            eventtab[ev_copper].oldcycles = cycles;
                   3071:            if (!copper_init_read (3))
                   3072:                return;
                   3073:            copstate = COP_do_read;
                   3074:            return;
                   3075: 
                   3076:         case COP_stop:
1.1       root     3077:            eventtab[ev_copper].active = 0;
                   3078:            copper_active = 0;
1.1.1.2   root     3079:            return;
1.1       root     3080:        }
                   3081: }
                   3082: 
                   3083: static void diskblk_handler(void)
                   3084: {
                   3085:     regs.spcflags |= SPCFLAG_DISK;
                   3086:     eventtab[ev_diskblk].active = 0;
                   3087: }
                   3088: 
                   3089: void do_disk(void)
                   3090: {
                   3091:     if (dskdmaen != 2 && (regs.spcflags & SPCFLAG_DISK)) {
1.1.1.3 ! root     3092:        static int warned = 0;
        !          3093:        if (!warned)
        !          3094:            warned++, write_log ("BUG!\n");
1.1       root     3095:        return;
                   3096:     }
                   3097:     if (dmaen(0x10)){
                   3098:        if (dsklen & 0x4000) {
                   3099:            if (!chipmem_bank.check (dskpt, 2*dsklength)) {
1.1.1.3 ! root     3100:                write_log ("warning: Bad disk write DMA pointer\n");
1.1       root     3101:            } else {
1.1.1.3 ! root     3102:                uae_u8 *mfmp = get_real_address (dskpt);
1.1       root     3103:                int i;
                   3104:                DISK_InitWrite();
                   3105: 
                   3106:                for (i = 0; i < dsklength; i++) {
1.1.1.3 ! root     3107:                    uae_u16 d = (*mfmp << 8) + *(mfmp+1);
1.1       root     3108:                    mfmwrite[i] = d;
                   3109:                    mfmp += 2;
                   3110:                }
                   3111:                DISK_WriteData(dsklength);
                   3112:            }
                   3113:        } else {
                   3114:            int result = DISK_ReadMFM (dskpt);
                   3115:        }
                   3116:        regs.spcflags &= ~SPCFLAG_DISK;
                   3117:        INTREQ(0x9002);
                   3118:        dskdmaen = -1;
                   3119:     }
                   3120: }
                   3121: 
                   3122: static void gen_pfield_tables(void)
                   3123: {
                   3124:     int i;
                   3125:     union {
                   3126:        struct {
1.1.1.3 ! root     3127:            uae_u8 a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p;
1.1       root     3128:        } foo;
                   3129:        struct {
1.1.1.3 ! root     3130:            uae_u32 a, b, c, d;
1.1       root     3131:        } bar;
                   3132:     } baz;
1.1.1.3 ! root     3133: 
1.1       root     3134:     for (i = 0; i < 256; i++) {
                   3135:        /* We lose every second pixel in HiRes if UAE runs in a 320x200 screen. */
                   3136:        baz.foo.a = i & 64 ? 1 : 0;
                   3137:        baz.foo.b = i & 16 ? 1 : 0;
                   3138:        baz.foo.c = i & 4 ? 1 : 0;
                   3139:        baz.foo.d = i & 1 ? 1 : 0;
                   3140:        hirestab_l[i][0] = baz.bar.a;
1.1.1.3 ! root     3141: 
1.1       root     3142:        baz.foo.a = i & 128 ? 1 : 0;
                   3143:        baz.foo.b = i & 64 ? 1 : 0;
                   3144:        baz.foo.c = i & 32 ? 1 : 0;
                   3145:        baz.foo.d = i & 16 ? 1 : 0;
                   3146:        baz.foo.e = i & 8 ? 1 : 0;
                   3147:        baz.foo.f = i & 4 ? 1 : 0;
                   3148:        baz.foo.g = i & 2 ? 1 : 0;
                   3149:        baz.foo.h = i & 1 ? 1 : 0;
                   3150:        lorestab_l[i][0] = baz.bar.a;
                   3151:        lorestab_l[i][1] = baz.bar.b;
1.1.1.3 ! root     3152:        sprtaba[i] = ((((i >> 7) & 1) << 0)
        !          3153:                      | (((i >> 6) & 1) << 2)
        !          3154:                      | (((i >> 5) & 1) << 4)
        !          3155:                      | (((i >> 4) & 1) << 6)
        !          3156:                      | (((i >> 3) & 1) << 8)
        !          3157:                      | (((i >> 2) & 1) << 10)
        !          3158:                      | (((i >> 1) & 1) << 12)
        !          3159:                      | (((i >> 0) & 1) << 14));
        !          3160:        sprtabb[i] = sprtaba[i] * 2;
        !          3161:        clxtab[i] = ((((i & 3) && (i & 12)) << 9)
        !          3162:                     | (((i & 3) && (i & 48)) << 10)
        !          3163:                     | (((i & 3) && (i & 192)) << 11)
        !          3164:                     | (((i & 12) && (i & 48)) << 12)
        !          3165:                     | (((i & 12) && (i & 192)) << 13)
        !          3166:                     | (((i & 48) && (i & 192)) << 14));
1.1       root     3167:     }
1.1.1.3 ! root     3168: 
1.1       root     3169:     for (i = 0; i < 256; i++) {
                   3170:        baz.foo.a = i & 128 ? 1 : 0;
                   3171:        baz.foo.b = i & 64 ? 1 : 0;
                   3172:        baz.foo.c = i & 32 ? 1 : 0;
                   3173:        baz.foo.d = i & 16 ? 1 : 0;
                   3174:        baz.foo.e = i & 8 ? 1 : 0;
                   3175:        baz.foo.f = i & 4 ? 1 : 0;
                   3176:        baz.foo.g = i & 2 ? 1 : 0;
                   3177:        baz.foo.h = i & 1 ? 1 : 0;
                   3178:        hirestab_h[i][0] = baz.bar.a;
                   3179:        hirestab_h[i][1] = baz.bar.b;
1.1.1.3 ! root     3180: 
1.1       root     3181:        baz.foo.a = i & 128 ? 1 : 0;
                   3182:        baz.foo.b = i & 128 ? 1 : 0;
                   3183:        baz.foo.c = i & 64 ? 1 : 0;
                   3184:        baz.foo.d = i & 64 ? 1 : 0;
                   3185:        baz.foo.e = i & 32 ? 1 : 0;
                   3186:        baz.foo.f = i & 32 ? 1 : 0;
                   3187:        baz.foo.g = i & 16 ? 1 : 0;
                   3188:        baz.foo.h = i & 16 ? 1 : 0;
                   3189:        baz.foo.i = i & 8 ? 1 : 0;
                   3190:        baz.foo.j = i & 8 ? 1 : 0;
                   3191:        baz.foo.k = i & 4 ? 1 : 0;
                   3192:        baz.foo.l = i & 4 ? 1 : 0;
                   3193:        baz.foo.m = i & 2 ? 1 : 0;
                   3194:        baz.foo.n = i & 2 ? 1 : 0;
                   3195:        baz.foo.o = i & 1 ? 1 : 0;
                   3196:        baz.foo.p = i & 1 ? 1 : 0;
                   3197:        lorestab_h[i][0] = baz.bar.a;
                   3198:        lorestab_h[i][1] = baz.bar.b;
                   3199:        lorestab_h[i][2] = baz.bar.c;
                   3200:        lorestab_h[i][3] = baz.bar.d;
                   3201:     }
                   3202: }
                   3203: 
1.1.1.3 ! root     3204: static void do_sprites(int currvp, int currhp)
1.1.1.2   root     3205: {
                   3206:     int i;
1.1.1.3 ! root     3207:     /* The graph in the HRM, p. 195 seems to indicate that sprite 0 is
        !          3208:      * fetched at cycle 0x14 and thus can't be disabled by bitplane DMA. */
        !          3209:     int maxspr = currhp/4 - 0x14/4;
        !          3210: #if 0
        !          3211:     if (currvp == 0)
        !          3212:        return;
        !          3213: #else
        !          3214:     /* I don't know whether this is right. Some programs write the sprite pointers
        !          3215:      * directly at the start of the copper list. With the currvp==0 check, the
        !          3216:      * first two words of data are read on the second line in the frame. The problem
        !          3217:      * occurs when the program jumps to another copperlist a few lines further down
        !          3218:      * which _also_ writes the sprite pointer registers. This means that a) writing
        !          3219:      * to the sprite pointers sets the state to SPR_restart; or b) that sprite DMA
        !          3220:      * is disabled until the end of the vertical blanking interval. The HRM
        !          3221:      * isn't clear - it says that the vertical sprite position can be set to any
        !          3222:      * value, but this wouldn't be the first mistake... */
        !          3223:     /* Update: I modified one of the programs to write the sprite pointers the
        !          3224:      * second time only _after_ the VBlank interval, and it showed the same behaviour
        !          3225:      * as it did unmodified under UAE with the above check. This indicates that the
        !          3226:      * solution below is correct. */
        !          3227:     if (currvp < vblank_endline)
        !          3228:        return;
        !          3229: #endif
        !          3230:     if (maxspr < 0)
        !          3231:        return;
        !          3232:     if (maxspr > 8)
        !          3233:        maxspr = 8;
1.1.1.2   root     3234: 
1.1.1.3 ! root     3235:     for (i = 0; i < maxspr; i++) {
        !          3236:        int fetch = 0;
1.1.1.2   root     3237: 
1.1.1.3 ! root     3238:        if (spron[i] == 0)
        !          3239:            continue;
        !          3240: 
        !          3241:        if (sprst[i] == SPR_restart) {
        !          3242:            fetch = 2;
        !          3243:            spron[i] = 1;
        !          3244:        } else if ((sprst[i] == SPR_waiting_start && sprvstart[i] == vpos) || sprst[i] == SPR_waiting_stop) {
        !          3245:            fetch = 1;
        !          3246:            sprst[i] = SPR_waiting_stop;
        !          3247:        }
        !          3248:        if (sprst[i] == SPR_waiting_stop && sprvstop[i] == vpos) {
        !          3249:            fetch = 2;
        !          3250:            sprst[i] = SPR_waiting_start;
1.1.1.2   root     3251:        }
                   3252: 
1.1.1.3 ! root     3253:        if (fetch && dmaen(DMA_SPRITE)) {
        !          3254:            uae_u16 data1 = chipmem_bank.wget(sprpt[i]);
        !          3255:            uae_u16 data2 = chipmem_bank.wget(sprpt[i]+2);
        !          3256:            sprpt[i] += 4;
        !          3257: 
        !          3258:            if (fetch == 1) {
        !          3259:                /* Hack for X mouse auto-calibration */
        !          3260:                if (i == 0 && !sprvbfl && ((sprpos[0] & 0xff) << 2) > 2 * DISPLAY_LEFT_SHIFT) {
        !          3261:                    spr0ctl=sprctl[0];
        !          3262:                    spr0pos=sprpos[0];
        !          3263:                    sprvbfl=2;
        !          3264:                }
        !          3265:                SPRxDATB_1(data2, i);
        !          3266:                SPRxDATA_1(data1, i);
        !          3267:            } else {
        !          3268:                SPRxPOS_1(data1, i);
        !          3269:                SPRxCTL_1(data2, i);
        !          3270:            }
1.1.1.2   root     3271:        }
                   3272:     }
                   3273: }
                   3274: 
1.1.1.3 ! root     3275: static uae_u32 attach_2nd;
1.1.1.2   root     3276: 
1.1.1.3 ! root     3277: static uae_u32 do_sprite_collisions (struct sprite_draw *spd, int prev_overlap, int i, int nr_spr)
        !          3278: {
        !          3279:     int j;
        !          3280:     int sprxp = spd[i].linepos;
        !          3281:     uae_u32 datab = spd[i].datab;
        !          3282:     uae_u32 mask2 = 0;
        !          3283:     int sbit = 1 << spd[i].num;
        !          3284:     int sprx_shift = 1;
        !          3285:     int attach_compare = -1;
        !          3286:     if (currprefs.gfx_lores != 1)
        !          3287:        sprx_shift = 0;
        !          3288: 
        !          3289:     attach_2nd = 0;
        !          3290:     if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80)
        !          3291:        attach_compare = spd[i].num - 1;
        !          3292: 
        !          3293:     for (j = prev_overlap; j < i; j++) {
        !          3294:        uae_u32 mask1;
        !          3295:        int off;
1.1.1.2   root     3296: 
1.1.1.3 ! root     3297:        if (spd[i].num < spd[j].num)
        !          3298:            continue;
1.1.1.2   root     3299: 
1.1.1.3 ! root     3300:        off = sprxp - spd[j].linepos;
        !          3301:        off <<= sprx_shift;
        !          3302:        mask1 = spd[j].datab >> off;
        !          3303: 
        !          3304:        /* If j is an attachment for i, then j doesn't block i */
        !          3305:        if (spd[j].num == attach_compare) {
        !          3306:            attach_2nd |= mask1;
        !          3307:        } else {
        !          3308:            mask1 |= (mask1 & 0xAAAAAAAA) >> 1;
        !          3309:            mask1 |= (mask1 & 0x55555555) << 1;
        !          3310:            if (datab & mask1)
        !          3311:                clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask];
        !          3312:            mask2 |= mask1;
1.1.1.2   root     3313:        }
1.1.1.3 ! root     3314:     }
        !          3315:     for (j = i+1; j < nr_spr; j++) {
        !          3316:        uae_u32 mask1;
        !          3317:        int off = spd[j].linepos - sprxp;
1.1.1.2   root     3318: 
1.1.1.3 ! root     3319:        if (off >= sprite_width || spd[i].num < spd[j].num)
        !          3320:            break;
1.1.1.2   root     3321: 
1.1.1.3 ! root     3322:        off <<= sprx_shift;
        !          3323:        mask1 = spd[j].datab << off;
1.1.1.2   root     3324: 
1.1.1.3 ! root     3325:        /* If j is an attachment for i, then j doesn't block i */
        !          3326:        if (spd[j].num == attach_compare) {
        !          3327:            attach_2nd |= mask1;
        !          3328:        } else {
        !          3329:            mask1 |= (mask1 & 0xAAAAAAAA) >> 1;
        !          3330:            mask1 |= (mask1 & 0x55555555) << 1;
        !          3331:            if (datab & mask1)
        !          3332:                clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask];
        !          3333:            mask2 |= mask1;
1.1.1.2   root     3334:        }
                   3335:     }
1.1.1.3 ! root     3336:     datab &= ~mask2;
        !          3337:     return datab;
1.1.1.2   root     3338: }
                   3339: 
1.1.1.3 ! root     3340: static __inline__ void render_sprite (int spr, int sprxp, uae_u32 datab, int ham, int attch, int sprx_inc)
1.1.1.2   root     3341: {
1.1.1.3 ! root     3342:     uae_u32 datcd;
        !          3343:     int basecol = 16;
        !          3344:     if (!attch)
        !          3345:        basecol += (spr & ~1)*2;
        !          3346:     if (bpldualpf)
        !          3347:        basecol |= 128;
        !          3348:     if (attch)
        !          3349:        datcd = attach_2nd;
1.1.1.2   root     3350: 
1.1.1.3 ! root     3351:     for(; attch ? datab | datcd : datab; sprxp += sprx_inc) {
        !          3352:        int col;
1.1.1.2   root     3353: 
1.1.1.3 ! root     3354:        if (attch) {
        !          3355:            col = ((datab & 3) << 2) | (datcd & 3);
        !          3356:            datcd >>= 2;
        !          3357:        } else
        !          3358:            col = datab & 3;
        !          3359:        datab >>= 2;
        !          3360:        if (col) {
        !          3361:            col |= basecol;
        !          3362:            if (ham) {
        !          3363:                col = colors_for_drawing.color_regs[col];
        !          3364:                ham_linebuf[sprxp] = col;
        !          3365:                if (sprx_inc == 2) {
        !          3366:                    ham_linebuf[sprxp+1] = col;
        !          3367:                }
        !          3368:            } else {
        !          3369:                pixdata.apixels[sprxp] = col;
        !          3370:                if (sprx_inc == 2) {
        !          3371:                    pixdata.apixels[sprxp+1] = col;
        !          3372:                }
        !          3373:            }
1.1.1.2   root     3374:        }
                   3375:     }
                   3376: }
                   3377: 
1.1.1.3 ! root     3378: static void walk_sprites (struct sprite_draw *spd, int nr_spr)
1.1.1.2   root     3379: {
1.1.1.3 ! root     3380:     int i, prev_overlap;
        !          3381:     int last_sprite_pos = -64;
        !          3382:     uae_u32 plane1 = 0, plane2 = 0;
        !          3383:     int sprx_inc = 1, sprx_shift = 1;
        !          3384: 
        !          3385:     if (currprefs.gfx_lores == 0)
        !          3386:        sprx_inc = 2, sprx_shift = 0;
        !          3387: 
        !          3388:     prev_overlap = 0;
        !          3389:     for (i = 0; i < nr_spr; i++) {
        !          3390:        int sprxp = spd[i].linepos;
        !          3391:        int m = 1 << spd[i].num;
        !          3392:        uae_u32 datab;
        !          3393:        while (prev_overlap < i && spd[prev_overlap].linepos + sprite_width <= sprxp)
        !          3394:            prev_overlap++;
1.1.1.2   root     3395: 
1.1.1.3 ! root     3396:        datab = do_sprite_collisions (spd, prev_overlap, i, nr_spr);
        !          3397: #ifdef LORES_HACK
        !          3398:        if (currprefs.gfx_lores == 2)
        !          3399:            sprxp >>= 1;
        !          3400: #endif
        !          3401:        if ((bpldualpf && plfpri[1] < 256) || (plfpri[2] < 256)) {
        !          3402:            if (sprxp != last_sprite_pos) {
        !          3403:                int ok = last_sprite_pos-sprxp+16;
        !          3404:                int ok2;
        !          3405:                if (ok <= 0) {
        !          3406:                    ok = ok2 = 0;
        !          3407:                    plane1 = 0;
        !          3408:                    plane2 = 0;
        !          3409:                } else {
        !          3410:                    ok2 = ok << sprx_shift;
        !          3411:                    plane1 >>= 32 - ok2;
        !          3412:                    plane2 >>= 32 - ok2;
        !          3413:                }
        !          3414:                last_sprite_pos = sprxp;
1.1.1.2   root     3415: 
1.1.1.3 ! root     3416:                if (bpldualpf) {
        !          3417:                    uae_u32 mask = 3 << ok2;
        !          3418:                    int p = sprxp+ok;
        !          3419: 
        !          3420:                    for (; mask; mask <<= 2, p += sprx_inc) {
        !          3421:                        int data = pixdata.apixels[p];
        !          3422:                        if (dblpf_2nd2[data] == 2)
        !          3423:                            plane2 |= mask;
        !          3424:                        if (dblpf_2nd1[data] == 1)
        !          3425:                            plane1 |= mask;
        !          3426:                    }
        !          3427:                } else {
        !          3428:                    uae_u32 mask = 3 << ok2;
        !          3429:                    int p = sprxp+ok;
1.1.1.2   root     3430: 
1.1.1.3 ! root     3431:                    for (; mask; mask <<= 2, p += sprx_inc) {
        !          3432:                        if (pixdata.apixels[p])
        !          3433:                            plane2 |= mask;
        !          3434:                    }
        !          3435:                }
        !          3436:            }
        !          3437:            if (bpldualpf && m >= plfpri[1]) {
        !          3438:                datab &= ~plane1;
        !          3439:                attach_2nd &= ~plane1;
        !          3440:            }
        !          3441:            if (m >= plfpri[2]) {
        !          3442:                datab &= ~plane2;
        !          3443:                attach_2nd &= ~plane2;
        !          3444:            }
1.1.1.2   root     3445:        }
1.1.1.3 ! root     3446:        if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80) {
        !          3447:            /* Attached sprite */
        !          3448:            if (bplham) {
        !          3449:                if (sprx_inc == 1) {
        !          3450:                    render_sprite (spd[i].num, sprxp, datab, 1, 1, 1);
        !          3451:                } else {
        !          3452:                    render_sprite (spd[i].num, sprxp, datab, 1, 1, 2);
        !          3453:                }
        !          3454:            } else {
        !          3455:                if (sprx_inc == 1) {
        !          3456:                    render_sprite (spd[i].num, sprxp, datab, 0, 1, 1);
        !          3457:                } else {
        !          3458:                    render_sprite (spd[i].num, sprxp, datab, 0, 1, 2);
        !          3459:                }
        !          3460:            }
        !          3461:            /* This still leaves one attached sprite bug, but at the moment I'm too lazy */
        !          3462:            if (i + 1 < nr_spr && spd[i+1].num == spd[i].num - 1 && spd[i+1].linepos == spd[i].linepos)
        !          3463:                i++;
        !          3464:        } else {
        !          3465:            if (bplham) {
        !          3466:                if (sprx_inc == 1) {
        !          3467:                    render_sprite (spd[i].num, sprxp, datab, 1, 0, 1);
        !          3468:                } else {
        !          3469:                    render_sprite (spd[i].num, sprxp, datab, 1, 0, 2);
        !          3470:                }
        !          3471:            } else {
        !          3472:                if (sprx_inc == 1) {
        !          3473:                    render_sprite (spd[i].num, sprxp, datab, 0, 0, 1);
        !          3474:                } else {
        !          3475:                    render_sprite (spd[i].num, sprxp, datab, 0, 0, 2);
        !          3476:                }
        !          3477:            }
1.1.1.2   root     3478:        }
                   3479:     }
                   3480: }
                   3481: 
1.1.1.3 ! root     3482: #ifndef SMART_UPDATE
        !          3483: #undef UNALIGNED_PROFITABLE
        !          3484: #endif
        !          3485: 
        !          3486: #ifdef UNALIGNED_PROFITABLE
        !          3487: 
1.1.1.2   root     3488: static void pfield_doline_unaligned_h (int lineno)
                   3489: {
                   3490:     int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2;
1.1.1.3 ! root     3491: 
1.1.1.2   root     3492:     if (bplhires) {
                   3493:        int xpos1 = xpos + 16 + bpldelay1*2;
                   3494:        int xpos2;
1.1.1.3 ! root     3495:        uae_u8 *dataptr = line_data[lineno];
        !          3496:        int len = dp_for_drawing->plflinelen >> 1;
        !          3497: 
        !          3498:        if (len <= 0)
        !          3499:            return;
        !          3500: 
1.1.1.2   root     3501:        if (bpldelay1 == bpldelay2) {
                   3502:            switch (bplplanecnt) {
1.1.1.3 ! root     3503:             case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3504:             case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3505:             case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3506:             case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3507:             case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3508:             case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3509:             case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3510:             case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1.1.1.2   root     3511:            }
                   3512:        } else {
                   3513:            switch (bplplanecnt) {
1.1.1.3 ! root     3514:             case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3515:             case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3516:             case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3517:             case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1.1.1.2   root     3518:            }
                   3519: 
                   3520:            xpos2 = xpos + 16 + bpldelay2*2;
                   3521:            switch (bplplanecnt) {
1.1.1.3 ! root     3522:             case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
        !          3523:             case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
        !          3524:             case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
        !          3525:             case 8:         set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1.1.1.2   root     3526:            }
                   3527:        }
                   3528:     } else {
                   3529:        int xpos1 = xpos + 32 + bpldelay1*2;
                   3530:        int xpos2;
1.1.1.3 ! root     3531:        uae_u8 *dataptr = line_data[lineno];
        !          3532:        int len = dp_for_drawing->plflinelen >> 2;
        !          3533: 
        !          3534:        if (len <= 0)
        !          3535:            return;
1.1.1.2   root     3536: 
                   3537:        if (bpldelay1 == bpldelay2) {
                   3538:            switch (bplplanecnt) {
1.1.1.3 ! root     3539:             case 1: set_lores_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3540:             case 2: set_lores_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3541:             case 3: set_lores_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3542:             case 4: set_lores_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3543:             case 5: set_lores_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3544:             case 6: set_lores_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3545:             case 7: set_lores_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3546:             case 8: set_lores_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1.1.1.2   root     3547:            }
                   3548:        } else {
                   3549:            switch (bplplanecnt) {
1.1.1.3 ! root     3550:             case 1: case 2: set_lores_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3551:             case 3: case 4: set_lores_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3552:             case 5: case 6: set_lores_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3553:             case 7: case 8: set_lores_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1.1.1.2   root     3554:            }
1.1.1.3 ! root     3555: 
1.1.1.2   root     3556:            xpos2 = xpos + 32 + bpldelay2*2;
                   3557:            switch (bplplanecnt) {
1.1.1.3 ! root     3558:             case 2: case 3: set_lores_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
        !          3559:             case 4: case 5: set_lores_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
        !          3560:             case 6: case 7: set_lores_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
        !          3561:             case 8:         set_lores_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1.1.1.2   root     3562:            }
                   3563:        }
                   3564:     }
                   3565: }
                   3566: 
                   3567: static void pfield_doline_unaligned_l (int lineno)
                   3568: {
                   3569:     int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT;
1.1.1.3 ! root     3570: 
1.1.1.2   root     3571:     if (bplhires) {
                   3572:        int xpos1 = xpos + 8 + bpldelay1;
                   3573:        int xpos2;
1.1.1.3 ! root     3574:        uae_u8 *dataptr = line_data[lineno];
        !          3575:        int len = dp_for_drawing->plflinelen >> 1;
        !          3576: 
        !          3577:        if (len <= 0)
        !          3578:            return;
1.1.1.2   root     3579: 
                   3580:        if (bpldelay1 == bpldelay2) {
                   3581:            switch (bplplanecnt) {
1.1.1.3 ! root     3582:             case 1: set_hires_l_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3583:             case 2: set_hires_l_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3584:             case 3: set_hires_l_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3585:             case 4: set_hires_l_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3586:             case 5: set_hires_l_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3587:             case 6: set_hires_l_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3588:             case 7: set_hires_l_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3589:             case 8: set_hires_l_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1.1.1.2   root     3590:            }
                   3591:        } else {
                   3592:            switch (bplplanecnt) {
1.1.1.3 ! root     3593:             case 1: case 2: set_hires_l_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3594:             case 3: case 4: set_hires_l_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3595:             case 5: case 6: set_hires_l_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3596:             case 7: case 8: set_hires_l_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1.1.1.2   root     3597:            }
                   3598: 
                   3599:            xpos2 = xpos + 8 + bpldelay2;
                   3600:            switch (bplplanecnt) {
1.1.1.3 ! root     3601:             case 2: case 3: set_hires_l_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
        !          3602:             case 4: case 5: set_hires_l_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
        !          3603:             case 6: case 7: set_hires_l_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
        !          3604:             case 8:         set_hires_l_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1.1.1.2   root     3605:            }
                   3606:        }
                   3607:     } else {
                   3608:        int xpos1 = xpos + 16 + bpldelay1;
                   3609:        int xpos2;
1.1.1.3 ! root     3610:        uae_u8 *dataptr = line_data[lineno];
        !          3611:        int len = dp_for_drawing->plflinelen >> 2;
        !          3612: 
        !          3613:        if (len <= 0)
        !          3614:            return;
1.1.1.2   root     3615: 
                   3616:        if (bpldelay1 == bpldelay2) {
                   3617:            switch (bplplanecnt) {
1.1.1.3 ! root     3618:             case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3619:             case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3620:             case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3621:             case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3622:             case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3623:             case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3624:             case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3625:             case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1.1.1.2   root     3626:            }
                   3627:        } else {
                   3628:            switch (bplplanecnt) {
1.1.1.3 ! root     3629:             case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3630:             case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3631:             case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
        !          3632:             case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1.1.1.2   root     3633:            }
1.1.1.3 ! root     3634: 
1.1.1.2   root     3635:            xpos2 = xpos + 16 + bpldelay2;
                   3636:            switch (bplplanecnt) {
1.1.1.3 ! root     3637:             case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
        !          3638:             case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
        !          3639:             case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
        !          3640:             case 8:         set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1.1.1.2   root     3641:            }
                   3642:        }
                   3643:     }
                   3644: }
                   3645: 
                   3646: #define pfield_doline_h pfield_doline_unaligned_h
                   3647: #define pfield_doline_l pfield_doline_unaligned_l
                   3648: 
                   3649: #else /* not UNALIGNED_PROFITABLE */
                   3650: 
                   3651: 
1.1       root     3652: static __inline__ void pfield_orword_hires_h(int data, unsigned char *dp, int bit)
                   3653: {
1.1.1.3 ! root     3654:     uae_u32 *pixptr = (uae_u32 *)dp;
1.1       root     3655: 
                   3656:     *pixptr |= hirestab_h[data >> 8][0] << bit;
                   3657:     *(pixptr+1) |= hirestab_h[data >> 8][1] << bit;
                   3658:     *(pixptr+2) |= hirestab_h[data & 255][0] << bit;
                   3659:     *(pixptr+3) |= hirestab_h[data & 255][1] << bit;
                   3660: }
                   3661: 
                   3662: static __inline__ void pfield_orword_lores_h(int data, unsigned char *dp, int bit)
                   3663: {
1.1.1.3 ! root     3664:     uae_u32 *pixptr = (uae_u32 *)dp;
        !          3665: 
1.1       root     3666:     *pixptr |= lorestab_h[data >> 8][0] << bit;
                   3667:     *(pixptr+1) |= lorestab_h[data >> 8][1] << bit;
                   3668:     *(pixptr+2) |= lorestab_h[data >> 8][2] << bit;
                   3669:     *(pixptr+3) |= lorestab_h[data >> 8][3] << bit;
                   3670:     *(pixptr+4) |= lorestab_h[data & 255][0] << bit;
                   3671:     *(pixptr+5) |= lorestab_h[data & 255][1] << bit;
                   3672:     *(pixptr+6) |= lorestab_h[data & 255][2] << bit;
                   3673:     *(pixptr+7) |= lorestab_h[data & 255][3] << bit;
                   3674: }
                   3675: 
                   3676: static __inline__ void pfield_setword_hires_h(int data, unsigned char *dp, int bit)
                   3677: {
1.1.1.3 ! root     3678:     uae_u32 *pixptr = (uae_u32 *)dp;
1.1       root     3679: 
                   3680:     *pixptr = hirestab_h[data >> 8][0] << bit;
                   3681:     *(pixptr+1) = hirestab_h[data >> 8][1] << bit;
                   3682:     *(pixptr+2) = hirestab_h[data & 255][0] << bit;
                   3683:     *(pixptr+3) = hirestab_h[data & 255][1] << bit;
                   3684: }
                   3685: 
                   3686: static __inline__ void pfield_setword_lores_h(int data, unsigned char *dp, int bit)
                   3687: {
1.1.1.3 ! root     3688:     uae_u32 *pixptr = (uae_u32 *)dp;
        !          3689: 
1.1       root     3690:     *pixptr = lorestab_h[data >> 8][0] << bit;
                   3691:     *(pixptr+1) = lorestab_h[data >> 8][1] << bit;
                   3692:     *(pixptr+2) = lorestab_h[data >> 8][2] << bit;
                   3693:     *(pixptr+3) = lorestab_h[data >> 8][3] << bit;
                   3694:     *(pixptr+4) = lorestab_h[data & 255][0] << bit;
                   3695:     *(pixptr+5) = lorestab_h[data & 255][1] << bit;
                   3696:     *(pixptr+6) = lorestab_h[data & 255][2] << bit;
                   3697:     *(pixptr+7) = lorestab_h[data & 255][3] << bit;
                   3698: }
                   3699: 
                   3700: static __inline__ void pfield_orword_hires_l(int data, unsigned char *dp, int bit)
                   3701: {
1.1.1.3 ! root     3702:     uae_u32 *pixptr = (uae_u32 *)dp;
1.1       root     3703: 
                   3704:     *pixptr |= hirestab_l[data >> 8][0] << bit;
                   3705:     *(pixptr+1) |= hirestab_l[data & 255][0] << bit;
                   3706: }
                   3707: 
                   3708: static __inline__ void pfield_orword_lores_l(int data, unsigned char *dp, int bit)
                   3709: {
1.1.1.3 ! root     3710:     uae_u32 *pixptr = (uae_u32 *)dp;
        !          3711: 
1.1       root     3712:     *pixptr |= lorestab_l[data >> 8][0] << bit;
                   3713:     *(pixptr+1) |= lorestab_l[data >> 8][1] << bit;
                   3714:     *(pixptr+2) |= lorestab_l[data & 255][0] << bit;
                   3715:     *(pixptr+3) |= lorestab_l[data & 255][1] << bit;
                   3716: }
                   3717: 
                   3718: static __inline__ void pfield_setword_hires_l(int data, unsigned char *dp, int bit)
                   3719: {
1.1.1.3 ! root     3720:     uae_u32 *pixptr = (uae_u32 *)dp;
1.1       root     3721: 
                   3722:     *pixptr = hirestab_l[data >> 8][0] << bit;
                   3723:     *(pixptr+1) = hirestab_l[data & 255][0] << bit;
                   3724: }
                   3725: 
                   3726: static __inline__ void pfield_setword_lores_l(int data, unsigned char *dp, int bit)
                   3727: {
1.1.1.3 ! root     3728:     uae_u32 *pixptr = (uae_u32 *)dp;
        !          3729: 
1.1       root     3730:     *pixptr = lorestab_l[data >> 8][0] << bit;
                   3731:     *(pixptr+1) = lorestab_l[data >> 8][1] << bit;
                   3732:     *(pixptr+2) = lorestab_l[data & 255][0] << bit;
                   3733:     *(pixptr+3) = lorestab_l[data & 255][1] << bit;
                   3734: }
                   3735: 
                   3736: #define DO_ONE_PLANE(POINTER, MULT, FUNC, DELAY, LL_SUB, P_ADD) { \
                   3737:     int i; \
                   3738:     unsigned int bpldat1; \
1.1.1.3 ! root     3739:     uae_u16 data; \
1.1       root     3740:     unsigned int bpldat2 = 0; \
1.1.1.3 ! root     3741:     uae_u8 *ptr = (POINTER); \
1.1.1.2   root     3742:     for (i = dp_for_drawing->plflinelen; i > 0; i -= LL_SUB) { \
1.1.1.3 ! root     3743:        bpldat1 = bpldat2; \
        !          3744:        bpldat2 = do_get_mem_word ((uae_u16 *)ptr); \
        !          3745:        ptr+=2; \
1.1       root     3746:        data = (bpldat1 << (16 - DELAY)) | (bpldat2 >> DELAY); \
                   3747:        FUNC(data, app, MULT); \
                   3748:        app += P_ADD; \
                   3749:     } \
                   3750:     data = bpldat2 << (16 - DELAY); \
                   3751:     FUNC(data, app, MULT); \
                   3752: }
                   3753: 
1.1.1.2   root     3754: #ifdef SMART_UPDATE
                   3755: #define DATA_POINTER(n) (dataptr + (n)*MAX_WORDS_PER_LINE*2)
                   3756: #else
                   3757: #define DATA_POINTER(n) (real_bplpt[n])
                   3758: #endif
1.1       root     3759: 
1.1.1.2   root     3760: static void pfield_doline_aligned_h (int lineno)
                   3761: {
                   3762:     int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2;
1.1.1.3 ! root     3763: 
1.1       root     3764:     if (bplhires) {
                   3765:        if (bplplanecnt > 0) {
                   3766:            int xpos1 = xpos + 16 + (bpldelay1 >= 8 ? 16 : 0);
                   3767:            int xpos2 = xpos + 16 + (bpldelay2 >= 8 ? 16 : 0);
                   3768:            int delay1 = 2*(bpldelay1 & 7);
                   3769:            int delay2 = 2*(bpldelay2 & 7);
                   3770:            unsigned char *app = pixdata.apixels + xpos1;
1.1.1.3 ! root     3771:            uae_u8 *dataptr = line_data[lineno];
1.1       root     3772: 
1.1.1.2   root     3773:            DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_h, delay1, 4, 16);
1.1       root     3774:            if (bplplanecnt > 2) {
                   3775:                app = pixdata.apixels + xpos1;
1.1.1.2   root     3776:                DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_hires_h, delay1, 4, 16);
1.1       root     3777:            }
                   3778: #if AGA_CHIPSET == 1
                   3779:            if (bplplanecnt > 4) {
                   3780:                app = pixdata.apixels + xpos1;
1.1.1.2   root     3781:                DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_hires_h, delay1, 4, 16);
1.1       root     3782:            }
                   3783:            if (bplplanecnt > 6) {
                   3784:                app = pixdata.apixels + xpos1;
1.1.1.2   root     3785:                DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_hires_h, delay1, 4, 16);
1.1       root     3786:            }
                   3787: #endif
                   3788:            if (bplplanecnt > 1) {
                   3789:                app = pixdata.apixels + xpos2;
1.1.1.2   root     3790:                DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_hires_h, delay2, 4, 16);
1.1       root     3791:            }
                   3792:            if (bplplanecnt > 3) {
                   3793:                app = pixdata.apixels + xpos2;
1.1.1.2   root     3794:                DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_hires_h, delay2, 4, 16);
1.1       root     3795:            }
                   3796: #if AGA_CHIPSET == 1
                   3797:            if (bplplanecnt > 5) {
                   3798:                app = pixdata.apixels + xpos2;
1.1.1.2   root     3799:                DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_hires_h, delay2, 4, 16);
1.1       root     3800:            }
                   3801:            if (bplplanecnt > 7) {
                   3802:                app = pixdata.apixels + xpos2;
1.1.1.2   root     3803:                DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_hires_h, delay2, 4, 16);
1.1       root     3804:            }
                   3805: #endif
                   3806:        } else {
                   3807:            memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
                   3808:        }
                   3809:     } else {
                   3810:        if (bplplanecnt > 0) {
                   3811:            int x = xpos + 32;
                   3812:            unsigned char *app = pixdata.apixels + x;
1.1.1.3 ! root     3813:            uae_u8 *dataptr = line_data[lineno];
        !          3814: 
1.1.1.2   root     3815:            DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_h, bpldelay1, 8, 32);
1.1       root     3816:            if (bplplanecnt > 2) {
                   3817:                app = pixdata.apixels + x;
1.1.1.2   root     3818:                DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_lores_h, bpldelay1, 8, 32);
1.1       root     3819:            }
                   3820:            if (bplplanecnt > 4) {
                   3821:                app = pixdata.apixels + x;
1.1.1.2   root     3822:                DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_lores_h, bpldelay1, 8, 32);
1.1       root     3823:            }
                   3824: #if AGA_CHIPSET == 1
                   3825:            if (bplplanecnt > 6) {
                   3826:                app = pixdata.apixels + x;
1.1.1.2   root     3827:                DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_lores_h, bpldelay1, 8, 32);
1.1       root     3828:            }
                   3829: #endif
                   3830:            if (bplplanecnt > 1) {
                   3831:                app = pixdata.apixels + x;
1.1.1.2   root     3832:                DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_lores_h, bpldelay2, 8, 32);
1.1       root     3833:            }
                   3834:            if (bplplanecnt > 3) {
                   3835:                app = pixdata.apixels + x;
1.1.1.2   root     3836:                DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_lores_h, bpldelay2, 8, 32);
1.1       root     3837:            }
                   3838:            if (bplplanecnt > 5) {
                   3839:                app = pixdata.apixels + x;
1.1.1.2   root     3840:                DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_lores_h, bpldelay2, 8, 32);
1.1       root     3841:            }
                   3842: #if AGA_CHIPSET == 1
                   3843:            if (bplplanecnt > 7) {
                   3844:                app = pixdata.apixels + x;
1.1.1.2   root     3845:                DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_lores_h, bpldelay2, 8, 32);
1.1       root     3846:            }
                   3847: #endif
                   3848:        } else {
                   3849:            memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
                   3850:        }
                   3851:     }
                   3852: }
1.1.1.2   root     3853: 
                   3854: static void pfield_doline_aligned_l (int lineno)
1.1       root     3855: {
1.1.1.2   root     3856:     int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT;
1.1.1.3 ! root     3857: 
1.1       root     3858:     if (bplhires) {
                   3859:        if (bplplanecnt > 0) {
                   3860:            int xpos1 = xpos + 8 + (bpldelay1 >= 8 ? 8 : 0);
                   3861:            int xpos2 = xpos + 8 + (bpldelay2 >= 8 ? 8 : 0);
                   3862:            int delay1 = (bpldelay1 & 7) * 2;
                   3863:            int delay2 = (bpldelay2 & 7) * 2;
                   3864:            unsigned char *app = pixdata.apixels + xpos1;
1.1.1.3 ! root     3865:            uae_u8 *dataptr = line_data[lineno];
        !          3866: 
1.1.1.2   root     3867:            DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_l, delay1, 4, 8);
1.1       root     3868:            if (bplplanecnt > 2) {
                   3869:                app = pixdata.apixels + xpos1;
1.1.1.2   root     3870:                DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_hires_l, delay1, 4, 8);
1.1       root     3871:            }
                   3872: #if AGA_CHIPSET == 1
                   3873:            if (bplplanecnt > 4) {
                   3874:                app = pixdata.apixels + xpos1;
1.1.1.2   root     3875:                DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_hires_l, delay1, 4, 8);
1.1       root     3876:            }
                   3877:            if (bplplanecnt > 6) {
                   3878:                app = pixdata.apixels + xpos1;
1.1.1.2   root     3879:                DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_hires_l, delay1, 4, 8);
1.1       root     3880:            }
                   3881: #endif
                   3882:            if (bplplanecnt > 1) {
                   3883:                app = pixdata.apixels + xpos2;
1.1.1.2   root     3884:                DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_hires_l, delay2, 4, 8);
1.1       root     3885:            }
                   3886:            if (bplplanecnt > 3) {
                   3887:                app = pixdata.apixels + xpos2;
1.1.1.2   root     3888:                DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_hires_l, delay2, 4, 8);
1.1       root     3889:            }
                   3890: #if AGA_CHIPSET == 1
                   3891:            if (bplplanecnt > 5) {
                   3892:                app = pixdata.apixels + xpos2;
1.1.1.2   root     3893:                DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_hires_l, delay2, 4, 8);
1.1       root     3894:            }
                   3895:            if (bplplanecnt > 7) {
                   3896:                app = pixdata.apixels + xpos2;
1.1.1.2   root     3897:                DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_hires_l, delay2, 4, 8);
1.1       root     3898:            }
                   3899: #endif
                   3900:        } else {
                   3901:            memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
                   3902:        }
                   3903:     } else {
                   3904:        if (bplplanecnt > 0) {
                   3905:            int x = xpos + 16;
                   3906:            int delay1 = bpldelay1;
                   3907:            int delay2 = bpldelay2;
                   3908:            unsigned char *app = pixdata.apixels + x;
1.1.1.3 ! root     3909:            uae_u8 *dataptr = line_data[lineno];
        !          3910: 
1.1.1.2   root     3911:            DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_l, delay1, 8, 16);
1.1       root     3912:            if (bplplanecnt > 2) {
                   3913:                app = pixdata.apixels + x;
1.1.1.2   root     3914:                DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_lores_l, delay1, 8, 16);
1.1       root     3915:            }
                   3916:            if (bplplanecnt > 4) {
                   3917:                app = pixdata.apixels + x;
1.1.1.2   root     3918:                DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_lores_l, delay1, 8, 16);
1.1       root     3919:            }
                   3920: #if AGA_CHIPSET == 1
                   3921:            if (bplplanecnt > 6) {
                   3922:                app = pixdata.apixels + x;
1.1.1.2   root     3923:                DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_lores_l, delay1, 8, 16);
1.1       root     3924:            }
                   3925: #endif
                   3926:            if (bplplanecnt > 1) {
                   3927:                app = pixdata.apixels + x;
1.1.1.2   root     3928:                DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_lores_l, delay2, 8, 16);
1.1       root     3929:            }
                   3930:            if (bplplanecnt > 3) {
                   3931:                app = pixdata.apixels + x;
1.1.1.2   root     3932:                DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_lores_l, delay2, 8, 16);
1.1       root     3933:            }
                   3934:            if (bplplanecnt > 5) {
                   3935:                app = pixdata.apixels + x;
1.1.1.2   root     3936:                DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_lores_l, delay2, 8, 16);
1.1       root     3937:            }
                   3938: #if AGA_CHIPSET == 1
                   3939:            if (bplplanecnt > 7) {
                   3940:                app = pixdata.apixels + x;
1.1.1.2   root     3941:                DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_lores_l, delay2, 8, 16);
1.1       root     3942:            }
                   3943: #endif
                   3944:        } else {
                   3945:            memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
                   3946:        }
                   3947:     }
1.1.1.2   root     3948: }
1.1       root     3949: 
1.1.1.2   root     3950: #define pfield_doline_h pfield_doline_aligned_h
                   3951: #define pfield_doline_l pfield_doline_aligned_l
1.1       root     3952: 
1.1.1.2   root     3953: #endif /* UNALIGNED_PROFITABLE */
1.1       root     3954: 
1.1.1.2   root     3955: static void pfield_adjust_delay (void)
                   3956: {
                   3957:     int ddf_left = dp_for_drawing->plfstrt;
                   3958:     int ddf_right = dp_for_drawing->plfstrt + dp_for_drawing->plflinelen;
                   3959:     int i;
                   3960: 
1.1.1.3 ! root     3961:     for (i = dip_for_drawing->last_delay_change-1; i >= dip_for_drawing->first_delay_change-1; i--) {
        !          3962:        int delayreg = i < dip_for_drawing->first_delay_change ? dp_for_drawing->bplcon1 : delay_changes[i].value;
        !          3963:        int delay1 = delayreg & 0xF;
        !          3964:        int delay2 = (delayreg >> 4) & 0xF;
        !          3965:        int startpos = i == dip_for_drawing->last_delay_change - 1 ? ddf_right + 8 : delay_changes[i+1].linepos;
        !          3966:        int stoppos = i < dip_for_drawing->first_delay_change ? ddf_left : delay_changes[i].linepos;
        !          3967:        int j;
        !          3968:        startpos = PIXEL_XPOS (startpos + (bplhires ? 4 : 8));
        !          3969:        stoppos = PIXEL_XPOS (stoppos + (bplhires ? 4 : 8));
        !          3970:        if (currprefs.gfx_lores == 0)
        !          3971:            delay1 <<= 1, delay2 <<= 1;
        !          3972:        else if (currprefs.gfx_lores == 2)
        !          3973:            startpos >>= 1, stoppos >>= 1;
        !          3974:        for (j = startpos-1; j >= stoppos; j--) {
        !          3975:            pixdata.apixels [j] = (pixdata.apixels[j-delay1] & 0x55) | (pixdata.apixels[j-delay2] & 0xAA);
1.1.1.2   root     3976:        }
                   3977:     }
                   3978: }
                   3979: 
1.1.1.3 ! root     3980: static void init_sprites (void)
        !          3981: {
        !          3982:     int i;
        !          3983: 
        !          3984:     for (i = 0; i < 8; i++) {
        !          3985:        /* ???? */
        !          3986:        sprst[i] = SPR_stop;
        !          3987:        spron[i] = 0;
        !          3988:     }
        !          3989: 
        !          3990:     memset(sprpos, 0, sizeof sprpos);
        !          3991:     memset(sprctl, 0, sizeof sprctl);
        !          3992: }
        !          3993: 
        !          3994: static void init_hardware_frame (void)
        !          3995: {
        !          3996:     next_lineno = 0;
        !          3997:     nln_how = 0;
        !          3998:     diwstate = DIW_waiting_start;
        !          3999:     hdiwstate = DIW_waiting_start;
        !          4000: }
        !          4001: 
        !          4002: void init_row_map(void)
        !          4003: {
        !          4004:     int i;
        !          4005:     if (gfxvidinfo.height > 2048) {
        !          4006:        write_log ("Resolution too high, aborting\n");
        !          4007:     }
        !          4008:     for (i = 0; i < gfxvidinfo.height + 1; i++)
        !          4009:        row_map[i] = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * i;
        !          4010: }
1.1.1.2   root     4011: 
                   4012: /*
                   4013:  * A raster line has been built in the graphics buffer. Tell the graphics code
                   4014:  * to do anything necessary to display it.
                   4015:  */
1.1.1.3 ! root     4016: static void do_flush_line_1 (int lineno)
1.1.1.2   root     4017: {
                   4018:     if (lineno < first_drawn_line)
                   4019:        first_drawn_line = lineno;
                   4020:     if (lineno > last_drawn_line)
                   4021:        last_drawn_line = lineno;
                   4022: 
                   4023:     if (gfxvidinfo.maxblocklines == 0)
                   4024:        flush_line(lineno);
                   4025:     else {
                   4026:        if ((last_block_line+1) != lineno) {
                   4027:            if (first_block_line != -2)
                   4028:                flush_block (first_block_line, last_block_line);
                   4029:            first_block_line = lineno;
                   4030:        }
                   4031:        last_block_line = lineno;
                   4032:        if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) {
                   4033:            flush_block (first_block_line, last_block_line);
                   4034:            first_block_line = last_block_line = -2;
                   4035:        }
                   4036:     }
                   4037: }
                   4038: 
1.1.1.3 ! root     4039: static __inline__ void do_flush_line (int lineno)
1.1.1.2   root     4040: {
                   4041:     /* We don't want to call X libraries from the second thread right now. */
                   4042: #ifndef SUPPORT_PENGUINS
                   4043:     do_flush_line_1 (lineno);
1.1       root     4044: #else
1.1.1.2   root     4045:     line_drawn[lineno] = 1;
1.1       root     4046: #endif
                   4047: }
                   4048: 
1.1.1.2   root     4049: /*
1.1.1.3 ! root     4050:  * One drawing frame has been finished. Tell the graphics code about it.
1.1.1.2   root     4051:  * Note that the actual flush_screen() call is a no-op for all reasonable
                   4052:  * systems.
                   4053:  */
                   4054: 
1.1.1.3 ! root     4055: static __inline__ void do_flush_screen (int start, int stop)
1.1       root     4056: {
                   4057:     int i;
1.1.1.2   root     4058: #ifdef SUPPORT_PENGUINS
1.1.1.3 ! root     4059:     for (i = 0; i < gfxvidinfo.height; i++) {
1.1.1.2   root     4060:        if (line_drawn[i])
                   4061:            do_flush_line_1 (i);
                   4062:     }
                   4063: #endif
                   4064:     if (gfxvidinfo.maxblocklines != 0 && first_block_line != -2) {
                   4065:        flush_block (first_block_line, last_block_line);
                   4066:     }
                   4067:     if (start <= stop)
                   4068:        flush_screen (start, stop);
                   4069: }
                   4070: 
                   4071: static void adjust_drawing_colors (int ctable, int bplham)
                   4072: {
                   4073:     if (drawing_color_matches != ctable) {
                   4074:        if (bplham) {
                   4075:            memcpy (&colors_for_drawing, curr_color_tables + ctable,
                   4076:                    sizeof colors_for_drawing);
                   4077:            color_match_type = color_match_full;
                   4078:        } else {
                   4079:            memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors,
                   4080:                    sizeof colors_for_drawing.acolors);
                   4081:            color_match_type = color_match_acolors;
                   4082:        }
                   4083:        drawing_color_matches = ctable;
                   4084:     } else if (bplham && color_match_type != color_match_full) {
                   4085:        memcpy (colors_for_drawing.color_regs, curr_color_tables[ctable].color_regs,
                   4086:                sizeof colors_for_drawing.color_regs);
                   4087:        color_match_type = color_match_full;
                   4088:     }
                   4089: }
                   4090: 
                   4091: static __inline__ void adjust_color0_for_color_change (void)
                   4092: {
                   4093:     drawing_color_matches = -1;
                   4094:     if (dp_for_drawing->color0 != 0xFFFFFFFFul) {
                   4095:        colors_for_drawing.color_regs[0] = dp_for_drawing->color0;
                   4096:        colors_for_drawing.acolors[0] = xcolors[dp_for_drawing->color0];
                   4097:     }
                   4098: }
                   4099: 
                   4100: static __inline__ void do_color_changes (line_draw_func worker)
                   4101: {
                   4102:     int lastpos = 0, nextpos, i;
                   4103:     struct color_change *cc = curr_color_changes + dip_for_drawing->first_color_change;
1.1.1.3 ! root     4104: 
1.1.1.2   root     4105:     for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++, cc++) {
                   4106:        if (i == dip_for_drawing->last_color_change)
                   4107:            nextpos = max_diwlastword;
                   4108:        else
                   4109:            nextpos = PIXEL_XPOS (cc->linepos) + (COPPER_MAGIC_FUDGE << lores_shift);
                   4110:        worker (lastpos, nextpos);
                   4111:        if (i != dip_for_drawing->last_color_change) {
                   4112:            colors_for_drawing.color_regs[cc->regno] = cc->value;
                   4113:            colors_for_drawing.acolors[cc->regno] = xcolors[cc->value];
                   4114:        }
                   4115:        if (nextpos > lastpos) {
                   4116:            lastpos = nextpos;
                   4117:            if (lastpos >= linetoscr_right_x)
                   4118:                break;
                   4119:        }
                   4120:     }
                   4121: }
                   4122: 
1.1.1.3 ! root     4123: /* We only save hardware registers during the hardware frame. Now, when
        !          4124:  * drawing the frame, we expand the data into a slightly more useful
        !          4125:  * form. */
1.1.1.2   root     4126: static void pfield_expand_dp_bplcon (void)
                   4127: {
                   4128:     bplhires = (dp_for_drawing->bplcon0 & 0x8000) == 0x8000;
                   4129:     bplplanecnt = (dp_for_drawing->bplcon0 & 0x7000) >> 12;
                   4130:     bplham = (dp_for_drawing->bplcon0 & 0x800) == 0x800;
                   4131: #if AGA_CHIPSET == 1 /* The KILLEHB bit exists in ECS, but is apparently meant for Genlock
1.1.1.3 ! root     4132:                      * stuff, and it's set by some demos (e.g. Andromeda Seven Seas) */
1.1.1.2   root     4133:     bplehb = ((dp_for_drawing->bplcon0 & 0xFCC0) == 0x6000 && !(dp_for_drawing->bplcon2 & 0x200));
                   4134: #else
                   4135:     bplehb = (dp_for_drawing->bplcon0 & 0xFC00) == 0x6000;
                   4136: #endif
1.1.1.3 ! root     4137:     bpldelay1 = dp_for_drawing->bplcon1 & 0xF;
        !          4138:     bpldelay2 = (dp_for_drawing->bplcon1 >> 4) & 0xF;
1.1.1.2   root     4139:     plfpri[1] = 1 << 2*(dp_for_drawing->bplcon2 & 7);
                   4140:     plfpri[2] = 1 << 2*((dp_for_drawing->bplcon2 >> 3) & 7);
                   4141:     bpldualpf = (dp_for_drawing->bplcon0 & 0x400) == 0x400;
                   4142:     bpldualpfpri = (dp_for_drawing->bplcon2 & 0x40) == 0x40;
                   4143: }
                   4144: 
                   4145: static __inline__ void pfield_draw_line(int lineno, int gfx_ypos, int follow_ypos)
                   4146: {
                   4147:     int border = 0;
                   4148:     int to_screen = 0;
                   4149:     int do_double = 0;
1.1.1.3 ! root     4150: 
1.1.1.2   root     4151:     dp_for_drawing = 0;
                   4152:     dip_for_drawing = 0;
                   4153:     switch (linestate[lineno]) {
                   4154:      case LINE_AS_PREVIOUS:
                   4155:      case LINE_REMEMBERED_AS_PREVIOUS:
                   4156:        {
                   4157:            static int warned = 0;
                   4158:            if (!warned)
1.1.1.3 ! root     4159:                write_log ("Shouldn't get here... this is a bug.\n"), warned++;
1.1.1.2   root     4160:        }
                   4161:        line_decisions[lineno].which = -2;
                   4162:        return;
                   4163: 
                   4164:      case LINE_BORDER_PREV:
                   4165:        border = 1;
                   4166:        dp_for_drawing = line_decisions + lineno - 1;
                   4167:        dip_for_drawing = curr_drawinfo + lineno - 1;
                   4168:        break;
                   4169: 
                   4170:      case LINE_BORDER_NEXT:
                   4171:        border = 1;
                   4172:        dp_for_drawing = line_decisions + lineno + 1;
                   4173:        dip_for_drawing = curr_drawinfo + lineno + 1;
                   4174:        break;
                   4175: 
                   4176:      case LINE_DONE_AS_PREVIOUS:
                   4177:        line_decisions[lineno].which = -2;
                   4178:        /* fall through */
                   4179:      case LINE_DONE:
                   4180:        return;
                   4181: 
                   4182:      case LINE_DECIDED_DOUBLE:
                   4183:        line_decisions[lineno+1].which = -2;
                   4184:        if (follow_ypos != -1) {
                   4185:            do_double = 1;
                   4186:            linetoscr_double_offset = gfxvidinfo.rowbytes * (follow_ypos - gfx_ypos);
                   4187:        }
1.1.1.3 ! root     4188: 
1.1.1.2   root     4189:        /* fall through */
                   4190:      default:
                   4191:        dip_for_drawing = curr_drawinfo + lineno;
                   4192:        dp_for_drawing = line_decisions + lineno;
                   4193:        if (dp_for_drawing->which != 1)
                   4194:            border = 1;
                   4195:        break;
                   4196:     }
1.1.1.3 ! root     4197: 
1.1.1.2   root     4198:     if (!line_changed[lineno] && !frame_redraw_necessary) {
1.1.1.3 ! root     4199:        /* The case where we can skip redrawing this line. If this line
1.1.1.2   root     4200:         * is supposed to be doubled, and the next line is remembered as
                   4201:         * having been doubled, then the next line is done as well. */
                   4202:        if (do_double) {
                   4203:            if (linestate[lineno+1] != LINE_REMEMBERED_AS_PREVIOUS) {
1.1.1.3 ! root     4204:                if (gfxvidinfo.linemem == NULL)
        !          4205:                    memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
1.1.1.2   root     4206:                line_decisions[lineno + 1].which = -2;
                   4207:                do_flush_line (follow_ypos);
                   4208:            }
                   4209:            linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
                   4210:        }
                   4211:        linestate[lineno] = LINE_DONE;
                   4212:        return;
                   4213:     }
                   4214: 
                   4215:     if (!border) {
1.1.1.3 ! root     4216:        xlinebuffer = gfxvidinfo.linemem;
        !          4217:        if (xlinebuffer == NULL)
        !          4218:            xlinebuffer = row_map[gfx_ypos];
        !          4219:        xlinebuffer -= linetoscr_x_adjust_bytes;
1.1.1.2   root     4220:        aga_lbufptr = aga_linebuf;
1.1.1.3 ! root     4221: 
1.1.1.2   root     4222:        pfield_expand_dp_bplcon ();
                   4223: 
                   4224: #ifdef LORES_HACK
1.1.1.3 ! root     4225:        if (gfxvidinfo.can_double && !bplhires && !currprefs.gfx_lores
        !          4226:            && dip_for_drawing->nr_color_changes == 0 && !bplham)
        !          4227:            currprefs.gfx_lores = 2;
1.1.1.2   root     4228: #endif
                   4229:        pfield_init_linetoscr ();
                   4230:        if (dip_for_drawing->first_delay_change != dip_for_drawing->last_delay_change) {
                   4231:            bpldelay1 = bpldelay2 = 0;
1.1.1.3 ! root     4232:            if (currprefs.gfx_lores)
1.1.1.2   root     4233:                pfield_doline_l (lineno);
                   4234:            else
                   4235:                pfield_doline_h (lineno);
                   4236:            pfield_adjust_delay ();
                   4237:        } else {
1.1.1.3 ! root     4238:            if (currprefs.gfx_lores)
1.1.1.2   root     4239:                pfield_doline_l (lineno);
                   4240:            else
                   4241:                pfield_doline_h (lineno);
                   4242:        }
1.1.1.3 ! root     4243: 
1.1.1.2   root     4244:        /* Check color0 adjust only if we have color changes - shouldn't happen
                   4245:         * otherwise. */
                   4246:        adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
                   4247: 
                   4248:        /* The problem is that we must call decode_ham6() BEFORE we do the
                   4249:         * sprites. */
                   4250:        if (bplham) {
1.1.1.3 ! root     4251:            init_ham_decoding(linetoscr_x_adjust);
1.1.1.2   root     4252:            if (dip_for_drawing->nr_color_changes == 0) {
                   4253:                /* The easy case: need to do HAM decoding only once for the
                   4254:                 * full line. */
                   4255:                decode_ham6 (linetoscr_x_adjust, linetoscr_right_x);
1.1.1.3 ! root     4256:            } else /* Argh. */ {
1.1.1.2   root     4257:                adjust_color0_for_color_change ();
                   4258:                do_color_changes (decode_ham6);
                   4259:                adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
                   4260:            }
                   4261:        }
                   4262: 
                   4263:        if (dip_for_drawing->nr_sprites != 0) {
                   4264:            int spr;
1.1.1.3 ! root     4265:            walk_sprites (curr_sprite_positions + dip_for_drawing->first_sprite_draw, dip_for_drawing->nr_sprites);
1.1.1.2   root     4266:        }
                   4267:        if (dip_for_drawing->nr_color_changes == 0) {
1.1.1.3 ! root     4268:            pfield_do_linetoscr_full (gfxvidinfo.linemem == NULL ? do_double : 0);
1.1.1.2   root     4269:            do_flush_line (gfx_ypos);
                   4270:            linestate[lineno] = LINE_DONE;
                   4271: 
                   4272:            if (do_double) {
                   4273:                linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
                   4274:                do_flush_line (follow_ypos);
                   4275:            }
                   4276:        } else {
                   4277:            int lastpos = 0, nextpos, i;
                   4278: 
                   4279:            adjust_color0_for_color_change ();
                   4280:            do_color_changes (pfield_do_linetoscr);
                   4281: 
                   4282:            linestate[lineno] = LINE_DONE;
                   4283:            do_flush_line (gfx_ypos);
                   4284:            if (do_double) {
1.1.1.3 ! root     4285:                if (gfxvidinfo.linemem == NULL)
        !          4286:                    memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
1.1.1.2   root     4287:                linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
                   4288:                line_decisions[lineno + 1].which = -2;
                   4289:                do_flush_line (follow_ypos);
                   4290:            }
                   4291:        }
                   4292: #ifdef LORES_HACK
1.1.1.3 ! root     4293:        if (currprefs.gfx_lores == 2)
        !          4294:            currprefs.gfx_lores = 0;
1.1.1.2   root     4295: #endif
                   4296:     } else {
                   4297:        /* Border. */
                   4298:        int i, lastpos = 0, nextpos;
                   4299:        struct color_change *cc;
1.1       root     4300: 
1.1.1.3 ! root     4301:        xlinebuffer = gfxvidinfo.linemem;
        !          4302:        if (xlinebuffer == NULL)
        !          4303:            xlinebuffer = row_map[gfx_ypos];
        !          4304:        xlinebuffer -= linetoscr_x_adjust_bytes;
        !          4305: 
1.1.1.2   root     4306:        adjust_drawing_colors (dp_for_drawing->ctable, 0);
                   4307:        /* Check color0 adjust only if we have color changes - shouldn't happen
                   4308:         * otherwise. */
                   4309: 
                   4310:        if (dip_for_drawing->nr_color_changes == 0) {
                   4311:            fill_line ();
                   4312:            do_flush_line (gfx_ypos);
                   4313:            linestate[lineno] = LINE_DONE;
                   4314:            if (do_double) {
1.1.1.3 ! root     4315:                if (gfxvidinfo.linemem == NULL) {
        !          4316:                    xlinebuffer = row_map[follow_ypos] - linetoscr_x_adjust_bytes;
        !          4317:                    fill_line ();
        !          4318:                }
1.1.1.2   root     4319:                do_flush_line (follow_ypos);
                   4320:                linestate[lineno+1] = LINE_DONE_AS_PREVIOUS;
                   4321:            }
1.1       root     4322:            return;
1.1.1.2   root     4323:        }
                   4324: 
                   4325:        adjust_color0_for_color_change ();
                   4326:        do_color_changes (pfield_do_fill_line);
1.1.1.3 ! root     4327: 
1.1.1.2   root     4328:        do_flush_line (gfx_ypos);
                   4329:        linestate[lineno] = LINE_DONE;
                   4330:        if (do_double) {
1.1.1.3 ! root     4331:            if (gfxvidinfo.linemem == NULL)
        !          4332:                memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
1.1.1.2   root     4333:            linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
                   4334:            line_decisions[lineno + 1].which = -2;
                   4335:            do_flush_line (follow_ypos);
                   4336:        }
1.1       root     4337:     }
                   4338: }
                   4339: 
1.1.1.2   root     4340: #ifdef SUPPORT_PENGUINS
1.1.1.3 ! root     4341: static smp_comm_pipe drawing_pipe;
        !          4342: static uae_sem_t drawing_lock;
        !          4343: 
        !          4344: static void *drawing_penguin (void *cruxmedo)
1.1.1.2   root     4345: {
                   4346:     int l;
1.1.1.3 ! root     4347:     fprintf(stderr, "Hello, world!\n");
1.1.1.2   root     4348: 
                   4349:     for (;;) {
                   4350:        /* Start of a frame. */
1.1.1.3 ! root     4351:        int k;
        !          4352:        new_frame:
        !          4353:        k = read_comm_pipe_int_blocking (&drawing_pipe);
        !          4354: 
        !          4355:        switch (k) {
        !          4356:         case -2:
        !          4357:            /* Hoopy */
        !          4358:            break;
        !          4359: 
        !          4360:         default:
        !          4361:            write_log ("Penguin got out of sync.\n");
        !          4362:            /* what can we do? Try to reduce the damage */
        !          4363:            for (;;) {
        !          4364:                k = read_comm_pipe_int_blocking (&drawing_pipe);
        !          4365:                if (k == -3)
        !          4366:                    break;
        !          4367:                if (k == -1) {
        !          4368:                    uae_sem_post (&drawing_lock);
        !          4369:                    goto new_frame;
        !          4370:                }
        !          4371:            }
        !          4372:         case -3:
        !          4373:            UAE_PENGUIN_EXIT;
        !          4374:            /* Can't happen */
        !          4375:            return 0;
1.1.1.2   root     4376:        }
                   4377: 
                   4378:        for (;;) {
                   4379:            int i, where;
                   4380:            int l = read_comm_pipe_int_blocking (&drawing_pipe);
1.1.1.3 ! root     4381:            switch (l) {
        !          4382:             case -1:
1.1.1.2   root     4383:                /* End-of-frame synchronization. */
1.1.1.3 ! root     4384:                uae_sem_post (&drawing_lock);
        !          4385:                goto new_frame;
        !          4386:             case -2:
        !          4387:                /* customreset called a bit too often. That's harmless. */
        !          4388:                continue;
        !          4389:             case -3:
        !          4390:                write_log ("Penguin got out of sync.\n");
        !          4391:                UAE_PENGUIN_EXIT;
        !          4392:                return 0;
1.1.1.2   root     4393:            }
1.1.1.3 ! root     4394: 
1.1.1.2   root     4395:            /* l is the line that has been finished for drawing. */
                   4396:            i = l - thisframe_y_adjust_real;
                   4397:            if (i < 0 || i >= max_ypos_thisframe)
                   4398:                continue;
1.1       root     4399: 
1.1.1.2   root     4400:            if (linestate[l] == LINE_UNDECIDED) {
                   4401:                fprintf (stderr, "Line scheduled for drawing, but undecided %d!?\n", l);
                   4402:                continue;
                   4403:            }
1.1.1.3 ! root     4404:            if (inhibit_frame != 0)
        !          4405:                continue;
1.1.1.2   root     4406:            where = amiga2aspect_line_map[i+min_ypos_for_screen];
1.1.1.3 ! root     4407:            if (where >= gfxvidinfo.height || where == -1)
1.1.1.2   root     4408:                continue;
1.1       root     4409: 
1.1.1.2   root     4410:            pfield_draw_line (l, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
1.1       root     4411:        }
                   4412:     }
                   4413: }
                   4414: 
1.1.1.2   root     4415: static penguin_id our_penguin;
1.1       root     4416: 
1.1.1.2   root     4417: static void kill_drawing_penguin (void)
1.1       root     4418: {
1.1.1.3 ! root     4419:     /* ??? does libpthread do that for us? */
1.1.1.2   root     4420: }
                   4421: 
                   4422: #endif
                   4423: 
                   4424: static int penguins_enabled_thisframe;
                   4425: 
1.1.1.3 ! root     4426: static void adjust_array_sizes (void)
1.1.1.2   root     4427: {
                   4428: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
1.1.1.3 ! root     4429:     if (delta_sprite_draw) {
        !          4430:        void *p1,*p2;
        !          4431:        int mcc = max_sprite_draw + 200 + delta_sprite_draw;
        !          4432:        delta_sprite_draw = 0;
        !          4433:        p1 = realloc (sprite_positions[0], mcc * sizeof (struct sprite_draw));
        !          4434:        p2 = realloc (sprite_positions[1], mcc * sizeof (struct sprite_draw));
        !          4435:        if (p1) sprite_positions[0] = p1;
        !          4436:        if (p2) sprite_positions[1] = p2;
        !          4437:        if (p1 && p2) {
        !          4438:            fprintf (stderr, "new max_sprite_draw=%d\n",mcc);
1.1.1.2   root     4439:            max_sprite_draw = mcc;
                   4440:        }
                   4441:     }
1.1.1.3 ! root     4442:     if (delta_color_change) {
        !          4443:        void *p1,*p2;
        !          4444:        int mcc = max_color_change + 200 + delta_color_change;
        !          4445:        delta_color_change = 0;
        !          4446:        p1 = realloc (color_changes[0], mcc * sizeof (struct color_change));
        !          4447:        p2 = realloc (color_changes[1], mcc * sizeof (struct color_change));
        !          4448:        if (p1) color_changes[0] = p1;
        !          4449:        if (p2) color_changes[1] = p2;
        !          4450:        if (p1 && p2) {
        !          4451:            fprintf (stderr, "new max_color_change=%d\n",mcc);
1.1.1.2   root     4452:            max_color_change = mcc;
1.1.1.3 ! root     4453:        }
        !          4454:     }
        !          4455:     if (delta_delay_change) {
        !          4456:        void *p;
        !          4457:        int mcc = max_delay_change + 200 + delta_delay_change;
        !          4458:        delta_delay_change = 0;
        !          4459:        p = realloc (delay_changes, mcc * sizeof (struct delay_change));
        !          4460:        if (p) {
        !          4461:            fprintf (stderr, "new max_delay_change=%d\n",mcc);
        !          4462:            delay_changes = p;
        !          4463:            max_delay_change = mcc;
        !          4464:        }
1.1.1.2   root     4465:     }
                   4466: #endif
1.1.1.3 ! root     4467: }
        !          4468: 
        !          4469: static void init_drawing_frame (void)
        !          4470: {
        !          4471:     int i, maxline;
1.1.1.2   root     4472: 
1.1.1.3 ! root     4473:     adjust_array_sizes ();
        !          4474: 
        !          4475:     check_prefs_changed_custom ();
        !          4476:     check_prefs_changed_cpu ();
        !          4477:     
1.1       root     4478:     if (max_diwstop == 0)
                   4479:        max_diwstop = diwlastword;
1.1.1.2   root     4480:     if (min_diwstart > max_diwstop)
                   4481:        min_diwstart = 0;
1.1       root     4482: 
1.1.1.2   root     4483:     if (thisframe_first_drawn_line == -1)
                   4484:        thisframe_first_drawn_line = minfirstline;
                   4485:     if (thisframe_first_drawn_line > thisframe_last_drawn_line)
                   4486:        thisframe_last_drawn_line = thisframe_first_drawn_line;
                   4487: 
                   4488:     next_color_change = 0;
                   4489:     next_delay_change = 0;
                   4490:     next_sprite_draw = 0;
1.1.1.3 ! root     4491:     maxline = currprefs.gfx_linedbl ? (maxvpos+1) * 2 + 1 : (maxvpos+1) + 1;
1.1.1.2   root     4492: #ifdef SMART_UPDATE
                   4493:     for (i = 0; i < maxline; i++)
                   4494:        linestate[i] = linestate[i] == LINE_DONE_AS_PREVIOUS ? LINE_REMEMBERED_AS_PREVIOUS : LINE_UNDECIDED;
                   4495: #else
                   4496:     memset (linestate, LINE_UNDECIDED, maxline);
                   4497: #endif
1.1       root     4498:     last_drawn_line = 0;
                   4499:     first_drawn_line = 32767;
                   4500: 
                   4501:     first_block_line = last_block_line = -2;
1.1.1.3 ! root     4502:     if (currprefs.test_drawing_speed)
1.1.1.2   root     4503:        frame_redraw_necessary = 1;
                   4504:     else if (frame_redraw_necessary)
1.1       root     4505:        frame_redraw_necessary--;
1.1.1.3 ! root     4506: 
1.1.1.2   root     4507:     next_color_entry = 0;
                   4508:     remembered_color_entry = -1;
                   4509:     prev_sprite_positions = sprite_positions[current_change_set];
                   4510:     curr_sprite_positions = sprite_positions[current_change_set ^ 1];
                   4511:     prev_color_changes = color_changes[current_change_set];
                   4512:     curr_color_changes = color_changes[current_change_set ^ 1];
                   4513:     prev_color_tables = color_tables[current_change_set];
                   4514:     curr_color_tables = color_tables[current_change_set ^ 1];
1.1.1.3 ! root     4515: 
1.1.1.2   root     4516:     prev_drawinfo = line_drawinfo[current_change_set];
                   4517:     curr_drawinfo = line_drawinfo[current_change_set ^= 1];
                   4518:     drawing_color_matches = -1;
                   4519:     color_src_match = color_dest_match = -1;
                   4520: 
                   4521:     prev_x_adjust = linetoscr_x_adjust;
                   4522:     prev_y_adjust = thisframe_y_adjust;
                   4523: 
1.1.1.3 ! root     4524:     if (currprefs.gfx_xcenter) {
        !          4525:        if (max_diwstop - min_diwstart < gfxvidinfo.width && currprefs.gfx_xcenter == 2)
1.1.1.2   root     4526:            /* Try to center. */
1.1.1.3 ! root     4527:            linetoscr_x_adjust = ((max_diwstop - min_diwstart - gfxvidinfo.width) / 2 + min_diwstart) & ~1;
1.1.1.2   root     4528:        else
1.1.1.3 ! root     4529:            linetoscr_x_adjust = max_diwstop - gfxvidinfo.width;
1.1.1.2   root     4530: 
1.1.1.3 ! root     4531:        /* Would the old value be good enough? If so, leave it as it is if we want to
        !          4532:         * be clever. */
        !          4533:        if (currprefs.gfx_xcenter == 2) {
1.1.1.2   root     4534:            if (linetoscr_x_adjust < prev_x_adjust && prev_x_adjust < min_diwstart)
                   4535:                linetoscr_x_adjust = prev_x_adjust;
1.1       root     4536:        }
1.1.1.2   root     4537:     } else
1.1.1.3 ! root     4538:        linetoscr_x_adjust = max_diwlastword - gfxvidinfo.width;
1.1.1.2   root     4539:     if (linetoscr_x_adjust < 0)
                   4540:        linetoscr_x_adjust = 0;
1.1.1.3 ! root     4541: 
        !          4542:     linetoscr_x_adjust_bytes = linetoscr_x_adjust * gfxvidinfo.pixbytes;
        !          4543: 
        !          4544:     linetoscr_right_x = linetoscr_x_adjust + gfxvidinfo.width;
1.1.1.2   root     4545:     if (linetoscr_right_x > max_diwlastword)
                   4546:        linetoscr_right_x = max_diwlastword;
1.1.1.3 ! root     4547: 
1.1.1.2   root     4548:     thisframe_y_adjust = minfirstline;
1.1.1.3 ! root     4549:     if (currprefs.gfx_ycenter && thisframe_first_drawn_line != -1) {
        !          4550:        if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && currprefs.gfx_ycenter == 2)
1.1.1.2   root     4551:            thisframe_y_adjust = (thisframe_last_drawn_line - thisframe_first_drawn_line - max_drawn_amiga_line) / 2 + thisframe_first_drawn_line;
                   4552:        else
                   4553:            thisframe_y_adjust = thisframe_first_drawn_line;
1.1.1.3 ! root     4554:        /* Would the old value be good enough? If so, leave it as it is if we want to
        !          4555:         * be clever. */
        !          4556:        if (currprefs.gfx_ycenter == 2) {
1.1.1.2   root     4557:            if (thisframe_y_adjust != prev_y_adjust
                   4558:                && prev_y_adjust <= thisframe_first_drawn_line
                   4559:                && prev_y_adjust + max_drawn_amiga_line > thisframe_last_drawn_line)
                   4560:                thisframe_y_adjust = prev_y_adjust;
                   4561:        }
1.1.1.3 ! root     4562:        /* Make sure the value makes sense */
1.1.1.2   root     4563:        if (thisframe_y_adjust + max_drawn_amiga_line > maxvpos)
                   4564:            thisframe_y_adjust = maxvpos - max_drawn_amiga_line;
                   4565:        if (thisframe_y_adjust < minfirstline)
                   4566:            thisframe_y_adjust = minfirstline;
1.1       root     4567:     }
1.1.1.3 ! root     4568:     thisframe_y_adjust_real = thisframe_y_adjust << (currprefs.gfx_linedbl ? 1 : 0);
        !          4569:     max_ypos_thisframe = (maxvpos - thisframe_y_adjust) << (currprefs.gfx_linedbl ? 1 : 0);
1.1       root     4570: 
1.1.1.2   root     4571:     if (prev_x_adjust != linetoscr_x_adjust || prev_y_adjust != thisframe_y_adjust)
1.1.1.3 ! root     4572:        frame_redraw_necessary |= (bplcon0 & 4) && currprefs.gfx_linedbl ? 2 : 1;
1.1       root     4573: 
1.1.1.2   root     4574:     max_diwstop = 0;
                   4575:     min_diwstart = 10000;
                   4576:     thisframe_first_drawn_line = -1;
                   4577:     thisframe_last_drawn_line = -1;
                   4578: #ifdef SUPPORT_PENGUINS
                   4579:     penguins_enabled_thisframe = 1;
                   4580:     /* Tell the other thread that it can now expect data from us. */
1.1.1.3 ! root     4581:     write_comm_pipe_int (&drawing_pipe, -2, 1);
1.1.1.2   root     4582:     memset (line_drawn, 0, sizeof line_drawn);
                   4583: #endif
1.1       root     4584: }
                   4585: 
1.1.1.2   root     4586: static void finish_drawing_frame (void)
1.1       root     4587: {
1.1.1.2   root     4588:     int i;
1.1       root     4589: 
1.1.1.2   root     4590: #ifdef SUPPORT_PENGUINS
                   4591:     /* Synchronize with other thread, then see whether there's something left for
                   4592:      * us to draw. @@@ This is probably a big waste of cycles if the two threads
1.1.1.3 ! root     4593:      * run at very different speeds - this one could draw stuff as well. */
        !          4594:     write_comm_pipe_int (&drawing_pipe, -1, 1);
        !          4595:     uae_sem_wait (&drawing_lock);
        !          4596: #else
1.1       root     4597: 
1.1.1.2   root     4598: #ifndef SMART_UPDATE
                   4599:     /* @@@ This isn't exactly right yet. FIXME */
                   4600:     if (!interlace_seen) {
                   4601:        do_flush_screen (first_drawn_line, last_drawn_line);
                   4602:        return;
1.1       root     4603:     }
1.1.1.2   root     4604: #endif
                   4605:     for (i = 0; i < max_ypos_thisframe; i++) {
                   4606:        int where;
                   4607:        int line = i + thisframe_y_adjust_real;
                   4608: 
                   4609:        if (linestate[line] == LINE_UNDECIDED)
                   4610:            break;
                   4611: 
                   4612:        where = amiga2aspect_line_map[i+min_ypos_for_screen];
1.1.1.3 ! root     4613:        if (where >= gfxvidinfo.height)
1.1.1.2   root     4614:            break;
                   4615:        if (where == -1)
                   4616:            continue;
1.1       root     4617: 
1.1.1.2   root     4618:        pfield_draw_line (line, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
1.1       root     4619:     }
1.1.1.3 ! root     4620: #endif
1.1.1.2   root     4621:     do_flush_screen (first_drawn_line, last_drawn_line);
1.1       root     4622: }
                   4623: 
1.1.1.3 ! root     4624: static __inline__ void check_picasso (void)
        !          4625: {
        !          4626: #ifdef PICASSO96
        !          4627:     if (picasso_requested_on == picasso_on)
        !          4628:        return;
        !          4629: 
        !          4630:     picasso_on = picasso_requested_on;
        !          4631: 
        !          4632:     if (!picasso_on)
        !          4633:        clear_inhibit_frame (2);
        !          4634:     else
        !          4635:        set_inhibit_frame (2);
        !          4636: 
        !          4637:     gfx_set_picasso_state (picasso_on);
        !          4638:     picasso_enablescreen (picasso_requested_on);
        !          4639: 
        !          4640:     notice_screen_contents_lost ();
        !          4641: #endif
        !          4642: }
        !          4643: 
1.1.1.2   root     4644: static void vsync_handler (void)
1.1       root     4645: {
1.1.1.3 ! root     4646: #ifdef FRAME_RATE_HACK /* put this here or at the end of the function? */
        !          4647:     {
        !          4648:        frame_time_t curr_time = read_processor_time();
        !          4649:        vsyncmintime += vsynctime;
        !          4650:        /* @@@ Mathias? How do you think we should do this? */
        !          4651:        /* If we are too far behind, or we just did a reset, adjust the
        !          4652:         * needed time. */
        !          4653:        if ((long int)(curr_time - vsyncmintime) > 0 || did_reset)
        !          4654:            vsyncmintime = curr_time + vsynctime;
        !          4655:        did_reset = 0;
        !          4656:     }
        !          4657: #endif
        !          4658:     handle_events ();
1.1       root     4659: 
1.1.1.3 ! root     4660:     getjoystate (0, &joy0dir, &joy0button);
        !          4661:     getjoystate (1, &joy1dir, &joy1button);
1.1       root     4662: 
                   4663:     INTREQ(0x8020);
1.1.1.3 ! root     4664:     if (bplcon0 & 4)
1.1.1.2   root     4665:        lof ^= 0x8000;
1.1.1.3 ! root     4666: 
        !          4667:     if (quit_program < 0) {
        !          4668:        quit_program = -quit_program;
        !          4669:        set_inhibit_frame (1);
        !          4670:        regs.spcflags |= SPCFLAG_BRK;
        !          4671:        if (framecnt == 0)
        !          4672:            finish_drawing_frame ();
        !          4673:        filesys_prepare_reset ();
        !          4674: #ifdef SUPPORT_PENGUINS
        !          4675:        if (quit_program == 1)
        !          4676:            /* Stop eating herring */
        !          4677:            write_comm_pipe_int (&drawing_pipe, -3, 1);
        !          4678: #endif
        !          4679:        return;
        !          4680:     }
        !          4681: 
1.1.1.2   root     4682:     last_redraw_point++;
                   4683:     if (lof_changed || !interlace_seen || last_redraw_point >= 2 || lof) {
1.1.1.3 ! root     4684:        static int cnt = 0;
        !          4685: 
1.1.1.2   root     4686:        if (framecnt == 0)
                   4687:            finish_drawing_frame ();
                   4688:        count_frame ();
                   4689:        last_redraw_point = 0;
1.1.1.3 ! root     4690: 
        !          4691:        check_picasso ();
        !          4692: 
        !          4693:        uae_sem_wait (&ihf_sem);
        !          4694:        if (inhibit_frame != 0)
        !          4695:            framecnt = 1;
        !          4696:        if (frame_do_semup)
        !          4697:            uae_sem_post (&frame_sem);
        !          4698:        frame_do_semup = 0;
        !          4699:        uae_sem_post (&ihf_sem);
        !          4700: 
        !          4701:        if (cnt == 0) {
        !          4702:            /* resolution_check_change (); */
        !          4703:            DISK_check_change ();
        !          4704:            cnt = 5;
        !          4705:        }
        !          4706:        cnt--;
1.1.1.2   root     4707:        if (framecnt == 0)
                   4708:            init_drawing_frame ();
                   4709:     }
1.1.1.3 ! root     4710: 
1.1.1.2   root     4711:     lof_changed = 0;
                   4712:     interlace_seen = 0;
1.1       root     4713:     COPJMP1(0);
1.1.1.3 ! root     4714: 
1.1.1.2   root     4715:     init_hardware_frame();
1.1       root     4716: #ifdef HAVE_GETTIMEOFDAY
                   4717:     {
                   4718:        struct timeval tv;
                   4719:        unsigned long int newtime;
1.1.1.3 ! root     4720: 
        !          4721:        gettimeofday(&tv,NULL);
1.1       root     4722:        newtime = (tv.tv_sec-seconds_base) * 1000 + tv.tv_usec / 1000;
1.1.1.3 ! root     4723: 
        !          4724:        if (!bogusframe) {
1.1       root     4725:            frametime += newtime - msecs;
                   4726:            timeframes++;
                   4727:        }
                   4728:        msecs = newtime;
                   4729:        bogusframe = 0;
                   4730:     }
                   4731: #endif
1.1.1.3 ! root     4732:     if (ievent_alive > 0)
        !          4733:        ievent_alive--;
1.1       root     4734:     CIA_vsync_handler();
                   4735: }
                   4736: 
                   4737: static void hsync_handler(void)
                   4738: {
1.1.1.2   root     4739:     int lineno = next_lineno;
1.1       root     4740:     int lineisdouble = 0;
                   4741:     int line_was_doubled = 0;
1.1.1.3 ! root     4742: 
1.1.1.2   root     4743:     finish_decisions ();
                   4744:     do_modulos ();
                   4745: 
                   4746:     if (framecnt == 0) {
                   4747:        switch (nln_how) {
                   4748:         case 0:
                   4749:            linestate[lineno] = LINE_DECIDED;
                   4750:            break;
                   4751:         case 1:
                   4752:            linestate[lineno] = LINE_DECIDED_DOUBLE;
                   4753:            if (linestate[lineno+1] != LINE_REMEMBERED_AS_PREVIOUS)
                   4754:                linestate[lineno+1] = LINE_AS_PREVIOUS;
                   4755:            break;
                   4756:         case 2:
                   4757:            if (linestate[lineno-1] == LINE_UNDECIDED)
                   4758:                linestate[lineno-1] = LINE_BORDER_NEXT;
                   4759:            linestate[lineno] = LINE_DECIDED;
                   4760:            break;
                   4761:         case 3:
                   4762:            linestate[lineno] = LINE_DECIDED;
                   4763:            if (linestate[lineno+1] == LINE_UNDECIDED
                   4764:                || linestate[lineno+1] == LINE_REMEMBERED_AS_PREVIOUS
                   4765:                || linestate[lineno+1] == LINE_AS_PREVIOUS)
                   4766:                linestate[lineno+1] = LINE_BORDER_PREV;
                   4767:            break;
1.1       root     4768:        }
                   4769:     }
                   4770: 
                   4771:     eventtab[ev_hsync].evtime += cycles - eventtab[ev_hsync].oldcycles;
                   4772:     eventtab[ev_hsync].oldcycles = cycles;
                   4773:     CIA_hsync_handler();
1.1.1.3 ! root     4774: 
        !          4775:     if (currprefs.produce_sound > 0) {
1.1       root     4776:        int nr;
                   4777:        /* Sound data is fetched at the beginning of each line */
                   4778:        for (nr = 0; nr < 4; nr++) {
                   4779:            struct audio_channel_data *cdp = audio_channel + nr;
1.1.1.3 ! root     4780: 
1.1       root     4781:            if (cdp->data_written == 2) {
                   4782:                cdp->data_written = 0;
                   4783:                cdp->nextdat = chipmem_bank.wget(cdp->pt);
                   4784:                cdp->pt += 2;
                   4785:                if (cdp->state == 2 || cdp->state == 3) {
                   4786:                    if (cdp->wlen == 1) {
                   4787:                        cdp->pt = cdp->lc;
                   4788:                        cdp->wlen = cdp->len;
                   4789:                        cdp->intreq2 = 1;
                   4790:                    } else
                   4791:                        cdp->wlen--;
                   4792:                }
                   4793:            }
                   4794:        }
                   4795:     }
1.1.1.2   root     4796: #ifdef SUPPORT_PENGUINS
                   4797:     if (framecnt == 0 && penguins_enabled_thisframe) {
1.1.1.3 ! root     4798:        write_comm_pipe_int (&drawing_pipe, next_lineno, 0);
1.1.1.2   root     4799:     }
1.1       root     4800: #endif
1.1.1.2   root     4801: #ifndef SMART_UPDATE
                   4802:     {
                   4803:        int i, where;
                   4804:        /* l is the line that has been finished for drawing. */
                   4805:        i = next_lineno - thisframe_y_adjust_real;
                   4806:        if (i >= 0 && i < max_ypos_thisframe) {
                   4807:            where = amiga2aspect_line_map[i+min_ypos_for_screen];
1.1.1.3 ! root     4808:            if (where < gfxvidinfo.height && where != -1)
1.1.1.2   root     4809:                pfield_draw_line (next_lineno, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
1.1       root     4810:        }
                   4811:     }
1.1.1.2   root     4812: #endif
1.1       root     4813:     if (++vpos == (maxvpos + (lof != 0))) {
                   4814:        vpos = 0;
                   4815:        vsync_handler();
                   4816:     }
1.1.1.2   root     4817: 
1.1.1.3 ! root     4818:     is_lastline = vpos + 1 == maxvpos + (lof != 0);
        !          4819: 
        !          4820:     if ((bplcon0 & 4) && currprefs.gfx_linedbl) {
1.1.1.2   root     4821:        interlace_seen = 1, penguins_enabled_thisframe = 0;
                   4822:     }
                   4823: 
                   4824:     if (framecnt == 0) {
                   4825:        lineno = vpos;
                   4826:        nln_how = 0;
1.1.1.3 ! root     4827:        if (currprefs.gfx_linedbl) {
1.1       root     4828:            lineno *= 2;
1.1.1.2   root     4829:            nln_how = 1;
                   4830:            if (bplcon0 & 4) {
                   4831:                if (!lof) {
                   4832:                    lineno++;
                   4833:                    nln_how = 2;
                   4834:                } else {
                   4835:                    nln_how = 3;
                   4836:                }
1.1       root     4837:            }
                   4838:        }
                   4839:        next_lineno = lineno;
1.1.1.2   root     4840:        reset_decisions ();
1.1       root     4841:     }
1.1.1.3 ! root     4842:     if (uae_int_requested) {
        !          4843:        set_uae_int_flag ();
        !          4844:        INTREQ (0xA000);
        !          4845:     }
        !          4846: }
        !          4847: 
        !          4848: static void init_eventtab (void)
        !          4849: {
        !          4850:     int i;
        !          4851: 
        !          4852:     for(i = 0; i < ev_max; i++) {
        !          4853:        eventtab[i].active = 0;
        !          4854:        eventtab[i].oldcycles = 0;
        !          4855:     }
        !          4856:     copper_active = 0;
        !          4857:     eventtab[ev_cia].handler = CIA_handler;
        !          4858:     eventtab[ev_copper].handler = /* currprefs.copper_pos >= 0 ? do_copper_cheat : */ do_copper;
        !          4859:     eventtab[ev_hsync].handler = hsync_handler;
        !          4860:     eventtab[ev_hsync].evtime = maxhpos + cycles;
        !          4861:     eventtab[ev_hsync].active = 1;
        !          4862: 
        !          4863:     eventtab[ev_blitter].handler = blitter_handler;
        !          4864:     eventtab[ev_blitter].active = 0;
        !          4865:     eventtab[ev_diskblk].handler = diskblk_handler;
        !          4866:     eventtab[ev_diskblk].active = 0;
        !          4867:     eventtab[ev_diskindex].handler = diskindex_handler;
        !          4868:     eventtab[ev_diskindex].active = 0;
        !          4869: #ifndef DONT_WANT_SOUND
        !          4870:     eventtab[ev_aud0].handler = aud0_handler;
        !          4871:     eventtab[ev_aud0].active = 0;
        !          4872:     eventtab[ev_aud1].handler = aud1_handler;
        !          4873:     eventtab[ev_aud1].active = 0;
        !          4874:     eventtab[ev_aud2].handler = aud2_handler;
        !          4875:     eventtab[ev_aud2].active = 0;
        !          4876:     eventtab[ev_aud3].handler = aud3_handler;
        !          4877:     eventtab[ev_aud3].active = 0;
        !          4878:     if (sound_available && currprefs.produce_sound >= 2) {
        !          4879:        eventtab[ev_sample].active = 1;
        !          4880:        eventtab[ev_sample].evtime = sample_evtime;
        !          4881:     } else {
        !          4882:        eventtab[ev_sample].active = 0;
        !          4883:     }
        !          4884: #endif
        !          4885:     events_schedule ();
1.1       root     4886: }
                   4887: 
1.1.1.3 ! root     4888: void customreset (void)
1.1       root     4889: {
1.1.1.2   root     4890:     int i, maxl;
                   4891:     double native_lines_per_amiga_line;
1.1       root     4892: #ifdef HAVE_GETTIMEOFDAY
                   4893:     struct timeval tv;
                   4894: #endif
1.1.1.2   root     4895: 
1.1.1.3 ! root     4896:     for (i = 0; i < sizeof current_colors.color_regs / sizeof *current_colors.color_regs; i++)
        !          4897:        current_colors.color_regs[i] = -1;
        !          4898: 
        !          4899: #ifdef FRAME_RATE_HACK
        !          4900:     did_reset = 1;
        !          4901:     vsyncmintime = read_processor_time() + vsynctime;
        !          4902: #endif
1.1       root     4903:     inhibit_frame = 0;
1.1.1.3 ! root     4904:     frame_do_semup = 0;
        !          4905:     uae_sem_init (&frame_sem, 0, 0);
        !          4906:     uae_sem_init (&gui_sem, 0, 1);
        !          4907:     uae_sem_init (&ihf_sem, 0, 1);
        !          4908:     expamem_reset ();
        !          4909:     filesys_reset ();
        !          4910:     CIA_reset ();
        !          4911: #ifdef PICASSO96
        !          4912:     InitPicasso96 ();
        !          4913:     picasso_on = 0;
        !          4914:     picasso_requested_on = 0;
        !          4915:     gfx_set_picasso_state (0);
        !          4916: #endif
        !          4917:     cycles = 0;
1.1       root     4918:     regs.spcflags &= SPCFLAG_BRK;
1.1.1.3 ! root     4919: 
        !          4920:     lores_factor = currprefs.gfx_lores ? 1 : 2;
        !          4921:     lores_shift = currprefs.gfx_lores ? 0 : 1;
        !          4922:     sprite_width = currprefs.gfx_lores ? 16 : 32;
        !          4923: 
1.1.1.2   root     4924:     vpos = 0;
1.1.1.3 ! root     4925:     is_lastline = 0;
1.1       root     4926:     lof = 0;
                   4927:     max_diwstop = 0;
1.1.1.3 ! root     4928: 
1.1       root     4929:     if (needmousehack()) {
1.1.1.3 ! root     4930: #if 0
        !          4931:        if (mousestate != follow_mouse) setfollow();
        !          4932: #else
        !          4933:        if (mousestate != dont_care_mouse) setdontcare();
        !          4934: #endif
1.1       root     4935:     } else {
                   4936:        mousestate = normal_mouse;
                   4937:     }
1.1.1.3 ! root     4938:     ievent_alive = 0;
        !          4939: 
        !          4940:     clx_sprmask = 0xFF;
        !          4941:     clxdat = 0;
        !          4942: 
        !          4943:     memset(sprarmed, 0, sizeof sprarmed);
        !          4944:     nr_armed = 0;
1.1       root     4945: 
                   4946:     /*memset(blitcount, 0, sizeof(blitcount));  blitter debug */
1.1.1.2   root     4947:     for (i = 0; i < (maxvpos+1)*2 + 1; i++) {
                   4948:        linestate[i] = LINE_UNDECIDED;
1.1       root     4949:     }
                   4950:     xlinebuffer = gfxvidinfo.bufmem;
                   4951: 
                   4952:     dmacon = intena = 0;
                   4953:     bltstate = BLT_done;
                   4954:     copstate = COP_stop;
1.1.1.2   root     4955:     diwstate = DIW_waiting_start;
1.1.1.3 ! root     4956:     hdiwstate = DIW_waiting_start;
1.1       root     4957:     copcon = 0;
                   4958:     dskdmaen = 0;
                   4959:     cycles = 0;
1.1.1.3 ! root     4960: 
        !          4961:     audio_reset ();
1.1       root     4962: 
1.1.1.2   root     4963:     bplcon4 = 0x11; /* Get AGA chipset into ECS compatibility mode */
                   4964:     bplcon3 = 0xC00;
1.1       root     4965: 
1.1.1.3 ! root     4966:     init_eventtab ();
1.1.1.2   root     4967: 
                   4968:     if (native2amiga_line_map)
                   4969:        free (native2amiga_line_map);
                   4970:     if (amiga2aspect_line_map)
                   4971:        free (amiga2aspect_line_map);
                   4972: 
1.1.1.3 ! root     4973:     /* At least for this array the +1 is necessary. */
1.1.1.2   root     4974:     amiga2aspect_line_map = (int *)malloc (sizeof (int) * (maxvpos+1)*2 + 1);
1.1.1.3 ! root     4975:     native2amiga_line_map = (int *)malloc (sizeof (int) * gfxvidinfo.height);
1.1.1.2   root     4976: 
1.1.1.3 ! root     4977:     if (currprefs.gfx_correct_aspect)
        !          4978:        native_lines_per_amiga_line = ((double)gfxvidinfo.height
        !          4979:                                       * (currprefs.gfx_lores ? 320 : 640)
        !          4980:                                       / (currprefs.gfx_linedbl ? 512 : 256)
        !          4981:                                       / gfxvidinfo.width);
1.1.1.2   root     4982:     else
                   4983:        native_lines_per_amiga_line = 1;
                   4984: 
1.1.1.3 ! root     4985:     maxl = (maxvpos+1) * (currprefs.gfx_linedbl ? 2 : 1);
        !          4986:     min_ypos_for_screen = minfirstline << (currprefs.gfx_linedbl ? 1 : 0);
1.1.1.2   root     4987:     max_drawn_amiga_line = -1;
                   4988:     for (i = 0; i < maxl; i++) {
                   4989:        int v = (i - min_ypos_for_screen) * native_lines_per_amiga_line;
1.1.1.3 ! root     4990:        if (v >= gfxvidinfo.height && max_drawn_amiga_line == -1)
1.1.1.2   root     4991:            max_drawn_amiga_line = i-min_ypos_for_screen;
1.1.1.3 ! root     4992:        if (i < min_ypos_for_screen || v >= gfxvidinfo.height)
1.1.1.2   root     4993:            v = -1;
                   4994:        amiga2aspect_line_map[i] = v;
                   4995:     }
1.1.1.3 ! root     4996:     if (currprefs.gfx_linedbl)
1.1.1.2   root     4997:        max_drawn_amiga_line >>= 1;
                   4998: 
1.1.1.3 ! root     4999:     if (currprefs.gfx_ycenter && !(currprefs.gfx_correct_aspect)) {
        !          5000:        extra_y_adjust = (gfxvidinfo.height - (maxvpos << (currprefs.gfx_linedbl ? 1 : 0))) >> 1;
        !          5001:        if (extra_y_adjust < 0)
        !          5002:            extra_y_adjust = 0;
        !          5003:     }
        !          5004: 
        !          5005:     for (i = 0; i < gfxvidinfo.height; i++)
1.1.1.2   root     5006:        native2amiga_line_map[i] = -1;
                   5007: 
                   5008:     if (native_lines_per_amiga_line < 1) {
                   5009:        /* Must omit drawing some lines. */
                   5010:        for (i = maxl-1; i > min_ypos_for_screen; i--) {
                   5011:            if (amiga2aspect_line_map[i] == amiga2aspect_line_map[i-1]) {
1.1.1.3 ! root     5012:                if (currprefs.gfx_linedbl && (i & 1) == 0 && amiga2aspect_line_map[i+1] != -1) {
1.1.1.2   root     5013:                    /* If only the first line of a line pair would be omitted,
                   5014:                     * omit the second one instead to avoid problems with line
                   5015:                     * doubling. */
                   5016:                    amiga2aspect_line_map[i] = amiga2aspect_line_map[i+1];
                   5017:                    amiga2aspect_line_map[i+1] = -1;
                   5018:                } else
                   5019:                    amiga2aspect_line_map[i] = -1;
                   5020:            }
                   5021:        }
                   5022:     }
                   5023: 
                   5024:     for (i = maxl-1; i >= min_ypos_for_screen; i--) {
                   5025:        int j;
                   5026:        if (amiga2aspect_line_map[i] == -1)
                   5027:            continue;
1.1.1.3 ! root     5028:        for (j = amiga2aspect_line_map[i]; j < gfxvidinfo.height && native2amiga_line_map[j] == -1; j++)
        !          5029:            native2amiga_line_map[j] = i >> (currprefs.gfx_linedbl ? 1 : 0);
1.1.1.2   root     5030:     }
1.1.1.3 ! root     5031: 
        !          5032:     if (line_drawn == 0)
        !          5033:        line_drawn = (char *)malloc (gfxvidinfo.height);
        !          5034:     init_row_map();
        !          5035: 
        !          5036:     init_sprites ();
        !          5037: 
1.1.1.2   root     5038:     init_hardware_frame ();
                   5039:     init_drawing_frame ();
                   5040:     last_redraw_point = 0;
                   5041:     reset_decisions ();
1.1.1.3 ! root     5042: 
1.1       root     5043: #ifdef HAVE_GETTIMEOFDAY
                   5044:     gettimeofday(&tv,NULL);
                   5045:     seconds_base = tv.tv_sec;
                   5046:     bogusframe = 1;
                   5047: #endif
                   5048: }
                   5049: 
1.1.1.3 ! root     5050: void dumpcustom (void)
1.1       root     5051: {
                   5052:     int i;
                   5053:     fprintf(stderr, "DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR(),
                   5054:           intena, intreq, vpos, current_hpos());
1.1.1.3 ! root     5055:     if (timeframes) {
        !          5056:        fprintf(stderr, "Average frame time: %d ms [frames: %d time: %d]\n",
1.1       root     5057:               frametime/timeframes, timeframes, frametime);
                   5058:     }
1.1.1.3 ! root     5059:     dump_audio_bench ();
1.1       root     5060:     /*for (i=0; i<256; i++) if (blitcount[i]) fprintf(stderr, "minterm %x = %d\n",i,blitcount[i]);  blitter debug */
                   5061: }
                   5062: 
1.1.1.3 ! root     5063: int intlev (void)
1.1       root     5064: {
1.1.1.3 ! root     5065:     uae_u16 imask = intreq & intena;
1.1       root     5066:     if (imask && (intena & 0x4000)){
                   5067:        if (imask & 0x2000) return 6;
                   5068:        if (imask & 0x1800) return 5;
                   5069:        if (imask & 0x0780) return 4;
                   5070:        if (imask & 0x0070) return 3;
                   5071:        if (imask & 0x0008) return 2;
                   5072:        if (imask & 0x0007) return 1;
                   5073:     }
                   5074:     return -1;
                   5075: }
                   5076: 
1.1.1.3 ! root     5077: void custom_init (void)
1.1       root     5078: {
                   5079:     int num;
1.1.1.2   root     5080: 
                   5081: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
                   5082:     for(num=0;num<2;++num) {
1.1.1.3 ! root     5083:        sprite_positions[num] = xmalloc(max_sprite_draw * sizeof(struct sprite_draw));
        !          5084:        color_changes[num] = xmalloc(max_color_change * sizeof(struct color_change));
1.1.1.2   root     5085:     }
1.1.1.3 ! root     5086:     delay_changes = xmalloc(max_delay_change * sizeof(struct delay_change));
1.1.1.2   root     5087: #endif
1.1.1.3 ! root     5088: 
1.1       root     5089:     if (needmousehack())
                   5090:        setfollow();
1.1.1.2   root     5091:     init_regchanges ();
                   5092:     init_decisions ();
                   5093: 
1.1.1.3 ! root     5094:     /* For now, the AGA stuff is broken in the dual playfield case. We encode
        !          5095:      * sprites in dpf mode by ORing the pixel value with 0x80. To make dual
        !          5096:      * playfield rendering easy, the lookup tables contain are made linear for
        !          5097:      * values >= 128. That only works for OCS/ECS, though. */
        !          5098: 
        !          5099:     for (num = 0; num < 256; num++) {
1.1       root     5100:        int plane1 = (num & 1) | ((num >> 1) & 2) | ((num >> 2) & 4) | ((num >> 3) & 8);
                   5101:        int plane2 = ((num >> 1) & 1) | ((num >> 2) & 2) | ((num >> 3) & 4) | ((num >> 4) & 8);
                   5102:        dblpf_2nd1[num] = plane1 == 0 ? (plane2 == 0 ? 0 : 2) : 1;
                   5103:        dblpf_2nd2[num] = plane2 == 0 ? (plane1 == 0 ? 0 : 1) : 2;
                   5104:        if (plane2 > 0) plane2 += 8;
1.1.1.3 ! root     5105:        dblpf_ind1[num] = num >= 128 ? num & 0x7F : (plane1 == 0 ? plane2 : plane1);
        !          5106:        dblpf_ind2[num] = num >= 128 ? num & 0x7F : (plane2 == 0 ? plane1 : plane2);
        !          5107: 
1.1       root     5108:        lots_of_twos[num] = num == 0 ? 0 : 2;
                   5109:        linear_map_256[num] = num;
                   5110:     }
                   5111:     build_blitfilltable();
                   5112:     gen_pfield_tables();
1.1.1.2   root     5113:     native2amiga_line_map = 0;
                   5114:     amiga2aspect_line_map = 0;
                   5115:     line_drawn = 0;
1.1.1.3 ! root     5116: 
1.1.1.2   root     5117: #ifdef SUPPORT_PENGUINS
1.1.1.3 ! root     5118:     init_comm_pipe (&drawing_pipe, 800, 5);
        !          5119:     uae_sem_init (&drawing_lock, 0, 0);
        !          5120:     start_penguin (drawing_penguin, 0, &our_penguin);
        !          5121:     /*atexit(kill_drawing_penguin);*/
1.1.1.2   root     5122: #endif
1.1       root     5123: }
                   5124: 
                   5125: /* Custom chip memory bank */
                   5126: 
1.1.1.3 ! root     5127: static uae_u32 custom_lget(uaecptr) REGPARAM;
        !          5128: static uae_u32 custom_wget(uaecptr) REGPARAM;
        !          5129: static uae_u32 custom_bget(uaecptr) REGPARAM;
        !          5130: static void  custom_lput(uaecptr, uae_u32) REGPARAM;
        !          5131: static void  custom_wput(uaecptr, uae_u32) REGPARAM;
        !          5132: static void  custom_bput(uaecptr, uae_u32) REGPARAM;
1.1       root     5133: 
                   5134: addrbank custom_bank = {
                   5135:     custom_lget, custom_wget, custom_bget,
                   5136:     custom_lput, custom_wput, custom_bput,
                   5137:     default_xlate, default_check
                   5138: };
                   5139: 
1.1.1.3 ! root     5140: uae_u32 REGPARAM2 custom_wget (uaecptr addr)
1.1       root     5141: {
                   5142:     switch(addr & 0x1FE) {
                   5143:      case 0x002: return DMACONR();
                   5144:      case 0x004: return VPOSR();
                   5145:      case 0x006: return VHPOSR();
1.1.1.3 ! root     5146: 
1.1       root     5147:      case 0x008: return DSKDATR();
                   5148: 
                   5149:      case 0x00A: return JOY0DAT();
                   5150:      case 0x00C: return JOY1DAT();
1.1.1.3 ! root     5151:      case 0x00E: return CLXDAT();
1.1       root     5152:      case 0x010: return ADKCONR();
                   5153: 
                   5154:      case 0x012: return POT0DAT();
                   5155:      case 0x016: return POTGOR();
                   5156:      case 0x018: return SERDATR();
                   5157:      case 0x01A: return DSKBYTR();
                   5158:      case 0x01C: return INTENAR();
                   5159:      case 0x01E: return INTREQR();
                   5160: #if AGA_CHIPSET == 1
                   5161:      case 0x07C: return 0xF8;
                   5162: #elif defined ECS_DENISE
                   5163:      case 0x07C: return 0xFC;
                   5164: #endif
                   5165:      default:
                   5166:        custom_wput(addr,0);
                   5167:        return 0xffff;
                   5168:     }
                   5169: }
                   5170: 
1.1.1.3 ! root     5171: uae_u32 REGPARAM2 custom_bget (uaecptr addr)
1.1       root     5172: {
                   5173:     return custom_wget(addr & 0xfffe) >> (addr & 1 ? 0 : 8);
                   5174: }
                   5175: 
1.1.1.3 ! root     5176: uae_u32 REGPARAM2 custom_lget (uaecptr addr)
1.1       root     5177: {
1.1.1.3 ! root     5178:     return ((uae_u32)custom_wget(addr & 0xfffe) << 16) | custom_wget((addr+2) & 0xfffe);
1.1       root     5179: }
                   5180: 
1.1.1.3 ! root     5181: void REGPARAM2 custom_wput (uaecptr addr, uae_u32 value)
1.1       root     5182: {
                   5183:     addr &= 0x1FE;
                   5184:     cregs[addr>>1] = value;
1.1.1.3 ! root     5185:     switch (addr) {
        !          5186:      case 0x020: DSKPTH (value); break;
        !          5187:      case 0x022: DSKPTL (value); break;
        !          5188:      case 0x024: DSKLEN (value); break;
        !          5189:      case 0x026: DSKDAT (value); break;
        !          5190: 
        !          5191:      case 0x02A: VPOSW (value); break;
        !          5192:      case 0x2E:  COPCON (value); break;
        !          5193:      case 0x030: SERDAT (value); break;
        !          5194:      case 0x032: SERPER (value); break;
        !          5195:      case 0x34: POTGO (value); break;
        !          5196:      case 0x040: BLTCON0 (value); break;
        !          5197:      case 0x042: BLTCON1 (value); break;
        !          5198: 
        !          5199:      case 0x044: BLTAFWM (value); break;
        !          5200:      case 0x046: BLTALWM (value); break;
        !          5201: 
        !          5202:      case 0x050: BLTAPTH (value); break;
        !          5203:      case 0x052: BLTAPTL (value); break;
        !          5204:      case 0x04C: BLTBPTH (value); break;
        !          5205:      case 0x04E: BLTBPTL (value); break;
        !          5206:      case 0x048: BLTCPTH (value); break;
        !          5207:      case 0x04A: BLTCPTL (value); break;
        !          5208:      case 0x054: BLTDPTH (value); break;
        !          5209:      case 0x056: BLTDPTL (value); break;
        !          5210: 
        !          5211:      case 0x058: BLTSIZE (value); break;
        !          5212: 
        !          5213:      case 0x064: BLTAMOD (value); break;
        !          5214:      case 0x062: BLTBMOD (value); break;
        !          5215:      case 0x060: BLTCMOD (value); break;
        !          5216:      case 0x066: BLTDMOD (value); break;
        !          5217: 
        !          5218:      case 0x070: BLTCDAT (value); break;
        !          5219:      case 0x072: BLTBDAT (value); break;
        !          5220:      case 0x074: BLTADAT (value); break;
        !          5221: 
        !          5222:      case 0x07E: DSKSYNC (value); break;
        !          5223: 
        !          5224:      case 0x080: COP1LCH (value); break;
        !          5225:      case 0x082: COP1LCL (value); break;
        !          5226:      case 0x084: COP2LCH (value); break;
        !          5227:      case 0x086: COP2LCL (value); break;
        !          5228: 
        !          5229:      case 0x088: COPJMP1 (value); break;
        !          5230:      case 0x08A: COPJMP2 (value); break;
        !          5231: 
        !          5232:      case 0x08E: DIWSTRT (value); break;
        !          5233:      case 0x090: DIWSTOP (value); break;
        !          5234:      case 0x092: DDFSTRT (value); break;
        !          5235:      case 0x094: DDFSTOP (value); break;
        !          5236: 
        !          5237:      case 0x096: DMACON (value); break;
        !          5238:      case 0x098: CLXCON (value); break;
        !          5239:      case 0x09A: INTENA (value); break;
        !          5240:      case 0x09C: INTREQ (value); break;
        !          5241:      case 0x09E: ADKCON (value); break;
        !          5242: 
        !          5243:      case 0x0A0: AUDxLCH (0, value); break;
        !          5244:      case 0x0A2: AUDxLCL (0, value); break;
        !          5245:      case 0x0A4: AUDxLEN (0, value); break;
        !          5246:      case 0x0A6: AUDxPER (0, value); break;
        !          5247:      case 0x0A8: AUDxVOL (0, value); break;
        !          5248:      case 0x0AA: AUDxDAT (0, value); break;
        !          5249: 
        !          5250:      case 0x0B0: AUDxLCH (1, value); break;
        !          5251:      case 0x0B2: AUDxLCL (1, value); break;
        !          5252:      case 0x0B4: AUDxLEN (1, value); break;
        !          5253:      case 0x0B6: AUDxPER (1, value); break;
        !          5254:      case 0x0B8: AUDxVOL (1, value); break;
        !          5255:      case 0x0BA: AUDxDAT (1, value); break;
        !          5256: 
        !          5257:      case 0x0C0: AUDxLCH (2, value); break;
        !          5258:      case 0x0C2: AUDxLCL (2, value); break;
        !          5259:      case 0x0C4: AUDxLEN (2, value); break;
        !          5260:      case 0x0C6: AUDxPER (2, value); break;
        !          5261:      case 0x0C8: AUDxVOL (2, value); break;
        !          5262:      case 0x0CA: AUDxDAT (2, value); break;
        !          5263: 
        !          5264:      case 0x0D0: AUDxLCH (3, value); break;
        !          5265:      case 0x0D2: AUDxLCL (3, value); break;
        !          5266:      case 0x0D4: AUDxLEN (3, value); break;
        !          5267:      case 0x0D6: AUDxPER (3, value); break;
        !          5268:      case 0x0D8: AUDxVOL (3, value); break;
        !          5269:      case 0x0DA: AUDxDAT (3, value); break;
        !          5270: 
        !          5271:      case 0x0E0: BPLPTH (value, 0); break;
        !          5272:      case 0x0E2: BPLPTL (value, 0); break;
        !          5273:      case 0x0E4: BPLPTH (value, 1); break;
        !          5274:      case 0x0E6: BPLPTL (value, 1); break;
        !          5275:      case 0x0E8: BPLPTH (value, 2); break;
        !          5276:      case 0x0EA: BPLPTL (value, 2); break;
        !          5277:      case 0x0EC: BPLPTH (value, 3); break;
        !          5278:      case 0x0EE: BPLPTL (value, 3); break;
        !          5279:      case 0x0F0: BPLPTH (value, 4); break;
        !          5280:      case 0x0F2: BPLPTL (value, 4); break;
        !          5281:      case 0x0F4: BPLPTH (value, 5); break;
        !          5282:      case 0x0F6: BPLPTL (value, 5); break;
        !          5283: 
        !          5284:      case 0x100: BPLCON0 (value); break;
        !          5285:      case 0x102: BPLCON1 (value); break;
        !          5286:      case 0x104: BPLCON2 (value); break;
        !          5287:      case 0x106: BPLCON3 (value); break;
        !          5288: 
        !          5289:      case 0x108: BPL1MOD (value); break;
        !          5290:      case 0x10A: BPL2MOD (value); break;
        !          5291: 
        !          5292:      case 0x110: BPL1DAT (value); break;
        !          5293:      case 0x112: BPL2DAT (value); break;
        !          5294:      case 0x114: BPL3DAT (value); break;
        !          5295:      case 0x116: BPL4DAT (value); break;
        !          5296:      case 0x118: BPL5DAT (value); break;
        !          5297:      case 0x11A: BPL6DAT (value); break;
1.1       root     5298: 
                   5299:      case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
                   5300:      case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
                   5301:      case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
                   5302:      case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
                   5303:      case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
1.1.1.2   root     5304:      case 0x1BC: case 0x1BE:
1.1.1.3 ! root     5305:        COLOR (value & 0xFFF, (addr & 0x3E) / 2);
1.1.1.2   root     5306:        break;
                   5307:      case 0x120: case 0x124: case 0x128: case 0x12C:
1.1       root     5308:      case 0x130: case 0x134: case 0x138: case 0x13C:
1.1.1.3 ! root     5309:        SPRxPTH (value, (addr - 0x120) / 4);
1.1       root     5310:        break;
1.1.1.2   root     5311:      case 0x122: case 0x126: case 0x12A: case 0x12E:
1.1       root     5312:      case 0x132: case 0x136: case 0x13A: case 0x13E:
1.1.1.3 ! root     5313:        SPRxPTL (value, (addr - 0x122) / 4);
1.1       root     5314:        break;
1.1.1.2   root     5315:      case 0x140: case 0x148: case 0x150: case 0x158:
1.1       root     5316:      case 0x160: case 0x168: case 0x170: case 0x178:
1.1.1.3 ! root     5317:        SPRxPOS (value, (addr - 0x140) / 8);
1.1       root     5318:        break;
1.1.1.2   root     5319:      case 0x142: case 0x14A: case 0x152: case 0x15A:
1.1       root     5320:      case 0x162: case 0x16A: case 0x172: case 0x17A:
1.1.1.3 ! root     5321:        SPRxCTL (value, (addr - 0x142) / 8);
1.1       root     5322:        break;
                   5323:      case 0x144: case 0x14C: case 0x154: case 0x15C:
                   5324:      case 0x164: case 0x16C: case 0x174: case 0x17C:
1.1.1.3 ! root     5325:        SPRxDATA (value, (addr - 0x144) / 8);
1.1       root     5326:        break;
1.1.1.2   root     5327:      case 0x146: case 0x14E: case 0x156: case 0x15E:
1.1       root     5328:      case 0x166: case 0x16E: case 0x176: case 0x17E:
1.1.1.3 ! root     5329:        SPRxDATB (value, (addr - 0x146) / 8);
1.1       root     5330:        break;
1.1.1.3 ! root     5331: 
        !          5332:      case 0x36: JOYTEST (value); break;
        !          5333: #if defined (ECS_AGNUS) || (AGA_CHIPSET == 1)
1.1       root     5334:      case 0x5A: BLTCON0L(value); break;
1.1.1.3 ! root     5335:      case 0x5C: BLTSIZV (value); break;
        !          5336:      case 0x5E: BLTSIZH (value); break;
1.1       root     5337: #endif
                   5338: #if AGA_CHIPSET == 1
1.1.1.3 ! root     5339:      case 0x10C: BPLCON4 (value); break;
1.1       root     5340:      case 0x1FC: fmode = value; break;
                   5341: #endif
                   5342:     }
                   5343: }
                   5344: 
1.1.1.3 ! root     5345: void REGPARAM2 custom_bput(uaecptr addr, uae_u32 value)
1.1       root     5346: {
1.1.1.2   root     5347:     static int warned = 0;
                   5348:     /* Is this correct now? (There are people who bput things to the upper byte of AUDxVOL). */
1.1.1.3 ! root     5349:     uae_u16 rval = (value << 8) | (value & 0xFF);
1.1.1.2   root     5350:     custom_wput(addr, rval);
                   5351:     if (!warned)
1.1.1.3 ! root     5352:        write_log ("Byte put to custom register.\n"), warned++;
1.1       root     5353: }
                   5354: 
1.1.1.3 ! root     5355: void REGPARAM2 custom_lput(uaecptr addr, uae_u32 value)
1.1       root     5356: {
                   5357:     custom_wput(addr & 0xfffe, value >> 16);
1.1.1.3 ! root     5358:     custom_wput((addr+2) & 0xfffe, (uae_u16)value);
1.1       root     5359: }

unix.superglobalmegacorp.com

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