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

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

unix.superglobalmegacorp.com

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