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