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

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

unix.superglobalmegacorp.com

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