Annotation of uae/src/drawing.c, revision 1.1.1.1

1.1       root        1:  /*
                      2:   * UAE - The Un*x Amiga Emulator
                      3:   *
                      4:   * Screen drawing functions
                      5:   *
                      6:   * Copyright 1995-1998 Bernd Schmidt
                      7:   * Copyright 1995 Alessandro Bissacco
                      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 "threaddep/penguin.h"
                     19: #include "uae.h"
                     20: #include "memory.h"
                     21: #include "custom.h"
                     22: #include "readcpu.h"
                     23: #include "newcpu.h"
                     24: #include "xwin.h"
                     25: #include "autoconf.h"
                     26: #include "gui.h"
                     27: #include "picasso96.h"
                     28: #include "drawing.h"
                     29: #include "p2c.h"
                     30: 
                     31: #if defined X86_ASSEMBLY
                     32: #define LORES_HACK
                     33: #endif
                     34: 
                     35: int lores_factor, lores_shift, sprite_width;
                     36: 
                     37: static int interlace_seen = 0;
                     38: 
                     39: static int dblpf_ind1[256], dblpf_ind2[256], dblpf_2nd1[256], dblpf_2nd2[256];
                     40: static int dblpf_aga1[256], dblpf_aga2[256], linear_map_256[256], lots_of_twos[256];
                     41: 
                     42: static int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 };
                     43: 
                     44: /* Big lookup tables for planar to chunky conversion. */
                     45: 
                     46: uae_u32 hirestab_h[256][2];
                     47: uae_u32 lorestab_h[256][4];
                     48: 
                     49: uae_u32 hirestab_l[256][1];
                     50: uae_u32 lorestab_l[256][2];
                     51: 
                     52: static uae_u32 clxtab[256];
                     53: 
                     54: /* Video buffer description structure. Filled in by the graphics system
                     55:  * dependent code. */
                     56: 
                     57: struct vidbuf_description gfxvidinfo;
                     58: 
                     59: /* The color lookup table. */
                     60: 
                     61: xcolnr xcolors[4096];
                     62: 
                     63: struct color_entry colors_for_drawing;
                     64: 
                     65: /* 880 isn't a magic number, it's a safe number with some padding at the end.
                     66:  * This used to be 1000, but that's excessive. (840 is too low). I'm too lazy
                     67:  * to figure out the exact space needed. */
                     68: union {
                     69:     /* Let's try to align this thing. */
                     70:     double uupzuq;
                     71:     long int cruxmedo;
                     72:     unsigned char apixels[880];
                     73: } pixdata;
                     74: 
                     75: uae_u32 ham_linebuf[880];
                     76: uae_u32 aga_linebuf[880], *aga_lbufptr;
                     77: 
                     78: char *xlinebuffer;
                     79: 
                     80: static int *amiga2aspect_line_map, *native2amiga_line_map;
                     81: static char *row_map[2049];
                     82: static int max_drawn_amiga_line;
                     83: 
                     84: /* line_draw_funcs: pfield_do_linetoscr, pfield_do_fill_line, decode_ham6 */
                     85: typedef void (*line_draw_func)(int, int);
                     86: 
                     87: #define LINE_UNDECIDED 1
                     88: #define LINE_DECIDED 2
                     89: #define LINE_DECIDED_DOUBLE 3
                     90: #define LINE_AS_PREVIOUS 4
                     91: #define LINE_BORDER_NEXT 5
                     92: #define LINE_BORDER_PREV 6
                     93: #define LINE_DONE 7
                     94: #define LINE_DONE_AS_PREVIOUS 8
                     95: #define LINE_REMEMBERED_AS_PREVIOUS 9
                     96: 
                     97: static char *line_drawn;
                     98: static char linestate[(maxvpos + 1)*2 + 1];
                     99: 
                    100: uae_u8 line_data[(maxvpos+1) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2];
                    101: 
                    102: static int min_diwstart, max_diwstop, prev_x_adjust, linetoscr_x_adjust, linetoscr_right_x;
                    103: static int linetoscr_x_adjust_bytes;
                    104: static int thisframe_y_adjust, prev_y_adjust;
                    105: static int thisframe_y_adjust_real, max_ypos_thisframe, min_ypos_for_screen;
                    106: static int extra_y_adjust;
                    107: int thisframe_first_drawn_line, thisframe_last_drawn_line;
                    108: 
                    109: static int last_redraw_point;
                    110: 
                    111: static int first_drawn_line, last_drawn_line;
                    112: static int first_block_line, last_block_line;
                    113: 
                    114: /* These are generated by the drawing code from the line_decisions array for
                    115:  * each line that needs to be drawn. */
                    116: static int bplehb, bplham, bpldualpf, bpldualpfpri, bplplanecnt, bplhires;
                    117: static int bpldelay1, bpldelay2;
                    118: static int plfpri[3];
                    119: 
                    120: int picasso_requested_on;
                    121: int picasso_on;
                    122: 
                    123: uae_sem_t gui_sem;
                    124: int inhibit_frame;
                    125: 
                    126: int framecnt = 0;
                    127: static int frame_redraw_necessary;
                    128: static int picasso_redraw_necessary;
                    129: 
                    130: static __inline__ void count_frame (void)
                    131: {
                    132:     framecnt++;
                    133:     if (framecnt >= currprefs.framerate)
                    134:        framecnt = 0;
                    135: }
                    136: 
                    137: int coord_native_to_amiga_x (int x)
                    138: {
                    139:     x += linetoscr_x_adjust;
                    140:     x <<= (1 - lores_shift);
                    141:     return x + 2*DISPLAY_LEFT_SHIFT;
                    142: }
                    143: 
                    144: int coord_native_to_amiga_y (int y)
                    145: {
                    146:     return native2amiga_line_map[y] + thisframe_y_adjust - minfirstline;
                    147: }
                    148: 
                    149: void notice_screen_contents_lost (void)
                    150: {
                    151:     picasso_redraw_necessary = 1;
                    152:     frame_redraw_necessary = 2;
                    153: }
                    154: 
                    155: static struct decision *dp_for_drawing;
                    156: static struct draw_info *dip_for_drawing;
                    157: 
                    158: void record_diw_line (int first, int last)
                    159: {
                    160:     if (last > max_diwstop)
                    161:        max_diwstop = last;
                    162:     if (first < min_diwstart)
                    163:        min_diwstart = first;
                    164: }
                    165: 
                    166: /*
                    167:  * Screen update macros/functions
                    168:  */
                    169: 
                    170: static unsigned int ham_lastcolor;
                    171: 
                    172: static void init_ham_decoding(int first)
                    173: {
                    174:     int pix = dp_for_drawing->diwfirstword;
                    175:     ham_lastcolor = colors_for_drawing.color_regs[0];
                    176:     while (pix < first) {
                    177:        int pv = pixdata.apixels[pix];
                    178:        switch(pv & 0x30) {
                    179:         case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break;
                    180:         case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
                    181:         case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
                    182:         case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
                    183:        }
                    184:        pix++;
                    185:     }
                    186: }
                    187: 
                    188: static void decode_ham6 (int pix, int stoppos)
                    189: {
                    190:     uae_u32 *buf = ham_linebuf;
                    191: 
                    192:     if (!bplham || bplplanecnt != 6)
                    193:        return;
                    194: 
                    195:     if (stoppos > dp_for_drawing->diwlastword)
                    196:        stoppos = dp_for_drawing->diwlastword;
                    197:     if (pix < dp_for_drawing->diwfirstword) {
                    198:        ham_lastcolor = colors_for_drawing.color_regs[0];
                    199:        pix = dp_for_drawing->diwfirstword;
                    200:     }
                    201: #ifdef LORES_HACK
                    202:     if (currprefs.gfx_lores == 2)
                    203:        pix <<= 1, stoppos <<= 1;
                    204: #endif
                    205:     while (pix < stoppos) {
                    206:        int pv = pixdata.apixels[pix];
                    207:        switch(pv & 0x30) {
                    208:         case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break;
                    209:         case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
                    210:         case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
                    211:         case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
                    212:        }
                    213: 
                    214:        buf[pix++] = ham_lastcolor;
                    215:     }
                    216: }
                    217: #if 0
                    218: static void decode_ham_aga (int pix, int stoppos)
                    219: {
                    220:     static uae_u32 lastcolor;
                    221:     uae_u32 *buf = ham_linebuf;
                    222: 
                    223:     if (!bplham || (bplplanecnt != 6 && bplplanecnt != 8))
                    224:        return;
                    225: 
                    226:     if (pix <= dp_for_drawing->diwfirstword) {
                    227:        pix = dp_for_drawing->diwfirstword;
                    228:        lastcolor = colors_for_drawing.color_regs[0];
                    229:     }
                    230: 
                    231:     if (dp_for_drawing->bplplanecnt == 6) {
                    232:        /* HAM 6 */
                    233:        while (pix < dp_for_drawing->diwlastword && pix < stoppos) {
                    234:            int pv = pixdata.apixels[pix];
                    235:            switch(pv & 0x30) {
                    236:             case 0x00: lastcolor = colors_for_drawing.color_regs[pv]; break;
                    237:             case 0x10: lastcolor &= 0xFFFF00; lastcolor |= (pv & 0xF)*0x11; break;
                    238:             case 0x20: lastcolor &= 0x00FFFF; lastcolor |= (pv & 0xF)*0x11 << 16; break;
                    239:             case 0x30: lastcolor &= 0xFF00FF; lastcolor |= (pv & 0xF)*0x11 << 8; break;
                    240:            }
                    241:            buf[pix++] = lastcolor;
                    242:        }
                    243:     } else if (dp_for_drawing->bplplanecnt == 8) {
                    244:        /* HAM 8 */
                    245:        while (pix < dp_for_drawing->diwlastword && pix < stoppos) {
                    246:            int pv = pixdata.apixels[pix];
                    247:            switch(pv & 0x3) {
                    248:             case 0x0: lastcolor = colors_for_drawing.color_regs[pv >> 2]; break;
                    249:             case 0x1: lastcolor &= 0xFFFF03; lastcolor |= (pv & 0xFC); break;
                    250:             case 0x2: lastcolor &= 0x03FFFF; lastcolor |= (pv & 0xFC) << 16; break;
                    251:             case 0x3: lastcolor &= 0xFF03FF; lastcolor |= (pv & 0xFC) << 8; break;
                    252:            }
                    253:            buf[pix++] = lastcolor;
                    254:        }
                    255:     }
                    256: }
                    257: #endif
                    258: 
                    259: #if AGA_CHIPSET != 0
                    260: /* WARNING: Not too much of this will work correctly yet. */
                    261: 
                    262: static void pfield_linetoscr_aga(int pix, int stoppos)
                    263: {
                    264:     uae_u32 *buf = aga_lbufptr;
                    265:     int i;
                    266:     int xor = (uae_u8)(bplcon4 >> 8);
                    267:     int oldpix = pix; \
                    268: 
                    269:     buf -= pix; \
                    270: 
                    271:     for (i = 0; i < stoppos; i++)
                    272:        pixdata.apixels[i] ^= xor;
                    273: 
                    274:     while (pix < dp_for_drawing->diwfirstword && pix < stoppos) {
                    275:        buf[pix++] = colors_for_drawing.color_regs[0];
                    276:     }
                    277:     if (bplham) {
                    278:        while (pix < dp_for_drawing->diwlastword && pix < stoppos) {
                    279:            uae_u32 d = ham_linebuf[pix];
                    280:            buf[pix] = d;
                    281:            pix++;
                    282:        }
                    283:     } else if (bpldualpf) {
                    284:        /* Dual playfield */
                    285:        int *lookup = bpldualpfpri ? dblpf_aga2 : dblpf_aga1;
                    286:        int *lookup_no = bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1;
                    287:        while (pix < dp_for_drawing->diwlastword && pix < stoppos) {
                    288:            int pixcol = pixdata.apixels[pix];
                    289:            int pfno = lookup_no[pixcol];
                    290: 
                    291:            if (spixstate[pix]) {
                    292:                buf[pix] = colors_for_drawing.color_regs[pixcol];
                    293:            } else {
                    294:                int val = lookup[pixdata.apixels[pix]];
                    295:                if (pfno == 2)
                    296:                    val += dblpfofs[(bplcon2 >> 10) & 7];
                    297:                buf[pix] = colors_for_drawing.color_regs[val];
                    298:            }
                    299:            pix++;
                    300:        }
                    301:     } else if (bplehb) {
                    302:        while (pix < dp_for_drawing->diwlastword && pix < stoppos) {
                    303:            int pixcol = pixdata.apixels[pix];
                    304:            uae_u32 d = colors_for_drawing.color_regs[pixcol];
                    305:            /* What about sprites? */
                    306:            if (pixcol & 0x20)
                    307:                d = (d & 0x777777) >> 1;
                    308:            buf[pix] = d;
                    309:            pix++;
                    310:        }
                    311:     } else {
                    312:        while (pix < dp_for_drawing->diwlastword && pix < stoppos) {
                    313:            int pixcol = pixdata.apixels[pix];
                    314:            buf[pix] = colors_for_drawing.color_regs[pixcol];
                    315:            pix++;
                    316:        }
                    317:     }
                    318:     while (pix < stoppos) {
                    319:        buf[pix++] = colors_for_drawing.color_regs[0];
                    320:     }
                    321:     aga_lbufptr += pix - oldpix;
                    322: }
                    323: 
                    324: static void aga_translate32(int start, int stop)
                    325: {
                    326:     memcpy (((uae_u32 *)xlinebuffer) + start, aga_linebuf + start, 4*(stop-start));
                    327: }
                    328: 
                    329: static void aga_translate16(int start, int stop)
                    330: {
                    331:     int i;
                    332:     for (i = start; i < stop; i++) {
                    333:        uae_u32 d = aga_linebuf[i];
                    334:        uae_u16 v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12);
                    335:        ((uae_u16 *)xlinebuffer)[i] = xcolors[v];
                    336:     }
                    337: }
                    338: 
                    339: static void aga_translate8(int start, int stop)
                    340: {
                    341:     int i;
                    342:     for (i = start; i < stop; i++) {
                    343:        uae_u32 d = aga_linebuf[i];
                    344:        uae_u16 v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12);
                    345:        ((uae_u8 *)xlinebuffer)[i] = xcolors[v];
                    346:     }
                    347: }
                    348: #endif
                    349: 
                    350: static int linetoscr_double_offset;
                    351: 
                    352: #define LINE_TO_SCR(NAME, TYPE, DO_DOUBLE, CONVERT) \
                    353: static void NAME(int pix, int lframe_end, int diw_end, int stoppos) \
                    354: { \
                    355:     TYPE *buf = ((TYPE *)xlinebuffer); \
                    356: /*    int oldpix = pix;*/ \
                    357:     /* These are different for register-allocation purposes. */ \
                    358:     TYPE d1, d2; \
                    359:     int offset; \
                    360: \
                    361:     if (DO_DOUBLE) offset = linetoscr_double_offset / sizeof(TYPE); \
                    362: \
                    363:     d1 = CONVERT(colors_for_drawing.acolors[0]); \
                    364:     while (pix < lframe_end) { \
                    365:        buf[pix] = d1; if (DO_DOUBLE) buf[pix+offset] = d1; \
                    366:        pix++; \
                    367:     } \
                    368:     if (bplham && bplplanecnt == 6) { \
                    369:        /* HAM 6 */ \
                    370:        while (pix < diw_end) { \
                    371:            TYPE d = CONVERT(xcolors[ham_linebuf[pix]]); \
                    372:            buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
                    373:            pix++; \
                    374:        } \
                    375:     } else if (bpldualpf) { \
                    376:        /* Dual playfield */ \
                    377:        int *lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; \
                    378:        while (pix < diw_end) { \
                    379:            int pixcol = pixdata.apixels[pix]; \
                    380:            TYPE d; \
                    381:            d = CONVERT(colors_for_drawing.acolors[lookup[pixcol]]); \
                    382:            buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
                    383:            pix++; \
                    384:        } \
                    385:     } else if (bplehb) { \
                    386:        while (pix < diw_end) { \
                    387:            int p = pixdata.apixels[pix]; \
                    388:            TYPE d = CONVERT (colors_for_drawing.acolors[p]); \
                    389:            if (p >= 32) d = CONVERT(xcolors[(colors_for_drawing.color_regs[p-32] >> 1) & 0x777]); \
                    390:            buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
                    391:            pix++; \
                    392:        } \
                    393:     } else { \
                    394:        while (pix < diw_end) { \
                    395:            TYPE d = CONVERT (colors_for_drawing.acolors[pixdata.apixels[pix]]); \
                    396:            buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
                    397:            pix++; \
                    398:        } \
                    399:     } \
                    400:     d2 = CONVERT (colors_for_drawing.acolors[0]); \
                    401:     while (pix < stoppos) { \
                    402:        buf[pix] = d2; if (DO_DOUBLE) buf[pix+offset] = d2; \
                    403:        pix++; \
                    404:     } \
                    405: }
                    406: 
                    407: #define FILL_LINE(NAME, TYPE, CONVERT) \
                    408: static void NAME(char *buf, int start, int stop) \
                    409: { \
                    410:     TYPE *b = (TYPE *)buf; \
                    411:     int i;\
                    412:     xcolnr col = colors_for_drawing.acolors[0]; \
                    413:     for (i = start; i < stop; i++) \
                    414:        b[i] = CONVERT (col); \
                    415: }
                    416: 
                    417: LINE_TO_SCR(pfield_linetoscr_8, uae_u8, 0,)
                    418: LINE_TO_SCR(pfield_linetoscr_16, uae_u16, 0,)
                    419: LINE_TO_SCR(pfield_linetoscr_32, uae_u32, 0,)
                    420: LINE_TO_SCR(pfield_linetoscr_8_double_slow, uae_u8, 1,)
                    421: LINE_TO_SCR(pfield_linetoscr_16_double_slow, uae_u16, 1,)
                    422: LINE_TO_SCR(pfield_linetoscr_32_double_slow, uae_u32, 1,)
                    423: 
                    424: FILL_LINE(fill_line_8, uae_u8,)
                    425: FILL_LINE(fill_line_16, uae_u16,)
                    426: FILL_LINE(fill_line_32, uae_u32,)
                    427: 
                    428: #ifdef HAVE_UAE_U24
                    429: LINE_TO_SCR(pfield_linetoscr_24, uae_u24, 0, uae24_convert)
                    430: LINE_TO_SCR(pfield_linetoscr_24_double_slow, uae_u24, 1, uae24_convert)
                    431: FILL_LINE(fill_line_24, uae_u24, uae24_convert)
                    432: #else
                    433: /* Dummy versions */
                    434: static void pfield_linetoscr_24 (int pix, int lframe_end, int diw_end, int stoppos)
                    435: {
                    436: }
                    437: static void pfield_linetoscr_24_double_slow (int pix, int lframe_end, int diw_end, int stoppos)
                    438: {
                    439: }
                    440: static void fill_line_24 (char *buf, int start, int stop)
                    441: {
                    442: }
                    443: #endif
                    444: 
                    445: static __inline__ void fill_line_full (void)
                    446: {
                    447:     switch (gfxvidinfo.pixbytes) {
                    448:      case 1: fill_line_8(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
                    449:      case 2: fill_line_16(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
                    450:      case 3: fill_line_24(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
                    451:      case 4: fill_line_32(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
                    452:     }
                    453: }
                    454: 
                    455: #define fill_line fill_line_full
                    456: 
                    457: #define pfield_linetoscr_full8 pfield_linetoscr_8
                    458: #define pfield_linetoscr_full16 pfield_linetoscr_16
                    459: #define pfield_linetoscr_full24 pfield_linetoscr_24
                    460: #define pfield_linetoscr_full32 pfield_linetoscr_32
                    461: 
                    462: #define pfield_linetoscr_full8_double pfield_linetoscr_8_double_slow
                    463: #define pfield_linetoscr_full16_double pfield_linetoscr_16_double_slow
                    464: #define pfield_linetoscr_full24_double pfield_linetoscr_24_double_slow
                    465: #define pfield_linetoscr_full32_double pfield_linetoscr_32_double_slow
                    466: 
                    467: #if 1
                    468: #undef fill_line
                    469: static __inline__ void fill_line (void)
                    470: {
                    471:     int shift;
                    472:     int nints, nrem;
                    473:     int *start;
                    474:     xcolnr val;
                    475: 
                    476: #ifdef HAVE_UAE_U24
                    477:     if (gfxvidinfo.pixbytes == 3) {
                    478:        fill_line_24 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width);
                    479:        return;
                    480:     }
                    481: #endif
                    482:     
                    483:     shift = 0;
                    484:     if (gfxvidinfo.pixbytes == 2)
                    485:        shift = 1;
                    486:     if (gfxvidinfo.pixbytes == 4)
                    487:        shift = 2;
                    488: 
                    489:     nints = gfxvidinfo.width >> (2-shift);
                    490:     nrem = nints & 7;
                    491:     nints &= ~7;
                    492:     start = (int *)(((char *)xlinebuffer) + (linetoscr_x_adjust << shift));
                    493:     val = colors_for_drawing.acolors[0];
                    494:     for (; nints > 0; nints -= 8, start += 8) {
                    495:        *start = val;
                    496:        *(start+1) = val;
                    497:        *(start+2) = val;
                    498:        *(start+3) = val;
                    499:        *(start+4) = val;
                    500:        *(start+5) = val;
                    501:        *(start+6) = val;
                    502:        *(start+7) = val;
                    503:     }
                    504: 
                    505:     switch (nrem) {
                    506:      case 7:
                    507:        *start++ = val;
                    508:      case 6:
                    509:        *start++ = val;
                    510:      case 5:
                    511:        *start++ = val;
                    512:      case 4:
                    513:        *start++ = val;
                    514:      case 3:
                    515:        *start++ = val;
                    516:      case 2:
                    517:        *start++ = val;
                    518:      case 1:
                    519:        *start = val;
                    520:     }
                    521: }
                    522: 
                    523: #ifdef X86_ASSEMBLY
                    524: 
                    525: #undef pfield_linetoscr_full8
                    526: /* The types are lies, of course. */
                    527: extern void pfield_linetoscr_normal_asm8(void) __asm__("pfield_linetoscr_normal_asm8");
                    528: extern void pfield_linetoscr_ehb_asm8(void) __asm__("pfield_linetoscr_ehb_asm8");
                    529: extern void pfield_linetoscr_ham6_asm8(void) __asm__("pfield_linetoscr_ham6_asm8");
                    530: extern void pfield_linetoscr_dualpf_asm8(void) __asm__("pfield_linetoscr_dualpf_asm8");
                    531: extern void pfield_linetoscr_hdouble_asm8(void) __asm__("pfield_linetoscr_hdouble_asm8");
                    532: extern void pfield_linetoscr_hdouble_dpf_asm8(void) __asm__("pfield_linetoscr_hdouble_dpf_asm8");
                    533: extern void pfield_linetoscr_hdouble_ehb_asm8(void) __asm__("pfield_linetoscr_hdouble_ehb_asm8");
                    534: extern void pfield_linetoscr_asm8(void (*)(void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm8");
                    535: 
                    536: static void pfield_linetoscr_full8(int pix, int lframe_end, int diw_end, int stoppos)
                    537: {
                    538:     int lframe_end_1, diw_end_1;
                    539: 
                    540:     lframe_end_1 = pix + ((lframe_end - pix) & ~3);
                    541:     diw_end_1 = stoppos - ((stoppos - diw_end) & ~3);
                    542: 
                    543:     if (bplham && bplplanecnt == 6) {
                    544:        pfield_linetoscr_asm8(pfield_linetoscr_ham6_asm8, pix, lframe_end_1, diw_end_1, stoppos);
                    545:     } else if (bpldualpf) {
                    546: #ifdef LORES_HACK
                    547:        if (currprefs.gfx_lores == 2)
                    548:            pfield_linetoscr_asm8(pfield_linetoscr_hdouble_dpf_asm8, pix, lframe_end_1, diw_end_1, stoppos,
                    549:                                   bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
                    550:        else
                    551: #endif
                    552:            pfield_linetoscr_asm8(pfield_linetoscr_dualpf_asm8, pix, lframe_end_1, diw_end_1, stoppos,
                    553:                                  bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
                    554:     } else if (bplehb) {
                    555: #ifdef LORES_HACK
                    556:        if (currprefs.gfx_lores == 2)
                    557:            pfield_linetoscr_asm8(pfield_linetoscr_hdouble_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos);
                    558:        else
                    559: #endif
                    560:            pfield_linetoscr_asm8(pfield_linetoscr_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos);
                    561:     } else {
                    562: #ifdef LORES_HACK
                    563:        if (currprefs.gfx_lores == 2)
                    564:            pfield_linetoscr_asm8(pfield_linetoscr_hdouble_asm8, pix, lframe_end_1, diw_end_1, stoppos);
                    565:        else
                    566: #endif
                    567:            pfield_linetoscr_asm8(pfield_linetoscr_normal_asm8, pix, lframe_end_1, diw_end_1, stoppos);
                    568:     }
                    569: 
                    570:     /* The assembly functions work on aligned data, so we may have to do some
                    571:      * additional work at the edges. */
                    572:     if (lframe_end != lframe_end_1) {
                    573:        int i, c = colors_for_drawing.acolors[0];
                    574:        for (i = lframe_end_1; i < lframe_end; i++)
                    575:            xlinebuffer[i] = c;
                    576:     }
                    577:     if (diw_end != diw_end_1) {
                    578:        int i, c = colors_for_drawing.acolors[0];
                    579:        for (i = diw_end; i < diw_end_1; i++)
                    580:            xlinebuffer[i] = c;
                    581:     }
                    582: }
                    583: 
                    584: #undef pfield_linetoscr_full16
                    585: extern void pfield_linetoscr_normal_asm16(void) __asm__("pfield_linetoscr_normal_asm16");
                    586: extern void pfield_linetoscr_ehb_asm16(void) __asm__("pfield_linetoscr_ehb_asm16");
                    587: extern void pfield_linetoscr_ham6_asm16(void) __asm__("pfield_linetoscr_ham6_asm16");
                    588: extern void pfield_linetoscr_dualpf_asm16(void) __asm__("pfield_linetoscr_dualpf_asm16");
                    589: extern void pfield_linetoscr_hdouble_asm16(void) __asm__("pfield_linetoscr_hdouble_asm16");
                    590: extern void pfield_linetoscr_hdouble_dpf_asm16(void) __asm__("pfield_linetoscr_hdouble_dpf_asm16");
                    591: extern void pfield_linetoscr_hdouble_ehb_asm16(void) __asm__("pfield_linetoscr_hdouble_ehb_asm16");
                    592: extern void pfield_linetoscr_asm16(void (*)(void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm16");
                    593: 
                    594: static void pfield_linetoscr_full16(int pix, int lframe_end, int diw_end, int stoppos)
                    595: {
                    596:     int lframe_end_1, diw_end_1;
                    597: 
                    598:     lframe_end_1 = pix + ((lframe_end - pix) & ~3);
                    599:     diw_end_1 = stoppos - ((stoppos - diw_end) & ~3);
                    600: 
                    601:     if (bplham && bplplanecnt == 6) {
                    602:        pfield_linetoscr_asm16(pfield_linetoscr_ham6_asm16, pix, lframe_end_1, diw_end_1, stoppos);
                    603:     } else if (bpldualpf) {
                    604: #ifdef LORES_HACK
                    605:        if (currprefs.gfx_lores == 2)
                    606:            pfield_linetoscr_asm16(pfield_linetoscr_hdouble_dpf_asm16, pix, lframe_end_1, diw_end_1, stoppos,
                    607:                                   bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
                    608:        else
                    609: #endif
                    610:            pfield_linetoscr_asm16(pfield_linetoscr_dualpf_asm16, pix, lframe_end_1, diw_end_1, stoppos,
                    611:                                   bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
                    612:     } else if (bplehb) {
                    613: #ifdef LORES_HACK
                    614:        if (currprefs.gfx_lores == 2)
                    615:            pfield_linetoscr_asm16(pfield_linetoscr_hdouble_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos);
                    616:        else
                    617: #endif
                    618:            pfield_linetoscr_asm16(pfield_linetoscr_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos);
                    619:     } else {
                    620: #ifdef LORES_HACK
                    621:        if (currprefs.gfx_lores == 2)
                    622:            pfield_linetoscr_asm16(pfield_linetoscr_hdouble_asm16, pix, lframe_end_1, diw_end_1, stoppos);
                    623:        else
                    624: #endif
                    625:            pfield_linetoscr_asm16(pfield_linetoscr_normal_asm16, pix, lframe_end_1, diw_end_1, stoppos);
                    626:     }
                    627: 
                    628:     /* The assembly functions work on aligned data, so we may have to do some
                    629:      * additional work at the edges. */
                    630:     if (lframe_end != lframe_end_1) {
                    631:        int i, c = colors_for_drawing.acolors[0];
                    632:        for (i = lframe_end_1; i < lframe_end; i++)
                    633:            ((uae_u16 *)xlinebuffer)[i] = c;
                    634:     }
                    635:     if (diw_end != diw_end_1) {
                    636:        int i, c = colors_for_drawing.acolors[0];
                    637:        for (i = diw_end; i < diw_end_1; i++)
                    638:            ((uae_u16 *)xlinebuffer)[i] = c;
                    639:     }
                    640: }
                    641: #endif
                    642: 
                    643: #ifndef NO_DOUBLING_LINETOSCR
                    644: #define NO_DOUBLING_LINETOSCR
                    645: #endif
                    646: 
                    647: #endif
                    648: 
                    649: #ifdef NO_DOUBLING_LINETOSCR
                    650: #undef pfield_linetoscr_full8_double
                    651: #undef pfield_linetoscr_full16_double
                    652: static void pfield_linetoscr_full8_double(int start, int lframe_end, int diw_end, int stop)
                    653: {
                    654:     char *oldxlb = (char *)xlinebuffer;
                    655:     pfield_linetoscr_full8(start, lframe_end, diw_end, stop);
                    656:     xlinebuffer = oldxlb + linetoscr_double_offset;
                    657:     pfield_linetoscr_full8(start, lframe_end, diw_end, stop);
                    658: }
                    659: static void pfield_linetoscr_full16_double(int start, int lframe_end, int diw_end, int stop)
                    660: {
                    661:     char *oldxlb = (char *)xlinebuffer;
                    662:     pfield_linetoscr_full16(start, lframe_end, diw_end, stop);
                    663:     xlinebuffer = oldxlb + linetoscr_double_offset;
                    664:     pfield_linetoscr_full16(start, lframe_end, diw_end, stop);
                    665: }
                    666: #endif
                    667: 
                    668: static int linetoscr_diw_end, linetoscr_diw_start;
                    669: 
                    670: /* Initialize the variables necessary for drawing a line.
                    671:  * This involves setting up start/stop positions and display window
                    672:  * borders. Also, since the drawing code may not fully overwrite all
                    673:  * releveant areas in the pixdata.apixels array for speed reasons, parts of
                    674:  * it must possibly be cleared here. */
                    675: static void pfield_init_linetoscr (void)
                    676: {
                    677:     int ddf_left, ddf_right;
                    678:     int mindelay = bpldelay1, maxdelay = bpldelay2;
                    679:     if (bpldelay1 > bpldelay2)
                    680:        maxdelay = bpldelay1, mindelay = bpldelay2;
                    681: 
                    682:     linetoscr_diw_start = dp_for_drawing->diwfirstword;
                    683:     linetoscr_diw_end = dp_for_drawing->diwlastword;
                    684: 
                    685:     /* We should really look at DDF also when calculating max_diwstop/min_diwstrt,
                    686:      * so that centering works better, but I'm afraid that might cost too many
                    687:      * cycles. Plus it's dangerous, see the code below that handles the case
                    688:      * with sprites. */
                    689:     if (dip_for_drawing->nr_sprites == 0) {
                    690:        int hiresadjust = bplhires ? 4 : 8;
                    691:        ddf_left = ((dp_for_drawing->plfstrt + hiresadjust)*2 + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift;
                    692:        ddf_right = ((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2 + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift;
                    693: 
                    694:        if (linetoscr_diw_start < ddf_left)
                    695:            linetoscr_diw_start = ddf_left;
                    696:        if (linetoscr_diw_end > ddf_right)
                    697:            linetoscr_diw_end = ddf_right;
                    698: 
                    699:        if (mindelay != maxdelay) {
                    700:            /* Raahh...
                    701:             * We just clear the maximum amount of space that may need to be
                    702:             * cleared. We could do this exactly, but it would come out slower
                    703:             * because of the overhead. */
                    704:            if (currprefs.gfx_lores == 2) {
                    705:                fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_left>>1), 15);
                    706:                fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_right>>1) - 15, 15);
                    707:            } else if (currprefs.gfx_lores) {
                    708:                fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 15);
                    709:                fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 15, 15);
                    710:            } else {
                    711:                fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 30);
                    712:                fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 30, 30);
                    713:            }
                    714:        }
                    715:     } else {
                    716:        int hiresadjust = bplhires ? 4 : 8;
                    717:        /* We swap mindelay and maxdelay here to get rid of the mindelay != maxdelay check.
                    718:         * Since we have to do a memset anyway (because there may be sprites),
                    719:         * we might as well clear all at once. */
                    720:        ddf_left = ((dp_for_drawing->plfstrt + hiresadjust)*2 + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift;
                    721:        ddf_right = ((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2 + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift;
                    722:        if (linetoscr_diw_start < ddf_left) {
                    723:            int strt = linetoscr_diw_start;
                    724:            int stop = ddf_left;
                    725: #ifdef LORES_HACK
                    726:            if (currprefs.gfx_lores == 2)
                    727:                strt >>= 1, stop >>= 1;
                    728: #endif
                    729:            if (strt < stop)
                    730:                fuzzy_memset (pixdata.apixels, 0, strt, stop - strt);
                    731:        }
                    732: 
                    733:        if (linetoscr_diw_end > ddf_right) {
                    734:            int strt = ddf_right;
                    735:            int stop = linetoscr_diw_end;
                    736: #ifdef LORES_HACK
                    737:            if (currprefs.gfx_lores == 2)
                    738:                strt >>= 1, stop >>= 1;
                    739: #endif
                    740:            if (strt < stop)
                    741:                fuzzy_memset (pixdata.apixels, 0, strt, stop - strt);
                    742:        }
                    743:     }
                    744:     /* Perverse cases happen. */
                    745:     if (linetoscr_diw_end < linetoscr_diw_start)
                    746:        linetoscr_diw_end = linetoscr_diw_start;
                    747: }
                    748: 
                    749: static void pfield_do_linetoscr(int start, int stop)
                    750: {
                    751:     int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end;
                    752: 
                    753:     if (stop > linetoscr_right_x)
                    754:        stop = linetoscr_right_x;
                    755:     if (start < linetoscr_x_adjust)
                    756:        start = linetoscr_x_adjust;
                    757: 
                    758:     if (lframe_end < start)
                    759:        lframe_end = start;
                    760:     if (diw_end > stop)
                    761:        diw_end = stop;
                    762: 
                    763:     if (start >= stop)
                    764:        return;
                    765: 
                    766: #if AGA_CHIPSET == 0
                    767:     if (start == linetoscr_x_adjust && stop == linetoscr_right_x) {
                    768:        switch (gfxvidinfo.pixbytes) {
                    769:         case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break;
                    770:         case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break;
                    771:         case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break;
                    772:         case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break;
                    773:        }
                    774:     } else {
                    775:        switch (gfxvidinfo.pixbytes) {
                    776:         case 1: pfield_linetoscr_8 (start, lframe_end, diw_end, stop); break;
                    777:         case 2: pfield_linetoscr_16 (start, lframe_end, diw_end, stop); break;
                    778:         case 3: pfield_linetoscr_24 (start, lframe_end, diw_end, stop); break;
                    779:         case 4: pfield_linetoscr_32 (start, lframe_end, diw_end, stop); break;
                    780:        }
                    781:     }
                    782: #else
                    783:     pfield_linetoscr_aga(start, lframe_end, diw_end, stop);
                    784: #endif
                    785: }
                    786: 
                    787: static void pfield_do_fill_line(int start, int stop)
                    788: {
                    789:     if (stop > linetoscr_right_x)
                    790:        stop = linetoscr_right_x;
                    791:     if (start < linetoscr_x_adjust)
                    792:        start = linetoscr_x_adjust;
                    793: 
                    794:     if (start >= stop)
                    795:        return;
                    796: 
                    797:     switch (gfxvidinfo.pixbytes) {
                    798:      case 1: fill_line_8 (xlinebuffer, start, stop); break;
                    799:      case 2: fill_line_16 (xlinebuffer, start, stop); break;
                    800:      case 3: fill_line_24 (xlinebuffer, start, stop); break;
                    801:      case 4: fill_line_32 (xlinebuffer, start, stop); break;
                    802:     }
                    803: }
                    804: 
                    805: static void pfield_do_linetoscr_full(int double_line)
                    806: {
                    807:     int start = linetoscr_x_adjust, stop = start + gfxvidinfo.width;
                    808:     int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end;
                    809:     if (lframe_end < start)
                    810:        lframe_end = start;
                    811:     if (diw_end > stop)
                    812:        diw_end = stop;
                    813: 
                    814: #if AGA_CHIPSET == 0
                    815:     if (double_line) {
                    816:        switch (gfxvidinfo.pixbytes) {
                    817:         case 1: pfield_linetoscr_full8_double (start, lframe_end, diw_end, stop); break;
                    818:         case 2: pfield_linetoscr_full16_double (start, lframe_end, diw_end, stop); break;
                    819:         case 3: pfield_linetoscr_full24_double (start, lframe_end, diw_end, stop); break;
                    820:         case 4: pfield_linetoscr_full32_double (start, lframe_end, diw_end, stop); break;
                    821:        }
                    822:     } else
                    823:        switch (gfxvidinfo.pixbytes) {
                    824:         case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break;
                    825:         case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break;
                    826:         case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break;
                    827:         case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break;
                    828:        }
                    829: #else
                    830:     pfield_linetoscr_aga(start, lframe_end, diw_end, stop);
                    831: #endif
                    832: }
                    833: 
                    834: static void gen_pfield_tables(void)
                    835: {
                    836:     int i;
                    837:     union {
                    838:        struct {
                    839:            uae_u8 a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p;
                    840:        } foo;
                    841:        struct {
                    842:            uae_u32 a, b, c, d;
                    843:        } bar;
                    844:     } baz;
                    845: 
                    846:     /* For now, the AGA stuff is broken in the dual playfield case. We encode
                    847:      * sprites in dpf mode by ORing the pixel value with 0x80. To make dual
                    848:      * playfield rendering easy, the lookup tables contain are made linear for
                    849:      * values >= 128. That only works for OCS/ECS, though. */
                    850: 
                    851:     for (i = 0; i < 256; i++) {
                    852:        int plane1 = (i & 1) | ((i >> 1) & 2) | ((i >> 2) & 4) | ((i >> 3) & 8);
                    853:        int plane2 = ((i >> 1) & 1) | ((i >> 2) & 2) | ((i >> 3) & 4) | ((i >> 4) & 8);
                    854:        dblpf_2nd1[i] = plane1 == 0 ? (plane2 == 0 ? 0 : 2) : 1;
                    855:        dblpf_2nd2[i] = plane2 == 0 ? (plane1 == 0 ? 0 : 1) : 2;
                    856:        if (plane2 > 0)
                    857:            plane2 += 8;
                    858:        dblpf_ind1[i] = i >= 128 ? i & 0x7F : (plane1 == 0 ? plane2 : plane1);
                    859:        dblpf_ind2[i] = i >= 128 ? i & 0x7F : (plane2 == 0 ? plane1 : plane2);
                    860: 
                    861:        lots_of_twos[i] = i == 0 ? 0 : 2;
                    862:        linear_map_256[i] = i;
                    863:     }
                    864: 
                    865:     for (i = 0; i < 256; i++) {
                    866:        /* We lose every second pixel in HiRes if UAE runs in a 320x200 screen. */
                    867:        baz.foo.a = i & 64 ? 1 : 0;
                    868:        baz.foo.b = i & 16 ? 1 : 0;
                    869:        baz.foo.c = i & 4 ? 1 : 0;
                    870:        baz.foo.d = i & 1 ? 1 : 0;
                    871:        hirestab_l[i][0] = baz.bar.a;
                    872: 
                    873:        baz.foo.a = i & 128 ? 1 : 0;
                    874:        baz.foo.b = i & 64 ? 1 : 0;
                    875:        baz.foo.c = i & 32 ? 1 : 0;
                    876:        baz.foo.d = i & 16 ? 1 : 0;
                    877:        baz.foo.e = i & 8 ? 1 : 0;
                    878:        baz.foo.f = i & 4 ? 1 : 0;
                    879:        baz.foo.g = i & 2 ? 1 : 0;
                    880:        baz.foo.h = i & 1 ? 1 : 0;
                    881:        lorestab_l[i][0] = baz.bar.a;
                    882:        lorestab_l[i][1] = baz.bar.b;
                    883:        clxtab[i] = ((((i & 3) && (i & 12)) << 9)
                    884:                     | (((i & 3) && (i & 48)) << 10)
                    885:                     | (((i & 3) && (i & 192)) << 11)
                    886:                     | (((i & 12) && (i & 48)) << 12)
                    887:                     | (((i & 12) && (i & 192)) << 13)
                    888:                     | (((i & 48) && (i & 192)) << 14));
                    889:     }
                    890: 
                    891:     for (i = 0; i < 256; i++) {
                    892:        baz.foo.a = i & 128 ? 1 : 0;
                    893:        baz.foo.b = i & 64 ? 1 : 0;
                    894:        baz.foo.c = i & 32 ? 1 : 0;
                    895:        baz.foo.d = i & 16 ? 1 : 0;
                    896:        baz.foo.e = i & 8 ? 1 : 0;
                    897:        baz.foo.f = i & 4 ? 1 : 0;
                    898:        baz.foo.g = i & 2 ? 1 : 0;
                    899:        baz.foo.h = i & 1 ? 1 : 0;
                    900:        hirestab_h[i][0] = baz.bar.a;
                    901:        hirestab_h[i][1] = baz.bar.b;
                    902: 
                    903:        baz.foo.a = i & 128 ? 1 : 0;
                    904:        baz.foo.b = i & 128 ? 1 : 0;
                    905:        baz.foo.c = i & 64 ? 1 : 0;
                    906:        baz.foo.d = i & 64 ? 1 : 0;
                    907:        baz.foo.e = i & 32 ? 1 : 0;
                    908:        baz.foo.f = i & 32 ? 1 : 0;
                    909:        baz.foo.g = i & 16 ? 1 : 0;
                    910:        baz.foo.h = i & 16 ? 1 : 0;
                    911:        baz.foo.i = i & 8 ? 1 : 0;
                    912:        baz.foo.j = i & 8 ? 1 : 0;
                    913:        baz.foo.k = i & 4 ? 1 : 0;
                    914:        baz.foo.l = i & 4 ? 1 : 0;
                    915:        baz.foo.m = i & 2 ? 1 : 0;
                    916:        baz.foo.n = i & 2 ? 1 : 0;
                    917:        baz.foo.o = i & 1 ? 1 : 0;
                    918:        baz.foo.p = i & 1 ? 1 : 0;
                    919:        lorestab_h[i][0] = baz.bar.a;
                    920:        lorestab_h[i][1] = baz.bar.b;
                    921:        lorestab_h[i][2] = baz.bar.c;
                    922:        lorestab_h[i][3] = baz.bar.d;
                    923:     }
                    924: }
                    925: 
                    926: static uae_u32 attach_2nd;
                    927: 
                    928: static uae_u32 do_sprite_collisions (struct sprite_draw *spd, int prev_overlap, int i, int nr_spr)
                    929: {
                    930:     int j;
                    931:     int sprxp = spd[i].linepos;
                    932:     uae_u32 datab = spd[i].datab;
                    933:     uae_u32 mask2 = 0;
                    934:     int sbit = 1 << spd[i].num;
                    935:     int sprx_shift = 1;
                    936:     int attach_compare = -1;
                    937:     if (currprefs.gfx_lores != 1)
                    938:        sprx_shift = 0;
                    939: 
                    940:     attach_2nd = 0;
                    941:     if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80)
                    942:        attach_compare = spd[i].num - 1;
                    943: 
                    944:     for (j = prev_overlap; j < i; j++) {
                    945:        uae_u32 mask1;
                    946:        int off;
                    947: 
                    948:        if (spd[i].num < spd[j].num)
                    949:            continue;
                    950: 
                    951:        off = sprxp - spd[j].linepos;
                    952:        off <<= sprx_shift;
                    953:        mask1 = spd[j].datab >> off;
                    954: 
                    955:        /* If j is an attachment for i, then j doesn't block i */
                    956:        if (spd[j].num == attach_compare) {
                    957:            attach_2nd |= mask1;
                    958:        } else {
                    959:            mask1 |= (mask1 & 0xAAAAAAAA) >> 1;
                    960:            mask1 |= (mask1 & 0x55555555) << 1;
                    961:            if (datab & mask1)
                    962:                clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask];
                    963:            mask2 |= mask1;
                    964:        }
                    965:     }
                    966:     for (j = i+1; j < nr_spr; j++) {
                    967:        uae_u32 mask1;
                    968:        int off = spd[j].linepos - sprxp;
                    969: 
                    970:        if (off >= sprite_width || spd[i].num < spd[j].num)
                    971:            break;
                    972: 
                    973:        off <<= sprx_shift;
                    974:        mask1 = spd[j].datab << off;
                    975: 
                    976:        /* If j is an attachment for i, then j doesn't block i */
                    977:        if (spd[j].num == attach_compare) {
                    978:            attach_2nd |= mask1;
                    979:        } else {
                    980:            mask1 |= (mask1 & 0xAAAAAAAA) >> 1;
                    981:            mask1 |= (mask1 & 0x55555555) << 1;
                    982:            if (datab & mask1)
                    983:                clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask];
                    984:            mask2 |= mask1;
                    985:        }
                    986:     }
                    987:     datab &= ~mask2;
                    988:     return datab;
                    989: }
                    990: 
                    991: static __inline__ void render_sprite (int spr, int sprxp, uae_u32 datab, int ham, int attch, int sprx_inc)
                    992: {
                    993:     uae_u32 datcd;
                    994:     int basecol = 16;
                    995:     if (!attch)
                    996:        basecol += (spr & ~1)*2;
                    997:     if (bpldualpf)
                    998:        basecol |= 128;
                    999:     if (attch)
                   1000:        datcd = attach_2nd;
                   1001: 
                   1002:     for(; attch ? datab | datcd : datab; sprxp += sprx_inc) {
                   1003:        int col;
                   1004: 
                   1005:        if (attch) {
                   1006:            col = ((datab & 3) << 2) | (datcd & 3);
                   1007:            datcd >>= 2;
                   1008:        } else
                   1009:            col = datab & 3;
                   1010:        datab >>= 2;
                   1011:        if (col) {
                   1012:            col |= basecol;
                   1013:            if (ham) {
                   1014:                col = colors_for_drawing.color_regs[col];
                   1015:                ham_linebuf[sprxp] = col;
                   1016:                if (sprx_inc == 2) {
                   1017:                    ham_linebuf[sprxp+1] = col;
                   1018:                }
                   1019:            } else {
                   1020:                pixdata.apixels[sprxp] = col;
                   1021:                if (sprx_inc == 2) {
                   1022:                    pixdata.apixels[sprxp+1] = col;
                   1023:                }
                   1024:            }
                   1025:        }
                   1026:     }
                   1027: }
                   1028: 
                   1029: static void walk_sprites (struct sprite_draw *spd, int nr_spr)
                   1030: {
                   1031:     int i, prev_overlap;
                   1032:     int last_sprite_pos = -64;
                   1033:     uae_u32 plane1 = 0, plane2 = 0;
                   1034:     int sprx_inc = 1, sprx_shift = 1;
                   1035: 
                   1036:     if (currprefs.gfx_lores == 0)
                   1037:        sprx_inc = 2, sprx_shift = 0;
                   1038: 
                   1039:     prev_overlap = 0;
                   1040:     for (i = 0; i < nr_spr; i++) {
                   1041:        int sprxp = spd[i].linepos;
                   1042:        int m = 1 << spd[i].num;
                   1043:        uae_u32 datab;
                   1044:        while (prev_overlap < i && spd[prev_overlap].linepos + sprite_width <= sprxp)
                   1045:            prev_overlap++;
                   1046: 
                   1047:        datab = do_sprite_collisions (spd, prev_overlap, i, nr_spr);
                   1048: #ifdef LORES_HACK
                   1049:        if (currprefs.gfx_lores == 2)
                   1050:            sprxp >>= 1;
                   1051: #endif
                   1052:        if ((bpldualpf && plfpri[1] < 256) || (plfpri[2] < 256)) {
                   1053:            if (sprxp != last_sprite_pos) {
                   1054:                int ok = last_sprite_pos-sprxp+16;
                   1055:                int ok2;
                   1056:                if (ok <= 0) {
                   1057:                    ok = ok2 = 0;
                   1058:                    plane1 = 0;
                   1059:                    plane2 = 0;
                   1060:                } else {
                   1061:                    ok2 = ok << sprx_shift;
                   1062:                    plane1 >>= 32 - ok2;
                   1063:                    plane2 >>= 32 - ok2;
                   1064:                }
                   1065:                last_sprite_pos = sprxp;
                   1066: 
                   1067:                if (bpldualpf) {
                   1068:                    uae_u32 mask = 3 << ok2;
                   1069:                    int p = sprxp+ok;
                   1070: 
                   1071:                    for (; mask; mask <<= 2, p += sprx_inc) {
                   1072:                        int data = pixdata.apixels[p];
                   1073:                        if (dblpf_2nd2[data] == 2)
                   1074:                            plane2 |= mask;
                   1075:                        if (dblpf_2nd1[data] == 1)
                   1076:                            plane1 |= mask;
                   1077:                    }
                   1078:                } else {
                   1079:                    uae_u32 mask = 3 << ok2;
                   1080:                    int p = sprxp+ok;
                   1081: 
                   1082:                    for (; mask; mask <<= 2, p += sprx_inc) {
                   1083:                        if (pixdata.apixels[p])
                   1084:                            plane2 |= mask;
                   1085:                    }
                   1086:                }
                   1087:            }
                   1088:            if (bpldualpf && m >= plfpri[1]) {
                   1089:                datab &= ~plane1;
                   1090:                attach_2nd &= ~plane1;
                   1091:            }
                   1092:            if (m >= plfpri[2]) {
                   1093:                datab &= ~plane2;
                   1094:                attach_2nd &= ~plane2;
                   1095:            }
                   1096:        }
                   1097:        if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80) {
                   1098:            /* Attached sprite */
                   1099:            if (bplham) {
                   1100:                if (sprx_inc == 1) {
                   1101:                    render_sprite (spd[i].num, sprxp, datab, 1, 1, 1);
                   1102:                } else {
                   1103:                    render_sprite (spd[i].num, sprxp, datab, 1, 1, 2);
                   1104:                }
                   1105:            } else {
                   1106:                if (sprx_inc == 1) {
                   1107:                    render_sprite (spd[i].num, sprxp, datab, 0, 1, 1);
                   1108:                } else {
                   1109:                    render_sprite (spd[i].num, sprxp, datab, 0, 1, 2);
                   1110:                }
                   1111:            }
                   1112:            /* This still leaves one attached sprite bug, but at the moment I'm too lazy */
                   1113:            if (i + 1 < nr_spr && spd[i+1].num == spd[i].num - 1 && spd[i+1].linepos == spd[i].linepos)
                   1114:                i++;
                   1115:        } else {
                   1116:            if (bplham) {
                   1117:                if (sprx_inc == 1) {
                   1118:                    render_sprite (spd[i].num, sprxp, datab, 1, 0, 1);
                   1119:                } else {
                   1120:                    render_sprite (spd[i].num, sprxp, datab, 1, 0, 2);
                   1121:                }
                   1122:            } else {
                   1123:                if (sprx_inc == 1) {
                   1124:                    render_sprite (spd[i].num, sprxp, datab, 0, 0, 1);
                   1125:                } else {
                   1126:                    render_sprite (spd[i].num, sprxp, datab, 0, 0, 2);
                   1127:                }
                   1128:            }
                   1129:        }
                   1130:     }
                   1131: }
                   1132: 
                   1133: #ifndef SMART_UPDATE
                   1134: #undef UNALIGNED_PROFITABLE
                   1135: #endif
                   1136: 
                   1137: #ifdef UNALIGNED_PROFITABLE
                   1138: 
                   1139: static void pfield_doline_unaligned_h (int lineno)
                   1140: {
                   1141:     int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2;
                   1142: 
                   1143:     if (bplhires) {
                   1144:        int xpos1 = xpos + 16 + bpldelay1*2;
                   1145:        int xpos2;
                   1146:        uae_u8 *dataptr = line_data[lineno];
                   1147:        int len = dp_for_drawing->plflinelen >> 1;
                   1148: 
                   1149:        if (len <= 0)
                   1150:            return;
                   1151: 
                   1152:        if (bpldelay1 == bpldelay2) {
                   1153:            switch (bplplanecnt) {
                   1154:             case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1155:             case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1156:             case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1157:             case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1158:             case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1159:             case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1160:             case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1161:             case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1162:            }
                   1163:        } else {
                   1164:            switch (bplplanecnt) {
                   1165:             case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1166:             case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1167:             case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1168:             case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1169:            }
                   1170: 
                   1171:            xpos2 = xpos + 16 + bpldelay2*2;
                   1172:            switch (bplplanecnt) {
                   1173:             case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1174:             case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1175:             case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1176:             case 8:         set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1177:            }
                   1178:        }
                   1179:     } else {
                   1180:        int xpos1 = xpos + 32 + bpldelay1*2;
                   1181:        int xpos2;
                   1182:        uae_u8 *dataptr = line_data[lineno];
                   1183:        int len = dp_for_drawing->plflinelen >> 2;
                   1184: 
                   1185:        if (len <= 0)
                   1186:            return;
                   1187: 
                   1188:        if (bpldelay1 == bpldelay2) {
                   1189:            switch (bplplanecnt) {
                   1190:             case 1: set_lores_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1191:             case 2: set_lores_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1192:             case 3: set_lores_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1193:             case 4: set_lores_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1194:             case 5: set_lores_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1195:             case 6: set_lores_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1196:             case 7: set_lores_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1197:             case 8: set_lores_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1198:            }
                   1199:        } else {
                   1200:            switch (bplplanecnt) {
                   1201:             case 1: case 2: set_lores_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1202:             case 3: case 4: set_lores_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1203:             case 5: case 6: set_lores_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1204:             case 7: case 8: set_lores_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1205:            }
                   1206: 
                   1207:            xpos2 = xpos + 32 + bpldelay2*2;
                   1208:            switch (bplplanecnt) {
                   1209:             case 2: case 3: set_lores_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1210:             case 4: case 5: set_lores_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1211:             case 6: case 7: set_lores_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1212:             case 8:         set_lores_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1213:            }
                   1214:        }
                   1215:     }
                   1216: }
                   1217: 
                   1218: static void pfield_doline_unaligned_l (int lineno)
                   1219: {
                   1220:     int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT;
                   1221: 
                   1222:     if (bplhires) {
                   1223:        int xpos1 = xpos + 8 + bpldelay1;
                   1224:        int xpos2;
                   1225:        uae_u8 *dataptr = line_data[lineno];
                   1226:        int len = dp_for_drawing->plflinelen >> 1;
                   1227: 
                   1228:        if (len <= 0)
                   1229:            return;
                   1230: 
                   1231:        if (bpldelay1 == bpldelay2) {
                   1232:            switch (bplplanecnt) {
                   1233:             case 1: set_hires_l_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1234:             case 2: set_hires_l_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1235:             case 3: set_hires_l_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1236:             case 4: set_hires_l_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1237:             case 5: set_hires_l_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1238:             case 6: set_hires_l_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1239:             case 7: set_hires_l_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1240:             case 8: set_hires_l_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1241:            }
                   1242:        } else {
                   1243:            switch (bplplanecnt) {
                   1244:             case 1: case 2: set_hires_l_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1245:             case 3: case 4: set_hires_l_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1246:             case 5: case 6: set_hires_l_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1247:             case 7: case 8: set_hires_l_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1248:            }
                   1249: 
                   1250:            xpos2 = xpos + 8 + bpldelay2;
                   1251:            switch (bplplanecnt) {
                   1252:             case 2: case 3: set_hires_l_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1253:             case 4: case 5: set_hires_l_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1254:             case 6: case 7: set_hires_l_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1255:             case 8:         set_hires_l_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1256:            }
                   1257:        }
                   1258:     } else {
                   1259:        int xpos1 = xpos + 16 + bpldelay1;
                   1260:        int xpos2;
                   1261:        uae_u8 *dataptr = line_data[lineno];
                   1262:        int len = dp_for_drawing->plflinelen >> 2;
                   1263: 
                   1264:        if (len <= 0)
                   1265:            return;
                   1266: 
                   1267:        if (bpldelay1 == bpldelay2) {
                   1268:            switch (bplplanecnt) {
                   1269:             case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1270:             case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1271:             case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1272:             case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1273:             case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1274:             case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1275:             case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1276:             case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1277:            }
                   1278:        } else {
                   1279:            switch (bplplanecnt) {
                   1280:             case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1281:             case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1282:             case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1283:             case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1284:            }
                   1285: 
                   1286:            xpos2 = xpos + 16 + bpldelay2;
                   1287:            switch (bplplanecnt) {
                   1288:             case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1289:             case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1290:             case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1291:             case 8:         set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1292:            }
                   1293:        }
                   1294:     }
                   1295: }
                   1296: 
                   1297: #define pfield_doline_h pfield_doline_unaligned_h
                   1298: #define pfield_doline_l pfield_doline_unaligned_l
                   1299: 
                   1300: #else /* not UNALIGNED_PROFITABLE */
                   1301: 
                   1302: 
                   1303: static __inline__ void pfield_orword_hires_h(int data, unsigned char *dp, int bit)
                   1304: {
                   1305:     uae_u32 *pixptr = (uae_u32 *)dp;
                   1306: 
                   1307:     *pixptr |= hirestab_h[data >> 8][0] << bit;
                   1308:     *(pixptr+1) |= hirestab_h[data >> 8][1] << bit;
                   1309:     *(pixptr+2) |= hirestab_h[data & 255][0] << bit;
                   1310:     *(pixptr+3) |= hirestab_h[data & 255][1] << bit;
                   1311: }
                   1312: 
                   1313: static __inline__ void pfield_orword_lores_h(int data, unsigned char *dp, int bit)
                   1314: {
                   1315:     uae_u32 *pixptr = (uae_u32 *)dp;
                   1316: 
                   1317:     *pixptr |= lorestab_h[data >> 8][0] << bit;
                   1318:     *(pixptr+1) |= lorestab_h[data >> 8][1] << bit;
                   1319:     *(pixptr+2) |= lorestab_h[data >> 8][2] << bit;
                   1320:     *(pixptr+3) |= lorestab_h[data >> 8][3] << bit;
                   1321:     *(pixptr+4) |= lorestab_h[data & 255][0] << bit;
                   1322:     *(pixptr+5) |= lorestab_h[data & 255][1] << bit;
                   1323:     *(pixptr+6) |= lorestab_h[data & 255][2] << bit;
                   1324:     *(pixptr+7) |= lorestab_h[data & 255][3] << bit;
                   1325: }
                   1326: 
                   1327: static __inline__ void pfield_setword_hires_h(int data, unsigned char *dp, int bit)
                   1328: {
                   1329:     uae_u32 *pixptr = (uae_u32 *)dp;
                   1330: 
                   1331:     *pixptr = hirestab_h[data >> 8][0] << bit;
                   1332:     *(pixptr+1) = hirestab_h[data >> 8][1] << bit;
                   1333:     *(pixptr+2) = hirestab_h[data & 255][0] << bit;
                   1334:     *(pixptr+3) = hirestab_h[data & 255][1] << bit;
                   1335: }
                   1336: 
                   1337: static __inline__ void pfield_setword_lores_h(int data, unsigned char *dp, int bit)
                   1338: {
                   1339:     uae_u32 *pixptr = (uae_u32 *)dp;
                   1340: 
                   1341:     *pixptr = lorestab_h[data >> 8][0] << bit;
                   1342:     *(pixptr+1) = lorestab_h[data >> 8][1] << bit;
                   1343:     *(pixptr+2) = lorestab_h[data >> 8][2] << bit;
                   1344:     *(pixptr+3) = lorestab_h[data >> 8][3] << bit;
                   1345:     *(pixptr+4) = lorestab_h[data & 255][0] << bit;
                   1346:     *(pixptr+5) = lorestab_h[data & 255][1] << bit;
                   1347:     *(pixptr+6) = lorestab_h[data & 255][2] << bit;
                   1348:     *(pixptr+7) = lorestab_h[data & 255][3] << bit;
                   1349: }
                   1350: 
                   1351: static __inline__ void pfield_orword_hires_l(int data, unsigned char *dp, int bit)
                   1352: {
                   1353:     uae_u32 *pixptr = (uae_u32 *)dp;
                   1354: 
                   1355:     *pixptr |= hirestab_l[data >> 8][0] << bit;
                   1356:     *(pixptr+1) |= hirestab_l[data & 255][0] << bit;
                   1357: }
                   1358: 
                   1359: static __inline__ void pfield_orword_lores_l(int data, unsigned char *dp, int bit)
                   1360: {
                   1361:     uae_u32 *pixptr = (uae_u32 *)dp;
                   1362: 
                   1363:     *pixptr |= lorestab_l[data >> 8][0] << bit;
                   1364:     *(pixptr+1) |= lorestab_l[data >> 8][1] << bit;
                   1365:     *(pixptr+2) |= lorestab_l[data & 255][0] << bit;
                   1366:     *(pixptr+3) |= lorestab_l[data & 255][1] << bit;
                   1367: }
                   1368: 
                   1369: static __inline__ void pfield_setword_hires_l(int data, unsigned char *dp, int bit)
                   1370: {
                   1371:     uae_u32 *pixptr = (uae_u32 *)dp;
                   1372: 
                   1373:     *pixptr = hirestab_l[data >> 8][0] << bit;
                   1374:     *(pixptr+1) = hirestab_l[data & 255][0] << bit;
                   1375: }
                   1376: 
                   1377: static __inline__ void pfield_setword_lores_l(int data, unsigned char *dp, int bit)
                   1378: {
                   1379:     uae_u32 *pixptr = (uae_u32 *)dp;
                   1380: 
                   1381:     *pixptr = lorestab_l[data >> 8][0] << bit;
                   1382:     *(pixptr+1) = lorestab_l[data >> 8][1] << bit;
                   1383:     *(pixptr+2) = lorestab_l[data & 255][0] << bit;
                   1384:     *(pixptr+3) = lorestab_l[data & 255][1] << bit;
                   1385: }
                   1386: 
                   1387: #define DO_ONE_PLANE(POINTER, MULT, FUNC, DELAY, LL_SUB, P_ADD) { \
                   1388:     int i; \
                   1389:     unsigned int bpldat1; \
                   1390:     uae_u16 data; \
                   1391:     unsigned int bpldat2 = 0; \
                   1392:     uae_u8 *ptr = (POINTER); \
                   1393:     for (i = dp_for_drawing->plflinelen; i > 0; i -= LL_SUB) { \
                   1394:        bpldat1 = bpldat2; \
                   1395:        bpldat2 = do_get_mem_word ((uae_u16 *)ptr); \
                   1396:        ptr+=2; \
                   1397:        data = (bpldat1 << (16 - DELAY)) | (bpldat2 >> DELAY); \
                   1398:        FUNC(data, app, MULT); \
                   1399:        app += P_ADD; \
                   1400:     } \
                   1401:     data = bpldat2 << (16 - DELAY); \
                   1402:     FUNC(data, app, MULT); \
                   1403: }
                   1404: 
                   1405: #ifdef SMART_UPDATE
                   1406: #define DATA_POINTER(n) (dataptr + (n)*MAX_WORDS_PER_LINE*2)
                   1407: #else
                   1408: #define DATA_POINTER(n) (real_bplpt[n])
                   1409: #endif
                   1410: 
                   1411: static void pfield_doline_aligned_h (int lineno)
                   1412: {
                   1413:     int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2;
                   1414: 
                   1415:     if (bplhires) {
                   1416:        if (bplplanecnt > 0) {
                   1417:            int xpos1 = xpos + 16 + (bpldelay1 >= 8 ? 16 : 0);
                   1418:            int xpos2 = xpos + 16 + (bpldelay2 >= 8 ? 16 : 0);
                   1419:            int delay1 = 2*(bpldelay1 & 7);
                   1420:            int delay2 = 2*(bpldelay2 & 7);
                   1421:            unsigned char *app = pixdata.apixels + xpos1;
                   1422:            uae_u8 *dataptr = line_data[lineno];
                   1423: 
                   1424:            DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_h, delay1, 4, 16);
                   1425:            if (bplplanecnt > 2) {
                   1426:                app = pixdata.apixels + xpos1;
                   1427:                DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_hires_h, delay1, 4, 16);
                   1428:            }
                   1429: #if AGA_CHIPSET == 1
                   1430:            if (bplplanecnt > 4) {
                   1431:                app = pixdata.apixels + xpos1;
                   1432:                DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_hires_h, delay1, 4, 16);
                   1433:            }
                   1434:            if (bplplanecnt > 6) {
                   1435:                app = pixdata.apixels + xpos1;
                   1436:                DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_hires_h, delay1, 4, 16);
                   1437:            }
                   1438: #endif
                   1439:            if (bplplanecnt > 1) {
                   1440:                app = pixdata.apixels + xpos2;
                   1441:                DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_hires_h, delay2, 4, 16);
                   1442:            }
                   1443:            if (bplplanecnt > 3) {
                   1444:                app = pixdata.apixels + xpos2;
                   1445:                DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_hires_h, delay2, 4, 16);
                   1446:            }
                   1447: #if AGA_CHIPSET == 1
                   1448:            if (bplplanecnt > 5) {
                   1449:                app = pixdata.apixels + xpos2;
                   1450:                DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_hires_h, delay2, 4, 16);
                   1451:            }
                   1452:            if (bplplanecnt > 7) {
                   1453:                app = pixdata.apixels + xpos2;
                   1454:                DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_hires_h, delay2, 4, 16);
                   1455:            }
                   1456: #endif
                   1457:        } else {
                   1458:            memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
                   1459:        }
                   1460:     } else {
                   1461:        if (bplplanecnt > 0) {
                   1462:            int x = xpos + 32;
                   1463:            unsigned char *app = pixdata.apixels + x;
                   1464:            uae_u8 *dataptr = line_data[lineno];
                   1465: 
                   1466:            DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_h, bpldelay1, 8, 32);
                   1467:            if (bplplanecnt > 2) {
                   1468:                app = pixdata.apixels + x;
                   1469:                DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_lores_h, bpldelay1, 8, 32);
                   1470:            }
                   1471:            if (bplplanecnt > 4) {
                   1472:                app = pixdata.apixels + x;
                   1473:                DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_lores_h, bpldelay1, 8, 32);
                   1474:            }
                   1475: #if AGA_CHIPSET == 1
                   1476:            if (bplplanecnt > 6) {
                   1477:                app = pixdata.apixels + x;
                   1478:                DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_lores_h, bpldelay1, 8, 32);
                   1479:            }
                   1480: #endif
                   1481:            if (bplplanecnt > 1) {
                   1482:                app = pixdata.apixels + x;
                   1483:                DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_lores_h, bpldelay2, 8, 32);
                   1484:            }
                   1485:            if (bplplanecnt > 3) {
                   1486:                app = pixdata.apixels + x;
                   1487:                DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_lores_h, bpldelay2, 8, 32);
                   1488:            }
                   1489:            if (bplplanecnt > 5) {
                   1490:                app = pixdata.apixels + x;
                   1491:                DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_lores_h, bpldelay2, 8, 32);
                   1492:            }
                   1493: #if AGA_CHIPSET == 1
                   1494:            if (bplplanecnt > 7) {
                   1495:                app = pixdata.apixels + x;
                   1496:                DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_lores_h, bpldelay2, 8, 32);
                   1497:            }
                   1498: #endif
                   1499:        } else {
                   1500:            memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
                   1501:        }
                   1502:     }
                   1503: }
                   1504: 
                   1505: static void pfield_doline_aligned_l (int lineno)
                   1506: {
                   1507:     int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT;
                   1508: 
                   1509:     if (bplhires) {
                   1510:        if (bplplanecnt > 0) {
                   1511:            int xpos1 = xpos + 8 + (bpldelay1 >= 8 ? 8 : 0);
                   1512:            int xpos2 = xpos + 8 + (bpldelay2 >= 8 ? 8 : 0);
                   1513:            int delay1 = (bpldelay1 & 7) * 2;
                   1514:            int delay2 = (bpldelay2 & 7) * 2;
                   1515:            unsigned char *app = pixdata.apixels + xpos1;
                   1516:            uae_u8 *dataptr = line_data[lineno];
                   1517: 
                   1518:            DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_l, delay1, 4, 8);
                   1519:            if (bplplanecnt > 2) {
                   1520:                app = pixdata.apixels + xpos1;
                   1521:                DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_hires_l, delay1, 4, 8);
                   1522:            }
                   1523: #if AGA_CHIPSET == 1
                   1524:            if (bplplanecnt > 4) {
                   1525:                app = pixdata.apixels + xpos1;
                   1526:                DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_hires_l, delay1, 4, 8);
                   1527:            }
                   1528:            if (bplplanecnt > 6) {
                   1529:                app = pixdata.apixels + xpos1;
                   1530:                DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_hires_l, delay1, 4, 8);
                   1531:            }
                   1532: #endif
                   1533:            if (bplplanecnt > 1) {
                   1534:                app = pixdata.apixels + xpos2;
                   1535:                DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_hires_l, delay2, 4, 8);
                   1536:            }
                   1537:            if (bplplanecnt > 3) {
                   1538:                app = pixdata.apixels + xpos2;
                   1539:                DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_hires_l, delay2, 4, 8);
                   1540:            }
                   1541: #if AGA_CHIPSET == 1
                   1542:            if (bplplanecnt > 5) {
                   1543:                app = pixdata.apixels + xpos2;
                   1544:                DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_hires_l, delay2, 4, 8);
                   1545:            }
                   1546:            if (bplplanecnt > 7) {
                   1547:                app = pixdata.apixels + xpos2;
                   1548:                DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_hires_l, delay2, 4, 8);
                   1549:            }
                   1550: #endif
                   1551:        } else {
                   1552:            memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
                   1553:        }
                   1554:     } else {
                   1555:        if (bplplanecnt > 0) {
                   1556:            int x = xpos + 16;
                   1557:            int delay1 = bpldelay1;
                   1558:            int delay2 = bpldelay2;
                   1559:            unsigned char *app = pixdata.apixels + x;
                   1560:            uae_u8 *dataptr = line_data[lineno];
                   1561: 
                   1562:            DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_l, delay1, 8, 16);
                   1563:            if (bplplanecnt > 2) {
                   1564:                app = pixdata.apixels + x;
                   1565:                DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_lores_l, delay1, 8, 16);
                   1566:            }
                   1567:            if (bplplanecnt > 4) {
                   1568:                app = pixdata.apixels + x;
                   1569:                DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_lores_l, delay1, 8, 16);
                   1570:            }
                   1571: #if AGA_CHIPSET == 1
                   1572:            if (bplplanecnt > 6) {
                   1573:                app = pixdata.apixels + x;
                   1574:                DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_lores_l, delay1, 8, 16);
                   1575:            }
                   1576: #endif
                   1577:            if (bplplanecnt > 1) {
                   1578:                app = pixdata.apixels + x;
                   1579:                DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_lores_l, delay2, 8, 16);
                   1580:            }
                   1581:            if (bplplanecnt > 3) {
                   1582:                app = pixdata.apixels + x;
                   1583:                DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_lores_l, delay2, 8, 16);
                   1584:            }
                   1585:            if (bplplanecnt > 5) {
                   1586:                app = pixdata.apixels + x;
                   1587:                DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_lores_l, delay2, 8, 16);
                   1588:            }
                   1589: #if AGA_CHIPSET == 1
                   1590:            if (bplplanecnt > 7) {
                   1591:                app = pixdata.apixels + x;
                   1592:                DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_lores_l, delay2, 8, 16);
                   1593:            }
                   1594: #endif
                   1595:        } else {
                   1596:            memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
                   1597:        }
                   1598:     }
                   1599: }
                   1600: 
                   1601: #define pfield_doline_h pfield_doline_aligned_h
                   1602: #define pfield_doline_l pfield_doline_aligned_l
                   1603: 
                   1604: #endif /* UNALIGNED_PROFITABLE */
                   1605: 
                   1606: static void pfield_adjust_delay (void)
                   1607: {
                   1608:     int ddf_left = dp_for_drawing->plfstrt;
                   1609:     int ddf_right = dp_for_drawing->plfstrt + dp_for_drawing->plflinelen;
                   1610:     int i;
                   1611: 
                   1612:     for (i = dip_for_drawing->last_delay_change-1; i >= dip_for_drawing->first_delay_change-1; i--) {
                   1613:        int delayreg = i < dip_for_drawing->first_delay_change ? dp_for_drawing->bplcon1 : delay_changes[i].value;
                   1614:        int delay1 = delayreg & 0xF;
                   1615:        int delay2 = (delayreg >> 4) & 0xF;
                   1616:        int startpos = i == dip_for_drawing->last_delay_change - 1 ? ddf_right + 8 : delay_changes[i+1].linepos;
                   1617:        int stoppos = i < dip_for_drawing->first_delay_change ? ddf_left : delay_changes[i].linepos;
                   1618:        int j;
                   1619:        startpos = PIXEL_XPOS (startpos + (bplhires ? 4 : 8));
                   1620:        stoppos = PIXEL_XPOS (stoppos + (bplhires ? 4 : 8));
                   1621:        if (currprefs.gfx_lores == 0)
                   1622:            delay1 <<= 1, delay2 <<= 1;
                   1623:        else if (currprefs.gfx_lores == 2)
                   1624:            startpos >>= 1, stoppos >>= 1;
                   1625:        for (j = startpos-1; j >= stoppos; j--) {
                   1626:            pixdata.apixels [j] = (pixdata.apixels[j-delay1] & 0x55) | (pixdata.apixels[j-delay2] & 0xAA);
                   1627:        }
                   1628:     }
                   1629: }
                   1630: 
                   1631: void init_row_map (void)
                   1632: {
                   1633:     int i;
                   1634:     if (gfxvidinfo.height > 2048) {
                   1635:        write_log ("Resolution too high, aborting\n");
                   1636:        abort ();
                   1637:     }
                   1638:     for (i = 0; i < gfxvidinfo.height + 1; i++)
                   1639:        row_map[i] = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * i;
                   1640: }
                   1641: 
                   1642: static void init_aspect_maps (void)
                   1643: {
                   1644:     int i, maxl;
                   1645:     double native_lines_per_amiga_line;
                   1646: 
                   1647:     if (native2amiga_line_map)
                   1648:        free (native2amiga_line_map);
                   1649:     if (amiga2aspect_line_map)
                   1650:        free (amiga2aspect_line_map);
                   1651: 
                   1652:     /* At least for this array the +1 is necessary. */
                   1653:     amiga2aspect_line_map = (int *)malloc (sizeof (int) * (maxvpos+1)*2 + 1);
                   1654:     native2amiga_line_map = (int *)malloc (sizeof (int) * gfxvidinfo.height);
                   1655: 
                   1656:     if (currprefs.gfx_correct_aspect)
                   1657:        native_lines_per_amiga_line = ((double)gfxvidinfo.height
                   1658:                                       * (currprefs.gfx_lores ? 320 : 640)
                   1659:                                       / (currprefs.gfx_linedbl ? 512 : 256)
                   1660:                                       / gfxvidinfo.width);
                   1661:     else
                   1662:        native_lines_per_amiga_line = 1;
                   1663: 
                   1664:     maxl = (maxvpos+1) * (currprefs.gfx_linedbl ? 2 : 1);
                   1665:     min_ypos_for_screen = minfirstline << (currprefs.gfx_linedbl ? 1 : 0);
                   1666:     max_drawn_amiga_line = -1;
                   1667:     for (i = 0; i < maxl; i++) {
                   1668:        int v = (i - min_ypos_for_screen) * native_lines_per_amiga_line;
                   1669:        if (v >= gfxvidinfo.height && max_drawn_amiga_line == -1)
                   1670:            max_drawn_amiga_line = i - min_ypos_for_screen;
                   1671:        if (i < min_ypos_for_screen || v >= gfxvidinfo.height)
                   1672:            v = -1;
                   1673:        amiga2aspect_line_map[i] = v;
                   1674:     }
                   1675:     if (currprefs.gfx_linedbl)
                   1676:        max_drawn_amiga_line >>= 1;
                   1677: 
                   1678:     if (currprefs.gfx_ycenter && !(currprefs.gfx_correct_aspect)) {
                   1679:        extra_y_adjust = (gfxvidinfo.height - (maxvpos << (currprefs.gfx_linedbl ? 1 : 0))) >> 1;
                   1680:        if (extra_y_adjust < 0)
                   1681:            extra_y_adjust = 0;
                   1682:     }
                   1683: 
                   1684:     for (i = 0; i < gfxvidinfo.height; i++)
                   1685:        native2amiga_line_map[i] = -1;
                   1686: 
                   1687:     if (native_lines_per_amiga_line < 1) {
                   1688:        /* Must omit drawing some lines. */
                   1689:        for (i = maxl - 1; i > min_ypos_for_screen; i--) {
                   1690:            if (amiga2aspect_line_map[i] == amiga2aspect_line_map[i-1]) {
                   1691:                if (currprefs.gfx_linedbl && (i & 1) == 0 && amiga2aspect_line_map[i+1] != -1) {
                   1692:                    /* If only the first line of a line pair would be omitted,
                   1693:                     * omit the second one instead to avoid problems with line
                   1694:                     * doubling. */
                   1695:                    amiga2aspect_line_map[i] = amiga2aspect_line_map[i+1];
                   1696:                    amiga2aspect_line_map[i+1] = -1;
                   1697:                } else
                   1698:                    amiga2aspect_line_map[i] = -1;
                   1699:            }
                   1700:        }
                   1701:     }
                   1702: 
                   1703:     for (i = maxl-1; i >= min_ypos_for_screen; i--) {
                   1704:        int j;
                   1705:        if (amiga2aspect_line_map[i] == -1)
                   1706:            continue;
                   1707:        for (j = amiga2aspect_line_map[i]; j < gfxvidinfo.height && native2amiga_line_map[j] == -1; j++)
                   1708:            native2amiga_line_map[j] = i >> (currprefs.gfx_linedbl ? 1 : 0);
                   1709:     }
                   1710: }
                   1711: 
                   1712: /*
                   1713:  * A raster line has been built in the graphics buffer. Tell the graphics code
                   1714:  * to do anything necessary to display it.
                   1715:  */
                   1716: static void do_flush_line_1 (int lineno)
                   1717: {
                   1718:     if (lineno < first_drawn_line)
                   1719:        first_drawn_line = lineno;
                   1720:     if (lineno > last_drawn_line)
                   1721:        last_drawn_line = lineno;
                   1722: 
                   1723:     if (gfxvidinfo.maxblocklines == 0)
                   1724:        flush_line(lineno);
                   1725:     else {
                   1726:        if ((last_block_line+1) != lineno) {
                   1727:            if (first_block_line != -2)
                   1728:                flush_block (first_block_line, last_block_line);
                   1729:            first_block_line = lineno;
                   1730:        }
                   1731:        last_block_line = lineno;
                   1732:        if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) {
                   1733:            flush_block (first_block_line, last_block_line);
                   1734:            first_block_line = last_block_line = -2;
                   1735:        }
                   1736:     }
                   1737: }
                   1738: 
                   1739: static __inline__ void do_flush_line (int lineno)
                   1740: {
                   1741:     /* We don't want to call X libraries from the second thread right now. */
                   1742: #ifndef SUPPORT_PENGUINS
                   1743:     do_flush_line_1 (lineno);
                   1744: #else
                   1745:     line_drawn[lineno] = 1;
                   1746: #endif
                   1747: }
                   1748: 
                   1749: /*
                   1750:  * One drawing frame has been finished. Tell the graphics code about it.
                   1751:  * Note that the actual flush_screen() call is a no-op for all reasonable
                   1752:  * systems.
                   1753:  */
                   1754: 
                   1755: static __inline__ void do_flush_screen (int start, int stop)
                   1756: {
                   1757: #ifdef SUPPORT_PENGUINS
                   1758:     int i;
                   1759:     for (i = 0; i < gfxvidinfo.height; i++) {
                   1760:        if (line_drawn[i])
                   1761:            do_flush_line_1 (i);
                   1762:     }
                   1763: #endif
                   1764:     if (gfxvidinfo.maxblocklines != 0 && first_block_line != -2) {
                   1765:        flush_block (first_block_line, last_block_line);
                   1766:     }
                   1767:     if (start <= stop)
                   1768:        flush_screen (start, stop);
                   1769: }
                   1770: 
                   1771: static int drawing_color_matches;
                   1772: static enum { color_match_acolors, color_match_full } color_match_type;
                   1773: 
                   1774: static void adjust_drawing_colors (int ctable, int bplham)
                   1775: {
                   1776:     if (drawing_color_matches != ctable) {
                   1777:        if (bplham) {
                   1778:            memcpy (&colors_for_drawing, curr_color_tables + ctable,
                   1779:                    sizeof colors_for_drawing);
                   1780:            color_match_type = color_match_full;
                   1781:        } else {
                   1782:            memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors,
                   1783:                    sizeof colors_for_drawing.acolors);
                   1784:            color_match_type = color_match_acolors;
                   1785:        }
                   1786:        drawing_color_matches = ctable;
                   1787:     } else if (bplham && color_match_type != color_match_full) {
                   1788:        memcpy (colors_for_drawing.color_regs, curr_color_tables[ctable].color_regs,
                   1789:                sizeof colors_for_drawing.color_regs);
                   1790:        color_match_type = color_match_full;
                   1791:     }
                   1792: }
                   1793: 
                   1794: static __inline__ void adjust_color0_for_color_change (void)
                   1795: {
                   1796:     drawing_color_matches = -1;
                   1797:     if (dp_for_drawing->color0 != 0xFFFFFFFFul) {
                   1798:        colors_for_drawing.color_regs[0] = dp_for_drawing->color0;
                   1799:        colors_for_drawing.acolors[0] = xcolors[dp_for_drawing->color0];
                   1800:     }
                   1801: }
                   1802: 
                   1803: /* Fetched data spends 9 lores pixels somewhere in the chips before it appears
                   1804:  * on-screen. We don't emulate this. Instead, we cheat with the copper to
                   1805:  * compensate (much easier that way). */
                   1806: #define COPPER_MAGIC_FUDGE -9
                   1807: 
                   1808: static __inline__ void do_color_changes (line_draw_func worker)
                   1809: {
                   1810:     int lastpos = 0, nextpos, i;
                   1811:     struct color_change *cc = curr_color_changes + dip_for_drawing->first_color_change;
                   1812: 
                   1813:     for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++, cc++) {
                   1814:        if (i == dip_for_drawing->last_color_change)
                   1815:            nextpos = max_diwlastword;
                   1816:        else
                   1817:            nextpos = PIXEL_XPOS (cc->linepos) + (COPPER_MAGIC_FUDGE << lores_shift);
                   1818:        worker (lastpos, nextpos);
                   1819:        if (i != dip_for_drawing->last_color_change) {
                   1820:            colors_for_drawing.color_regs[cc->regno] = cc->value;
                   1821:            colors_for_drawing.acolors[cc->regno] = xcolors[cc->value];
                   1822:        }
                   1823:        if (nextpos > lastpos) {
                   1824:            lastpos = nextpos;
                   1825:            if (lastpos >= linetoscr_right_x)
                   1826:                break;
                   1827:        }
                   1828:     }
                   1829: }
                   1830: 
                   1831: /* We only save hardware registers during the hardware frame. Now, when
                   1832:  * drawing the frame, we expand the data into a slightly more useful
                   1833:  * form. */
                   1834: static void pfield_expand_dp_bplcon (void)
                   1835: {
                   1836:     bplhires = (dp_for_drawing->bplcon0 & 0x8000) == 0x8000;
                   1837:     bplplanecnt = (dp_for_drawing->bplcon0 & 0x7000) >> 12;
                   1838:     bplham = (dp_for_drawing->bplcon0 & 0x800) == 0x800;
                   1839: #if AGA_CHIPSET == 1 /* The KILLEHB bit exists in ECS, but is apparently meant for Genlock
                   1840:                      * stuff, and it's set by some demos (e.g. Andromeda Seven Seas) */
                   1841:     bplehb = ((dp_for_drawing->bplcon0 & 0xFCC0) == 0x6000 && !(dp_for_drawing->bplcon2 & 0x200));
                   1842: #else
                   1843:     bplehb = (dp_for_drawing->bplcon0 & 0xFC00) == 0x6000;
                   1844: #endif
                   1845:     bpldelay1 = dp_for_drawing->bplcon1 & 0xF;
                   1846:     bpldelay2 = (dp_for_drawing->bplcon1 >> 4) & 0xF;
                   1847:     plfpri[1] = 1 << 2*(dp_for_drawing->bplcon2 & 7);
                   1848:     plfpri[2] = 1 << 2*((dp_for_drawing->bplcon2 >> 3) & 7);
                   1849:     bpldualpf = (dp_for_drawing->bplcon0 & 0x400) == 0x400;
                   1850:     bpldualpfpri = (dp_for_drawing->bplcon2 & 0x40) == 0x40;
                   1851: }
                   1852: 
                   1853: enum double_how {
                   1854:     dh_buf,
                   1855:     dh_line,
                   1856:     dh_emerg
                   1857: };
                   1858: 
                   1859: static __inline__ void pfield_draw_line (int lineno, int gfx_ypos, int follow_ypos)
                   1860: {
                   1861:     int border = 0;
                   1862:     int do_double = 0;
                   1863:     enum double_how dh;
                   1864: 
                   1865:     dp_for_drawing = 0;
                   1866:     dip_for_drawing = 0;
                   1867:     switch (linestate[lineno]) {
                   1868:      case LINE_AS_PREVIOUS:
                   1869:      case LINE_REMEMBERED_AS_PREVIOUS:
                   1870:        {
                   1871:            static int warned = 0;
                   1872:            if (!warned)
                   1873:                write_log ("Shouldn't get here... this is a bug.\n"), warned++;
                   1874:        }
                   1875:        line_decisions[lineno].which = -2;
                   1876:        return;
                   1877: 
                   1878:      case LINE_BORDER_PREV:
                   1879:        border = 1;
                   1880:        dp_for_drawing = line_decisions + lineno - 1;
                   1881:        dip_for_drawing = curr_drawinfo + lineno - 1;
                   1882:        break;
                   1883: 
                   1884:      case LINE_BORDER_NEXT:
                   1885:        border = 1;
                   1886:        dp_for_drawing = line_decisions + lineno + 1;
                   1887:        dip_for_drawing = curr_drawinfo + lineno + 1;
                   1888:        break;
                   1889: 
                   1890:      case LINE_DONE_AS_PREVIOUS:
                   1891:        line_decisions[lineno].which = -2;
                   1892:        /* fall through */
                   1893:      case LINE_DONE:
                   1894:        return;
                   1895: 
                   1896:      case LINE_DECIDED_DOUBLE:
                   1897:        line_decisions[lineno+1].which = -2;
                   1898:        if (follow_ypos != -1) {
                   1899:            do_double = 1;
                   1900:            linetoscr_double_offset = gfxvidinfo.rowbytes * (follow_ypos - gfx_ypos);
                   1901:        }
                   1902: 
                   1903:        /* fall through */
                   1904:      default:
                   1905:        dip_for_drawing = curr_drawinfo + lineno;
                   1906:        dp_for_drawing = line_decisions + lineno;
                   1907:        if (dp_for_drawing->which != 1)
                   1908:            border = 1;
                   1909:        break;
                   1910:     }
                   1911: 
                   1912:     if (!line_changed[lineno] && !frame_redraw_necessary) {
                   1913:        /* The case where we can skip redrawing this line. If this line
                   1914:         * is supposed to be doubled, and the next line is remembered as
                   1915:         * having been doubled, then the next line is done as well. */
                   1916:        if (do_double) {
                   1917:            /* @@@ This is buggy. FIXME */
                   1918:            if (linestate[lineno+1] != LINE_REMEMBERED_AS_PREVIOUS) {
                   1919:                if (gfxvidinfo.linemem == 0)
                   1920:                    memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
                   1921:                line_decisions[lineno + 1].which = -2;
                   1922:                do_flush_line (follow_ypos);
                   1923:            }
                   1924:            linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
                   1925:        }
                   1926:        linestate[lineno] = LINE_DONE;
                   1927:        return;
                   1928:     }
                   1929: 
                   1930:     dh = dh_line;
                   1931:     xlinebuffer = gfxvidinfo.linemem;
                   1932:     if (xlinebuffer == 0 && do_double && dip_for_drawing->nr_color_changes != 0)
                   1933:        xlinebuffer = gfxvidinfo.emergmem, dh = dh_emerg;
                   1934:     if (xlinebuffer == 0)
                   1935:        xlinebuffer = row_map[gfx_ypos], dh = dh_buf;
                   1936:     xlinebuffer -= linetoscr_x_adjust_bytes;
                   1937:     aga_lbufptr = aga_linebuf;
                   1938: 
                   1939:     if (!border) {
                   1940:        pfield_expand_dp_bplcon ();
                   1941: 
                   1942: #ifdef LORES_HACK
                   1943:        if (gfxvidinfo.can_double && !bplhires && !currprefs.gfx_lores
                   1944:            && dip_for_drawing->nr_color_changes == 0 && !bplham)
                   1945:            currprefs.gfx_lores = 2;
                   1946: #endif
                   1947:        pfield_init_linetoscr ();
                   1948:        if (dip_for_drawing->first_delay_change != dip_for_drawing->last_delay_change) {
                   1949:            bpldelay1 = bpldelay2 = 0;
                   1950:            if (currprefs.gfx_lores)
                   1951:                pfield_doline_l (lineno);
                   1952:            else
                   1953:                pfield_doline_h (lineno);
                   1954:            pfield_adjust_delay ();
                   1955:        } else {
                   1956:            if (currprefs.gfx_lores)
                   1957:                pfield_doline_l (lineno);
                   1958:            else
                   1959:                pfield_doline_h (lineno);
                   1960:        }
                   1961: 
                   1962:        /* Check color0 adjust only if we have color changes - shouldn't happen
                   1963:         * otherwise. */
                   1964:        adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
                   1965: 
                   1966:        /* The problem is that we must call decode_ham6() BEFORE we do the
                   1967:         * sprites. */
                   1968:        if (bplham) {
                   1969:            init_ham_decoding(linetoscr_x_adjust);
                   1970:            if (dip_for_drawing->nr_color_changes == 0) {
                   1971:                /* The easy case: need to do HAM decoding only once for the
                   1972:                 * full line. */
                   1973:                decode_ham6 (linetoscr_x_adjust, linetoscr_right_x);
                   1974:            } else /* Argh. */ {
                   1975:                adjust_color0_for_color_change ();
                   1976:                do_color_changes (decode_ham6);
                   1977:                adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
                   1978:            }
                   1979:        }
                   1980: 
                   1981:        if (dip_for_drawing->nr_sprites != 0)
                   1982:            walk_sprites (curr_sprite_positions + dip_for_drawing->first_sprite_draw, dip_for_drawing->nr_sprites);
                   1983: 
                   1984:        if (dip_for_drawing->nr_color_changes == 0) {
                   1985:            pfield_do_linetoscr_full (dh == dh_buf ? do_double : 0);
                   1986:            do_flush_line (gfx_ypos);
                   1987:            linestate[lineno] = LINE_DONE;
                   1988: #if 0
                   1989:            if (dh == dh_emerg)
                   1990:                abort ();
                   1991: #endif
                   1992:            if (do_double) {
                   1993:                /* If dh == dh_line, do_flush_line will re-use the rendered line
                   1994:                 * from linemem.  If dh == dh_buf, the line will have been doubled
                   1995:                 * by pfield_do_linetoscr_full.  */
                   1996:                linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
                   1997:                do_flush_line (follow_ypos);
                   1998:            }
                   1999:        } else {
                   2000:            adjust_color0_for_color_change ();
                   2001:            do_color_changes (pfield_do_linetoscr);
                   2002: 
                   2003:            if (dh == dh_emerg)
                   2004:                memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
                   2005: 
                   2006:            linestate[lineno] = LINE_DONE;
                   2007:            do_flush_line (gfx_ypos);
                   2008:            if (do_double) {
                   2009:                if (dh == dh_emerg)
                   2010:                    memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
                   2011:                else if (dh == dh_buf)
                   2012:                    memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
                   2013:                linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
                   2014:                line_decisions[lineno + 1].which = -2;
                   2015:                do_flush_line (follow_ypos);
                   2016:            }
                   2017:        }
                   2018: #ifdef LORES_HACK
                   2019:        if (currprefs.gfx_lores == 2)
                   2020:            currprefs.gfx_lores = 0;
                   2021: #endif
                   2022:     } else { /* Border. */
                   2023:        adjust_drawing_colors (dp_for_drawing->ctable, 0);
                   2024: 
                   2025:        /* Check color0 adjust only if we have color changes - shouldn't happen
                   2026:         * otherwise. */
                   2027: 
                   2028:        if (dip_for_drawing->nr_color_changes == 0) {
                   2029:            fill_line ();
                   2030:            do_flush_line (gfx_ypos);
                   2031:            linestate[lineno] = LINE_DONE;
                   2032: #if 0
                   2033:            if (dh == dh_emerg)
                   2034:                abort ();
                   2035: #endif
                   2036:            if (do_double) {
                   2037:                if (dh == dh_buf) {
                   2038:                    xlinebuffer = row_map[follow_ypos] - linetoscr_x_adjust_bytes;
                   2039:                    fill_line ();
                   2040:                }
                   2041:                /* If dh == dh_line, do_flush_line will re-use the rendered line
                   2042:                 * from linemem.  */
                   2043:                do_flush_line (follow_ypos);
                   2044:                linestate[lineno+1] = LINE_DONE_AS_PREVIOUS;
                   2045:            }
                   2046:            return;
                   2047:        }
                   2048: 
                   2049:        adjust_color0_for_color_change ();
                   2050:        do_color_changes (pfield_do_fill_line);
                   2051: 
                   2052:        if (dh == dh_emerg)
                   2053:            memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
                   2054: 
                   2055:        do_flush_line (gfx_ypos);
                   2056:        linestate[lineno] = LINE_DONE;
                   2057:        if (do_double) {
                   2058:            if (dh == dh_emerg)
                   2059:                memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
                   2060:            else if (dh == dh_buf)
                   2061:                memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
                   2062:            /* If dh == dh_line, do_flush_line will re-use the rendered line
                   2063:             * from linemem.  */
                   2064:            do_flush_line (follow_ypos);
                   2065:            linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
                   2066:            line_decisions[lineno + 1].which = -2;
                   2067:        }
                   2068:     }
                   2069: }
                   2070: 
                   2071: #ifdef SUPPORT_PENGUINS
                   2072: static smp_comm_pipe drawing_pipe;
                   2073: static uae_sem_t drawing_lock;
                   2074: 
                   2075: static void *drawing_penguin (void *cruxmedo)
                   2076: {
                   2077:     int l;
                   2078:     fprintf (stderr, "Hello, world!\n");
                   2079: 
                   2080:     for (;;) {
                   2081:        /* Start of a frame. */
                   2082:        int k;
                   2083:        new_frame:
                   2084:        k = read_comm_pipe_int_blocking (&drawing_pipe);
                   2085: 
                   2086:        switch (k) {
                   2087:         case -2:
                   2088:            /* Hoopy */
                   2089:            break;
                   2090: 
                   2091:         default:
                   2092:            write_log ("Penguin got out of sync.\n");
                   2093:            /* what can we do? Try to reduce the damage */
                   2094:            for (;;) {
                   2095:                k = read_comm_pipe_int_blocking (&drawing_pipe);
                   2096:                if (k == -3)
                   2097:                    break;
                   2098:                if (k == -1) {
                   2099:                    uae_sem_post (&drawing_lock);
                   2100:                    goto new_frame;
                   2101:                }
                   2102:            }
                   2103:         case -3:
                   2104:            UAE_PENGUIN_EXIT;
                   2105:            /* Can't happen */
                   2106:            return 0;
                   2107:        }
                   2108: 
                   2109:        for (;;) {
                   2110:            int i, where;
                   2111:            int l = read_comm_pipe_int_blocking (&drawing_pipe);
                   2112:            switch (l) {
                   2113:             case -1:
                   2114:                /* End-of-frame synchronization. */
                   2115:                uae_sem_post (&drawing_lock);
                   2116:                goto new_frame;
                   2117:             case -2:
                   2118:                /* customreset called a bit too often. That's harmless. */
                   2119:                continue;
                   2120:             case -3:
                   2121:                write_log ("Penguin got out of sync.\n");
                   2122:                UAE_PENGUIN_EXIT;
                   2123:                return 0;
                   2124:            }
                   2125: 
                   2126:            /* l is the line that has been finished for drawing. */
                   2127:            i = l - thisframe_y_adjust_real;
                   2128:            if (i < 0 || i >= max_ypos_thisframe)
                   2129:                continue;
                   2130: 
                   2131:            if (linestate[l] == LINE_UNDECIDED) {
                   2132:                fprintf (stderr, "Line scheduled for drawing, but undecided %d!?\n", l);
                   2133:                continue;
                   2134:            }
                   2135:            if (inhibit_frame != 0)
                   2136:                continue;
                   2137:            where = amiga2aspect_line_map[i+min_ypos_for_screen];
                   2138:            if (where >= gfxvidinfo.height || where == -1)
                   2139:                continue;
                   2140: 
                   2141:            pfield_draw_line (l, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
                   2142:        }
                   2143:     }
                   2144: }
                   2145: 
                   2146: static penguin_id our_penguin;
                   2147: 
                   2148: static void kill_drawing_penguin (void)
                   2149: {
                   2150:     /* ??? does libpthread do that for us? */
                   2151: }
                   2152: 
                   2153: #endif
                   2154: 
                   2155: static int penguins_enabled_thisframe;
                   2156: 
                   2157: static void center_image (void)
                   2158: {
                   2159:     prev_x_adjust = linetoscr_x_adjust;
                   2160:     prev_y_adjust = thisframe_y_adjust;
                   2161: 
                   2162:     if (currprefs.gfx_xcenter) {
                   2163:        if (max_diwstop - min_diwstart < gfxvidinfo.width && currprefs.gfx_xcenter == 2)
                   2164:            /* Try to center. */
                   2165:            linetoscr_x_adjust = ((max_diwstop - min_diwstart - gfxvidinfo.width) / 2 + min_diwstart) & ~1;
                   2166:        else
                   2167:            linetoscr_x_adjust = max_diwstop - gfxvidinfo.width;
                   2168: 
                   2169:        /* Would the old value be good enough? If so, leave it as it is if we want to
                   2170:         * be clever. */
                   2171:        if (currprefs.gfx_xcenter == 2) {
                   2172:            if (linetoscr_x_adjust < prev_x_adjust && prev_x_adjust < min_diwstart)
                   2173:                linetoscr_x_adjust = prev_x_adjust;
                   2174:        }
                   2175:     } else
                   2176:        linetoscr_x_adjust = max_diwlastword - gfxvidinfo.width;
                   2177:     if (linetoscr_x_adjust < 0)
                   2178:        linetoscr_x_adjust = 0;
                   2179: 
                   2180:     linetoscr_x_adjust_bytes = linetoscr_x_adjust * gfxvidinfo.pixbytes;
                   2181: 
                   2182:     linetoscr_right_x = linetoscr_x_adjust + gfxvidinfo.width;
                   2183:     if (linetoscr_right_x > max_diwlastword)
                   2184:        linetoscr_right_x = max_diwlastword;
                   2185: 
                   2186:     thisframe_y_adjust = minfirstline;
                   2187:     if (currprefs.gfx_ycenter && thisframe_first_drawn_line != -1) {
                   2188:        if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && currprefs.gfx_ycenter == 2)
                   2189:            thisframe_y_adjust = (thisframe_last_drawn_line - thisframe_first_drawn_line - max_drawn_amiga_line) / 2 + thisframe_first_drawn_line;
                   2190:        else
                   2191:            thisframe_y_adjust = thisframe_first_drawn_line;
                   2192:        /* Would the old value be good enough? If so, leave it as it is if we want to
                   2193:         * be clever. */
                   2194:        if (currprefs.gfx_ycenter == 2) {
                   2195:            if (thisframe_y_adjust != prev_y_adjust
                   2196:                && prev_y_adjust <= thisframe_first_drawn_line
                   2197:                && prev_y_adjust + max_drawn_amiga_line > thisframe_last_drawn_line)
                   2198:                thisframe_y_adjust = prev_y_adjust;
                   2199:        }
                   2200:        /* Make sure the value makes sense */
                   2201:        if (thisframe_y_adjust + max_drawn_amiga_line > maxvpos)
                   2202:            thisframe_y_adjust = maxvpos - max_drawn_amiga_line;
                   2203:        if (thisframe_y_adjust < minfirstline)
                   2204:            thisframe_y_adjust = minfirstline;
                   2205:     }
                   2206:     thisframe_y_adjust_real = thisframe_y_adjust << (currprefs.gfx_linedbl ? 1 : 0);
                   2207:     max_ypos_thisframe = (maxvpos - thisframe_y_adjust) << (currprefs.gfx_linedbl ? 1 : 0);
                   2208: 
                   2209:     /* @@@ interlace_seen used to be (bplcon0 & 4), but this is probably
                   2210:      * better.  */
                   2211:     if (prev_x_adjust != linetoscr_x_adjust || prev_y_adjust != thisframe_y_adjust)
                   2212:        frame_redraw_necessary |= interlace_seen && currprefs.gfx_linedbl ? 2 : 1;
                   2213: 
                   2214:     max_diwstop = 0;
                   2215:     min_diwstart = 10000;
                   2216: }
                   2217: 
                   2218: static void init_drawing_frame (void)
                   2219: {
                   2220:     int i, maxline;
                   2221: 
                   2222:     init_hardware_for_drawing_frame ();
                   2223: 
                   2224:     if (max_diwstop == 0)
                   2225:        max_diwstop = diwlastword;
                   2226:     if (min_diwstart > max_diwstop)
                   2227:        min_diwstart = 0;
                   2228: 
                   2229:     if (thisframe_first_drawn_line == -1)
                   2230:        thisframe_first_drawn_line = minfirstline;
                   2231:     if (thisframe_first_drawn_line > thisframe_last_drawn_line)
                   2232:        thisframe_last_drawn_line = thisframe_first_drawn_line;
                   2233: 
                   2234:     maxline = currprefs.gfx_linedbl ? (maxvpos+1) * 2 + 1 : (maxvpos+1) + 1;
                   2235: #ifdef SMART_UPDATE
                   2236:     for (i = 0; i < maxline; i++)
                   2237:        linestate[i] = linestate[i] == LINE_DONE_AS_PREVIOUS ? LINE_REMEMBERED_AS_PREVIOUS : LINE_UNDECIDED;
                   2238: #else
                   2239:     memset (linestate, LINE_UNDECIDED, maxline);
                   2240: #endif
                   2241:     last_drawn_line = 0;
                   2242:     first_drawn_line = 32767;
                   2243: 
                   2244:     first_block_line = last_block_line = -2;
                   2245:     if (currprefs.test_drawing_speed)
                   2246:        frame_redraw_necessary = 1;
                   2247:     else if (frame_redraw_necessary)
                   2248:        frame_redraw_necessary--;
                   2249: 
                   2250:     center_image ();
                   2251: 
                   2252:     thisframe_first_drawn_line = -1;
                   2253:     thisframe_last_drawn_line = -1;
                   2254: #ifdef SUPPORT_PENGUINS
                   2255:     penguins_enabled_thisframe = 1;
                   2256:     /* Tell the other thread that it can now expect data from us. */
                   2257:     write_comm_pipe_int (&drawing_pipe, -2, 1);
                   2258:     memset (line_drawn, 0, sizeof line_drawn);
                   2259: #endif
                   2260: 
                   2261:     drawing_color_matches = -1;
                   2262: }
                   2263: 
                   2264: void finish_drawing_frame (void)
                   2265: {
                   2266:     int i;
                   2267: 
                   2268: #ifdef SUPPORT_PENGUINS
                   2269:     /* Synchronize with other thread, then see whether there's something left for
                   2270:      * us to draw. @@@ This is probably a big waste of cycles if the two threads
                   2271:      * run at very different speeds - this one could draw stuff as well. */
                   2272:     write_comm_pipe_int (&drawing_pipe, -1, 1);
                   2273:     uae_sem_wait (&drawing_lock);
                   2274: #else
                   2275: 
                   2276: #ifndef SMART_UPDATE
                   2277:     /* @@@ This isn't exactly right yet. FIXME */
                   2278:     if (!interlace_seen) {
                   2279:        do_flush_screen (first_drawn_line, last_drawn_line);
                   2280:        return;
                   2281:     }
                   2282: #endif
                   2283:     if (! lockscr ()) {
                   2284:        notice_screen_contents_lost ();
                   2285:        return;
                   2286:     }
                   2287:     for (i = 0; i < max_ypos_thisframe; i++) {
                   2288:        int where;
                   2289:        int line = i + thisframe_y_adjust_real;
                   2290: 
                   2291:        if (linestate[line] == LINE_UNDECIDED)
                   2292:            break;
                   2293: 
                   2294:        where = amiga2aspect_line_map[i+min_ypos_for_screen];
                   2295:        if (where >= gfxvidinfo.height)
                   2296:            break;
                   2297:        if (where == -1)
                   2298:            continue;
                   2299: 
                   2300:        pfield_draw_line (line, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
                   2301:     }
                   2302:     unlockscr ();
                   2303: #endif
                   2304:     do_flush_screen (first_drawn_line, last_drawn_line);
                   2305: }
                   2306: 
                   2307: void hardware_line_completed (int lineno)
                   2308: {
                   2309: #ifdef SUPPORT_PENGUINS
                   2310:     if (framecnt == 0 && penguins_enabled_thisframe) {
                   2311:        write_comm_pipe_int (&drawing_pipe, lineno, 0);
                   2312:     }
                   2313: #endif
                   2314: #ifndef SMART_UPDATE
                   2315:     {
                   2316:        int i, where;
                   2317:        /* l is the line that has been finished for drawing. */
                   2318:        i = lineno - thisframe_y_adjust_real;
                   2319:        if (i >= 0 && i < max_ypos_thisframe) {
                   2320:            where = amiga2aspect_line_map[i+min_ypos_for_screen];
                   2321:            if (where < gfxvidinfo.height && where != -1)
                   2322:                pfield_draw_line (lineno, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
                   2323:        }
                   2324:     }
                   2325: #endif
                   2326: }
                   2327: 
                   2328: static __inline__ void check_picasso (void)
                   2329: {
                   2330: #ifdef PICASSO96
                   2331:     if (picasso_on && picasso_redraw_necessary)
                   2332:        picasso_refresh ();
                   2333:     picasso_redraw_necessary = 0;
                   2334: 
                   2335:     if (picasso_requested_on == picasso_on)
                   2336:        return;
                   2337: 
                   2338:     picasso_on = picasso_requested_on;
                   2339: 
                   2340:     if (!picasso_on)
                   2341:        clear_inhibit_frame (2);
                   2342:     else
                   2343:        set_inhibit_frame (2);
                   2344: 
                   2345:     gfx_set_picasso_state (picasso_on);
                   2346:     picasso_enablescreen (picasso_requested_on);
                   2347: 
                   2348:     notice_screen_contents_lost ();
                   2349:     notice_new_xcolors ();
                   2350: #endif
                   2351: }
                   2352: 
                   2353: void vsync_handle_redraw (int long_frame, int lof_changed)
                   2354: {
                   2355:     last_redraw_point++;
                   2356:     if (lof_changed || ! interlace_seen || last_redraw_point >= 2 || long_frame) {
                   2357:        last_redraw_point = 0;
                   2358:        interlace_seen = 0;
                   2359: 
                   2360:        if (framecnt == 0)
                   2361:            finish_drawing_frame ();
                   2362: 
                   2363:        /* At this point, we have finished both the hardware and the
                   2364:         * drawing frame. Essentially, we are outside of all loops and
                   2365:         * can do some things which would cause confusion if they were
                   2366:         * done at other times.
                   2367:         */
                   2368: 
                   2369:        if (quit_program < 0) {
                   2370:            quit_program = -quit_program;
                   2371:            set_inhibit_frame (1);
                   2372:            regs.spcflags |= SPCFLAG_BRK;
                   2373:            filesys_prepare_reset ();
                   2374: #ifdef SUPPORT_PENGUINS
                   2375:            if (quit_program == 1)
                   2376:                /* Stop eating herring */
                   2377:                write_comm_pipe_int (&drawing_pipe, -3, 1);
                   2378: #endif
                   2379:            return;
                   2380:        }
                   2381: 
                   2382:        count_frame ();
                   2383:        check_picasso ();
                   2384: 
                   2385:        check_prefs_changed_custom ();
                   2386:        check_prefs_changed_cpu ();
                   2387:        if (check_prefs_changed_gfx ()) {
                   2388:            init_row_map ();
                   2389:            init_aspect_maps ();
                   2390:            notice_screen_contents_lost ();
                   2391:            notice_new_xcolors ();
                   2392:        }
                   2393: 
                   2394:        if (inhibit_frame != 0)
                   2395:            framecnt = 1;
                   2396: 
                   2397:        if (framecnt == 0)
                   2398:            init_drawing_frame ();
                   2399:     }
                   2400: }
                   2401: 
                   2402: void hsync_record_line_state (int lineno, enum nln_how how)
                   2403: {
                   2404:     if (framecnt != 0)
                   2405:        return;
                   2406:     switch (how) {
                   2407:      case nln_normal:
                   2408:        linestate[lineno] = LINE_DECIDED;
                   2409:        break;
                   2410:      case nln_doubled:
                   2411:        linestate[lineno] = LINE_DECIDED_DOUBLE;
                   2412:        if (linestate[lineno+1] != LINE_REMEMBERED_AS_PREVIOUS)
                   2413:            linestate[lineno+1] = LINE_AS_PREVIOUS;
                   2414:        break;
                   2415:      case nln_lower:
                   2416:        if (linestate[lineno-1] == LINE_UNDECIDED)
                   2417:            linestate[lineno-1] = LINE_BORDER_NEXT;
                   2418:        linestate[lineno] = LINE_DECIDED;
                   2419:        break;
                   2420:      case nln_upper:
                   2421:        linestate[lineno] = LINE_DECIDED;
                   2422:        if (linestate[lineno+1] == LINE_UNDECIDED
                   2423:            || linestate[lineno+1] == LINE_REMEMBERED_AS_PREVIOUS
                   2424:            || linestate[lineno+1] == LINE_AS_PREVIOUS)
                   2425:            linestate[lineno+1] = LINE_BORDER_PREV;
                   2426:        break;
                   2427:     }
                   2428: }
                   2429: 
                   2430: void notice_interlace_seen (void)
                   2431: {
                   2432:     interlace_seen = 1;
                   2433:     penguins_enabled_thisframe = 0;
                   2434: }
                   2435: 
                   2436: void reset_drawing (void)
                   2437: {
                   2438:     int i;
                   2439: 
                   2440:     inhibit_frame = 0;
                   2441:     uae_sem_init (&gui_sem, 0, 1);
                   2442: 
                   2443: #ifdef PICASSO96
                   2444:     InitPicasso96 ();
                   2445:     picasso_on = 0;
                   2446:     picasso_requested_on = 0;
                   2447:     gfx_set_picasso_state (0);
                   2448: #endif
                   2449:     max_diwstop = 0;
                   2450: 
                   2451:     lores_factor = currprefs.gfx_lores ? 1 : 2;
                   2452:     lores_shift = currprefs.gfx_lores ? 0 : 1;
                   2453:     sprite_width = currprefs.gfx_lores ? 16 : 32;
                   2454: 
                   2455:     /*memset(blitcount, 0, sizeof(blitcount));  blitter debug */
                   2456:     for (i = 0; i < sizeof linestate / sizeof *linestate; i++)
                   2457:        linestate[i] = LINE_UNDECIDED;
                   2458: 
                   2459:     xlinebuffer = gfxvidinfo.bufmem;
                   2460: 
                   2461:     init_aspect_maps ();
                   2462: 
                   2463:     if (line_drawn == 0)
                   2464:        line_drawn = (char *)malloc (gfxvidinfo.height);
                   2465: 
                   2466:     init_row_map();
                   2467: 
                   2468:     last_redraw_point = 0;
                   2469: 
                   2470:     init_drawing_frame ();
                   2471: }
                   2472: 
                   2473: void drawing_init ()
                   2474: {
                   2475:     native2amiga_line_map = 0;
                   2476:     amiga2aspect_line_map = 0;
                   2477:     line_drawn = 0;
                   2478: 
                   2479:     gen_pfield_tables();
                   2480: 
                   2481: #ifdef SUPPORT_PENGUINS
                   2482:     init_comm_pipe (&drawing_pipe, 800, 5);
                   2483:     uae_sem_init (&drawing_lock, 0, 0);
                   2484:     start_penguin (drawing_penguin, 0, &our_penguin);
                   2485:     /*atexit(kill_drawing_penguin);*/
                   2486: #endif
                   2487: }
                   2488: 

unix.superglobalmegacorp.com

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