diff --git a/MCUME_teensy/teensyuae41/audio.c b/MCUME_teensy/teensyuae41/audio.c index eee3a5b..18efa87 100644 --- a/MCUME_teensy/teensyuae41/audio.c +++ b/MCUME_teensy/teensyuae41/audio.c @@ -64,6 +64,28 @@ void AUDxDAT(int nr, uae_u16 v) #endif } +void AUDxLCH(int nr, uae_u16 v) { audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((uae_u32)v << 16); } +void AUDxLCL(int nr, uae_u16 v) { audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE); } +void AUDxPER(int nr, uae_u16 v) +{ + if (v <= 0) { +#if 0 /* v == 0 is rather common, and harmless, and the value isn't signed anyway */ + static int warned = 0; + if (!warned) + write_log ("Broken program accessing the sound hardware\n"), warned++; +#endif + v = 65535; + } + if (v < maxhpos/2 && currprefs.produce_sound < 3) + v = maxhpos/2; + + audio_channel[nr].per = v; +} + +void AUDxVOL(int nr, uae_u16 v) { audio_channel[nr].vol = v & 64 ? 63 : v & 63; } +void AUDxLEN(int nr, uae_u16 v) { audio_channel[nr].len = v; } + + /* Templates! I want templates! */ void sample16_handler(void) { diff --git a/MCUME_teensy/teensyuae41/audio.h b/MCUME_teensy/teensyuae41/audio.h index 2bb80a1..cd73949 100644 --- a/MCUME_teensy/teensyuae41/audio.h +++ b/MCUME_teensy/teensyuae41/audio.h @@ -10,6 +10,7 @@ extern struct audio_channel_data { uaecptr lc, pt, dmaen; int data_written, snum, state, intreq2, wper, wlen; uae_u16 dat, nextdat, vol, per, len; + unsigned long adk_mask; int current_sample; } audio_channel[4]; @@ -21,4 +22,9 @@ extern void aud3_handler(void); #endif extern void AUDxDAT(int nr, uae_u16 value); +extern void AUDxVOL(int nr, uae_u16 value); +extern void AUDxPER(int nr, uae_u16 value); +extern void AUDxLCH(int nr, uae_u16 value); +extern void AUDxLCL(int nr, uae_u16 value); +extern void AUDxLEN(int nr, uae_u16 value); diff --git a/MCUME_teensy/teensyuae41/custom.c b/MCUME_teensy/teensyuae41/custom.c index ee8820e..02631c5 100644 --- a/MCUME_teensy/teensyuae41/custom.c +++ b/MCUME_teensy/teensyuae41/custom.c @@ -1,20 +1,30 @@ /* * UAE - The Un*x Amiga Emulator - * + * * Custom chip emulation - * + * * Copyright 1995, 1996, 1997 Bernd Schmidt * Copyright 1995 Alessandro Bissacco */ + /* + * This file should be split into two parts. There are two concepts of a + * "frame" here: a hardware frame which emulates the display hardware of + * the A500, and a "drawing" frame, which renders data on the screen. You + * can have multiple hardware frames for one drawing frame, or completely + * inhibit drawing while hardware frames continue to be emulated. There + * should be a separate file "drawing.c" or something. + */ #include "shared.h" #include #include + +//#include "threaddep/penguin.h" +#include "uae.h" #include "gensound.h" #include "sounddep/sound.h" #include "events.h" -#include "uae.h" #include "memory.h" #include "custom.h" #include "readcpu.h" @@ -23,15 +33,22 @@ #include "disk.h" #include "blitter.h" #include "xwin.h" +#include "joystick.h" #include "audio.h" #include "keybuf.h" #include "serial.h" +//#include "osemu.h" #include "autoconf.h" +//#include "gui.h" +//#include "picasso96.h" +//#include "p2c.h" + + +#define MAX_WORDS_PER_LINE 50 -#define OS_WITHOUT_MEMORY_MANAGEMENT -//#define LORES_HACK //#define SMART_UPDATE 1 - +#define OS_WITHOUT_MEMORY_MANAGEMENT +#define LORES_HACK #define SPRITE_COLLISIONS #define HALF_HEIGHT @@ -41,11 +58,11 @@ * function - the AGA timing parameters are different, and apparently I * haven't figured out the correct formula yet. Pity, the current one looks * logical. - * + * * @@@ Probably won't compile in this version. */ -//#define EMULATE_AGA +/* #define EMULATE_AGA */ #ifndef EMULATE_AGA #define AGA_CHIPSET 0 @@ -54,6 +71,11 @@ #endif +#ifdef SUPPORT_PENGUINS +#undef SMART_UPDATE +#define SMART_UPDATE 1 +#endif + #if AGA_CHIPSET == 1 #define MAX_PLANES 8 #else @@ -74,28 +96,37 @@ static int lores_factor, lores_shift, sprite_width; /* @@@ Is maxhpos + 4 - 1 correct? (4 less isn't enough) */ #define max_diwlastword (PIXEL_XPOS(maxhpos + 4 -1)) -/* These are default values for mouse calibration. - * The first two are default values for mstepx and mstepy. - * The second line set the horizontal and vertical offset for amiga and X - * pointer matching - */ +/* Mouse and joystick emulation */ #define defstepx (1<<16) #define defstepy (1<<16) #define defxoffs 0 #define defyoffs 0 - -/* Values below define mouse auto calibration process. - * They are not critical, change them if you want. - * The most important is calweight, which sets mouse adjustement rate */ static const int docal = 60, xcaloff = 40, ycaloff = 20; static const int calweight = 3; static int lastsampledmx, lastsampledmy; - /* - * Events - */ +//int buttonstate[3]; +//int lastmx, lastmy; +//int newmousecounters; +int ievent_alive = 0; + +static enum { normal_mouse, dont_care_mouse, follow_mouse } mousestate; + +static int mouse_x, mouse_y; +int joy0button, joy1button; +unsigned int joy0dir, joy1dir; +static int lastspr0x,lastspr0y,lastdiffx,lastdiffy,spr0pos,spr0ctl; +static int mstepx,mstepy,xoffs=defxoffs,yoffs=defyoffs; +static int sprvbfl; + +/* Video buffer description structure. Filled in by the graphics system + * dependent code. */ + +struct vidbuf_description gfxvidinfo; + +/* Events */ unsigned long int cycles, nextevent, is_lastline, did_reset; struct ev eventtab[ev_max]; @@ -114,6 +145,21 @@ static int dblpf_aga1[256], dblpf_aga2[256], linear_map_256[256], lots_of_twos[2 static int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 }; +/* Big lookup tables for planar to chunky conversion. */ + +uae_u32 hirestab_h[256][2]; +uae_u32 lorestab_h[256][4]; + +uae_u32 hirestab_l[256][1]; +uae_u32 lorestab_l[256][2]; + +static uae_u32 sprtaba[256],sprtabb[256]; +static uae_u32 clxtab[256]; + +/* The color lookup table. */ + +xcolnr xcolors[4096]; + /* * Hardware registers of all sorts. */ @@ -137,7 +183,7 @@ static uaecptr sprpt[8]; static int sprxpos[8], sprvstart[8], sprvstop[8]; static uae_u32 bpl1dat,bpl2dat,bpl3dat,bpl4dat,bpl5dat,bpl6dat,bpl7dat,bpl8dat; -static uae_s16 bpl1mod,bpl2mod; +static uae_s16 bpl1mod,bpl2mod; static uaecptr bplpt[8]; #ifndef SMART_UPDATE @@ -163,20 +209,13 @@ static int nr_planes_from_bplcon0, corrected_nr_planes_from_bplcon0; static unsigned int diwstrt,diwstop,ddfstrt,ddfstop; static unsigned int sprdata[8], sprdatb[8], sprctl[8], sprpos[8]; static int sprarmed[8], sprite_last_drawn_at[8]; +static int last_sprite_point, nr_armed; static uae_u16 clxdat, clxcon; static int clx_sprmask; static uae_u32 dskpt; static uae_u16 dsklen,dsksync; +static int dsklength, syncfound; -static int mouse_x, mouse_y; -int joy0button, joy1button; -unsigned int joy0dir, joy1dir; -static int lastspr0x,lastspr0y,lastdiffx,lastdiffy,spr0pos,spr0ctl; -static int mstepx,mstepy,xoffs=defxoffs,yoffs=defyoffs; -static int sprvbfl; - -static enum { normal_mouse, dont_care_mouse, follow_mouse } mousestate; -static int ievent_alive = 0; static uae_u32 coplc; static unsigned int copi1,copi2; @@ -187,7 +226,6 @@ static enum copper_states { * possible, we calculate a fixed value and store it here. */ static int copper_cycle_time; -static int dsklength; static int plffirstline,plflastline,plfstrt,plfstop,plflinelen; static int diwfirstword,diwlastword; @@ -205,21 +243,15 @@ union { unsigned char apixels[880]; } pixdata; -char spixels[880]; /* for sprites */ -char spixstate[880]; /* more sprites */ - - uae_u32 ham_linebuf[880]; -#if AGA_CHIPSET != 0 uae_u32 aga_linebuf[880], *aga_lbufptr; -#endif char *xlinebuffer; int next_lineno; static int nln_how; static int *amiga2aspect_line_map, *native2amiga_line_map; -static char **row_map; +static char *row_map[2049]; static int max_drawn_amiga_line; /* @@ -235,19 +267,37 @@ int bogusframe; * helper functions */ -int inhibit_frame; +int picasso_requested_on; +int picasso_on; + +//uae_sem_t frame_sem, gui_sem, ihf_sem; +volatile int frame_do_semup; + int inhibit_frame; + static int framecnt = 0; static int frame_redraw_necessary; -static __inline__ void count_frame(void) +static __inline__ void count_frame (void) { framecnt++; if (framecnt >= currprefs.framerate) framecnt = 0; - } -static __inline__ void setclr(uae_u16 *p, uae_u16 val) +void check_prefs_changed_custom (void) +{ + currprefs.framerate = changed_prefs.framerate; + /* Not really the right place... */ + if (currprefs.fake_joystick != changed_prefs.fake_joystick) { + currprefs.fake_joystick = changed_prefs.fake_joystick; + joystick_setting_changed (); + } + currprefs.immediate_blits = changed_prefs.immediate_blits; + currprefs.blits_32bit_enabled = changed_prefs.blits_32bit_enabled; + +} + +static __inline__ void setclr (uae_u16 *p, uae_u16 val) { if (val & 0x8000) { *p |= val & 0x7FFF; @@ -256,12 +306,12 @@ static __inline__ void setclr(uae_u16 *p, uae_u16 val) } } -__inline__ int current_hpos(void) +__inline__ int current_hpos (void) { return cycles - eventtab[ev_hsync].oldcycles; } -static __inline__ uae_u8 *pfield_xlateptr(uaecptr plpt, int bytecount) +static __inline__ uae_u8 *pfield_xlateptr (uaecptr plpt, int bytecount) { if (!chipmem_bank.check(plpt,bytecount)) { static int count = 0; @@ -281,8 +331,6 @@ static void calculate_copper_cycle_time (void) copper_cycle_time = corrected_nr_planes_from_bplcon0 <= 4 ? 2 : -1; } -struct vidbuf_description gfxvidinfo; - /* line_draw_funcs: pfield_do_linetoscr, pfield_do_fill_line, decode_ham6 */ typedef void (*line_draw_func)(int, int); @@ -309,9 +357,6 @@ static int thisframe_y_adjust, prev_y_adjust, thisframe_first_drawn_line, thisfr static int thisframe_y_adjust_real, max_ypos_thisframe, min_ypos_for_screen; static int extra_y_adjust; -/* 50 words give you 800 horizontal pixels. An A500 can't do that, so it ought - * to be enough. */ -#define MAX_WORDS_PER_LINE 50 #ifdef HALF_HEIGHT static uae_u8 line_data[(maxvpos+1)][MAX_PLANES * MAX_WORDS_PER_LINE * 2]; #else @@ -323,8 +368,8 @@ static uae_u8 line_data[(maxvpos+1) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2]; * line, we decide how to draw this line. There are many more-or-less * independent decisions, each of which can be taken at a different horizontal * position. - * Sprites, color changes and bitplane delay changes are handled specially: - * There isn't a single decision, but a list of structures containing + * Sprites, color changes and bitplane delay changes are handled specially: + * There isn't a single decision, but a list of structures containing * information on how to draw the line. */ @@ -338,7 +383,7 @@ struct sprite_draw { int linepos; int num; int ctl; - uae_u16 data, datb; + uae_u32 datab; }; struct delay_change { @@ -372,7 +417,7 @@ static int delta_delay_change = 0; #else static struct sprite_draw sprite_positions[2][MAX_REG_CHANGE]; static struct color_change color_changes[2][MAX_REG_CHANGE]; -/* We don't remember those across frames, that would be too much effort. +/* We don't remember those across frames, that would be too much effort. * We simply redraw the line whenever we see one of these. */ static struct delay_change delay_changes[MAX_REG_CHANGE]; #endif @@ -401,21 +446,26 @@ static __inline__ void docols(struct color_entry *colentry) { #if AGA_CHIPSET == 0 int i; - for (i = 0; i < 32; i++) - colentry->acolors[i] = xcolors[colentry->color_regs[i]]; + for (i = 0; i < 32; i++) { + int v = colentry->color_regs[i]; + if (v < 0 || v > 4095) + continue; + colentry->acolors[i] = xcolors[v]; + } #endif } void notice_new_xcolors (void) { int i; + docols(¤t_colors); docols(&colors_for_drawing); #ifdef HALF_HEIGHT for (i = 0; i < (maxvpos+1); i++) { #else for (i = 0; i < (maxvpos+1)*2; i++) { -#endif +#endif docols(color_tables[0]+i); docols(color_tables[1]+i); } @@ -433,7 +483,7 @@ static void init_regchanges (void) next_color_change = 0; next_sprite_draw = 0; current_change_set = 0; - for (i = 0; i < (sizeof (linestate) / sizeof (*linestate)); i++) + for (i = 0; i < sizeof linestate / sizeof *linestate; i++) linestate[i] = LINE_UNDECIDED; } @@ -530,9 +580,9 @@ static void remember_ctable (void) changed = 1; color_src_match = color_dest_match = -1; } else { - color_compare_result = fast_memcmp (&prev_color_tables[oldctable].color_regs, - ¤t_colors.color_regs, - sizeof current_colors.color_regs) != 0; + color_compare_result = memcmp (&prev_color_tables[oldctable].color_regs, + ¤t_colors.color_regs, + sizeof current_colors.color_regs) != 0; if (color_compare_result) changed = 1; color_src_match = oldctable; @@ -570,9 +620,9 @@ static void remember_ctable_for_border (void) changed = 1; color_src_match = color_dest_match = -1; } else { - color_compare_result = fast_memcmp (&prev_color_tables[oldctable].color_regs, - ¤t_colors.color_regs, - sizeof current_colors.color_regs) != 0; + color_compare_result = memcmp (&prev_color_tables[oldctable].color_regs, + ¤t_colors.color_regs, + sizeof current_colors.color_regs) != 0; if (color_compare_result) changed = 1; color_src_match = oldctable; @@ -589,10 +639,13 @@ static void remember_ctable_for_border (void) #endif } +/* Called to determine the state of the horizontal display window state + * machine at the current position. It might have changed since we last + * checked. */ static void decide_diw (void) { if (hdiwstate == DIW_waiting_start && thisline_decision.diwfirstword == -1 - && PIXEL_XPOS (current_hpos ()) >= diwfirstword) + && PIXEL_XPOS (current_hpos ()) >= diwfirstword) { thisline_decision.diwfirstword = diwfirstword; hdiwstate = DIW_waiting_stop; @@ -603,7 +656,7 @@ static void decide_diw (void) MARK_LINE_CHANGED (next_lineno); thisline_decision.diwlastword = -1; } - if (hdiwstate == DIW_waiting_stop && thisline_decision.diwlastword == -1 + if (hdiwstate == DIW_waiting_stop && thisline_decision.diwlastword == -1 && PIXEL_XPOS (current_hpos ()) >= diwlastword) { thisline_decision.diwlastword = diwlastword; @@ -613,6 +666,8 @@ static void decide_diw (void) } } +/* Called when we know that the line is not in the border and we want to it. + * The data fetch starting position and length are passed as parameters. */ static __inline__ void decide_as_playfield (int startpos, int len) { thisline_decision.which = 1; @@ -645,6 +700,9 @@ static __inline__ void decide_as_playfield (int startpos, int len) line_changed[next_lineno] = 1; } +/* Called when we already decided whether the line is playfield or border, + * but are no longer sure that this was such a good idea. This can make a + * difference only for very badly written software. */ static __inline__ void post_decide_line (void) { static int warned = 0; @@ -662,7 +720,7 @@ static __inline__ void post_decide_line (void) modulos_added = 1; return; } - + if (thisline_decision.which != -1 || diwstate == DIW_waiting_start || (bplcon0 & 0x7000) == 0 || !dmaen (DMA_BITPLANE) || current_hpos () >= thisline_decision.plfstrt + thisline_decision.plflinelen) return; @@ -720,7 +778,7 @@ static void decide_line_1 (void) decided_hires = (bplcon0 & 0x8000) == 0x8000; decided_nr_planes = nr_planes_from_bplcon0; #if 0 - /* The blitter gets slower if there's high bitplane activity. + /* The blitter gets slower if there's high bitplane activity. * @@@ but the values must be different. FIXME */ if (bltstate != BLT_done && ((decided_hires && decided_nr_planes > 2) @@ -745,12 +803,16 @@ static void decide_line_1 (void) decide_as_playfield (plfstrt, plflinelen); } +/* Main entry point for deciding how to draw a line. May either do + * nothing, decide the line as border, or decide the line as playfield. */ static __inline__ void decide_line (void) { if (thisline_decision.which == 0 && current_hpos() >= plfstrt) decide_line_1 (); } +/* Called when a color is about to be changed (write to a color register), + * but the new color has not been entered into the table yet. */ static void record_color_change (int regno, unsigned long value) { /* Early positions don't appear on-screen. */ @@ -768,7 +830,9 @@ static void record_color_change (int regno, unsigned long value) * @@@ There might be a slightly larger performance loss if we're drawing * this line as border... especially if there are changes in colors != 0 * we might end up setting line_changed for no reason. FIXME */ - if (thisline_decision.diwfirstword >= 0) { + if (thisline_decision.diwfirstword >= 0 + && thisline_decision.which != 0) + { if (thisline_decision.ctable == -1) remember_ctable (); } @@ -781,7 +845,7 @@ static void record_color_change (int regno, unsigned long value) || thisline_decision.which == 0 || (thisline_decision.which == 1 && current_hpos() >= thisline_decision.plfstrt + thisline_decision.plflinelen))) return; - + /* If the border is changed the first time before the DIW, record the * original starting border value. */ if (regno == 0 && thisline_decision.color0 == 0xFFFFFFFFul && thisline_decision.diwfirstword < 0) { @@ -792,7 +856,7 @@ static void record_color_change (int regno, unsigned long value) /* Anything else gets recorded in the color_changes table. */ #ifdef OS_WITHOUT_MEMORY_MANAGEMENT if(next_color_change >= max_color_change) { - ++delta_color_change; + ++delta_color_change; return; } #endif @@ -801,6 +865,7 @@ static void record_color_change (int regno, unsigned long value) curr_color_changes[next_color_change++].value = value; } +/* Stupid hack to get some Sanity demos working. */ static void decide_delay (void) { static int warned; @@ -816,10 +881,10 @@ static void decide_delay (void) return; } /* @@@ Could check here for DDF stopping earlier than DIW */ - + #ifdef OS_WITHOUT_MEMORY_MANAGEMENT if(next_delay_change >= max_delay_change) { - ++delta_delay_change; + ++delta_delay_change; return; } #endif @@ -884,7 +949,7 @@ static void decide_plane (void) for (i = 0; i < decided_nr_planes; i++, dataptr += MAX_WORDS_PER_LINE*2) { uaecptr pt = bplpt[i]; uae_u8 *real_ptr; - + if (decided_hires) { switch (i) { case 3: pt -= 2; @@ -933,12 +998,15 @@ static void decide_modulos (void) } /* - * Call decide_plane() before calling this. + * Add the modulos to the bitplane pointers if data fetch is already + * finished for the current line. + * Call decide_plane() before calling this, so that we won't use the + * new values of the plane pointers for the current line. */ static void do_modulos (void) { /* decided_nr_planes is != -1 if this line should be drawn by the - * display hardware, regardless of whether it fits on the emulated screen. + * display hardware, regardless of whether it fits on the emulated screen. */ if (decided_nr_planes != -1 && plane_decided && !modulos_added && current_hpos() >= thisline_decision.plfstrt + thisline_decision.plflinelen) @@ -958,7 +1026,7 @@ static void do_modulos (void) case 2: bplpt[1] += add2; case 1: bplpt[0] += add1; } - } else if (bplhires) { + } else if (decided_hires) { /* @@@ used to be bplhires which is clearly wrong */ switch (decided_nr_planes) { case 8: bplpt[7] += add2; case 7: bplpt[6] += add1; @@ -968,7 +1036,7 @@ static void do_modulos (void) case 3: bplpt[2] += add1 - (very_broken_program >= 3 ? 2 : 0); case 2: bplpt[1] += add2 - (very_broken_program >= 2 ? 2 : 0); case 1: bplpt[0] += add1; - } + } } else { switch (decided_nr_planes) { case 8: bplpt[7] += add2; @@ -979,81 +1047,100 @@ static void do_modulos (void) case 3: bplpt[2] += add1 - (very_broken_program >= 6 ? 2 : 0); case 2: bplpt[1] += add2 - (very_broken_program >= 4 ? 2 : 0); case 1: bplpt[0] += add1; - } + } } modulos_added = 1; } } -static void decide_sprite (int spr) +static __inline__ void record_sprite (int spr, int sprxp) { - int sprxp; + int pos = next_sprite_draw; + unsigned int data, datb; - if (framecnt != 0) +#ifdef OS_WITHOUT_MEMORY_MANAGEMENT + if(pos >= max_sprite_draw) { + ++delta_sprite_draw; + return; + } +#endif + data = sprdata[spr]; + datb = sprdatb[spr]; + + /* XXX FIXME, this isn't very clever, but it might do */ + for (;;) { + if (pos == curr_drawinfo[next_lineno].first_sprite_draw) + break; + if (curr_sprite_positions[pos-1].linepos < sprxp) + break; + if (curr_sprite_positions[pos-1].linepos == sprxp + && curr_sprite_positions[pos-1].num > spr) + break; + printf("Foo\n"); + pos--; + } + if (pos != next_sprite_draw) { + int pos2 = next_sprite_draw; + while (pos2 != pos) { + curr_sprite_positions[pos2] = curr_sprite_positions[pos2-1]; + pos2--; + } + } + curr_sprite_positions[pos].linepos = sprxp; + curr_sprite_positions[pos].num = spr; + curr_sprite_positions[pos].ctl = sprctl[spr]; + curr_sprite_positions[pos].datab = ((sprtaba[data & 0xFF] << 16) | sprtaba[data >> 8] + | (sprtabb[datb & 0xFF] << 16) | sprtabb[datb >> 8]); + next_sprite_draw++; +} + +static void decide_sprites (void) +{ + int nrs[8], posns[8], count, i; + int point = PIXEL_XPOS (current_hpos ()); + + if (framecnt != 0 || current_hpos() < 0x14 || nr_armed == 0 || point == last_sprite_point) return; decide_diw (); decide_line (); - if (!sprarmed[spr] || thisline_decision.which != 1 || current_hpos () < 0x14) + if (thisline_decision.which != 1) return; - sprxp = sprxpos[spr]; - /* We _must_ check at the start of the sprite - we might avoid some - * unnecessary redraws by testing at the end, but that doesn't always - * work. */ - if (sprxp > PIXEL_XPOS (current_hpos ()) || sprite_last_drawn_at[spr] >= sprxp) - return; - - sprite_last_drawn_at[spr] = sprxp; + count = 0; + for (i = 0; i < 8; i++) { + int sprxp = sprxpos[i]; + int j, bestp; - /* Ignore sprites outside the DIW. There is a small problem here when - * we haven't decided diwstart yet - but that should be very rare and - * drawing one sprite too much doesn't hurt all that much. - * We don't draw sprites with zero data, unless they might be attached - * sprites (I hope that the logic here doesn't miss any attached sprites). */ - if (sprxp < 0 - || (thisline_decision.diwfirstword >= 0 && sprxp + sprite_width < thisline_decision.diwfirstword) - || (thisline_decision.diwlastword >= 0 && sprxp > thisline_decision.diwlastword) - || (sprdata[spr] == 0 && sprdatb[spr] == 0 && (sprctl[(spr & ~1)+1] & 0x80) == 0)) - return; -#ifdef OS_WITHOUT_MEMORY_MANAGEMENT - if(next_sprite_draw >= max_sprite_draw) { - ++delta_sprite_draw; - return; + if (!sprarmed[i] || sprxp < 0 || sprxp > point || last_sprite_point >= sprxp) + continue; + if ((thisline_decision.diwfirstword >= 0 && sprxp + sprite_width < thisline_decision.diwfirstword) + || (thisline_decision.diwlastword >= 0 && sprxp > thisline_decision.diwlastword)) + continue; + + for (bestp = 0; bestp < count; bestp++) { + if (posns[bestp] > sprxp) + break; + if (posns[bestp] == sprxp && nrs[bestp] < i) + break; + } + for (j = count; j > bestp; j--) { + posns[j] = posns[j-1]; + nrs[j] = nrs[j-1]; + } + posns[j] = sprxp; + nrs[j] = i; + count++; } -#endif - curr_sprite_positions[next_sprite_draw].linepos = sprxp; - curr_sprite_positions[next_sprite_draw].num = spr; - curr_sprite_positions[next_sprite_draw].ctl = sprctl[spr]; - curr_sprite_positions[next_sprite_draw].data = sprdata[spr]; - curr_sprite_positions[next_sprite_draw++].datb = sprdatb[spr]; -} - -static __inline__ void decide_sprite_1 (int spr) -{ - int sprxp = sprxpos[spr]; - - if (sprxp > max_diwlastword || sprite_last_drawn_at[spr] >= sprxp - || sprxp < 0 - || (thisline_decision.diwfirstword >= 0 && sprxp + sprite_width < thisline_decision.diwfirstword) - || (thisline_decision.diwlastword >= 0 && sprxp > thisline_decision.diwlastword) - || (sprdata[spr] == 0 && sprdatb[spr] == 0 && (sprctl[(spr & ~1)+1] & 0x80) == 0)) - return; -#ifdef OS_WITHOUT_MEMORY_MANAGEMENT - if(next_sprite_draw >= max_sprite_draw) { - ++delta_sprite_draw; - return; - } -#endif - curr_sprite_positions[next_sprite_draw].linepos = sprxp; - curr_sprite_positions[next_sprite_draw].num = spr; - curr_sprite_positions[next_sprite_draw].ctl = sprctl[spr]; - curr_sprite_positions[next_sprite_draw].data = sprdata[spr]; - curr_sprite_positions[next_sprite_draw++].datb = sprdatb[spr]; + for (i = 0; i < count; i++) + record_sprite(nrs[i], posns[i]); + last_sprite_point = point; } +/* End of a horizontal scan line. Finish off all decisions that were not + * made yet. */ static void finish_decisions (void) { struct draw_info *dip; @@ -1068,6 +1155,9 @@ static void finish_decisions (void) if (thisline_decision.which == 0) decide_line_1 (); + /* Large DIWSTOP values can cause the stop position never to be + * reached, so the state machine always stays in the same state and + * there's a more-or-less full-screen DIW. */ if (hdiwstate == DIW_waiting_stop) { thisline_decision.diwlastword = max_diwlastword; if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword) @@ -1089,15 +1179,8 @@ static void finish_decisions (void) if (diwfirstword < min_diwstart) min_diwstart = diwfirstword; - if (sprarmed[0]) decide_sprite_1 (0); - if (sprarmed[1]) decide_sprite_1 (1); - if (sprarmed[2]) decide_sprite_1 (2); - if (sprarmed[3]) decide_sprite_1 (3); - if (sprarmed[4]) decide_sprite_1 (4); - if (sprarmed[5]) decide_sprite_1 (5); - if (sprarmed[6]) decide_sprite_1 (6); - if (sprarmed[7]) decide_sprite_1 (7); - + decide_sprites(); + if (thisline_decision.bplcon1 != line_decisions[next_lineno].bplcon1) changed = 1; } @@ -1105,7 +1188,7 @@ static void finish_decisions (void) dip->last_color_change = next_color_change; dip->last_delay_change = next_delay_change; dip->last_sprite_draw = next_sprite_draw; - + if (thisline_decision.ctable == -1) { if (thisline_decision.which == 1) remember_ctable (); @@ -1122,17 +1205,17 @@ static void finish_decisions (void) changed = 1; if (!changed && (dip->nr_color_changes != dip_old->nr_color_changes - || (dip->nr_color_changes > 0 - && fast_memcmp (curr_color_changes + dip->first_color_change, - prev_color_changes + dip_old->first_color_change, - dip->nr_color_changes * sizeof *curr_color_changes) != 0))) + || (dip->nr_color_changes > 0 + && memcmp (curr_color_changes + dip->first_color_change, + prev_color_changes + dip_old->first_color_change, + dip->nr_color_changes * sizeof *curr_color_changes) != 0))) changed = 1; if (!changed && thisline_decision.which == 1 && (dip->nr_sprites != dip_old->nr_sprites || (dip->nr_sprites > 0 - && fast_memcmp (curr_sprite_positions + dip->first_sprite_draw, - prev_sprite_positions + dip_old->first_sprite_draw, - dip->nr_sprites * sizeof *curr_sprite_positions) != 0))) + && memcmp (curr_sprite_positions + dip->first_sprite_draw, + prev_sprite_positions + dip_old->first_sprite_draw, + dip->nr_sprites * sizeof *curr_sprite_positions) != 0))) changed = 1; if (changed) { @@ -1143,6 +1226,7 @@ static void finish_decisions (void) dp->ctable = thisline_decision.ctable; } +/* Set the state of all decisions to "undecided" for a new scanline. */ static void reset_decisions (void) { if (framecnt != 0) @@ -1168,13 +1252,15 @@ static void reset_decisions (void) curr_drawinfo[next_lineno].first_delay_change = next_delay_change; curr_drawinfo[next_lineno].first_sprite_draw = next_sprite_draw; - memset(sprite_last_drawn_at, 0, sizeof sprite_last_drawn_at); + /* memset(sprite_last_drawn_at, 0, sizeof sprite_last_drawn_at); */ + last_sprite_point = 0; modulos_added = 0; plane_decided = 0; color_decided = 0; very_broken_program = 0; } +/* Initialize the decision array, once before the emulator really starts. */ static void init_decisions (void) { size_t i; @@ -1184,6 +1270,8 @@ static void init_decisions (void) } } +/* Calculate display window and data fetch values from the corresponding + * hardware registers. */ static void calcdiw (void) { diwfirstword = ((diwstrt & 0xFF) - DISPLAY_LEFT_SHIFT - 1) << lores_shift; @@ -1195,7 +1283,7 @@ static void calcdiw (void) diwfirstword = 0; if (diwlastword < 0) diwlastword = 0; - + plffirstline = diwstrt >> 8; plflastline = diwstop >> 8; #if 0 @@ -1237,18 +1325,35 @@ static void calcdiw (void) * Screen update macros/functions */ +static unsigned int ham_lastcolor; + +static void init_ham_decoding(int first) +{ + int pix = dp_for_drawing->diwfirstword; + ham_lastcolor = colors_for_drawing.color_regs[0]; + while (pix < first) { + int pv = pixdata.apixels[pix]; + switch(pv & 0x30) { + case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break; + case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break; + case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break; + case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break; + } + pix++; + } +} + static void decode_ham6 (int pix, int stoppos) { - static uae_u16 lastcolor; - uae_u32 *buf = ham_linebuf; + uae_u32 *buf = ham_linebuf; if (!bplham || bplplanecnt != 6) return; - + if (stoppos > dp_for_drawing->diwlastword) stoppos = dp_for_drawing->diwlastword; if (pix < dp_for_drawing->diwfirstword) { - lastcolor = colors_for_drawing.color_regs[0]; + ham_lastcolor = colors_for_drawing.color_regs[0]; pix = dp_for_drawing->diwfirstword; } #ifdef LORES_HACK @@ -1258,24 +1363,24 @@ static void decode_ham6 (int pix, int stoppos) while (pix < stoppos) { int pv = pixdata.apixels[pix]; switch(pv & 0x30) { - case 0x00: lastcolor = colors_for_drawing.color_regs[pv]; break; - case 0x10: lastcolor &= 0xFF0; lastcolor |= (pv & 0xF); break; - case 0x20: lastcolor &= 0x0FF; lastcolor |= (pv & 0xF) << 8; break; - case 0x30: lastcolor &= 0xF0F; lastcolor |= (pv & 0xF) << 4; break; + case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break; + case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break; + case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break; + case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break; } - buf[pix++] = lastcolor; - } + buf[pix++] = ham_lastcolor; + } } #if 0 static void decode_ham_aga (int pix, int stoppos) { static uae_u32 lastcolor; - uae_u32 *buf = ham_linebuf; + uae_u32 *buf = ham_linebuf; if (!bplham || (bplplanecnt != 6 && bplplanecnt != 8)) return; - + if (pix <= dp_for_drawing->diwfirstword) { pix = dp_for_drawing->diwfirstword; lastcolor = colors_for_drawing.color_regs[0]; @@ -1290,7 +1395,7 @@ static void decode_ham_aga (int pix, int stoppos) case 0x10: lastcolor &= 0xFFFF00; lastcolor |= (pv & 0xF)*0x11; break; case 0x20: lastcolor &= 0x00FFFF; lastcolor |= (pv & 0xF)*0x11 << 16; break; case 0x30: lastcolor &= 0xFF00FF; lastcolor |= (pv & 0xF)*0x11 << 8; break; - } + } buf[pix++] = lastcolor; } } else if (dp_for_drawing->bplplanecnt == 8) { @@ -1323,7 +1428,7 @@ static void pfield_linetoscr_aga(int pix, int stoppos) for (i = 0; i < stoppos; i++) pixdata.apixels[i] ^= xor; - + while (pix < diwfirstword && pix < stoppos) { buf[pix++] = colors_for_drawing.color_regs[0]; } @@ -1340,12 +1445,12 @@ static void pfield_linetoscr_aga(int pix, int stoppos) while (pix < diwlastword && pix < stoppos) { int pixcol = pixdata.apixels[pix]; int pfno = lookup_no[pixcol]; - + if (spixstate[pix]) { - buf[pix] = colors_for_drawing.color_regs[pixcol]; + buf[pix] = colors_for_drawing.color_regs[pixcol]; } else { int val = lookup[pixdata.apixels[pix]]; - if (pfno == 2) + if (pfno == 2) val += dblpfofs[(bplcon2 >> 10) & 7]; buf[pix] = colors_for_drawing.color_regs[val]; } @@ -1353,7 +1458,7 @@ static void pfield_linetoscr_aga(int pix, int stoppos) } } else if (bplehb) { while (pix < diwlastword && pix < stoppos) { - int pixcol = pixdata.apixels[pix]; + int pixcol = pixdata.apixels[pix]; uae_u32 d = colors_for_drawing.color_regs[pixcol]; /* What about sprites? */ if (pixcol & 0x20) @@ -1402,7 +1507,7 @@ static void aga_translate8(int start, int stop) static int linetoscr_double_offset; -#define LINE_TO_SCR(NAME, TYPE, DO_DOUBLE) \ +#define LINE_TO_SCR(NAME, TYPE, DO_DOUBLE, CONVERT) \ static void NAME(int pix, int lframe_end, int diw_end, int stoppos) \ { \ TYPE *buf = ((TYPE *)xlinebuffer); \ @@ -1413,7 +1518,7 @@ static void NAME(int pix, int lframe_end, int diw_end, int stoppos) \ \ if (DO_DOUBLE) offset = linetoscr_double_offset / sizeof(TYPE); \ \ - d1 = colors_for_drawing.acolors[0]; \ + d1 = CONVERT(colors_for_drawing.acolors[0]); \ while (pix < lframe_end) { \ buf[pix] = d1; if (DO_DOUBLE) buf[pix+offset] = d1; \ pix++; \ @@ -1421,7 +1526,7 @@ static void NAME(int pix, int lframe_end, int diw_end, int stoppos) \ if (bplham && bplplanecnt == 6) { \ /* HAM 6 */ \ while (pix < diw_end) { \ - TYPE d = xcolors[ham_linebuf[pix]]; \ + TYPE d = CONVERT(xcolors[ham_linebuf[pix]]); \ buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \ pix++; \ } \ @@ -1431,65 +1536,299 @@ static void NAME(int pix, int lframe_end, int diw_end, int stoppos) \ while (pix < diw_end) { \ int pixcol = pixdata.apixels[pix]; \ TYPE d; \ - if (spixstate[pix]) { \ - d = colors_for_drawing.acolors[pixcol]; \ - } else { \ - d = colors_for_drawing.acolors[lookup[pixcol]]; \ - } \ + d = CONVERT(colors_for_drawing.acolors[lookup[pixcol]]); \ buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \ pix++; \ } \ } else if (bplehb) { \ while (pix < diw_end) { \ int p = pixdata.apixels[pix]; \ - TYPE d = colors_for_drawing.acolors[p]; \ - if (p >= 32) d = xcolors[(colors_for_drawing.color_regs[p-32] >> 1) & 0x777]; \ + TYPE d = CONVERT (colors_for_drawing.acolors[p]); \ + if (p >= 32) d = CONVERT(xcolors[(colors_for_drawing.color_regs[p-32] >> 1) & 0x777]); \ buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \ pix++; \ } \ } else { \ while (pix < diw_end) { \ - TYPE d = colors_for_drawing.acolors[pixdata.apixels[pix]]; \ + TYPE d = CONVERT (colors_for_drawing.acolors[pixdata.apixels[pix]]); \ buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \ pix++; \ } \ } \ - d2 = colors_for_drawing.acolors[0]; \ + d2 = CONVERT (colors_for_drawing.acolors[0]); \ while (pix < stoppos) { \ buf[pix] = d2; if (DO_DOUBLE) buf[pix+offset] = d2; \ pix++; \ } \ } -#define FILL_LINE(NAME, TYPE) \ +#define FILL_LINE(NAME, TYPE, CONVERT) \ static void NAME(char *buf, int start, int stop) \ { \ TYPE *b = (TYPE *)buf; \ int i;\ xcolnr col = colors_for_drawing.acolors[0]; \ for (i = start; i < stop; i++) \ - b[i] = col; \ + b[i] = CONVERT (col); \ } -LINE_TO_SCR(pfield_linetoscr_16, uae_u16, 0) -LINE_TO_SCR(pfield_linetoscr_16_double_slow, uae_u16, 1) -FILL_LINE(fill_line_16, uae_u16) +LINE_TO_SCR(pfield_linetoscr_8, uae_u8, 0,) +LINE_TO_SCR(pfield_linetoscr_16, uae_u16, 0,) +LINE_TO_SCR(pfield_linetoscr_32, uae_u32, 0,) +LINE_TO_SCR(pfield_linetoscr_8_double_slow, uae_u8, 1,) +LINE_TO_SCR(pfield_linetoscr_16_double_slow, uae_u16, 1,) +LINE_TO_SCR(pfield_linetoscr_32_double_slow, uae_u32, 1,) + +FILL_LINE(fill_line_8, uae_u8,) +FILL_LINE(fill_line_16, uae_u16,) +FILL_LINE(fill_line_32, uae_u32,) + +#ifdef HAVE_UAE_U24 +LINE_TO_SCR(pfield_linetoscr_24, uae_u24, 0, uae24_convert) +LINE_TO_SCR(pfield_linetoscr_24_double_slow, uae_u24, 1, uae24_convert) +FILL_LINE(fill_line_24, uae_u24, uae24_convert) +#else +/* Dummy versions */ +static void pfield_linetoscr_24 (int pix, int lframe_end, int diw_end, int stoppos) +{ +} +static void pfield_linetoscr_24_double_slow (int pix, int lframe_end, int diw_end, int stoppos) +{ +} +static void fill_line_24 (char *buf, int start, int stop) +{ +} +#endif static __inline__ void fill_line_full (void) { - fill_line_16(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.maxlinetoscr); + switch (gfxvidinfo.pixbytes) { + case 1: fill_line_8(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break; + case 2: fill_line_16(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break; + case 3: fill_line_24(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break; + case 4: fill_line_32(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break; + } } #define fill_line fill_line_full + +#define pfield_linetoscr_full8 pfield_linetoscr_8 #define pfield_linetoscr_full16 pfield_linetoscr_16 +#define pfield_linetoscr_full24 pfield_linetoscr_24 +#define pfield_linetoscr_full32 pfield_linetoscr_32 + +#define pfield_linetoscr_full8_double pfield_linetoscr_8_double_slow #define pfield_linetoscr_full16_double pfield_linetoscr_16_double_slow +#define pfield_linetoscr_full24_double pfield_linetoscr_24_double_slow +#define pfield_linetoscr_full32_double pfield_linetoscr_32_double_slow +#if 1 && defined(X86_ASSEMBLY) +/* This version of fill_line is probably a win on all machines, but for + * now I'm cautious */ +#undef fill_line +static __inline__ void fill_line (void) +{ + int shift; + int nints, nrem; + int *start; + xcolnr val; +#ifdef HAVE_UAE_U24 + if (gfxvidinfo.pixbytes == 3) { + fill_line_24 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); + return; + } +#endif + + shift = 0; + if (gfxvidinfo.pixbytes == 2) + shift = 1; + if (gfxvidinfo.pixbytes == 4) + shift = 2; + nints = gfxvidinfo.width >> (2-shift); + nrem = nints & 7; + nints &= ~7; + start = (int *)(((char *)xlinebuffer) + (linetoscr_x_adjust << shift)); + val = colors_for_drawing.acolors[0]; + for (; nints > 0; nints -= 8, start+=8) { + *start = val; + *(start+1) = val; + *(start+2) = val; + *(start+3) = val; + *(start+4) = val; + *(start+5) = val; + *(start+6) = val; + *(start+7) = val; + } + switch (nrem) { + case 7: + *start++ = val; + case 6: + *start++ = val; + case 5: + *start++ = val; + case 4: + *start++ = val; + case 3: + *start++ = val; + case 2: + *start++ = val; + case 1: + *start = val; + } +} + +#undef pfield_linetoscr_full8 +/* The types are lies, of course. */ +extern void pfield_linetoscr_normal_asm8(void) __asm__("pfield_linetoscr_normal_asm8"); +extern void pfield_linetoscr_ehb_asm8(void) __asm__("pfield_linetoscr_ehb_asm8"); +extern void pfield_linetoscr_ham6_asm8(void) __asm__("pfield_linetoscr_ham6_asm8"); +extern void pfield_linetoscr_dualpf_asm8(void) __asm__("pfield_linetoscr_dualpf_asm8"); +extern void pfield_linetoscr_hdouble_asm8(void) __asm__("pfield_linetoscr_hdouble_asm8"); +extern void pfield_linetoscr_hdouble_dpf_asm8(void) __asm__("pfield_linetoscr_hdouble_dpf_asm8"); +extern void pfield_linetoscr_hdouble_ehb_asm8(void) __asm__("pfield_linetoscr_hdouble_ehb_asm8"); +extern void pfield_linetoscr_asm8(void (*)(void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm8"); + +static void pfield_linetoscr_full8(int pix, int lframe_end, int diw_end, int stoppos) +{ + int lframe_end_1, diw_end_1; + + lframe_end_1 = pix + ((lframe_end - pix) & ~3); + diw_end_1 = stoppos - ((stoppos - diw_end) & ~3); + + if (bplham && bplplanecnt == 6) { + pfield_linetoscr_asm8(pfield_linetoscr_ham6_asm8, pix, lframe_end_1, diw_end_1, stoppos); + } else if (bpldualpf) { +#ifdef LORES_HACK + if (currprefs.gfx_lores == 2) + pfield_linetoscr_asm8(pfield_linetoscr_hdouble_dpf_asm8, pix, lframe_end_1, diw_end_1, stoppos, + bpldualpfpri ? dblpf_ind2 : dblpf_ind1); + else +#endif + pfield_linetoscr_asm8(pfield_linetoscr_dualpf_asm8, pix, lframe_end_1, diw_end_1, stoppos, + bpldualpfpri ? dblpf_ind2 : dblpf_ind1); + } else if (bplehb) { +#ifdef LORES_HACK + if (currprefs.gfx_lores == 2) + pfield_linetoscr_asm8(pfield_linetoscr_hdouble_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos); + else +#endif + pfield_linetoscr_asm8(pfield_linetoscr_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos); + } else { +#ifdef LORES_HACK + if (currprefs.gfx_lores == 2) + pfield_linetoscr_asm8(pfield_linetoscr_hdouble_asm8, pix, lframe_end_1, diw_end_1, stoppos); + else +#endif + pfield_linetoscr_asm8(pfield_linetoscr_normal_asm8, pix, lframe_end_1, diw_end_1, stoppos); + } + + /* The assembly functions work on aligned data, so we may have to do some + * additional work at the edges. */ + if (lframe_end != lframe_end_1) { + int i, c = colors_for_drawing.acolors[0]; + for (i = lframe_end_1; i < lframe_end; i++) + xlinebuffer[i] = c; + } + if (diw_end != diw_end_1) { + int i, c = colors_for_drawing.acolors[0]; + for (i = diw_end; i < diw_end_1; i++) + xlinebuffer[i] = c; + } +} + +#undef pfield_linetoscr_full16 +extern void pfield_linetoscr_normal_asm16(void) __asm__("pfield_linetoscr_normal_asm16"); +extern void pfield_linetoscr_ehb_asm16(void) __asm__("pfield_linetoscr_ehb_asm16"); +extern void pfield_linetoscr_ham6_asm16(void) __asm__("pfield_linetoscr_ham6_asm16"); +extern void pfield_linetoscr_dualpf_asm16(void) __asm__("pfield_linetoscr_dualpf_asm16"); +extern void pfield_linetoscr_hdouble_asm16(void) __asm__("pfield_linetoscr_hdouble_asm16"); +extern void pfield_linetoscr_hdouble_dpf_asm16(void) __asm__("pfield_linetoscr_hdouble_dpf_asm16"); +extern void pfield_linetoscr_hdouble_ehb_asm16(void) __asm__("pfield_linetoscr_hdouble_ehb_asm16"); +extern void pfield_linetoscr_asm16(void (*)(void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm16"); + +static void pfield_linetoscr_full16(int pix, int lframe_end, int diw_end, int stoppos) +{ + int lframe_end_1, diw_end_1; + + lframe_end_1 = pix + ((lframe_end - pix) & ~3); + diw_end_1 = stoppos - ((stoppos - diw_end) & ~3); + + if (bplham && bplplanecnt == 6) { + pfield_linetoscr_asm16(pfield_linetoscr_ham6_asm16, pix, lframe_end_1, diw_end_1, stoppos); + } else if (bpldualpf) { +#ifdef LORES_HACK + if (currprefs.gfx_lores == 2) + pfield_linetoscr_asm16(pfield_linetoscr_hdouble_dpf_asm16, pix, lframe_end_1, diw_end_1, stoppos, + bpldualpfpri ? dblpf_ind2 : dblpf_ind1); + else +#endif + pfield_linetoscr_asm16(pfield_linetoscr_dualpf_asm16, pix, lframe_end_1, diw_end_1, stoppos, + bpldualpfpri ? dblpf_ind2 : dblpf_ind1); + } else if (bplehb) { +#ifdef LORES_HACK + if (currprefs.gfx_lores == 2) + pfield_linetoscr_asm16(pfield_linetoscr_hdouble_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos); + else +#endif + pfield_linetoscr_asm16(pfield_linetoscr_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos); + } else { +#ifdef LORES_HACK + if (currprefs.gfx_lores == 2) + pfield_linetoscr_asm16(pfield_linetoscr_hdouble_asm16, pix, lframe_end_1, diw_end_1, stoppos); + else +#endif + pfield_linetoscr_asm16(pfield_linetoscr_normal_asm16, pix, lframe_end_1, diw_end_1, stoppos); + } + + /* The assembly functions work on aligned data, so we may have to do some + * additional work at the edges. */ + if (lframe_end != lframe_end_1) { + int i, c = colors_for_drawing.acolors[0]; + for (i = lframe_end_1; i < lframe_end; i++) + ((uae_u16 *)xlinebuffer)[i] = c; + } + if (diw_end != diw_end_1) { + int i, c = colors_for_drawing.acolors[0]; + for (i = diw_end; i < diw_end_1; i++) + ((uae_u16 *)xlinebuffer)[i] = c; + } +} + +#ifndef NO_DOUBLING_LINETOSCR +#define NO_DOUBLING_LINETOSCR +#endif + +#endif + +#ifdef NO_DOUBLING_LINETOSCR +#undef pfield_linetoscr_full8_double +#undef pfield_linetoscr_full16_double +static void pfield_linetoscr_full8_double(int start, int lframe_end, int diw_end, int stop) +{ + char *oldxlb = (char *)xlinebuffer; + pfield_linetoscr_full8(start, lframe_end, diw_end, stop); + xlinebuffer = oldxlb + linetoscr_double_offset; + pfield_linetoscr_full8(start, lframe_end, diw_end, stop); +} +static void pfield_linetoscr_full16_double(int start, int lframe_end, int diw_end, int stop) +{ + char *oldxlb = (char *)xlinebuffer; + pfield_linetoscr_full16(start, lframe_end, diw_end, stop); + xlinebuffer = oldxlb + linetoscr_double_offset; + pfield_linetoscr_full16(start, lframe_end, diw_end, stop); +} +#endif static int linetoscr_diw_end, linetoscr_diw_start; +/* Initialize the variables necessary for drawing a line. + * This involves setting up start/stop positions and display window + * borders. Also, since the drawing code may not fully overwrite all + * releveant areas in the pixdata.apixels array for speed reasons, parts of + * it must possibly be cleared here. */ static void pfield_init_linetoscr (void) { int ddf_left, ddf_right; @@ -1502,13 +1841,13 @@ static void pfield_init_linetoscr (void) /* We should really look at DDF also when calculating max_diwstop/min_diwstrt, * so that centering works better, but I'm afraid that might cost too many - * cycles. Plus it's dangerous, see the code below that handles the case + * cycles. Plus it's dangerous, see the code below that handles the case * with sprites. */ if (dip_for_drawing->nr_sprites == 0) { int hiresadjust = bplhires ? 4 : 8; ddf_left = ((dp_for_drawing->plfstrt + hiresadjust)*2 + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift; ddf_right = ((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2 + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift; - + if (linetoscr_diw_start < ddf_left) linetoscr_diw_start = ddf_left; if (linetoscr_diw_end > ddf_right) @@ -1573,7 +1912,7 @@ static void pfield_do_linetoscr(int start, int stop) stop = linetoscr_right_x; if (start < linetoscr_x_adjust) start = linetoscr_x_adjust; - + if (lframe_end < start) lframe_end = start; if (diw_end > stop) @@ -1584,9 +1923,19 @@ static void pfield_do_linetoscr(int start, int stop) #if AGA_CHIPSET == 0 if (start == linetoscr_x_adjust && stop == linetoscr_right_x) { - pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); + switch (gfxvidinfo.pixbytes) { + case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break; + case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break; + case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break; + case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break; + } } else { - pfield_linetoscr_16 (start, lframe_end, diw_end, stop); + switch (gfxvidinfo.pixbytes) { + case 1: pfield_linetoscr_8 (start, lframe_end, diw_end, stop); break; + case 2: pfield_linetoscr_16 (start, lframe_end, diw_end, stop); break; + case 3: pfield_linetoscr_24 (start, lframe_end, diw_end, stop); break; + case 4: pfield_linetoscr_32 (start, lframe_end, diw_end, stop); break; + } } #else pfield_linetoscr_aga(start, lframe_end, diw_end, stop); @@ -1603,13 +1952,17 @@ static void pfield_do_fill_line(int start, int stop) if (start >= stop) return; - - fill_line_16 (xlinebuffer, start, stop); + switch (gfxvidinfo.pixbytes) { + case 1: fill_line_8 (xlinebuffer, start, stop); break; + case 2: fill_line_16 (xlinebuffer, start, stop); break; + case 3: fill_line_24 (xlinebuffer, start, stop); break; + case 4: fill_line_32 (xlinebuffer, start, stop); break; + } } static void pfield_do_linetoscr_full(int double_line) { - int start = linetoscr_x_adjust, stop = start + gfxvidinfo.maxlinetoscr; + int start = linetoscr_x_adjust, stop = start + gfxvidinfo.width; int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end; if (lframe_end < start) lframe_end = start; @@ -1618,31 +1971,174 @@ static void pfield_do_linetoscr_full(int double_line) #if AGA_CHIPSET == 0 if (double_line) { - pfield_linetoscr_full16_double (start, lframe_end, diw_end, stop); - } else { - pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); + switch (gfxvidinfo.pixbytes) { + case 1: pfield_linetoscr_full8_double (start, lframe_end, diw_end, stop); break; + case 2: pfield_linetoscr_full16_double (start, lframe_end, diw_end, stop); break; + case 3: pfield_linetoscr_full24_double (start, lframe_end, diw_end, stop); break; + case 4: pfield_linetoscr_full32_double (start, lframe_end, diw_end, stop); break; + } + } else + switch (gfxvidinfo.pixbytes) { + case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break; + case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break; + case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break; + case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break; } #else pfield_linetoscr_aga(start, lframe_end, diw_end, stop); #endif } - /* +/* Mouse stuff */ +static void setdontcare(void) +{ + write_log ("Don't care mouse mode set\n"); + mousestate = dont_care_mouse; + lastspr0x = lastmx; lastspr0y = lastmy; + mstepx = defstepx; mstepy = defstepy; +} + +static void setfollow(void) +{ + write_log ("Follow sprite mode set\n"); + mousestate = follow_mouse; + lastdiffx = lastdiffy = 0; + sprvbfl = 0; + spr0ctl=spr0pos = 0; + mstepx = defstepx; mstepy = defstepy; +} + +uae_u32 mousehack_helper (void) +{ + int mousexpos, mouseypos; + +#ifdef PICASSO96 + if (picasso_on) { + mousexpos = lastmx + picasso96_state.XOffset; + mouseypos = lastmy + picasso96_state.YOffset; + } else +#endif + { + mousexpos = lastmx + linetoscr_x_adjust; + if (lastmy >= gfxvidinfo.height) + lastmy = gfxvidinfo.height-1; + mouseypos = native2amiga_line_map[lastmy] + thisframe_y_adjust - minfirstline; + mouseypos <<= 1; + mousexpos <<= (1-lores_shift); + mousexpos += 2*DISPLAY_LEFT_SHIFT; + } + + switch (m68k_dreg (regs, 0)) { + case 0: + return ievent_alive ? -1 : needmousehack (); + case 1: + ievent_alive = 10; + return mousexpos; + case 2: + return mouseypos; + } + return 0; +} + +void togglemouse(void) +{ + switch(mousestate) { + case dont_care_mouse: setfollow(); break; + case follow_mouse: setdontcare(); break; + default: break; /* Nnnnnghh! */ + } +} + +static __inline__ int adjust(int val) +{ + if (val>127) + return 127; + else if (val<-127) + return -127; + return val; +} + +static void do_mouse_hack(void) +{ + int spr0x = ((spr0pos & 0xff) << 2) | ((spr0ctl & 1) << 1); + int spr0y = ((spr0pos >> 8) | ((spr0ctl & 4) << 6)) << 1; + int diffx, diffy; + + if (ievent_alive > 0) { + mouse_x = mouse_y = 0; + return; + } + switch (mousestate) { + case normal_mouse: + diffx = lastmx - lastsampledmx; + diffy = lastmy - lastsampledmy; + if (!newmousecounters) { + if (diffx > 127) diffx = 127; + if (diffx < -127) diffx = -127; + mouse_x += diffx; + if (diffy > 127) diffy = 127; + if (diffy < -127) diffy = -127; + mouse_y += diffy; + } + lastsampledmx += diffx; lastsampledmy += diffy; + break; + + case dont_care_mouse: + diffx = adjust (((lastmx-lastspr0x) * mstepx) >> 16); + diffy = adjust (((lastmy-lastspr0y) * mstepy) >> 16); + lastspr0x=lastmx; lastspr0y=lastmy; + mouse_x+=diffx; mouse_y+=diffy; + break; + + case follow_mouse: + if (sprvbfl && sprvbfl-- >1) { + int mousexpos, mouseypos; + + if ((lastdiffx > docal || lastdiffx < -docal) && lastspr0x != spr0x + && spr0x > plfstrt*4 + 34 + xcaloff && spr0x < plfstop*4 - xcaloff) + { + int val = (lastdiffx << 16) / (spr0x - lastspr0x); + if (val>=0x8000) mstepx=(mstepx*(calweight-1)+val)/calweight; + } + if ((lastdiffy > docal || lastdiffy < -docal) && lastspr0y != spr0y + && spr0y>plffirstline+ycaloff && spr0y=0x8000) mstepy=(mstepy*(calweight-1)+val)/calweight; + } + mousexpos = lastmx + linetoscr_x_adjust; + if (lastmy >= gfxvidinfo.height) + lastmy = gfxvidinfo.height-1; + mouseypos = native2amiga_line_map[lastmy] + thisframe_y_adjust - minfirstline; + mouseypos <<= 1; + mousexpos <<= (1-lores_shift); + mousexpos += 2*DISPLAY_LEFT_SHIFT; + diffx = adjust ((((mousexpos + xoffs - spr0x) & ~1) * mstepx) >> 16); + diffy = adjust ((((mouseypos + yoffs - spr0y) & ~1) * mstepy) >> 16); + lastspr0x=spr0x; lastspr0y=spr0y; + lastdiffx=diffx; lastdiffy=diffy; + mouse_x+=diffx; mouse_y+=diffy; + } + break; + } +} + + /* * register functions */ -uae_u16 DMACONR(void) +__inline__ uae_u16 DMACONR(void) { return (dmacon | (bltstate==BLT_done ? 0 : 0x4000) | (blt_info.blitzero ? 0x2000 : 0)); } -static uae_u16 INTENAR(void) { return intena; } +static __inline__ uae_u16 INTENAR(void) { return intena; } uae_u16 INTREQR(void) { return intreq | (currprefs.use_serial ? 0x0001 : 0); } -static uae_u16 ADKCONR(void) { return adkcon; } -static uae_u16 VPOSR(void) +static __inline__ uae_u16 ADKCONR(void) { return adkcon; } +static __inline__ uae_u16 VPOSR(void) { #if AGA_CHIPSET == 1 return (vpos >> 8) | lof | 0x2300; @@ -1657,17 +2153,21 @@ static void VPOSW(uae_u16 v) if (lof != (v & 0x8000)) lof_changed = 1; lof = v & 0x8000; + /* + * This register is much more fun on a real Amiga. You can program + * refresh rates with it ;) But I won't emulate this... + */ } -static uae_u16 VHPOSR(void) { return (vpos << 8) | current_hpos(); } +static __inline__ uae_u16 VHPOSR(void) { return (vpos << 8) | current_hpos(); } -static void COP1LCH(uae_u16 v) { cop1lc= (cop1lc & 0xffff) | ((uae_u32)v << 16); } -static void COP1LCL(uae_u16 v) { cop1lc= (cop1lc & ~0xffff) | v; } -static void COP2LCH(uae_u16 v) { cop2lc= (cop2lc & 0xffff) | ((uae_u32)v << 16); } -static void COP2LCL(uae_u16 v) { cop2lc= (cop2lc & ~0xffff) | v; } +static __inline__ void COP1LCH(uae_u16 v) { cop1lc = (cop1lc & 0xffff) | ((uae_u32)v << 16); } +static __inline__ void COP1LCL(uae_u16 v) { cop1lc = (cop1lc & ~0xffff) | (v & 0xfffe); } +static __inline__ void COP2LCH(uae_u16 v) { cop2lc = (cop2lc & 0xffff) | ((uae_u32)v << 16); } +static __inline__ void COP2LCL(uae_u16 v) { cop2lc = (cop2lc & ~0xffff) | (v & 0xfffe); } static void COPJMP1(uae_u16 a) { - coplc = cop1lc; copstate = COP_read; + coplc = cop1lc; copstate = COP_read; eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles; eventtab[ev_copper].evtime = 4 + cycles; events_schedule(); copper_active = 1; @@ -1675,26 +2175,26 @@ static void COPJMP1(uae_u16 a) } static void COPJMP2(uae_u16 a) { - coplc = cop2lc; copstate = COP_read; + coplc = cop2lc; copstate = COP_read; eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles; eventtab[ev_copper].evtime = 4 + cycles; events_schedule(); copper_active = 1; copper_waiting_for_blitter = 0; } -static void COPCON(uae_u16 a) { copcon = a; } -static void DMACON(uae_u16 v) +static __inline__ void COPCON(uae_u16 a) { copcon = a; } +static void DMACON(uae_u16 v) { int i, need_resched = 0; uae_u16 oldcon = dmacon; - + decide_line(); setclr(&dmacon,v); dmacon &= 0x1FFF; - post_decide_line (); - - /* FIXME? Maybe we need to think a bit more about the master DMA enable + /* ??? post_decide_line (); */ + + /* FIXME? Maybe we need to think a bit more about the master DMA enable * bit in these cases. */ - if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) { + if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) { COPJMP1(0); } if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done) { @@ -1708,7 +2208,7 @@ static void DMACON(uae_u16 v) #ifndef DONT_WANT_SOUND for (i = 0; i < 4; i++) { struct audio_channel_data *cdp = audio_channel + i; - + cdp->dmaen = (dmacon & 0x200) && (dmacon & (1<dmaen) { if (cdp->state == 0) { @@ -1745,25 +2245,46 @@ static void DMACON(uae_u16 v) /*static int trace_intena = 0;*/ -static void INTENA(uae_u16 v) +static __inline__ void INTENA (uae_u16 v) { /* if (trace_intena) fprintf(stderr, "INTENA: %04x\n", v);*/ - setclr(&intena,v); regs.spcflags |= SPCFLAG_INT; + setclr(&intena,v); regs.spcflags |= SPCFLAG_INT; } -void INTREQ(uae_u16 v) +void INTREQ (uae_u16 v) { setclr(&intreq,v); regs.spcflags |= SPCFLAG_INT; if ((v&0x8800)==0x0800) serdat&=0xbfff; } -static void ADKCON(uae_u16 v) { setclr(&adkcon,v); } +static void ADKCON (uae_u16 v) +{ + unsigned long t; + setclr (&adkcon,v); + t = adkcon | (adkcon >> 4); + audio_channel[0].adk_mask = (((t >> 0) & 1) - 1); + audio_channel[1].adk_mask = (((t >> 1) & 1) - 1); + audio_channel[2].adk_mask = (((t >> 2) & 1) - 1); + audio_channel[3].adk_mask = (((t >> 3) & 1) - 1); +} -static void BPLPTH(uae_u16 v, int num) { decide_line (); decide_plane(); do_modulos(); bplpt[num] = (bplpt[num] & 0xffff) | ((uae_u32)v << 16); } -static void BPLPTL(uae_u16 v, int num) { decide_line (); decide_plane(); do_modulos(); bplpt[num] = (bplpt[num] & ~0xffff) | (v & 0xFFFE); } +static void BPLPTH (uae_u16 v, int num) +{ + decide_line (); + decide_plane(); + do_modulos(); + bplpt[num] = (bplpt[num] & 0xffff) | ((uae_u32)v << 16); +} +static void BPLPTL (uae_u16 v, int num) +{ + decide_line (); + decide_plane(); + do_modulos(); + bplpt[num] = (bplpt[num] & ~0xffff) | (v & 0xfffe); +} -static void BPLCON0(uae_u16 v) +static void BPLCON0 (uae_u16 v) { #if AGA_CHIPSET == 0 v &= 0xFF0E; @@ -1787,7 +2308,7 @@ static void BPLCON0(uae_u16 v) calcdiw(); /* This should go away. */ #endif } -static void BPLCON1(uae_u16 v) +static __inline__ void BPLCON1 (uae_u16 v) { if (bplcon1 == v) return; @@ -1795,26 +2316,26 @@ static void BPLCON1(uae_u16 v) bplcon1 = v; decide_delay (); } -static void BPLCON2(uae_u16 v) +static __inline__ void BPLCON2 (uae_u16 v) { if (bplcon2 != v) decide_line (); bplcon2 = v; } -static void BPLCON3(uae_u16 v) +static __inline__ void BPLCON3 (uae_u16 v) { if (bplcon3 != v) decide_line (); - bplcon3 = v; + bplcon3 = v; } -static void BPLCON4(uae_u16 v) +static __inline__ void BPLCON4 (uae_u16 v) { if (bplcon4 != v) decide_line (); - bplcon4 = v; + bplcon4 = v; } -static void BPL1MOD(uae_u16 v) +static void BPL1MOD (uae_u16 v) { v &= ~1; if ((uae_s16)bpl1mod == (uae_s16)v) @@ -1823,8 +2344,8 @@ static void BPL1MOD(uae_u16 v) decide_modulos (); } -static void BPL2MOD(uae_u16 v) -{ +static void BPL2MOD (uae_u16 v) +{ v &= ~1; if ((uae_s16)bpl2mod == (uae_s16)v) return; @@ -1833,39 +2354,39 @@ static void BPL2MOD(uae_u16 v) } /* We could do as well without those... */ -static void BPL1DAT(uae_u16 v) { bpl1dat = v; } -static void BPL2DAT(uae_u16 v) { bpl2dat = v; } -static void BPL3DAT(uae_u16 v) { bpl3dat = v; } -static void BPL4DAT(uae_u16 v) { bpl4dat = v; } -static void BPL5DAT(uae_u16 v) { bpl5dat = v; } -static void BPL6DAT(uae_u16 v) { bpl6dat = v; } +static __inline__ void BPL1DAT (uae_u16 v) { bpl1dat = v; } +static __inline__ void BPL2DAT (uae_u16 v) { bpl2dat = v; } +static __inline__ void BPL3DAT (uae_u16 v) { bpl3dat = v; } +static __inline__ void BPL4DAT (uae_u16 v) { bpl4dat = v; } +static __inline__ void BPL5DAT (uae_u16 v) { bpl5dat = v; } +static __inline__ void BPL6DAT (uae_u16 v) { bpl6dat = v; } -static void DIWSTRT(uae_u16 v) +static void DIWSTRT (uae_u16 v) { if (diwstrt == v) return; decide_line (); - diwstrt = v; + diwstrt = v; calcdiw(); } -static void DIWSTOP(uae_u16 v) +static void DIWSTOP (uae_u16 v) { if (diwstop == v) return; - diwstop = v; + diwstop = v; calcdiw(); } -static void DDFSTRT(uae_u16 v) -{ +static void DDFSTRT (uae_u16 v) +{ v &= 0xFF; if (ddfstrt == v) return; decide_line (); - ddfstrt = v; + ddfstrt = v; calcdiw(); } -static void DDFSTOP(uae_u16 v) -{ +static void DDFSTOP (uae_u16 v) +{ v &= 0xFF; if (ddfstop == v) return; @@ -1874,7 +2395,7 @@ static void DDFSTOP(uae_u16 v) calcdiw(); } -static void BLTADAT(uae_u16 v) +static void BLTADAT(uae_u16 v) { maybe_blit(); @@ -1887,7 +2408,7 @@ static void BLTADAT(uae_u16 v) */ static void BLTBDAT(uae_u16 v) { - maybe_blit(); + maybe_blit(); if (bltcon1 & 2) blt_info.bltbhold = v << (bltcon1 >> 12); @@ -1903,7 +2424,7 @@ static void BLTCMOD(uae_u16 v) { maybe_blit(); blt_info.bltcmod = (uae_s16)(v & static void BLTDMOD(uae_u16 v) { maybe_blit(); blt_info.bltdmod = (uae_s16)(v & 0xFFFE); } static void BLTCON0(uae_u16 v) { maybe_blit(); bltcon0 = v; blinea_shift = v >> 12; } -/* The next category is "Most useless hardware register". +/* The next category is "Most useless hardware register". * And the winner is... */ static void BLTCON0L(uae_u16 v) { maybe_blit(); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF); } static void BLTCON1(uae_u16 v) { maybe_blit(); bltcon1 = v; } @@ -1911,31 +2432,31 @@ static void BLTCON1(uae_u16 v) { maybe_blit(); bltcon1 = v; } static void BLTAFWM(uae_u16 v) { maybe_blit(); blt_info.bltafwm = v; } static void BLTALWM(uae_u16 v) { maybe_blit(); blt_info.bltalwm = v; } -static void BLTAPTH(uae_u16 v) { maybe_blit(); bltapt= (bltapt & 0xffff) | ((uae_u32)v << 16); } -static void BLTAPTL(uae_u16 v) { maybe_blit(); bltapt= (bltapt & ~0xffff) | (v & 0xFFFE); } -static void BLTBPTH(uae_u16 v) { maybe_blit(); bltbpt= (bltbpt & 0xffff) | ((uae_u32)v << 16); } -static void BLTBPTL(uae_u16 v) { maybe_blit(); bltbpt= (bltbpt & ~0xffff) | (v & 0xFFFE); } -static void BLTCPTH(uae_u16 v) { maybe_blit(); bltcpt= (bltcpt & 0xffff) | ((uae_u32)v << 16); } -static void BLTCPTL(uae_u16 v) { maybe_blit(); bltcpt= (bltcpt & ~0xffff) | (v & 0xFFFE); } -static void BLTDPTH(uae_u16 v) { maybe_blit(); bltdpt= (bltdpt & 0xffff) | ((uae_u32)v << 16); } -static void BLTDPTL(uae_u16 v) { maybe_blit(); bltdpt= (bltdpt & ~0xffff) | (v & 0xFFFE); } -static void BLTSIZE(uae_u16 v) +static void BLTAPTH(uae_u16 v) { maybe_blit(); bltapt = (bltapt & 0xffff) | ((uae_u32)v << 16); } +static void BLTAPTL(uae_u16 v) { maybe_blit(); bltapt = (bltapt & ~0xffff) | (v & 0xFFFE); } +static void BLTBPTH(uae_u16 v) { maybe_blit(); bltbpt = (bltbpt & 0xffff) | ((uae_u32)v << 16); } +static void BLTBPTL(uae_u16 v) { maybe_blit(); bltbpt = (bltbpt & ~0xffff) | (v & 0xFFFE); } +static void BLTCPTH(uae_u16 v) { maybe_blit(); bltcpt = (bltcpt & 0xffff) | ((uae_u32)v << 16); } +static void BLTCPTL(uae_u16 v) { maybe_blit(); bltcpt = (bltcpt & ~0xffff) | (v & 0xFFFE); } +static void BLTDPTH(uae_u16 v) { maybe_blit(); bltdpt = (bltdpt & 0xffff) | ((uae_u32)v << 16); } +static void BLTDPTL(uae_u16 v) { maybe_blit(); bltdpt = (bltdpt & ~0xffff) | (v & 0xFFFE); } +static void BLTSIZE(uae_u16 v) { bltsize = v; - - maybe_blit(); + + maybe_blit(); blt_info.vblitsize = bltsize >> 6; blt_info.hblitsize = bltsize & 0x3F; if (!blt_info.vblitsize) blt_info.vblitsize = 1024; if (!blt_info.hblitsize) blt_info.hblitsize = 64; - - bltstate = BLT_init; + + bltstate = BLT_init; do_blitter(); } -static void BLTSIZV(uae_u16 v) +static void BLTSIZV(uae_u16 v) { - maybe_blit(); + maybe_blit(); oldvblts = v & 0x7FFF; } static void BLTSIZH(uae_u16 v) @@ -1948,10 +2469,11 @@ static void BLTSIZH(uae_u16 v) bltstate = BLT_init; do_blitter(); } -static void SPRxCTL_1(uae_u16 v, int num) +static __inline__ void SPRxCTL_1(uae_u16 v, int num) { int sprxp; sprctl[num] = v; + nr_armed -= sprarmed[num]; sprarmed[num] = 0; if (sprpos[num] == 0 && v == 0) { sprst[num] = SPR_stop; @@ -1966,7 +2488,7 @@ static void SPRxCTL_1(uae_u16 v, int num) sprvstart[num] = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100); sprvstop[num] = (sprctl[num] >> 8) | ((sprctl[num] << 7) & 0x100); } -static void SPRxPOS_1(uae_u16 v, int num) +static __inline__ void SPRxPOS_1(uae_u16 v, int num) { int sprxp; sprpos[num] = v; @@ -1976,36 +2498,37 @@ static void SPRxPOS_1(uae_u16 v, int num) sprxpos[num] = sprxp; sprvstart[num] = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100); } -static void SPRxDATA_1(uae_u16 v, int num) +static __inline__ void SPRxDATA_1(uae_u16 v, int num) { sprdata[num] = v; + nr_armed += 1 - sprarmed[num]; sprarmed[num] = 1; } -static void SPRxDATB_1(uae_u16 v, int num) +static __inline__ void SPRxDATB_1(uae_u16 v, int num) { sprdatb[num] = v; } -static void SPRxDATA(uae_u16 v, int num) { decide_sprite (num); SPRxDATA_1 (v, num); } -static void SPRxDATB(uae_u16 v, int num) { decide_sprite (num); SPRxDATB_1 (v, num); } -static void SPRxCTL(uae_u16 v, int num) { decide_sprite (num); SPRxCTL_1 (v, num); } -static void SPRxPOS(uae_u16 v, int num) { decide_sprite (num); SPRxPOS_1 (v, num); } +static void SPRxDATA(uae_u16 v, int num) { decide_sprites (); SPRxDATA_1 (v, num); } +static void SPRxDATB(uae_u16 v, int num) { decide_sprites (); SPRxDATB_1 (v, num); } +static void SPRxCTL(uae_u16 v, int num) { decide_sprites (); SPRxCTL_1 (v, num); } +static void SPRxPOS(uae_u16 v, int num) { decide_sprites (); SPRxPOS_1 (v, num); } static void SPRxPTH(uae_u16 v, int num) { decide_line (); - sprpt[num] &= 0xffff; + sprpt[num] &= 0xffff; sprpt[num] |= (uae_u32)v << 16; - if (sprst[num] == SPR_stop) + if (sprst[num] == SPR_stop || vpos < vblank_endline) sprst[num] = SPR_restart; spron[num] = 1; } static void SPRxPTL(uae_u16 v, int num) { decide_line (); - sprpt[num] &= ~0xffff; + sprpt[num] &= ~0xffff; sprpt[num] |= v; - if (sprst[num] == SPR_stop) + if (sprst[num] == SPR_stop || vpos < vblank_endline) sprst[num] = SPR_restart; spron[num] = 1; } @@ -2025,7 +2548,7 @@ static void COLOR(uae_u16 v, int num) int r,g,b; int cr,cg,cb; int colreg; - + v &= 0xFFF; #if AGA_CHIPSET == 1 { @@ -2054,7 +2577,7 @@ static void COLOR(uae_u16 v, int num) color_regs[colreg] = cval; pfield_may_need_update(1); } -#else +#else { if (current_colors.color_regs[num] == v) return; @@ -2067,69 +2590,117 @@ static void COLOR(uae_u16 v, int num) #endif } - static void DSKSYNC(uae_u16 v) { dsksync = v; } static void DSKDAT(uae_u16 v) { write_log ("DSKDAT written. Not good.\n"); } static void DSKPTH(uae_u16 v) { dskpt = (dskpt & 0xffff) | ((uae_u32)v << 16); } static void DSKPTL(uae_u16 v) { dskpt = (dskpt & ~0xffff) | (v); } -static void DSKLEN(uae_u16 v) +static void DSKLEN (uae_u16 v) { if (v & 0x8000) { - dskdmaen = dskdmaen == 1 ? 2 : 1; - } else { - dskdmaen = 0; - if (eventtab[ev_diskblk].active) - write_log ("warning: Disk DMA aborted!\n"); - eventtab[ev_diskblk].active = 0; - events_schedule(); - + dskdmaen = dskdmaen == 1 ? 2 : 1; + } else { + dskdmaen = 0; + if (eventtab[ev_diskblk].active) + write_log ("warning: Disk DMA aborted!\n"); + eventtab[ev_diskblk].active = 0; + events_schedule(); } dsklen = dsklength = v; dsklength &= 0x3fff; if (dskdmaen == 2 && dsksync != 0x4489 && (adkcon & 0x400)) { - //sprintf (warning_buffer, "Non-standard sync: %04x len: %x\n", dsksync, dsklength); - //write_log (warning_buffer); + //write_log ("Non-standard sync: %04x len: %x\n", dsksync, dsklength); } - if (dskdmaen > 1) { - if (dsklen & 0x4000) { - eventtab[ev_diskblk].active = 1; - eventtab[ev_diskblk].oldcycles = cycles; - eventtab[ev_diskblk].evtime = 40 + cycles; - events_schedule(); - } else { - int result = DISK_PrepareReadMFM(dsklength, dsksync, adkcon & 0x400); - if (result) { - eventtab[ev_diskblk].active = 1; - eventtab[ev_diskblk].oldcycles = cycles; - eventtab[ev_diskblk].evtime = result + cycles; - events_schedule(); - } - } + if (dskdmaen <= 1) + return; + + if (dsklen & 0x4000) { + eventtab[ev_diskblk].active = 1; + eventtab[ev_diskblk].oldcycles = cycles; + eventtab[ev_diskblk].evtime = 40 + cycles; /* ??? */ + events_schedule(); + dskdmaen = 3; + } else { + DISK_StartRead (); + syncfound = !(adkcon & 0x400); } } -static uae_u16 DSKBYTR(void) +static int update_disk_reads (void) +{ + int retval = 0; + /* If we get called from DSKBYTR or DSKDATR, we may not actually be + reading from disk, so skip the DMA update. */ + if (dskdmaen != 2) { + DISK_update_reads (0, 0, 0, 0); + return 0; + } + if (dsklength == 0) + write_log ("Bug in disk code: dsklength == 0\n"); + else + retval = DISK_update_reads (&dskpt, &dsklength, &syncfound, dsksync); + + if (dsklength == 0) { + dskdmaen = -1; + /* DISKBLK */ + INTREQ (0x8002); + } + return retval; +} + +static void disksync_handler (void) +{ + uae_u16 mfm, byte; + + eventtab[ev_disksync].active = 0; + + /* If no DMA, something weird happened. It's not clear what to do + about it. */ + if (! dmaen (0x10) || dskdmaen != 2) + return; + + /* Likewise... */ + if (! update_disk_reads ()) + return; + DISK_GetData (&mfm, &byte); + + if (dsksync == mfm) + INTREQ (0x9000); +} + + +static uae_u16 DSKBYTR (void) { uae_u16 v = (dsklen >> 1) & 0x6000; uae_u16 mfm, byte; - if (DISK_GetData(&mfm, &byte)) - v |= 0x8000; + if (update_disk_reads ()) + v |= 0x8000; + DISK_GetData (&mfm, &byte); v |= byte; - if (dsksync == mfm) v |= 0x1000; + if (dsksync == mfm) + v |= 0x1000; return v; } -static uae_u16 DSKDATR(void) +static uae_u16 DSKDATR (void) { uae_u16 mfm, byte; - DISK_GetData(&mfm, &byte); - return mfm; + update_disk_reads (); + DISK_GetData (&mfm, &byte); + return mfm; } +static uae_u16 potgo_value; + +static void POTGO(uae_u16 v) +{ + potgo_value = v; +} static uae_u16 POTGOR(void) { - uae_u16 v = 0xFF00; + uae_u16 v = (potgo_value | (potgo_value << 1)) & 0xAA00; + v |= v >> 1; + if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) { if (buttonstate[2]) v &= 0xFBFF; @@ -2138,15 +2709,15 @@ static uae_u16 POTGOR(void) v &= 0xFEFF; } else if (JSEM_ISJOY0(0, currprefs.fake_joystick) || JSEM_ISJOY1(0, currprefs.fake_joystick)) { - if (joy0button & 2) v &= 0xfbff; - if (joy0button & 4) v &= 0xfeff; + if (joy0button & 2) v &= 0xfbff; + if (joy0button & 4) v &= 0xfeff; } if (JSEM_ISJOY0(1, currprefs.fake_joystick) || JSEM_ISJOY1(1, currprefs.fake_joystick)) { - if (joy1button & 2) v &= 0xbfff; - if (joy1button & 4) v &= 0xefff; + if (joy1button & 2) v &= 0xbfff; + if (joy1button & 4) v &= 0xefff; } - + return v; } static uae_u16 POT0DAT(void) @@ -2164,6 +2735,7 @@ static uae_u16 POT0DAT(void) static uae_u16 JOY0DAT(void) { if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) { + do_mouse_hack(); return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8); } return joy0dir; @@ -2171,6 +2743,7 @@ static uae_u16 JOY0DAT(void) static uae_u16 JOY1DAT(void) { if (JSEM_ISMOUSE (1, currprefs.fake_joystick)) { + do_mouse_hack(); return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8); } return joy1dir; @@ -2182,26 +2755,6 @@ static void JOYTEST(uae_u16 v) mouse_y = (v >> 8) & 0xFC; } } -static void AUDxLCH(int nr, uae_u16 v) { audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((uae_u32)v << 16); } -static void AUDxLCL(int nr, uae_u16 v) { audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE); } -static void AUDxPER(int nr, uae_u16 v) -{ - if (v <= 0) { -#if 0 /* v == 0 is rather common, and harmless, and the value isn't signed anyway */ - static int warned = 0; - if (!warned) - write_log ("Broken program accessing the sound hardware\n"), warned++; -#endif - v = 65535; - } - if (v < maxhpos/2 && currprefs.produce_sound < 3) - v = maxhpos/2; - - audio_channel[nr].per = v; -} - -static void AUDxVOL(int nr, uae_u16 v) { audio_channel[nr].vol = v & 64 ? 63 : v & 63; } -static void AUDxLEN(int nr, uae_u16 v) { audio_channel[nr].len = v; } /* * Here starts the copper code. It should be rewritten. @@ -2213,7 +2766,7 @@ static void AUDxLEN(int nr, uae_u16 v) { audio_channel[nr].len = v; } * copper comparison becomes true. This is quite tricky. I hope it works. */ static int calc_copcomp_true(int currvpos, int currhpos) -{ +{ uae_u16 vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80); uae_u16 hp = currhpos & (copi2 & 0xFE); uae_u16 vcmp = ((copi1 & (copi2 | 0x8000)) >> 8); @@ -2221,6 +2774,8 @@ static int calc_copcomp_true(int currvpos, int currhpos) int copper_time_hpos; int cycleadd = maxhpos - currhpos; int coptime = 0; + int maxwait = 32767; + #if COPPER_ALTERNATIVE == 0 /* This is a kludge... the problem is that there are programs that wait for * FFDDFFFE and then for a line in the second display half, and this doesn't @@ -2231,8 +2786,17 @@ static int calc_copcomp_true(int currvpos, int currhpos) if (hcmp == 0xDC) hcmp += 2; #endif + decide_line(); + /* Copper DMA is turned off in Hires 4 bitplane mode */ + if (vp == vcmp + && decided_nr_planes == 4 /* -1 if before plfstrt */ + && decided_hires + && currhpos >= thisline_decision.plfstrt + && currhpos < thisline_decision.plfstrt + thisline_decision.plflinelen) + coptime += thisline_decision.plfstrt + thisline_decision.plflinelen - currhpos; + if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000))) - return 0; + return coptime; try_again: @@ -2245,11 +2809,16 @@ static int calc_copcomp_true(int currvpos, int currhpos) cycleadd = maxhpos; vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80); } - if (coptime > 0 && (bplcon0 & 0xF000) == 0xC000) - return coptime; + if ((bplcon0 & 0xF000) == 0xC000) { + if (coptime > 0) + return coptime; + maxwait = plfstrt - current_hpos(); + if (maxwait < 0) + maxwait = 32767; + } copper_time_hpos = currhpos; hp = copper_time_hpos & (copi2 & 0xFE); - if (!(vp > vcmp)) { + if (!(vp > vcmp)) { while ((int)hp < ((int)hcmp)) { currhpos++; /* Copper DMA is turned off in Hires 4 bitplane mode */ @@ -2257,7 +2826,7 @@ static int calc_copcomp_true(int currvpos, int currhpos) || !decided_hires || current_hpos () >= (thisline_decision.plfstrt + thisline_decision.plflinelen)) copper_time_hpos++; - + if (currhpos > maxhpos) { /* Now, what? There might be a good position on the * next line. But it can also be the FFFF FFFE @@ -2269,11 +2838,13 @@ static int calc_copcomp_true(int currvpos, int currhpos) goto try_again; } coptime++; + if (coptime >= maxwait) + return coptime; hp = copper_time_hpos & (copi2 & 0xFE); } } if (coptime == 0) /* waiting for the blitter */ - return 1; + return 1; return coptime; } @@ -2282,7 +2853,7 @@ static int calc_copcomp_true(int currvpos, int currhpos) * Simple version of the above which only tries to get vpos correct. */ static int calc_copcomp_true_vpos(int currvpos, int currhpos) -{ +{ uae_u16 vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80); uae_u16 hp = currhpos & (copi2 & 0xFE); uae_u16 vcmp = ((copi1 & (copi2 | 0x8000)) >> 8); @@ -2296,7 +2867,7 @@ static int calc_copcomp_true_vpos(int currvpos, int currhpos) hcmp += 2; #endif if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000))) - return 0; + return 0; while (vp < vcmp) { currvpos++; @@ -2331,7 +2902,7 @@ static int copper_memory_cycles (int n) continue; } #endif - if (copper_cycle_time == -1 && current_cycle >= 0x14 + if (copper_cycle_time == -1 && current_cycle >= 0x14 && current_cycle >= plfstrt && current_cycle < plfstrt + plflinelen && (planes == 6 || (planes == 5 && (current_cycle % 8) < 4))) { @@ -2339,7 +2910,7 @@ static int copper_memory_cycles (int n) current_cycle += 4; } else { n_needed += 2; - current_cycle += 2; + current_cycle += 2; } if (current_cycle >= maxhpos) current_cycle -= maxhpos; @@ -2370,12 +2941,12 @@ static __inline__ int copper_init_read (int n_cycles) static __inline__ void copper_read (void) { int cmd; - - copi1 = chipmem_bank.wget(coplc); + + copi1 = chipmem_bank.wget(coplc); copi2 = chipmem_bank.wget(coplc+2); coplc += 4; eventtab[ev_copper].oldcycles = cycles; - + cmd = (copi1 & 1) | ((copi2 & 1) << 1); copstate = cop_cmds[cmd]; eventtab[ev_copper].oldcycles = cycles; @@ -2404,6 +2975,86 @@ void blitter_done_notify (void) } } +#if 0 +static void do_copper_cheat(void) +{ + int coptime, t; + int nmoves = 100; /*??*/ + int nextcycles = eventtab[ev_hsync].evtime + currprefs.copper_pos; + + eventtab[ev_copper].evtime = nextcycles; + eventtab[ev_copper].oldcycles = cycles; + nextcycles -= cycles; + + if (!dmaen(DMA_COPPER)) { + eventtab[ev_copper].active = 0; + return; + } + for (; nmoves; nmoves--) + switch(copstate){ + case COP_read: + copper_read (); + break; + + case COP_read_ignore: + copper_read (); + copstate = COP_read; + break; + + case COP_move: + if (copi1 >= (copcon & 2 ? 0x40u : 0x80u)) { + custom_bank.wput(copi1,copi2); + copstate = COP_read; + } else { + copstate = COP_stop; + eventtab[ev_copper].active = 0; + copper_active = 0; + return; + } + break; + + case COP_skip: + copstate = COP_read; + if (calc_copcomp_true(vpos, current_hpos()) == 0) + copstate = COP_read_ignore; + break; + + case COP_wait: + coptime = calc_copcomp_true(vpos, current_hpos()); + if (coptime < 0) { + copstate = COP_stop; + eventtab[ev_copper].active = 0; + copper_active = 0; + return; + } + if (coptime == 0) { + copper_read(); + if (vpos != 255) + break; + eventtab[ev_copper].evtime = cycles + 6; + return; + } + if (coptime >= nextcycles) + return; + if (vpos == 255) + eventtab[ev_copper].evtime = cycles + coptime; + /*else + copstate = COP_read;*/ + return; + + case COP_stop: + eventtab[ev_copper].active = 0; + copper_active = 0; + return; + + case COP_morewait: + case COP_do_read: + case COP_do_read_ignore: + abort(); + } +} +#endif + static void do_copper(void) { int coptime, t; @@ -2415,7 +3066,7 @@ static void do_copper(void) return; copstate = COP_do_read; return; - + case COP_do_read: copper_read (); break; @@ -2509,56 +3160,88 @@ static void do_copper(void) } } + + +static void diskblk_handler (void) +{ + eventtab[ev_diskblk].active = 0; + + if (dskdmaen != 3) { + static int warned = 0; + if (!warned) + warned++, write_log ("BUG!\n"); + return; + } + if (dmaen (0x10)){ + if (dsklen & 0x4000) { + if (!chipmem_bank.check (dskpt, 2*dsklength)) { + write_log ("warning: Bad disk write DMA pointer\n"); + } else { +#ifdef HAS_FLOPPYWRITE + uae_u8 *mfmp = get_real_address (dskpt); + int i; + DISK_InitWrite(); + + for (i = 0; i < dsklength; i++) { + uae_u16 d = (*mfmp << 8) + *(mfmp+1); + mfmwrite[i] = d; + mfmp += 2; + } + DISK_WriteData(dsklength); +#endif + } + } else + write_log ("warning: diskblk_handler trying to read!\n"); + INTREQ(0x9002); + dskdmaen = -1; + } +} + +/* static void diskblk_handler(void) { regs.spcflags |= SPCFLAG_DISK; eventtab[ev_diskblk].active = 0; } - - void do_disk(void) { if (dskdmaen != 2 && (regs.spcflags & SPCFLAG_DISK)) { - //static int warned = 0; - //if (!warned) - // warned++, write_log ("BUG!\n"); - //return; + static int warned = 0; + if (!warned) + warned++, write_log ("BUG!\n"); + return; } if (dmaen(0x10)){ - if (dsklen & 0x4000) { - if (!chipmem_bank.check (dskpt, 2*dsklength)) { - write_log ("warning: Bad disk write DMA pointer\n"); - } else { - uae_u8 *mfmp = get_real_address (dskpt); - int i; - DISK_InitWrite(); - - for (i = 0; i < dsklength; i++) { - // JMH no write: uae_u16 d = (*mfmp << 8) + *(mfmp+1); - // mfmwrite[i] = d; - mfmp += 2; - } - DISK_WriteData(dsklength); - } - } else { - int result = DISK_ReadMFM (dskpt); - } - regs.spcflags &= ~SPCFLAG_DISK; - INTREQ(0x9002); - dskdmaen = -1; + if (dsklen & 0x4000) { + if (!chipmem_bank.check (dskpt, 2*dsklength)) { + write_log ("warning: Bad disk write DMA pointer\n"); + } else { + uae_u8 *mfmp = get_real_address (dskpt); + int i; + // + //DISK_InitWrite(); + //for (i = 0; i < dsklength; i++) { + // uae_u16 d = (*mfmp << 8) + *(mfmp+1); + // mfmwrite[i] = d; + // mfmp += 2; + //} + //DISK_WriteData(dsklength); + + } + } else { + int result = DISK_ReadMFM (dskpt); + } + regs.spcflags &= ~SPCFLAG_DISK; + INTREQ(0x9002); + dskdmaen = -1; } } +*/ - -static uae_u32 hirestab_h[256][2]; -static uae_u32 lorestab_h[256][4]; - -static uae_u32 hirestab_l[256][1]; -static uae_u32 lorestab_l[256][2]; - -static uae_u32 sprtaba[256],sprtabb[256]; -static uae_u32 clxtab[256]; +void do_disk(void) +{ +} static void gen_pfield_tables(void) { @@ -2571,7 +3254,7 @@ static void gen_pfield_tables(void) uae_u32 a, b, c, d; } bar; } baz; - + for (i = 0; i < 256; i++) { /* We lose every second pixel in HiRes if UAE runs in a 320x200 screen. */ baz.foo.a = i & 64 ? 1 : 0; @@ -2579,7 +3262,7 @@ static void gen_pfield_tables(void) baz.foo.c = i & 4 ? 1 : 0; baz.foo.d = i & 1 ? 1 : 0; hirestab_l[i][0] = baz.bar.a; - + baz.foo.a = i & 128 ? 1 : 0; baz.foo.b = i & 64 ? 1 : 0; baz.foo.c = i & 32 ? 1 : 0; @@ -2606,7 +3289,7 @@ static void gen_pfield_tables(void) | (((i & 12) && (i & 192)) << 13) | (((i & 48) && (i & 192)) << 14)); } - + for (i = 0; i < 256; i++) { baz.foo.a = i & 128 ? 1 : 0; baz.foo.b = i & 64 ? 1 : 0; @@ -2618,7 +3301,7 @@ static void gen_pfield_tables(void) baz.foo.h = i & 1 ? 1 : 0; hirestab_h[i][0] = baz.bar.a; hirestab_h[i][1] = baz.bar.b; - + baz.foo.a = i & 128 ? 1 : 0; baz.foo.b = i & 128 ? 1 : 0; baz.foo.c = i & 64 ? 1 : 0; @@ -2643,8 +3326,7 @@ static void gen_pfield_tables(void) } static void do_sprites(int currvp, int currhp) -{ - +{ int i; /* The graph in the HRM, p. 195 seems to indicate that sprite 0 is * fetched at cycle 0x14 and thus can't be disabled by bitplane DMA. */ @@ -2652,7 +3334,7 @@ static void do_sprites(int currvp, int currhp) #if 0 if (currvp == 0) return; -#else +#else /* I don't know whether this is right. Some programs write the sprite pointers * directly at the start of the copper list. With the currvp==0 check, the * first two words of data are read on the second line in the frame. The problem @@ -2662,7 +3344,7 @@ static void do_sprites(int currvp, int currhp) * is disabled until the end of the vertical blanking interval. The HRM * isn't clear - it says that the vertical sprite position can be set to any * value, but this wouldn't be the first mistake... */ - /* Update: I modified one of the programs to write the sprite pointers the + /* Update: I modified one of the programs to write the sprite pointers the * second time only _after_ the VBlank interval, and it showed the same behaviour * as it did unmodified under UAE with the above check. This indicates that the * solution below is correct. */ @@ -2696,7 +3378,7 @@ static void do_sprites(int currvp, int currhp) uae_u16 data1 = chipmem_bank.wget(sprpt[i]); uae_u16 data2 = chipmem_bank.wget(sprpt[i]+2); sprpt[i] += 4; - + if (fetch == 1) { /* Hack for X mouse auto-calibration */ if (i == 0 && !sprvbfl && ((sprpos[0] & 0xff) << 2) > 2 * DISPLAY_LEFT_SHIFT) { @@ -2714,186 +3396,381 @@ static void do_sprites(int currvp, int currhp) } } -#if AGA_CHIPSET == 0 -static void pfield_sprite (int num, int sprxp, uae_u32 data, uae_u32 datb, int ctl) +static uae_u32 attach_2nd; + +static uae_u32 do_sprite_collisions (struct sprite_draw *spd, int prev_overlap, int i, int nr_spr) { - int sprx_inc; - int *lookup = bpldualpf ? (bpldualpfpri ? dblpf_ind2 : dblpf_ind1) : linear_map_256; - int *lookup_no = bpldualpf ? (bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1) : lots_of_twos; - uae_u32 colors; - int old_sprxp = sprxp; + int j; + int sprxp = spd[i].linepos; + uae_u32 datab = spd[i].datab; + uae_u32 mask2 = 0; + int sbit = 1 << spd[i].num; + int sprx_shift = 1; + int attach_compare = -1; + if (currprefs.gfx_lores != 1) + sprx_shift = 0; - colors = ((sprtaba[data & 0xFF] << 16) | sprtaba[data >> 8] - | (sprtabb[datb & 0xFF] << 16) | sprtabb[datb >> 8]); + attach_2nd = 0; + if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80) + attach_compare = spd[i].num - 1; - sprx_inc = 1; - if (currprefs.gfx_lores == 0) - sprx_inc = 2; -#ifdef LORES_HACK - else if (currprefs.gfx_lores == 2) - sprxp >>= 1; -#endif - - if ((ctl & 0x80) && (num & 1)) { - int mask = 1 << num; - int i; - /* Attached sprite */ - for(i = 0; i < 16; i++, sprxp += sprx_inc, colors >>= 2) { - int plno; - int col; - - /* Check the priority, but only if we did not already put a sprite - * pixel at this position. If there's already a sprite pixel here, - * the priority was previously tested. */ - if (spixstate[sprxp] == 0) { - /* ??? What about hires mode when one hires pixel is 0, enabling the - * sprite, and the other is != 0, blocking it? */ - plno = lookup_no[pixdata.apixels[sprxp]]; - if (plno != 0 && mask >= plfpri[plno]) - continue; - } - col = (colors & 3) << 2; - spixstate[sprxp] |= mask >> 1; - spixels[sprxp] = col; - /* This would not be necessary if we knew that attached sprites are - * always kept together. */ - if (col) { - col += 16; - pixdata.apixels[sprxp] = col; - spixstate[sprxp] |= mask; -#ifdef SPRITE_COLLISIONS - clxdat |= clxtab[spixstate[sprxp] & clx_sprmask]; -#endif - if (!currprefs.gfx_lores) { - pixdata.apixels[sprxp+1] = col; - spixstate[sprxp+1] |= mask; + for (j = prev_overlap; j < i; j++) { + uae_u32 mask1; + int off; + + if (spd[i].num < spd[j].num) + continue; + + off = sprxp - spd[j].linepos; + off <<= sprx_shift; + mask1 = spd[j].datab >> off; + + /* If j is an attachment for i, then j doesn't block i */ + if (spd[j].num == attach_compare) { + attach_2nd |= mask1; + } else { + mask1 |= (mask1 & 0xAAAAAAAA) >> 1; + mask1 |= (mask1 & 0x55555555) << 1; + if (datab & mask1) + clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask]; + mask2 |= mask1; + } + } + for (j = i+1; j < nr_spr; j++) { + uae_u32 mask1; + int off = spd[j].linepos - sprxp; + + if (off >= sprite_width || spd[i].num < spd[j].num) + break; + + off <<= sprx_shift; + mask1 = spd[j].datab << off; + + /* If j is an attachment for i, then j doesn't block i */ + if (spd[j].num == attach_compare) { + attach_2nd |= mask1; + } else { + mask1 |= (mask1 & 0xAAAAAAAA) >> 1; + mask1 |= (mask1 & 0x55555555) << 1; + if (datab & mask1) + clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask]; + mask2 |= mask1; + } + } + datab &= ~mask2; + return datab; +} + +static __inline__ void render_sprite (int spr, int sprxp, uae_u32 datab, int ham, int attch, int sprx_inc) +{ + uae_u32 datcd; + int basecol = 16; + if (!attch) + basecol += (spr & ~1)*2; + if (bpldualpf) + basecol |= 128; + if (attch) + datcd = attach_2nd; + + for(; attch ? datab | datcd : datab; sprxp += sprx_inc) { + int col; + + if (attch) { + col = ((datab & 3) << 2) | (datcd & 3); + datcd >>= 2; + } else + col = datab & 3; + datab >>= 2; + if (col) { + col |= basecol; + if (ham) { + col = colors_for_drawing.color_regs[col]; + ham_linebuf[sprxp] = col; + if (sprx_inc == 2) { + ham_linebuf[sprxp+1] = col; } + } else { + pixdata.apixels[sprxp] = col; + if (sprx_inc == 2) { + pixdata.apixels[sprxp+1] = col; + } + } + } + } +} + +static void walk_sprites (struct sprite_draw *spd, int nr_spr) +{ + int i, prev_overlap; + int last_sprite_pos = -64; + uae_u32 plane1 = 0, plane2 = 0; + int sprx_inc = 1, sprx_shift = 1; + + if (currprefs.gfx_lores == 0) + sprx_inc = 2, sprx_shift = 0; + + prev_overlap = 0; + for (i = 0; i < nr_spr; i++) { + int sprxp = spd[i].linepos; + int m = 1 << spd[i].num; + uae_u32 datab; + while (prev_overlap < i && spd[prev_overlap].linepos + sprite_width <= sprxp) + prev_overlap++; + + datab = do_sprite_collisions (spd, prev_overlap, i, nr_spr); +#ifdef LORES_HACK + if (currprefs.gfx_lores == 2) + sprxp >>= 1; +#endif + if ((bpldualpf && plfpri[1] < 256) || (plfpri[2] < 256)) { + if (sprxp != last_sprite_pos) { + int ok = last_sprite_pos-sprxp+16; + int ok2; + if (ok <= 0) { + ok = ok2 = 0; + plane1 = 0; + plane2 = 0; + } else { + ok2 = ok << sprx_shift; + plane1 >>= 32 - ok2; + plane2 >>= 32 - ok2; + } + last_sprite_pos = sprxp; + + if (bpldualpf) { + uae_u32 mask = 3 << ok2; + int p = sprxp+ok; + + for (; mask; mask <<= 2, p += sprx_inc) { + int data = pixdata.apixels[p]; + if (dblpf_2nd2[data] == 2) + plane2 |= mask; + if (dblpf_2nd1[data] == 1) + plane1 |= mask; + } + } else { + uae_u32 mask = 3 << ok2; + int p = sprxp+ok; + + for (; mask; mask <<= 2, p += sprx_inc) { + if (pixdata.apixels[p]) + plane2 |= mask; + } + } + } + if (bpldualpf && m >= plfpri[1]) { + datab &= ~plane1; + attach_2nd &= ~plane1; + } + if (m >= plfpri[2]) { + datab &= ~plane2; + attach_2nd &= ~plane2; + } + } + if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80) { + /* Attached sprite */ + if (bplham) { + if (sprx_inc == 1) { + render_sprite (spd[i].num, sprxp, datab, 1, 1, 1); + } else { + render_sprite (spd[i].num, sprxp, datab, 1, 1, 2); + } + } else { + if (sprx_inc == 1) { + render_sprite (spd[i].num, sprxp, datab, 0, 1, 1); + } else { + render_sprite (spd[i].num, sprxp, datab, 0, 1, 2); + } + } + /* This still leaves one attached sprite bug, but at the moment I'm too lazy */ + if (i + 1 < nr_spr && spd[i+1].num == spd[i].num - 1 && spd[i+1].linepos == spd[i].linepos) + i++; + } else { + if (bplham) { + if (sprx_inc == 1) { + render_sprite (spd[i].num, sprxp, datab, 1, 0, 1); + } else { + render_sprite (spd[i].num, sprxp, datab, 1, 0, 2); + } + } else { + if (sprx_inc == 1) { + render_sprite (spd[i].num, sprxp, datab, 0, 0, 1); + } else { + render_sprite (spd[i].num, sprxp, datab, 0, 0, 2); + } + } + } + } +} + +#ifndef SMART_UPDATE +#undef UNALIGNED_PROFITABLE +#endif + +#ifdef UNALIGNED_PROFITABLE + +static void pfield_doline_unaligned_h (int lineno) +{ + int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2; + + if (bplhires) { + int xpos1 = xpos + 16 + bpldelay1*2; + int xpos2; + uae_u8 *dataptr = line_data[lineno]; + int len = dp_for_drawing->plflinelen >> 1; + + if (len <= 0) + return; + + if (bpldelay1 == bpldelay2) { + switch (bplplanecnt) { + case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + } + } else { + switch (bplplanecnt) { + case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + } + + xpos2 = xpos + 16 + bpldelay2*2; + switch (bplplanecnt) { + case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 8: set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; } } } else { - int mask = 1 << num; - int basecol = (num & 6) << 1; - int i; - /* Normal sprite */ - for(i = 0; i < 16; i++, sprxp += sprx_inc, colors >>= 2) { - int col; + int xpos1 = xpos + 32 + bpldelay1*2; + int xpos2; + uae_u8 *dataptr = line_data[lineno]; + int len = dp_for_drawing->plflinelen >> 2; - /* Check the priority, but only if we did not already put a sprite - * pixel at this position. If there's already a sprite pixel here, - * the priority was previously tested. */ - if (spixstate[sprxp] == 0) { - /* ??? What about hires mode when one hires pixel is 0, enabling the - * sprite, and the other is != 0, blocking it? */ - int plno = lookup_no[pixdata.apixels[sprxp]]; - if (plno != 0 && mask >= plfpri[plno]) - continue; - } - col = colors & 3; + if (len <= 0) + return; - if (spixstate[sprxp] & mask) { - /* Finish attached sprite */ - /* Did the upper half of the sprite have any bits set? */ - if (spixstate[sprxp] & (mask << 1)) - col += spixels[sprxp]; - /* Is there any sprite pixel at this position at all? */ - if (!col) - spixstate[sprxp] &= ~(3 << num); - } else { - if (col) { - col |= basecol; - } + if (bpldelay1 == bpldelay2) { + switch (bplplanecnt) { + case 1: set_lores_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 2: set_lores_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 3: set_lores_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 4: set_lores_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 5: set_lores_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 6: set_lores_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 7: set_lores_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 8: set_lores_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; } - if (col) { - col += 16; - pixdata.apixels[sprxp] = col; - spixstate[sprxp] |= mask; -#ifdef SPRITE_COLLISIONS - clxdat |= clxtab[spixstate[sprxp] & clx_sprmask]; -#endif - if (!currprefs.gfx_lores) { - pixdata.apixels[sprxp+1] = col; - spixstate[sprxp+1] |= mask; - } + } else { + switch (bplplanecnt) { + case 1: case 2: set_lores_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 3: case 4: set_lores_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 5: case 6: set_lores_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 7: case 8: set_lores_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + } + + xpos2 = xpos + 32 + bpldelay2*2; + switch (bplplanecnt) { + case 2: case 3: set_lores_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 4: case 5: set_lores_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 6: case 7: set_lores_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 8: set_lores_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; } - } - } - if (bplham && bplplanecnt == 6) { - int i; - sprxp = old_sprxp; - for (i = 0; i < 16; i++, sprxp += sprx_inc) { - int col = pixdata.apixels[sprxp]; - if (spixstate[sprxp] == 0) - continue; - ham_linebuf[sprxp] = colors_for_drawing.color_regs[col]; - if (!currprefs.gfx_lores) - ham_linebuf[sprxp+1] = colors_for_drawing.color_regs[col]; } } } -#else /* AGA version */ -static void pfield_sprite (int num, int sprxp, uae_u16 data, uae_u16 datb) + +static void pfield_doline_unaligned_l (int lineno) { - int i; + int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT; - int *lookup = bpldualpf ? (bpldualpfpri ? dblpf_ind2 : dblpf_ind1) : linear_map_256; - int *lookup_no = bpldualpf ? (bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1) : lots_of_twos; + if (bplhires) { + int xpos1 = xpos + 8 + bpldelay1; + int xpos2; + uae_u8 *dataptr = line_data[lineno]; + int len = dp_for_drawing->plflinelen >> 1; - for(i = 15; i >= 0; i--, data >>= 1, datb >>= 1) { - int sprxpos = sprxp + (i << lores_shift); - int plno; - int col; + if (len <= 0) + return; - /* Check the priority, but only if we did not already put a sprite - * pixel at this position. If there's already a sprite pixel here, - * the priority was previously tested. */ - if (!spixstate[sprxpos]) { - /* ??? What about hires mode when one hires pixel is 0, enabling the - * sprite, and the other is != 0, blocking it? */ - plno = lookup_no[pixdata.apixels[sprxpos]]; - if (plno != 0 && (1 << num) >= plfpri[plno]) - continue; - } + if (bpldelay1 == bpldelay2) { + switch (bplplanecnt) { + case 1: set_hires_l_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 2: set_hires_l_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 3: set_hires_l_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 4: set_hires_l_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 5: set_hires_l_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 6: set_hires_l_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 7: set_hires_l_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 8: set_hires_l_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + } + } else { + switch (bplplanecnt) { + case 1: case 2: set_hires_l_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 3: case 4: set_hires_l_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 5: case 6: set_hires_l_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 7: case 8: set_hires_l_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + } - if ((sprctl[num] & 0x80) && (num & 1)) { - /* Attached sprite */ - col = ((data << 2) & 4) + ((datb << 3) & 8); - spixstate[sprxpos] |= 1 << (num-1); - spixels[sprxpos] = col; - } else { - col = (data & 1) | ((datb << 1) & 2); - if (spixstate[sprxpos] & (1 << num)) { - /* Finish attached sprite */ - /* Did the upper half of the sprite have any bits set? */ - if (spixstate[sprxpos] & (1 << (num+1))) - col += spixels[sprxpos]; - /* Is there any sprite pixel at this position at all? */ - if (!col) { - spixstate[sprxpos] &= ~(3 << num); - } else - col += ((bplcon4 << (num & 1 ? 4 : 0)) & 240); - } else { - if (col) { - col |= ((bplcon4 << (num & 1 ? 4 : 0)) & 240) | ((num & 6) << 1); - } + xpos2 = xpos + 8 + bpldelay2; + switch (bplplanecnt) { + case 2: case 3: set_hires_l_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 4: case 5: set_hires_l_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 6: case 7: set_hires_l_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 8: set_hires_l_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; } } - if (col) { - pixdata.apixels[sprxpos] = col; - spixstate[sprxpos] |= 1<plflinelen >> 2; + + if (len <= 0) + return; + + if (bpldelay1 == bpldelay2) { + switch (bplplanecnt) { + case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; } - if (bplham && bplplanecnt == 6) { - ham_linebuf[sprxpos] = colors_for_drawing.color_regs[col]; - if (!currprefs.gfx_lores) - ham_linebuf[sprxpos+1] = colors_for_drawing.color_regs[col]; + } else { + switch (bplplanecnt) { + case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + } + + xpos2 = xpos + 16 + bpldelay2; + switch (bplplanecnt) { + case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 8: set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; } } } } -#endif +#define pfield_doline_h pfield_doline_unaligned_h +#define pfield_doline_l pfield_doline_unaligned_l + +#else /* not UNALIGNED_PROFITABLE */ static __inline__ void pfield_orword_hires_h(int data, unsigned char *dp, int bit) @@ -2909,7 +3786,7 @@ static __inline__ void pfield_orword_hires_h(int data, unsigned char *dp, int bi static __inline__ void pfield_orword_lores_h(int data, unsigned char *dp, int bit) { uae_u32 *pixptr = (uae_u32 *)dp; - + *pixptr |= lorestab_h[data >> 8][0] << bit; *(pixptr+1) |= lorestab_h[data >> 8][1] << bit; *(pixptr+2) |= lorestab_h[data >> 8][2] << bit; @@ -2933,7 +3810,7 @@ static __inline__ void pfield_setword_hires_h(int data, unsigned char *dp, int b static __inline__ void pfield_setword_lores_h(int data, unsigned char *dp, int bit) { uae_u32 *pixptr = (uae_u32 *)dp; - + *pixptr = lorestab_h[data >> 8][0] << bit; *(pixptr+1) = lorestab_h[data >> 8][1] << bit; *(pixptr+2) = lorestab_h[data >> 8][2] << bit; @@ -2955,7 +3832,7 @@ static __inline__ void pfield_orword_hires_l(int data, unsigned char *dp, int bi static __inline__ void pfield_orword_lores_l(int data, unsigned char *dp, int bit) { uae_u32 *pixptr = (uae_u32 *)dp; - + *pixptr |= lorestab_l[data >> 8][0] << bit; *(pixptr+1) |= lorestab_l[data >> 8][1] << bit; *(pixptr+2) |= lorestab_l[data & 255][0] << bit; @@ -2973,7 +3850,7 @@ static __inline__ void pfield_setword_hires_l(int data, unsigned char *dp, int b static __inline__ void pfield_setword_lores_l(int data, unsigned char *dp, int bit) { uae_u32 *pixptr = (uae_u32 *)dp; - + *pixptr = lorestab_l[data >> 8][0] << bit; *(pixptr+1) = lorestab_l[data >> 8][1] << bit; *(pixptr+2) = lorestab_l[data & 255][0] << bit; @@ -2987,9 +3864,9 @@ static __inline__ void pfield_setword_lores_l(int data, unsigned char *dp, int b unsigned int bpldat2 = 0; \ uae_u8 *ptr = (POINTER); \ for (i = dp_for_drawing->plflinelen; i > 0; i -= LL_SUB) { \ - bpldat1 = bpldat2; \ + bpldat1 = bpldat2; \ bpldat2 = do_get_mem_word ((uae_u16 *)ptr); \ - ptr+=2; \ + ptr+=2; \ data = (bpldat1 << (16 - DELAY)) | (bpldat2 >> DELAY); \ FUNC(data, app, MULT); \ app += P_ADD; \ @@ -3007,7 +3884,7 @@ static __inline__ void pfield_setword_lores_l(int data, unsigned char *dp, int b static void pfield_doline_aligned_h (int lineno) { int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2; - + if (bplhires) { if (bplplanecnt > 0) { int xpos1 = xpos + 16 + (bpldelay1 >= 8 ? 16 : 0); @@ -3058,7 +3935,7 @@ static void pfield_doline_aligned_h (int lineno) int x = xpos + 32; unsigned char *app = pixdata.apixels + x; uae_u8 *dataptr = line_data[lineno]; - + DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_h, bpldelay1, 8, 32); if (bplplanecnt > 2) { app = pixdata.apixels + x; @@ -3101,7 +3978,7 @@ static void pfield_doline_aligned_h (int lineno) static void pfield_doline_aligned_l (int lineno) { int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT; - + if (bplhires) { if (bplplanecnt > 0) { int xpos1 = xpos + 8 + (bpldelay1 >= 8 ? 8 : 0); @@ -3110,7 +3987,7 @@ static void pfield_doline_aligned_l (int lineno) int delay2 = (bpldelay2 & 7) * 2; unsigned char *app = pixdata.apixels + xpos1; uae_u8 *dataptr = line_data[lineno]; - + DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_l, delay1, 4, 8); if (bplplanecnt > 2) { app = pixdata.apixels + xpos1; @@ -3154,7 +4031,7 @@ static void pfield_doline_aligned_l (int lineno) int delay2 = bpldelay2; unsigned char *app = pixdata.apixels + x; uae_u8 *dataptr = line_data[lineno]; - + DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_l, delay1, 8, 16); if (bplplanecnt > 2) { app = pixdata.apixels + x; @@ -3197,13 +4074,14 @@ static void pfield_doline_aligned_l (int lineno) #define pfield_doline_h pfield_doline_aligned_h #define pfield_doline_l pfield_doline_aligned_l +#endif /* UNALIGNED_PROFITABLE */ static void pfield_adjust_delay (void) { int ddf_left = dp_for_drawing->plfstrt; int ddf_right = dp_for_drawing->plfstrt + dp_for_drawing->plflinelen; int i; - + for (i = dip_for_drawing->last_delay_change-1; i >= dip_for_drawing->first_delay_change-1; i--) { int delayreg = i < dip_for_drawing->first_delay_change ? dp_for_drawing->bplcon1 : delay_changes[i].value; int delay1 = delayreg & 0xF; @@ -3223,164 +4101,43 @@ static void pfield_adjust_delay (void) } } -static void init_hardware_frame (void) +static void init_sprites (void) { int i; for (i = 0; i < 8; i++) { + /* ???? */ sprst[i] = SPR_stop; spron[i] = 0; } -#if 0 + memset(sprpos, 0, sizeof sprpos); memset(sprctl, 0, sizeof sprctl); -#endif +} +static void init_hardware_frame (void) +{ next_lineno = 0; nln_how = 0; diwstate = DIW_waiting_start; hdiwstate = DIW_waiting_start; } -static void setdontcare(void) -{ - write_log ("Don't care mouse mode set\n"); - mousestate = dont_care_mouse; - lastspr0x = lastmx; lastspr0y = lastmy; - mstepx = defstepx; mstepy = defstepy; -} - -static void setfollow(void) -{ - write_log ("Follow sprite mode set\n"); - mousestate = follow_mouse; - lastdiffx = lastdiffy = 0; - sprvbfl = 0; - spr0ctl=spr0pos = 0; - mstepx = defstepx; mstepy = defstepy; -} - -uae_u32 mousehack_helper (void) -{ - int mousexpos, mouseypos; - - mousexpos = lastmx + linetoscr_x_adjust; - if (lastmy >= gfxvidinfo.maxline) - lastmy = gfxvidinfo.maxline-1; - mouseypos = native2amiga_line_map[lastmy] + thisframe_y_adjust - minfirstline; - mouseypos <<= 1; - mousexpos <<= (1-lores_shift); - mousexpos += 2*DISPLAY_LEFT_SHIFT; - - switch (m68k_dreg (regs, 0)) { - case 0: - return ievent_alive ? -1 : needmousehack (); - case 1: - ievent_alive = 10; - return mousexpos; - case 2: - return mouseypos; - } - return 0; -} - -void togglemouse(void) -{ - switch(mousestate) { - case dont_care_mouse: setfollow(); break; - case follow_mouse: setdontcare(); break; - default: break; /* Nnnnnghh! */ - } -} - -static __inline__ int adjust(int val) -{ - if (val>127) - return 127; - else if (val<-127) - return -127; - return val; -} - -static void do_mouse_hack(void) -{ - int spr0x = ((spr0pos & 0xff) << 2) | ((spr0ctl & 1) << 1); - int spr0y = ((spr0pos >> 8) | ((spr0ctl & 4) << 6)) << 1; - int diffx, diffy; - - if (ievent_alive > 0) { - mouse_x = mouse_y = 0; - return; - } - switch (mousestate) { - case normal_mouse: - diffx = lastmx - lastsampledmx; - diffy = lastmy - lastsampledmy; - if (!newmousecounters) { - if (diffx > 127) diffx = 127; - if (diffx < -127) diffx = -127; - mouse_x += diffx; - if (diffy > 127) diffy = 127; - if (diffy < -127) diffy = -127; - mouse_y += diffy; - } - lastsampledmx += diffx; lastsampledmy += diffy; - break; - - case dont_care_mouse: - diffx = adjust (((lastmx-lastspr0x) * mstepx) >> 16); - diffy = adjust (((lastmy-lastspr0y) * mstepy) >> 16); - lastspr0x=lastmx; lastspr0y=lastmy; - mouse_x+=diffx; mouse_y+=diffy; - break; - - case follow_mouse: - if (sprvbfl && sprvbfl-- >1) { - int mousexpos, mouseypos; - - if ((lastdiffx > docal || lastdiffx < -docal) && lastspr0x != spr0x - && spr0x > plfstrt*4 + 34 + xcaloff && spr0x < plfstop*4 - xcaloff) - { - int val = (lastdiffx << 16) / (spr0x - lastspr0x); - if (val>=0x8000) mstepx=(mstepx*(calweight-1)+val)/calweight; - } - if ((lastdiffy > docal || lastdiffy < -docal) && lastspr0y != spr0y - && spr0y>plffirstline+ycaloff && spr0y=0x8000) mstepy=(mstepy*(calweight-1)+val)/calweight; - } - mousexpos = lastmx + linetoscr_x_adjust; - if (lastmy >= gfxvidinfo.maxline) - lastmy = gfxvidinfo.maxline-1; - mouseypos = native2amiga_line_map[lastmy] + thisframe_y_adjust - minfirstline; - mouseypos <<= 1; - mousexpos <<= (1-lores_shift); - mousexpos += 2*DISPLAY_LEFT_SHIFT; - diffx = adjust ((((mousexpos + xoffs - spr0x) & ~1) * mstepx) >> 16); - diffy = adjust ((((mouseypos + yoffs - spr0y) & ~1) * mstepy) >> 16); - lastspr0x=spr0x; lastspr0y=spr0y; - lastdiffx=diffx; lastdiffy=diffy; - mouse_x+=diffx; mouse_y+=diffy; - } - break; - } -} - -static void init_row_map(void) +void init_row_map(void) { int i; - for (i = 0; i < gfxvidinfo.maxline + 1; i++) - row_map[i] = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * i; + if (gfxvidinfo.height > 2048) { + write_log ("Resolution too high, aborting\n"); + } + for (i = 0; i < gfxvidinfo.height + 1; i++) + row_map[i] = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * i; } -/* @@@ Are those still useful? */ - /* * A raster line has been built in the graphics buffer. Tell the graphics code * to do anything necessary to display it. */ -static __inline__ void do_flush_line_1 (int lineno) +static void do_flush_line_1 (int lineno) { if (lineno < first_drawn_line) first_drawn_line = lineno; @@ -3403,20 +4160,31 @@ static __inline__ void do_flush_line_1 (int lineno) } } -static void do_flush_line (int lineno) +static __inline__ void do_flush_line (int lineno) { + /* We don't want to call X libraries from the second thread right now. */ +#ifndef SUPPORT_PENGUINS do_flush_line_1 (lineno); +#else + line_drawn[lineno] = 1; +#endif } /* - * One Amiga frame has been finished. Tell the graphics code about it. + * One drawing frame has been finished. Tell the graphics code about it. * Note that the actual flush_screen() call is a no-op for all reasonable * systems. */ -static void do_flush_screen (int start, int stop) +static __inline__ void do_flush_screen (int start, int stop) { int i; +#ifdef SUPPORT_PENGUINS + for (i = 0; i < gfxvidinfo.height; i++) { + if (line_drawn[i]) + do_flush_line_1 (i); + } +#endif if (gfxvidinfo.maxblocklines != 0 && first_block_line != -2) { flush_block (first_block_line, last_block_line); } @@ -3457,7 +4225,7 @@ static __inline__ void do_color_changes (line_draw_func worker) { int lastpos = 0, nextpos, i; struct color_change *cc = curr_color_changes + dip_for_drawing->first_color_change; - + for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++, cc++) { if (i == dip_for_drawing->last_color_change) nextpos = max_diwlastword; @@ -3476,19 +4244,22 @@ static __inline__ void do_color_changes (line_draw_func worker) } } +/* We only save hardware registers during the hardware frame. Now, when + * drawing the frame, we expand the data into a slightly more useful + * form. */ static void pfield_expand_dp_bplcon (void) { bplhires = (dp_for_drawing->bplcon0 & 0x8000) == 0x8000; bplplanecnt = (dp_for_drawing->bplcon0 & 0x7000) >> 12; bplham = (dp_for_drawing->bplcon0 & 0x800) == 0x800; #if AGA_CHIPSET == 1 /* The KILLEHB bit exists in ECS, but is apparently meant for Genlock - * stuff, and it's set by some demos (e.g. Andromeda Seven Seas) */ + * stuff, and it's set by some demos (e.g. Andromeda Seven Seas) */ bplehb = ((dp_for_drawing->bplcon0 & 0xFCC0) == 0x6000 && !(dp_for_drawing->bplcon2 & 0x200)); #else bplehb = (dp_for_drawing->bplcon0 & 0xFC00) == 0x6000; #endif - bpldelay1 = dp_for_drawing->bplcon1 & 0xF; - bpldelay2 = (dp_for_drawing->bplcon1 >> 4) & 0xF; + bpldelay1 = dp_for_drawing->bplcon1 & 0xF; + bpldelay2 = (dp_for_drawing->bplcon1 >> 4) & 0xF; plfpri[1] = 1 << 2*(dp_for_drawing->bplcon2 & 7); plfpri[2] = 1 << 2*((dp_for_drawing->bplcon2 >> 3) & 7); bpldualpf = (dp_for_drawing->bplcon0 & 0x400) == 0x400; @@ -3500,275 +4271,334 @@ static __inline__ void pfield_draw_line(int lineno, int gfx_ypos, int follow_ypo int border = 0; int to_screen = 0; int do_double = 0; + dp_for_drawing = 0; dip_for_drawing = 0; - switch (linestate[lineno]) { - case LINE_AS_PREVIOUS: - case LINE_REMEMBERED_AS_PREVIOUS: - { - static int warned = 0; - if (!warned) - write_log ("Shouldn't get here... this is a bug.\n"), warned++; - } - line_decisions[lineno].which = -2; - return; + case LINE_AS_PREVIOUS: + case LINE_REMEMBERED_AS_PREVIOUS: + { + static int warned = 0; + if (!warned) + write_log ("Shouldn't get here... this is a bug.\n"), warned++; + } + line_decisions[lineno].which = -2; + return; - case LINE_BORDER_PREV: - border = 1; - dp_for_drawing = line_decisions + lineno - 1; - dip_for_drawing = curr_drawinfo + lineno - 1; - break; + case LINE_BORDER_PREV: + border = 1; + dp_for_drawing = line_decisions + lineno - 1; + dip_for_drawing = curr_drawinfo + lineno - 1; + break; - case LINE_BORDER_NEXT: - border = 1; - dp_for_drawing = line_decisions + lineno + 1; - dip_for_drawing = curr_drawinfo + lineno + 1; - break; + case LINE_BORDER_NEXT: + border = 1; + dp_for_drawing = line_decisions + lineno + 1; + dip_for_drawing = curr_drawinfo + lineno + 1; + break; - case LINE_DONE_AS_PREVIOUS: - line_decisions[lineno].which = -2; - /* fall through */ - case LINE_DONE: - return; + case LINE_DONE_AS_PREVIOUS: + line_decisions[lineno].which = -2; + /* fall through */ + case LINE_DONE: + return; - case LINE_DECIDED_DOUBLE: - line_decisions[lineno+1].which = -2; - if (follow_ypos != -1) { - do_double = 1; - linetoscr_double_offset = gfxvidinfo.rowbytes * (follow_ypos - gfx_ypos); - } - - /* fall through */ - default: - dip_for_drawing = curr_drawinfo + lineno; - dp_for_drawing = line_decisions + lineno; - if (dp_for_drawing->which != 1) - border = 1; - break; + case LINE_DECIDED_DOUBLE: + line_decisions[lineno+1].which = -2; + if (follow_ypos != -1) { + do_double = 1; + linetoscr_double_offset = gfxvidinfo.rowbytes * (follow_ypos - gfx_ypos); + } + + /* fall through */ + default: + dip_for_drawing = curr_drawinfo + lineno; + dp_for_drawing = line_decisions + lineno; + if (dp_for_drawing->which != 1) + border = 1; + break; } - + if (!line_changed[lineno] && !frame_redraw_necessary) { - /* The case where we can skip redrawing this line. If this line - * is supposed to be doubled, and the next line is remembered as - * having been doubled, then the next line is done as well. */ - if (do_double) { - if (linestate[lineno+1] != LINE_REMEMBERED_AS_PREVIOUS) { - if (gfxvidinfo.linemem == NULL) - memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes); - line_decisions[lineno + 1].which = -2; - do_flush_line (follow_ypos); - } - linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS; - } - linestate[lineno] = LINE_DONE; - return; + /* The case where we can skip redrawing this line. If this line + * is supposed to be doubled, and the next line is remembered as + * having been doubled, then the next line is done as well. */ + if (do_double) { + if (linestate[lineno+1] != LINE_REMEMBERED_AS_PREVIOUS) { + if (gfxvidinfo.linemem == NULL) + memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes); + line_decisions[lineno + 1].which = -2; + do_flush_line (follow_ypos); + } + linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS; + } + linestate[lineno] = LINE_DONE; + return; } if (!border) { - xlinebuffer = gfxvidinfo.linemem; - if (xlinebuffer == NULL) - xlinebuffer = row_map[gfx_ypos]; - xlinebuffer -= linetoscr_x_adjust_bytes; -#if AGA_CHIPSET != 0 - aga_lbufptr = aga_linebuf; -#endif - pfield_expand_dp_bplcon (); + xlinebuffer = gfxvidinfo.linemem; + if (xlinebuffer == NULL) + xlinebuffer = row_map[gfx_ypos]; + xlinebuffer -= linetoscr_x_adjust_bytes; + aga_lbufptr = aga_linebuf; + + pfield_expand_dp_bplcon (); #ifdef LORES_HACK - if (gfxvidinfo.can_double && !bplhires && !currprefs.gfx_lores - && dip_for_drawing->nr_color_changes == 0 && !bplham) - currprefs.gfx_lores = 2; + if (gfxvidinfo.can_double && !bplhires && !currprefs.gfx_lores + && dip_for_drawing->nr_color_changes == 0 && !bplham) + currprefs.gfx_lores = 2; #endif - pfield_init_linetoscr (); - if (dip_for_drawing->first_delay_change != dip_for_drawing->last_delay_change) { - bpldelay1 = bpldelay2 = 0; - if (currprefs.gfx_lores) - pfield_doline_l (lineno); - else - pfield_doline_h (lineno); - pfield_adjust_delay (); - } else { - if (currprefs.gfx_lores) - pfield_doline_l (lineno); - else - pfield_doline_h (lineno); - } + pfield_init_linetoscr (); + if (dip_for_drawing->first_delay_change != dip_for_drawing->last_delay_change) { + bpldelay1 = bpldelay2 = 0; + if (currprefs.gfx_lores) + pfield_doline_l (lineno); + else + pfield_doline_h (lineno); + pfield_adjust_delay (); + } else { + if (currprefs.gfx_lores) + pfield_doline_l (lineno); + else + pfield_doline_h (lineno); + } - /* Check color0 adjust only if we have color changes - shouldn't happen - * otherwise. */ - adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb); + /* Check color0 adjust only if we have color changes - shouldn't happen + * otherwise. */ + adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb); - /* The problem is that we must call decode_ham6() BEFORE we do the - * sprites. */ - if (bplham) { - if (dip_for_drawing->nr_color_changes == 0) { - /* The easy case: need to do HAM decoding only once for the - * full line. */ - decode_ham6 (linetoscr_x_adjust, linetoscr_right_x); - } else /* Argh. */ { - adjust_color0_for_color_change (); - do_color_changes (decode_ham6); - adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb); - } - } + /* The problem is that we must call decode_ham6() BEFORE we do the + * sprites. */ + if (bplham) { + init_ham_decoding(linetoscr_x_adjust); + if (dip_for_drawing->nr_color_changes == 0) { + /* The easy case: need to do HAM decoding only once for the + * full line. */ + decode_ham6 (linetoscr_x_adjust, linetoscr_right_x); + } else /* Argh. */ { + adjust_color0_for_color_change (); + do_color_changes (decode_ham6); + adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb); + } + } - if (dip_for_drawing->nr_sprites != 0) { - int spr; - for(spr = 7; spr >= 0; spr--) { - struct sprite_draw *spd = curr_sprite_positions + dip_for_drawing->first_sprite_draw; - int i; + if (dip_for_drawing->nr_sprites != 0) { + int spr; + walk_sprites (curr_sprite_positions + dip_for_drawing->first_sprite_draw, dip_for_drawing->nr_sprites); + } + if (dip_for_drawing->nr_color_changes == 0) { + pfield_do_linetoscr_full (gfxvidinfo.linemem == NULL ? do_double : 0); + do_flush_line (gfx_ypos); + linestate[lineno] = LINE_DONE; - for (i = dip_for_drawing->first_sprite_draw; i < dip_for_drawing->last_sprite_draw; i++, spd++) { - if (spd->num != spr) - continue; - pfield_sprite (spr, spd->linepos, spd->data, spd->datb, spd->ctl); - } - } - } - if (dip_for_drawing->nr_color_changes == 0) { - pfield_do_linetoscr_full (gfxvidinfo.linemem == NULL ? do_double : 0); - do_flush_line (gfx_ypos); - linestate[lineno] = LINE_DONE; + if (do_double) { + linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS; + do_flush_line (follow_ypos); + } + } else { + int lastpos = 0, nextpos, i; - if (do_double) { - linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS; - do_flush_line (follow_ypos); - } - } else { - int lastpos = 0, nextpos, i; - - adjust_color0_for_color_change (); - do_color_changes (pfield_do_linetoscr); - - linestate[lineno] = LINE_DONE; - do_flush_line (gfx_ypos); - if (do_double) { - if (gfxvidinfo.linemem == NULL) - memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes); - linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS; - line_decisions[lineno + 1].which = -2; - do_flush_line (follow_ypos); - } - } - /* Clean up the spixstate array. */ - { - struct sprite_draw *spd = curr_sprite_positions + dip_for_drawing->first_sprite_draw; - int i; + adjust_color0_for_color_change (); + do_color_changes (pfield_do_linetoscr); + linestate[lineno] = LINE_DONE; + do_flush_line (gfx_ypos); + if (do_double) { + if (gfxvidinfo.linemem == NULL) + memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes); + linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS; + line_decisions[lineno + 1].which = -2; + do_flush_line (follow_ypos); + } + } #ifdef LORES_HACK - if (currprefs.gfx_lores == 2) { - for (i = dip_for_drawing->first_sprite_draw; i < dip_for_drawing->last_sprite_draw; i++, spd++) - fuzzy_memset_le32 (spixstate, 0, (spd->linepos >> 1), 16*sizeof *spixstate); - } else + if (currprefs.gfx_lores == 2) + currprefs.gfx_lores = 0; #endif - if (currprefs.gfx_lores) { - for (i = dip_for_drawing->first_sprite_draw; i < dip_for_drawing->last_sprite_draw; i++, spd++) - fuzzy_memset_le32 (spixstate, 0, spd->linepos, 16*sizeof *spixstate); - } else { - for (i = dip_for_drawing->first_sprite_draw; i < dip_for_drawing->last_sprite_draw; i++, spd++) - fuzzy_memset_le32 (spixstate, 0, spd->linepos, 32*sizeof *spixstate); - } - } -#ifdef LORES_HACK - if (currprefs.gfx_lores == 2) - currprefs.gfx_lores = 0; -#endif - } else { /* Border. */ - int i, lastpos = 0, nextpos; - struct color_change *cc; + } else { + /* Border. */ + int i, lastpos = 0, nextpos; + struct color_change *cc; - xlinebuffer = gfxvidinfo.linemem; - if (xlinebuffer == NULL) - xlinebuffer = row_map[gfx_ypos]; - xlinebuffer -= linetoscr_x_adjust_bytes; + xlinebuffer = gfxvidinfo.linemem; + if (xlinebuffer == NULL) + xlinebuffer = row_map[gfx_ypos]; + xlinebuffer -= linetoscr_x_adjust_bytes; - adjust_drawing_colors (dp_for_drawing->ctable, 0); - /* Check color0 adjust only if we have color changes - shouldn't happen - * otherwise. */ + adjust_drawing_colors (dp_for_drawing->ctable, 0); + /* Check color0 adjust only if we have color changes - shouldn't happen + * otherwise. */ - if (dip_for_drawing->nr_color_changes == 0) { - fill_line (); - do_flush_line (gfx_ypos); - linestate[lineno] = LINE_DONE; - if (do_double) { - if (gfxvidinfo.linemem == NULL) { - xlinebuffer = row_map[follow_ypos] - linetoscr_x_adjust_bytes; - fill_line (); - } - do_flush_line (follow_ypos); - linestate[lineno+1] = LINE_DONE_AS_PREVIOUS; - } - return; - } + if (dip_for_drawing->nr_color_changes == 0) { + fill_line (); + do_flush_line (gfx_ypos); + linestate[lineno] = LINE_DONE; + if (do_double) { + if (gfxvidinfo.linemem == NULL) { + xlinebuffer = row_map[follow_ypos] - linetoscr_x_adjust_bytes; + fill_line (); + } + do_flush_line (follow_ypos); + linestate[lineno+1] = LINE_DONE_AS_PREVIOUS; + } + return; + } - adjust_color0_for_color_change (); - do_color_changes (pfield_do_fill_line); + adjust_color0_for_color_change (); + do_color_changes (pfield_do_fill_line); - do_flush_line (gfx_ypos); - linestate[lineno] = LINE_DONE; - if (do_double) { - if (gfxvidinfo.linemem == NULL) - memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes); - linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS; - line_decisions[lineno + 1].which = -2; - do_flush_line (follow_ypos); - } + do_flush_line (gfx_ypos); + linestate[lineno] = LINE_DONE; + if (do_double) { + if (gfxvidinfo.linemem == NULL) + memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes); + linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS; + line_decisions[lineno + 1].which = -2; + do_flush_line (follow_ypos); + } } } +#ifdef SUPPORT_PENGUINS +static smp_comm_pipe drawing_pipe; +static uae_sem_t drawing_lock; +static void *drawing_penguin (void *cruxmedo) +{ + int l; + fprintf(stderr, "Hello, world!\n"); + + for (;;) { + /* Start of a frame. */ + int k; + new_frame: + k = read_comm_pipe_int_blocking (&drawing_pipe); + + switch (k) { + case -2: + /* Hoopy */ + break; + + default: + write_log ("Penguin got out of sync.\n"); + /* what can we do? Try to reduce the damage */ + for (;;) { + k = read_comm_pipe_int_blocking (&drawing_pipe); + if (k == -3) + break; + if (k == -1) { + uae_sem_post (&drawing_lock); + goto new_frame; + } + } + case -3: + UAE_PENGUIN_EXIT; + /* Can't happen */ + return 0; + } + + for (;;) { + int i, where; + int l = read_comm_pipe_int_blocking (&drawing_pipe); + switch (l) { + case -1: + /* End-of-frame synchronization. */ + uae_sem_post (&drawing_lock); + goto new_frame; + case -2: + /* customreset called a bit too often. That's harmless. */ + continue; + case -3: + write_log ("Penguin got out of sync.\n"); + UAE_PENGUIN_EXIT; + return 0; + } + + /* l is the line that has been finished for drawing. */ + i = l - thisframe_y_adjust_real; + if (i < 0 || i >= max_ypos_thisframe) + continue; + + if (linestate[l] == LINE_UNDECIDED) { + fprintf (stderr, "Line scheduled for drawing, but undecided %d!?\n", l); + continue; + } + if (inhibit_frame != 0) + continue; + where = amiga2aspect_line_map[i+min_ypos_for_screen]; + if (where >= gfxvidinfo.height || where == -1) + continue; + + pfield_draw_line (l, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]); + } + } +} + +static penguin_id our_penguin; + +static void kill_drawing_penguin (void) +{ + /* ??? does libpthread do that for us? */ +} + +#endif + +static int penguins_enabled_thisframe; + +static void adjust_array_sizes (void) +{ +#ifdef OS_WITHOUT_MEMORY_MANAGEMENT + if (delta_sprite_draw) { + void *p1,*p2; + int mcc = max_sprite_draw + 200 + delta_sprite_draw; + delta_sprite_draw = 0; + p1 = realloc (sprite_positions[0], mcc * sizeof (struct sprite_draw)); + p2 = realloc (sprite_positions[1], mcc * sizeof (struct sprite_draw)); + if (p1) sprite_positions[0] = p1; + if (p2) sprite_positions[1] = p2; + if (p1 && p2) { + fprintf (stderr, "new max_sprite_draw=%d\n",mcc); + max_sprite_draw = mcc; + } + } + if (delta_color_change) { + void *p1,*p2; + int mcc = max_color_change + 200 + delta_color_change; + delta_color_change = 0; + p1 = realloc (color_changes[0], mcc * sizeof (struct color_change)); + p2 = realloc (color_changes[1], mcc * sizeof (struct color_change)); + if (p1) color_changes[0] = p1; + if (p2) color_changes[1] = p2; + if (p1 && p2) { + fprintf (stderr, "new max_color_change=%d\n",mcc); + max_color_change = mcc; + } + } + if (delta_delay_change) { + void *p; + int mcc = max_delay_change + 200 + delta_delay_change; + delta_delay_change = 0; + p = realloc (delay_changes, mcc * sizeof (struct delay_change)); + if (p) { + fprintf (stderr, "new max_delay_change=%d\n",mcc); + delay_changes = p; + max_delay_change = mcc; + } + } +#endif +} static void init_drawing_frame (void) { int i, maxline; -#ifdef OS_WITHOUT_MEMORY_MANAGEMENT - if(delta_sprite_draw) { - void *p1,*p2; - int mcc = max_sprite_draw + 200 + delta_sprite_draw; - delta_sprite_draw = 0; - p1 = realloc(sprite_positions[0], mcc*sizeof(struct sprite_draw)); - p2 = realloc(sprite_positions[1], mcc*sizeof(struct sprite_draw)); - emu_printf("spr realloc pos"); - emu_printi(mcc*sizeof(struct sprite_draw)*2); - if(p1) sprite_positions[0] = p1; - if(p2) sprite_positions[1] = p2; - if(p1 && p2) { - //fprintf(stderr,"new max_sprite_draw=%d\n",mcc); - max_sprite_draw = mcc; - } - } - if(delta_color_change) { - void *p1,*p2; - int mcc = max_color_change + 200 + delta_color_change; - delta_color_change = 0; - p1 = realloc(color_changes[0], mcc*sizeof(struct color_change)); - p2 = realloc(color_changes[1], mcc*sizeof(struct color_change)); - emu_printf("spr realloc color"); - emu_printi(mcc*sizeof(struct color_change)*2); - if(p1) color_changes[0] = p1; - if(p2) color_changes[1] = p2; - if(p1 && p2) { - //fprintf(stderr,"new max_color_change=%d\n",mcc); - max_color_change = mcc; - } - } - if(delta_delay_change) { - void *p; - int mcc = max_delay_change + 200 + delta_delay_change; - delta_delay_change = 0; - p = realloc(delay_changes, mcc*sizeof(struct delay_change)); - emu_printf("spr realloc delay"); - emu_printi(mcc*sizeof(struct delay_change)); - if(p) { - //fprintf(stderr,"new max_delay_change=%d\n",mcc); - delay_changes = p; - max_delay_change = mcc; - } - } -#endif + adjust_array_sizes (); + //check_prefs_changed_custom (); + //check_prefs_changed_cpu (); + if (max_diwstop == 0) max_diwstop = diwlastword; if (min_diwstart > max_diwstop) @@ -3797,7 +4627,7 @@ static void init_drawing_frame (void) frame_redraw_necessary = 1; else if (frame_redraw_necessary) frame_redraw_necessary--; - + next_color_entry = 0; remembered_color_entry = -1; prev_sprite_positions = sprite_positions[current_change_set]; @@ -3806,7 +4636,7 @@ static void init_drawing_frame (void) curr_color_changes = color_changes[current_change_set ^ 1]; prev_color_tables = color_tables[current_change_set]; curr_color_tables = color_tables[current_change_set ^ 1]; - + prev_drawinfo = line_drawinfo[current_change_set]; curr_drawinfo = line_drawinfo[current_change_set ^= 1]; drawing_color_matches = -1; @@ -3816,11 +4646,11 @@ static void init_drawing_frame (void) prev_y_adjust = thisframe_y_adjust; if (currprefs.gfx_xcenter) { - if (max_diwstop - min_diwstart < gfxvidinfo.maxlinetoscr && currprefs.gfx_xcenter == 2) + if (max_diwstop - min_diwstart < gfxvidinfo.width && currprefs.gfx_xcenter == 2) /* Try to center. */ - linetoscr_x_adjust = ((max_diwstop - min_diwstart - gfxvidinfo.maxlinetoscr) / 2 + min_diwstart) & ~1; + linetoscr_x_adjust = ((max_diwstop - min_diwstart - gfxvidinfo.width) / 2 + min_diwstart) & ~1; else - linetoscr_x_adjust = max_diwstop - gfxvidinfo.maxlinetoscr; + linetoscr_x_adjust = max_diwstop - gfxvidinfo.width; /* Would the old value be good enough? If so, leave it as it is if we want to * be clever. */ @@ -3829,13 +4659,13 @@ static void init_drawing_frame (void) linetoscr_x_adjust = prev_x_adjust; } } else - linetoscr_x_adjust = max_diwlastword - gfxvidinfo.maxlinetoscr; + linetoscr_x_adjust = max_diwlastword - gfxvidinfo.width; if (linetoscr_x_adjust < 0) linetoscr_x_adjust = 0; linetoscr_x_adjust_bytes = linetoscr_x_adjust * gfxvidinfo.pixbytes; - linetoscr_right_x = linetoscr_x_adjust + gfxvidinfo.maxlinetoscr; + linetoscr_right_x = linetoscr_x_adjust + gfxvidinfo.width; if (linetoscr_right_x > max_diwlastword) linetoscr_right_x = max_diwlastword; @@ -3869,118 +4699,157 @@ static void init_drawing_frame (void) min_diwstart = 10000; thisframe_first_drawn_line = -1; thisframe_last_drawn_line = -1; +#ifdef SUPPORT_PENGUINS + penguins_enabled_thisframe = 1; + /* Tell the other thread that it can now expect data from us. */ + write_comm_pipe_int (&drawing_pipe, -2, 1); + memset (line_drawn, 0, sizeof line_drawn); +#endif } static void finish_drawing_frame (void) { int i; +#ifdef SUPPORT_PENGUINS + /* Synchronize with other thread, then see whether there's something left for + * us to draw. @@@ This is probably a big waste of cycles if the two threads + * run at very different speeds - this one could draw stuff as well. */ + write_comm_pipe_int (&drawing_pipe, -1, 1); + uae_sem_wait (&drawing_lock); +#else + #ifndef SMART_UPDATE /* @@@ This isn't exactly right yet. FIXME */ if (!interlace_seen) { - do_flush_screen (first_drawn_line, last_drawn_line); - return; + do_flush_screen (first_drawn_line, last_drawn_line); + return; } #endif for (i = 0; i < max_ypos_thisframe; i++) { - int where; - int line = i + thisframe_y_adjust_real; + int where; + int line = i + thisframe_y_adjust_real; - if (linestate[line] == LINE_UNDECIDED) - break; + if (linestate[line] == LINE_UNDECIDED) + break; - where = amiga2aspect_line_map[i+min_ypos_for_screen]; - if (where >= gfxvidinfo.maxline) - break; - if (where == -1) - continue; + where = amiga2aspect_line_map[i+min_ypos_for_screen]; + if (where >= gfxvidinfo.height) + break; + if (where == -1) + continue; - pfield_draw_line (line, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]); + pfield_draw_line (line, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]); } - +#endif do_flush_screen (first_drawn_line, last_drawn_line); } +static __inline__ void check_picasso (void) +{ +#ifdef PICASSO96 + if (picasso_requested_on == picasso_on) + return; + + picasso_on = picasso_requested_on; + + if (!picasso_on) + clear_inhibit_frame (2); + // JMH + //else + //set_inhibit_frame (2); + + gfx_set_picasso_state (picasso_on); + picasso_enablescreen (picasso_requested_on); + + notice_screen_contents_lost (); +#endif +} + static void vsync_handler (void) { - - uae_u16 dir; - int button; - #ifdef FRAME_RATE_HACK /* put this here or at the end of the function? */ { - frame_time_t curr_time = read_processor_time(); - vsyncmintime += vsynctime; - /* @@@ Mathias? How do you think we should do this? */ - /* If we are too far behind, or we just did a reset, adjust the - * needed time. */ - if ((long int)(curr_time - vsyncmintime) > 0 || did_reset) - vsyncmintime = curr_time + vsynctime; - did_reset = 0; + frame_time_t curr_time = read_processor_time(); + vsyncmintime += vsynctime; + /* @@@ Mathias? How do you think we should do this? */ + /* If we are too far behind, or we just did a reset, adjust the + * needed time. */ + if ((long int)(curr_time - vsyncmintime) > 0 || did_reset) + vsyncmintime = curr_time + vsynctime; + did_reset = 0; } #endif handle_events (); - static int cnt = 0; - if (cnt == 0) { - DISK_check_change (); - cnt = 5; - } - cnt--; - getjoystate (0, &joy0dir, &joy0button); getjoystate (1, &joy1dir, &joy1button); - do_mouse_hack(); - + do_mouse_hack(); + INTREQ(0x8020); - if (bplcon0 & 4) + if (bplcon0 & 4) lof ^= 0x8000; if (quit_program < 0) { quit_program = -quit_program; - inhibit_frame = 2; + // JMH set_inhibit_frame (1); regs.spcflags |= SPCFLAG_BRK; if (framecnt == 0) finish_drawing_frame (); - -#ifdef HAS_FILESYS filesys_prepare_reset (); -#endif +#ifdef SUPPORT_PENGUINS + if (quit_program == 1) + /* Stop eating herring */ + write_comm_pipe_int (&drawing_pipe, -3, 1); +#endif return; } last_redraw_point++; if (lof_changed || !interlace_seen || last_redraw_point >= 2 || lof) { + static int cnt = 0; + if (framecnt == 0) finish_drawing_frame (); count_frame (); last_redraw_point = 0; - /* There may be reasons why we want to override count_frame()'s - * decision. */ - if (inhibit_frame > 0) + + check_picasso (); + +/* + uae_sem_wait (&ihf_sem); + if (inhibit_frame != 0) framecnt = 1; - else { - + if (frame_do_semup) + uae_sem_post (&frame_sem); + frame_do_semup = 0; + uae_sem_post (&ihf_sem); +*/ + if (cnt == 0) { + /* resolution_check_change (); */ + DISK_check_change (); + cnt = 5; } + cnt--; if (framecnt == 0) init_drawing_frame (); } - + lof_changed = 0; interlace_seen = 0; COPJMP1(0); - + init_hardware_frame(); #ifdef HAVE_GETTIMEOFDAY { struct timeval tv; unsigned long int newtime; - - gettimeofday(&tv,NULL); + + gettimeofday(&tv,NULL); newtime = (tv.tv_sec-seconds_base) * 1000 + tv.tv_usec / 1000; - - if (!bogusframe) { + + if (!bogusframe) { frametime += newtime - msecs; timeframes++; } @@ -3998,7 +4867,7 @@ static void hsync_handler(void) int lineno = next_lineno; int lineisdouble = 0; int line_was_doubled = 0; - + finish_decisions (); do_modulos (); @@ -4026,18 +4895,23 @@ static void hsync_handler(void) break; } } - eventtab[ev_hsync].evtime += cycles - eventtab[ev_hsync].oldcycles; eventtab[ev_hsync].oldcycles = cycles; CIA_hsync_handler(); - + + + if (dskdmaen == 2 && dmaen (0x10)) { + update_disk_reads (); + DISK_search_sync (maxhpos, dsksync); + } + if (currprefs.produce_sound > 0) { int nr; /* Sound data is fetched at the beginning of each line */ for (nr = 0; nr < 4; nr++) { struct audio_channel_data *cdp = audio_channel + nr; - + if (cdp->data_written == 2) { cdp->data_written = 0; cdp->nextdat = chipmem_bank.wget(cdp->pt); @@ -4053,7 +4927,11 @@ static void hsync_handler(void) } } } - +#ifdef SUPPORT_PENGUINS + if (framecnt == 0 && penguins_enabled_thisframe) { + write_comm_pipe_int (&drawing_pipe, next_lineno, 0); + } +#endif #ifndef SMART_UPDATE { int i, where; @@ -4061,7 +4939,7 @@ static void hsync_handler(void) i = next_lineno - thisframe_y_adjust_real; if (i >= 0 && i < max_ypos_thisframe) { where = amiga2aspect_line_map[i+min_ypos_for_screen]; - if (where < gfxvidinfo.maxline && where != -1) + if (where < gfxvidinfo.height && where != -1) pfield_draw_line (next_lineno, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]); } } @@ -4074,118 +4952,44 @@ static void hsync_handler(void) is_lastline = vpos + 1 == maxvpos + (lof != 0); if ((bplcon0 & 4) && currprefs.gfx_linedbl) { - interlace_seen = 1; + interlace_seen = 1, penguins_enabled_thisframe = 0; } if (framecnt == 0) { - lineno = vpos; - nln_how = 0; - if (currprefs.gfx_linedbl) { - lineno *= 2; - nln_how = 1; - if (bplcon0 & 4) { - if (!lof) { - lineno++; - nln_how = 2; - } else { - nln_how = 3; - } - } - } - next_lineno = lineno; - if (next_lineno > maxvpos) next_lineno = maxvpos; - reset_decisions (); + lineno = vpos; + nln_how = 0; + if (currprefs.gfx_linedbl) { + lineno *= 2; + nln_how = 1; + if (bplcon0 & 4) { + if (!lof) { + lineno++; + nln_how = 2; + } else { + nln_how = 3; + } + } + } + next_lineno = lineno; + reset_decisions (); } - -#ifdef HAS_HARDFILE if (uae_int_requested) { - set_uae_int_flag (); - INTREQ (0xA000); + set_uae_int_flag (); + INTREQ (0xA000); } -#endif } -void customreset(void) +static void init_eventtab (void) { - int i, maxl; - double native_lines_per_amiga_line; -#ifdef HAVE_GETTIMEOFDAY - struct timeval tv; -#endif + int i; - for (i = 0; i < sizeof current_colors.color_regs / sizeof *current_colors.color_regs; i++) - current_colors.color_regs[i] = -1; - -#ifdef FRAME_RATE_HACK - did_reset = 1; - vsyncmintime = read_processor_time() + vsynctime; -#endif - inhibit_frame = 0; -#ifdef HAS_EXPANMEM - expamem_reset (); -#endif -#ifdef HAS_FILESYS - filesys_reset (); -#endif - CIA_reset (); - cycles = 0; - regs.spcflags &= SPCFLAG_BRK; - - lores_factor = currprefs.gfx_lores ? 1 : 2; - lores_shift = currprefs.gfx_lores ? 0 : 1; - sprite_width = currprefs.gfx_lores ? 16 : 32; - - vpos = 0; - is_lastline = 0; - lof = 0; - max_diwstop = 0; - - if (needmousehack()) { -#if 0 - if (mousestate != follow_mouse) setfollow(); -#else - if (mousestate != dont_care_mouse) setdontcare(); -#endif - } else - { - mousestate = normal_mouse; - } - ievent_alive = 0; - - memset(spixstate, 0, sizeof(spixstate)); - clx_sprmask = 0xFF; - clxdat = 0; - - /*memset(blitcount, 0, sizeof(blitcount)); blitter debug */ -#ifdef HALF_HEIGHT - for (i = 0; i < (maxvpos+1) + 1; i++) { -#else - for (i = 0; i < (maxvpos+1)*2 + 1; i++) { -#endif - linestate[i] = LINE_UNDECIDED; - } - xlinebuffer = gfxvidinfo.bufmem; - - dmacon = intena = 0; - bltstate = BLT_done; - copstate = COP_stop; - diwstate = DIW_waiting_start; - hdiwstate = DIW_waiting_start; - copcon = 0; - dskdmaen = 0; - cycles = 0; - - memset(audio_channel, 0, sizeof audio_channel); - - bplcon4 = 0x11; /* Get AGA chipset into ECS compatibility mode */ - bplcon3 = 0xC00; for(i = 0; i < ev_max; i++) { eventtab[i].active = 0; eventtab[i].oldcycles = 0; } copper_active = 0; eventtab[ev_cia].handler = CIA_handler; - eventtab[ev_copper].handler = do_copper; + eventtab[ev_copper].handler = /* currprefs.copper_pos >= 0 ? do_copper_cheat : */ do_copper; eventtab[ev_hsync].handler = hsync_handler; eventtab[ev_hsync].evtime = maxhpos + cycles; eventtab[ev_hsync].active = 1; @@ -4196,6 +5000,8 @@ void customreset(void) eventtab[ev_diskblk].active = 0; eventtab[ev_diskindex].handler = diskindex_handler; eventtab[ev_diskindex].active = 0; + eventtab[ev_disksync].handler = disksync_handler; + eventtab[ev_disksync].active = 0; #ifndef DONT_WANT_SOUND eventtab[ev_aud0].handler = aud0_handler; eventtab[ev_aud0].active = 0; @@ -4213,11 +5019,96 @@ void customreset(void) } #endif events_schedule (); +} + +void customreset (void) +{ + int i, maxl; + double native_lines_per_amiga_line; +#ifdef HAVE_GETTIMEOFDAY + struct timeval tv; +#endif + + for (i = 0; i < sizeof current_colors.color_regs / sizeof *current_colors.color_regs; i++) + current_colors.color_regs[i] = -1; + +#ifdef FRAME_RATE_HACK + did_reset = 1; + vsyncmintime = read_processor_time() + vsynctime; +#endif + inhibit_frame = 0; + frame_do_semup = 0; + //uae_sem_init (&frame_sem, 0, 0); + //uae_sem_init (&gui_sem, 0, 1); + //uae_sem_init (&ihf_sem, 0, 1); + expamem_reset (); + filesys_reset (); + CIA_reset (); +#ifdef PICASSO96 + InitPicasso96 (); + picasso_on = 0; + picasso_requested_on = 0; + gfx_set_picasso_state (0); +#endif + cycles = 0; + regs.spcflags &= SPCFLAG_BRK; + + lores_factor = currprefs.gfx_lores ? 1 : 2; + lores_shift = currprefs.gfx_lores ? 0 : 1; + sprite_width = currprefs.gfx_lores ? 16 : 32; + + vpos = 0; + is_lastline = 0; + lof = 0; + max_diwstop = 0; + + if (needmousehack()) { +#if 0 + if (mousestate != follow_mouse) setfollow(); +#else + if (mousestate != dont_care_mouse) setdontcare(); +#endif + } else { + mousestate = normal_mouse; + } + ievent_alive = 0; + + clx_sprmask = 0xFF; + clxdat = 0; + + memset(sprarmed, 0, sizeof sprarmed); + nr_armed = 0; + + /*memset(blitcount, 0, sizeof(blitcount)); blitter debug */ +#ifdef HALF_HEIGHT + for (i = 0; i < (maxvpos+1) + 1; i++) { +#else + for (i = 0; i < (maxvpos+1)*2 + 1; i++) { +#endif + linestate[i] = LINE_UNDECIDED; + } + xlinebuffer = gfxvidinfo.bufmem; + + dmacon = intena = 0; + bltstate = BLT_done; + copstate = COP_stop; + diwstate = DIW_waiting_start; + hdiwstate = DIW_waiting_start; + copcon = 0; + dskdmaen = 0; + cycles = 0; + + //JMH audio_reset (); + + bplcon4 = 0x11; /* Get AGA chipset into ECS compatibility mode */ + bplcon3 = 0xC00; + + init_eventtab (); if (native2amiga_line_map) - emu_Free (native2amiga_line_map); + free (native2amiga_line_map); if (amiga2aspect_line_map) - emu_Free (amiga2aspect_line_map); + free (amiga2aspect_line_map); /* At least for this array the +1 is necessary. */ #ifdef HALF_HEIGHT @@ -4225,13 +5116,13 @@ void customreset(void) #else amiga2aspect_line_map = (int *)emu_Malloc (sizeof (int) * (maxvpos+1)*2 + 1); #endif - native2amiga_line_map = (int *)emu_Malloc (sizeof (int) * gfxvidinfo.maxline); + native2amiga_line_map = (int *)emu_Malloc (sizeof (int) * gfxvidinfo.height); if (currprefs.gfx_correct_aspect) - native_lines_per_amiga_line = ((double)gfxvidinfo.maxline + native_lines_per_amiga_line = ((double)gfxvidinfo.height * (currprefs.gfx_lores ? 320 : 640) / (currprefs.gfx_linedbl ? 512 : 256) - / gfxvidinfo.maxlinetoscr); + / gfxvidinfo.width); else native_lines_per_amiga_line = 1; @@ -4240,9 +5131,9 @@ void customreset(void) max_drawn_amiga_line = -1; for (i = 0; i < maxl; i++) { int v = (i - min_ypos_for_screen) * native_lines_per_amiga_line; - if (v >= gfxvidinfo.maxline && max_drawn_amiga_line == -1) + if (v >= gfxvidinfo.height && max_drawn_amiga_line == -1) max_drawn_amiga_line = i-min_ypos_for_screen; - if (i < min_ypos_for_screen || v >= gfxvidinfo.maxline) + if (i < min_ypos_for_screen || v >= gfxvidinfo.height) v = -1; amiga2aspect_line_map[i] = v; } @@ -4250,19 +5141,19 @@ void customreset(void) max_drawn_amiga_line >>= 1; if (currprefs.gfx_ycenter && !(currprefs.gfx_correct_aspect)) { - extra_y_adjust = (gfxvidinfo.maxline - (maxvpos << (currprefs.gfx_linedbl ? 1 : 0))) >> 1; + extra_y_adjust = (gfxvidinfo.height - (maxvpos << (currprefs.gfx_linedbl ? 1 : 0))) >> 1; if (extra_y_adjust < 0) extra_y_adjust = 0; } - for (i = 0; i < gfxvidinfo.maxline; i++) + for (i = 0; i < gfxvidinfo.height; i++) native2amiga_line_map[i] = -1; if (native_lines_per_amiga_line < 1) { /* Must omit drawing some lines. */ for (i = maxl-1; i > min_ypos_for_screen; i--) { if (amiga2aspect_line_map[i] == amiga2aspect_line_map[i-1]) { - if (currprefs.gfx_linedbl && (i & 1) == 0 && amiga2aspect_line_map[i+1] != -1) { + if (currprefs.gfx_linedbl && (i & 1) == 0 && amiga2aspect_line_map[i+1] != -1) { /* If only the first line of a line pair would be omitted, * omit the second one instead to avoid problems with line * doubling. */ @@ -4278,23 +5169,21 @@ void customreset(void) int j; if (amiga2aspect_line_map[i] == -1) continue; - for (j = amiga2aspect_line_map[i]; j < gfxvidinfo.maxline && native2amiga_line_map[j] == -1; j++) + for (j = amiga2aspect_line_map[i]; j < gfxvidinfo.height && native2amiga_line_map[j] == -1; j++) native2amiga_line_map[j] = i >> (currprefs.gfx_linedbl ? 1 : 0); } - + if (line_drawn == 0) - line_drawn = (char *)emu_Malloc (gfxvidinfo.maxline); - - if (gfxvidinfo.linemem == NULL) { - if (row_map != 0) - emu_Free (row_map); - row_map = (char **)emu_Malloc (sizeof (char *) * (gfxvidinfo.maxline+1)); - init_row_map(); - } + line_drawn = (char *)malloc (gfxvidinfo.height); + init_row_map(); + + init_sprites (); + init_hardware_frame (); init_drawing_frame (); last_redraw_point = 0; reset_decisions (); + #ifdef HAVE_GETTIMEOFDAY gettimeofday(&tv,NULL); seconds_base = tv.tv_sec; @@ -4304,21 +5193,21 @@ void customreset(void) -int intlev(void) +int intlev (void) { uae_u16 imask = intreq & intena; if (imask && (intena & 0x4000)){ - if (imask & 0x2000) return 6; - if (imask & 0x1800) return 5; - if (imask & 0x0780) return 4; - if (imask & 0x0070) return 3; - if (imask & 0x0008) return 2; - if (imask & 0x0007) return 1; + if (imask & 0x2000) return 6; + if (imask & 0x1800) return 5; + if (imask & 0x0780) return 4; + if (imask & 0x0070) return 3; + if (imask & 0x0008) return 2; + if (imask & 0x0007) return 1; } return -1; } -void custom_init(void) +void custom_init (void) { emu_printf("big structures:"); //emu_printi(sizeof(line_decisions)); @@ -4337,7 +5226,6 @@ void custom_init(void) memset(line_drawinfo[1],line_drawinfo_size, 0); emu_printi(sizeof(line_data)); - int num; #ifdef OS_WITHOUT_MEMORY_MANAGEMENT @@ -4350,8 +5238,8 @@ void custom_init(void) sprite_positions[num] = emu_Malloc(max_sprite_draw * sizeof(struct sprite_draw)); color_changes[num] = emu_Malloc(max_color_change * sizeof(struct color_change)); if(!sprite_positions[num] || !color_changes[num]) { - //printf("Out of mem in %s %d!\n",__FILE__,__LINE__); - abort(); + //printf("Out of mem in %s %d!\n",__FILE__,__LINE__); + abort(); } } if(!(delay_changes = emu_Malloc(max_delay_change * sizeof(struct delay_change)))) { @@ -4359,28 +5247,26 @@ void custom_init(void) abort(); } #endif - + if (needmousehack()) - setfollow(); - - - + setfollow(); init_regchanges (); init_decisions (); + /* For now, the AGA stuff is broken in the dual playfield case. We encode + * sprites in dpf mode by ORing the pixel value with 0x80. To make dual + * playfield rendering easy, the lookup tables contain are made linear for + * values >= 128. That only works for OCS/ECS, though. */ - - for (num = 0; num < 256; num++) { + for (num = 0; num < 256; num++) { int plane1 = (num & 1) | ((num >> 1) & 2) | ((num >> 2) & 4) | ((num >> 3) & 8); int plane2 = ((num >> 1) & 1) | ((num >> 2) & 2) | ((num >> 3) & 4) | ((num >> 4) & 8); dblpf_2nd1[num] = plane1 == 0 ? (plane2 == 0 ? 0 : 2) : 1; dblpf_2nd2[num] = plane2 == 0 ? (plane1 == 0 ? 0 : 1) : 2; - dblpf_aga1[num] = plane1 == 0 ? plane2 : plane1; - dblpf_aga2[num] = plane2 == 0 ? plane1 : plane2; if (plane2 > 0) plane2 += 8; - dblpf_ind1[num] = plane1 == 0 ? plane2 : plane1; - dblpf_ind2[num] = plane2 == 0 ? plane1 : plane2; - + dblpf_ind1[num] = num >= 128 ? num & 0x7F : (plane1 == 0 ? plane2 : plane1); + dblpf_ind2[num] = num >= 128 ? num & 0x7F : (plane2 == 0 ? plane1 : plane2); + lots_of_twos[num] = num == 0 ? 0 : 2; linear_map_256[num] = num; } @@ -4389,8 +5275,13 @@ void custom_init(void) native2amiga_line_map = 0; amiga2aspect_line_map = 0; line_drawn = 0; - row_map = 0; +#ifdef SUPPORT_PENGUINS + init_comm_pipe (&drawing_pipe, 800, 5); + uae_sem_init (&drawing_lock, 0, 0); + start_penguin (drawing_penguin, 0, &our_penguin); + /*atexit(kill_drawing_penguin);*/ +#endif } /* Custom chip memory bank */ @@ -4408,13 +5299,13 @@ addrbank custom_bank = { default_xlate, default_check }; -uae_u32 REGPARAM2 custom_wget(uaecptr addr) +uae_u32 REGPARAM2 custom_wget (uaecptr addr) { switch(addr & 0x1FE) { case 0x002: return DMACONR(); case 0x004: return VPOSR(); case 0x006: return VHPOSR(); - + case 0x008: return DSKDATR(); case 0x00A: return JOY0DAT(); @@ -4439,175 +5330,175 @@ uae_u32 REGPARAM2 custom_wget(uaecptr addr) } } -uae_u32 REGPARAM2 custom_bget(uaecptr addr) +uae_u32 REGPARAM2 custom_bget (uaecptr addr) { return custom_wget(addr & 0xfffe) >> (addr & 1 ? 0 : 8); } -uae_u32 REGPARAM2 custom_lget(uaecptr addr) +uae_u32 REGPARAM2 custom_lget (uaecptr addr) { return ((uae_u32)custom_wget(addr & 0xfffe) << 16) | custom_wget((addr+2) & 0xfffe); } -void REGPARAM2 custom_wput(uaecptr addr, uae_u32 value) +void REGPARAM2 custom_wput (uaecptr addr, uae_u32 value) { addr &= 0x1FE; cregs[addr>>1] = value; - switch(addr) { - case 0x020: DSKPTH(value); break; - case 0x022: DSKPTL(value); break; - case 0x024: DSKLEN(value); break; - case 0x026: DSKDAT(value); break; - - case 0x02A: VPOSW(value); break; - case 0x2E: COPCON(value); break; - case 0x030: SERDAT(value); break; - case 0x032: SERPER(value); break; - - case 0x040: BLTCON0(value); break; - case 0x042: BLTCON1(value); break; - - case 0x044: BLTAFWM(value); break; - case 0x046: BLTALWM(value); break; - - case 0x050: BLTAPTH(value); break; - case 0x052: BLTAPTL(value); break; - case 0x04C: BLTBPTH(value); break; - case 0x04E: BLTBPTL(value); break; - case 0x048: BLTCPTH(value); break; - case 0x04A: BLTCPTL(value); break; - case 0x054: BLTDPTH(value); break; - case 0x056: BLTDPTL(value); break; - - case 0x058: BLTSIZE(value); break; - - case 0x064: BLTAMOD(value); break; - case 0x062: BLTBMOD(value); break; - case 0x060: BLTCMOD(value); break; - case 0x066: BLTDMOD(value); break; - - case 0x070: BLTCDAT(value); break; - case 0x072: BLTBDAT(value); break; - case 0x074: BLTADAT(value); break; - - case 0x07E: DSKSYNC(value); break; + switch (addr) { + case 0x020: DSKPTH (value); break; + case 0x022: DSKPTL (value); break; + case 0x024: DSKLEN (value); break; + case 0x026: DSKDAT (value); break; - case 0x080: COP1LCH(value); break; - case 0x082: COP1LCL(value); break; - case 0x084: COP2LCH(value); break; - case 0x086: COP2LCL(value); break; - - case 0x088: COPJMP1(value); break; - case 0x08A: COPJMP2(value); break; - - case 0x08E: DIWSTRT(value); break; - case 0x090: DIWSTOP(value); break; - case 0x092: DDFSTRT(value); break; - case 0x094: DDFSTOP(value); break; - - case 0x096: DMACON(value); break; - case 0x098: CLXCON(value); break; - case 0x09A: INTENA(value); break; - case 0x09C: INTREQ(value); break; - case 0x09E: ADKCON(value); break; - - case 0x0A0: AUDxLCH(0, value); break; - case 0x0A2: AUDxLCL(0, value); break; - case 0x0A4: AUDxLEN(0, value); break; - case 0x0A6: AUDxPER(0, value); break; - case 0x0A8: AUDxVOL(0, value); break; - case 0x0AA: AUDxDAT(0, value); break; - - case 0x0B0: AUDxLCH(1, value); break; - case 0x0B2: AUDxLCL(1, value); break; - case 0x0B4: AUDxLEN(1, value); break; - case 0x0B6: AUDxPER(1, value); break; - case 0x0B8: AUDxVOL(1, value); break; - case 0x0BA: AUDxDAT(1, value); break; - - case 0x0C0: AUDxLCH(2, value); break; - case 0x0C2: AUDxLCL(2, value); break; - case 0x0C4: AUDxLEN(2, value); break; - case 0x0C6: AUDxPER(2, value); break; - case 0x0C8: AUDxVOL(2, value); break; - case 0x0CA: AUDxDAT(2, value); break; - - case 0x0D0: AUDxLCH(3, value); break; - case 0x0D2: AUDxLCL(3, value); break; - case 0x0D4: AUDxLEN(3, value); break; - case 0x0D6: AUDxPER(3, value); break; - case 0x0D8: AUDxVOL(3, value); break; - case 0x0DA: AUDxDAT(3, value); break; - - case 0x0E0: BPLPTH(value, 0); break; - case 0x0E2: BPLPTL(value, 0); break; - case 0x0E4: BPLPTH(value, 1); break; - case 0x0E6: BPLPTL(value, 1); break; - case 0x0E8: BPLPTH(value, 2); break; - case 0x0EA: BPLPTL(value, 2); break; - case 0x0EC: BPLPTH(value, 3); break; - case 0x0EE: BPLPTL(value, 3); break; - case 0x0F0: BPLPTH(value, 4); break; - case 0x0F2: BPLPTL(value, 4); break; - case 0x0F4: BPLPTH(value, 5); break; - case 0x0F6: BPLPTL(value, 5); break; - - case 0x100: BPLCON0(value); break; - case 0x102: BPLCON1(value); break; - case 0x104: BPLCON2(value); break; - case 0x106: BPLCON3(value); break; - - case 0x108: BPL1MOD(value); break; - case 0x10A: BPL2MOD(value); break; + case 0x02A: VPOSW (value); break; + case 0x2E: COPCON (value); break; + case 0x030: SERDAT (value); break; + case 0x032: SERPER (value); break; + case 0x34: POTGO (value); break; + case 0x040: BLTCON0 (value); break; + case 0x042: BLTCON1 (value); break; + + case 0x044: BLTAFWM (value); break; + case 0x046: BLTALWM (value); break; + + case 0x050: BLTAPTH (value); break; + case 0x052: BLTAPTL (value); break; + case 0x04C: BLTBPTH (value); break; + case 0x04E: BLTBPTL (value); break; + case 0x048: BLTCPTH (value); break; + case 0x04A: BLTCPTL (value); break; + case 0x054: BLTDPTH (value); break; + case 0x056: BLTDPTL (value); break; + + case 0x058: BLTSIZE (value); break; + + case 0x064: BLTAMOD (value); break; + case 0x062: BLTBMOD (value); break; + case 0x060: BLTCMOD (value); break; + case 0x066: BLTDMOD (value); break; + + case 0x070: BLTCDAT (value); break; + case 0x072: BLTBDAT (value); break; + case 0x074: BLTADAT (value); break; + + case 0x07E: DSKSYNC (value); break; + + case 0x080: COP1LCH (value); break; + case 0x082: COP1LCL (value); break; + case 0x084: COP2LCH (value); break; + case 0x086: COP2LCL (value); break; + + case 0x088: COPJMP1 (value); break; + case 0x08A: COPJMP2 (value); break; + + case 0x08E: DIWSTRT (value); break; + case 0x090: DIWSTOP (value); break; + case 0x092: DDFSTRT (value); break; + case 0x094: DDFSTOP (value); break; + + case 0x096: DMACON (value); break; + case 0x098: CLXCON (value); break; + case 0x09A: INTENA (value); break; + case 0x09C: INTREQ (value); break; + case 0x09E: ADKCON (value); break; + + case 0x0A0: AUDxLCH (0, value); break; + case 0x0A2: AUDxLCL (0, value); break; + case 0x0A4: AUDxLEN (0, value); break; + case 0x0A6: AUDxPER (0, value); break; + case 0x0A8: AUDxVOL (0, value); break; + case 0x0AA: AUDxDAT (0, value); break; + + case 0x0B0: AUDxLCH (1, value); break; + case 0x0B2: AUDxLCL (1, value); break; + case 0x0B4: AUDxLEN (1, value); break; + case 0x0B6: AUDxPER (1, value); break; + case 0x0B8: AUDxVOL (1, value); break; + case 0x0BA: AUDxDAT (1, value); break; + + case 0x0C0: AUDxLCH (2, value); break; + case 0x0C2: AUDxLCL (2, value); break; + case 0x0C4: AUDxLEN (2, value); break; + case 0x0C6: AUDxPER (2, value); break; + case 0x0C8: AUDxVOL (2, value); break; + case 0x0CA: AUDxDAT (2, value); break; + + case 0x0D0: AUDxLCH (3, value); break; + case 0x0D2: AUDxLCL (3, value); break; + case 0x0D4: AUDxLEN (3, value); break; + case 0x0D6: AUDxPER (3, value); break; + case 0x0D8: AUDxVOL (3, value); break; + case 0x0DA: AUDxDAT (3, value); break; + + case 0x0E0: BPLPTH (value, 0); break; + case 0x0E2: BPLPTL (value, 0); break; + case 0x0E4: BPLPTH (value, 1); break; + case 0x0E6: BPLPTL (value, 1); break; + case 0x0E8: BPLPTH (value, 2); break; + case 0x0EA: BPLPTL (value, 2); break; + case 0x0EC: BPLPTH (value, 3); break; + case 0x0EE: BPLPTL (value, 3); break; + case 0x0F0: BPLPTH (value, 4); break; + case 0x0F2: BPLPTL (value, 4); break; + case 0x0F4: BPLPTH (value, 5); break; + case 0x0F6: BPLPTL (value, 5); break; + + case 0x100: BPLCON0 (value); break; + case 0x102: BPLCON1 (value); break; + case 0x104: BPLCON2 (value); break; + case 0x106: BPLCON3 (value); break; + + case 0x108: BPL1MOD (value); break; + case 0x10A: BPL2MOD (value); break; + + case 0x110: BPL1DAT (value); break; + case 0x112: BPL2DAT (value); break; + case 0x114: BPL3DAT (value); break; + case 0x116: BPL4DAT (value); break; + case 0x118: BPL5DAT (value); break; + case 0x11A: BPL6DAT (value); break; - case 0x110: BPL1DAT(value); break; - case 0x112: BPL2DAT(value); break; - case 0x114: BPL3DAT(value); break; - case 0x116: BPL4DAT(value); break; - case 0x118: BPL5DAT(value); break; - case 0x11A: BPL6DAT(value); break; - case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A: case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196: case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2: case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE: case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA: case 0x1BC: case 0x1BE: - COLOR(value & 0xFFF, (addr & 0x3E) / 2); + COLOR (value & 0xFFF, (addr & 0x3E) / 2); break; case 0x120: case 0x124: case 0x128: case 0x12C: case 0x130: case 0x134: case 0x138: case 0x13C: - SPRxPTH(value, (addr - 0x120) / 4); + SPRxPTH (value, (addr - 0x120) / 4); break; case 0x122: case 0x126: case 0x12A: case 0x12E: case 0x132: case 0x136: case 0x13A: case 0x13E: - SPRxPTL(value, (addr - 0x122) / 4); + SPRxPTL (value, (addr - 0x122) / 4); break; case 0x140: case 0x148: case 0x150: case 0x158: case 0x160: case 0x168: case 0x170: case 0x178: - SPRxPOS(value, (addr - 0x140) / 8); + SPRxPOS (value, (addr - 0x140) / 8); break; case 0x142: case 0x14A: case 0x152: case 0x15A: case 0x162: case 0x16A: case 0x172: case 0x17A: - SPRxCTL(value, (addr - 0x142) / 8); + SPRxCTL (value, (addr - 0x142) / 8); break; case 0x144: case 0x14C: case 0x154: case 0x15C: case 0x164: case 0x16C: case 0x174: case 0x17C: - SPRxDATA(value, (addr - 0x144) / 8); + SPRxDATA (value, (addr - 0x144) / 8); break; case 0x146: case 0x14E: case 0x156: case 0x15E: case 0x166: case 0x16E: case 0x176: case 0x17E: - SPRxDATB(value, (addr - 0x146) / 8); + SPRxDATB (value, (addr - 0x146) / 8); break; - - case 0x36: JOYTEST(value); break; -#if defined(ECS_AGNUS) || (AGA_CHIPSET == 1) + + case 0x36: JOYTEST (value); break; +#if defined (ECS_AGNUS) || (AGA_CHIPSET == 1) case 0x5A: BLTCON0L(value); break; - case 0x5C: BLTSIZV(value); break; - case 0x5E: BLTSIZH(value); break; + case 0x5C: BLTSIZV (value); break; + case 0x5E: BLTSIZH (value); break; #endif #if AGA_CHIPSET == 1 - case 0x10C: BPLCON4(value); break; + case 0x10C: BPLCON4 (value); break; case 0x1FC: fmode = value; break; #endif } diff --git a/MCUME_teensy/teensyuae41/disk.c b/MCUME_teensy/teensyuae41/disk.c index 7896f51..0ab57f1 100644 --- a/MCUME_teensy/teensyuae41/disk.c +++ b/MCUME_teensy/teensyuae41/disk.c @@ -3,7 +3,7 @@ * * Floppy disk emulation * - * (c) 1995 Bernd Schmidt, Hannu Rummukainen + * Copyright 1995 Bernd Schmidt, Hannu Rummukainen */ #include @@ -11,29 +11,30 @@ #include "shared.h" #include "memory.h" -#include "gensound.h" -#include "sounddep/sound.h" #include "events.h" #include "custom.h" #include "ersatz.h" #include "disk.h" #include "gui.h" -//#include "zfile.h" +#include "zfile.h" #include "autoconf.h" #include "readcpu.h" #include "newcpu.h" #include "xwin.h" -//#include "osemu.h" -#include "execlib.h" #define NB_DRIVE 1 + +#define STATIC_INLINE static + #define FLOPPY_GAP_LEN 360 -#define FLOPPY_SPEED 3 +#define FLOPPY_SPEED 50 -//JMH: uae_u16* mfmwrite; -//JMH: static uae_u16 mfmwrbuffer[16384]; /* space for maximum disk DMA transfer */ +#ifdef HAS_FLOPPYWRITE +uae_u16* mfmwrite; +static uae_u16 mfmwrbuffer[16384]; /* space for maximum disk DMA transfer */ +#endif static int side, direction, step; static uae_u8 selected = 15; @@ -58,6 +59,7 @@ typedef struct { int motoroff; int wrprot; uae_u16 bigmfmbuf[0x4000]; + int mfmbufpos; int tracklen; unsigned long last_cycles; int mfmpos; @@ -75,120 +77,143 @@ typedef struct { drive floppy[NB_DRIVE]; -static void drive_fill_bigbuf(drive *drv); +static void drive_fill_bigbuf (drive *drv); +#ifdef unused +FILE *DISK_validate_filename (const char *fname, int leave_open, int *wrprot) +{ + FILE *f = fopen (fname, "r+b"); + if (f) { + if (wrprot) + *wrprot = 0; + } else { + if (wrprot) + *wrprot = 1; + f = fopen (fname, "rb"); + } + if (!leave_open) + fclose (f); + return f; +} +#endif -static int drive_insert(drive *drv, int dnum, const char *fname) +static int drive_insert (drive *drv, int dnum, const char *fname) { unsigned char buffer[10]; + emu_printf("insert"); + emu_printf(fname); - drv->diskfile = emu_FileOpen(fname); - if (drv->diskfile == 0) - return 0; - - strncpy (currprefs.df[dnum], fname, MAX_FILENAME-1); - currprefs.df[dnum][MAX_FILENAME-1] = 0; - strncpy (changed_prefs.df[dnum], fname, MAX_FILENAME-1); - changed_prefs.df[dnum][MAX_FILENAME-1] = 0; - - emu_printf("flop:"); - emu_printf(fname); +#ifdef unused + drv->diskfile = DISK_validate_filename (fname, 1, &drv->wrprot); +#endif + drv->diskfile = emu_FileOpen(fname); + if (drv->diskfile == 0) { + drv->tracklen = 2000; + return 0; + } + + strncpy (currprefs.df[dnum], fname, 255); + currprefs.df[dnum][255] = 0; + strncpy (changed_prefs.df[dnum], fname, 255); + changed_prefs.df[dnum][255] = 0; + //gui_filename(dnum, fname); emu_FileRead(buffer, 8); - if (strncmp((char *)buffer,"UAE--ADF",8) == 0) { - int offs = 160*4+8; - int i; - - drv->filetype = ADF_EXT1; - drv->num_tracks = 160; - drv->num_secs = 11; - - drv->wrprot = 1; /* write to adf_ext1 not implemented */ - for(i=0; i<160; i++) { - emu_FileRead(buffer, 4); - drv->trackdata[i].sync = buffer[0]*256 + buffer[1]; - drv->trackdata[i].len = buffer[2]*256 + buffer[3]; - drv->trackdata[i].offs = offs; - offs += drv->trackdata[i].len; - } - } - else { - unsigned int i; - - drv->filetype = ADF_NORMAL; + if (strncmp((char *)buffer,"UAE--ADF",8) == 0) { + emu_printf("UAE--ADF"); + int offs = 160*4+8; + int i; - i = emu_FileSize(fname); - drv->diskfile = emu_FileOpen(fname); - /* High-density disk? */ - if (i >= 160*22*512) - drv->num_tracks = i / (512*(drv->num_secs = 22)); - else - drv->num_tracks = i / (512*(drv->num_secs = 11)); - - if (drv->num_tracks > MAX_TRACKS) - emu_printf("Your diskfile is too big!\n"); - for(i = 0; i < drv->num_tracks; i++) { - drv->trackdata[i].len = 512 * drv->num_secs; - drv->trackdata[i].sync = 0; - drv->trackdata[i].offs = i * 512 * drv->num_secs; - } + drv->filetype = ADF_EXT1; + drv->num_tracks = 160; + drv->num_secs = 11; + + drv->wrprot = 1; /* write to adf_ext1 not implemented */ + for(i=0; i<160; i++) { + emu_FileRead(buffer, 4); + drv->trackdata[i].sync = buffer[0]*256 + buffer[1]; + drv->trackdata[i].len = buffer[2]*256 + buffer[3]; + drv->trackdata[i].offs = offs; + offs += drv->trackdata[i].len; + } + } else { + unsigned int i; + emu_printf("NORMAL"); + + drv->filetype = ADF_NORMAL; + + i = emu_FileSize(fname); + emu_FileOpen(fname); + /* High-density disk? */ + if (i >= 160*22*512) + drv->num_tracks = i / (512*(drv->num_secs = 22)); + else + drv->num_tracks = i / (512*(drv->num_secs = 11)); + + if (drv->num_tracks > MAX_TRACKS) + write_log ("Your diskfile is too big!\n"); + for(i = 0; i < drv->num_tracks; i++) { + drv->trackdata[i].len = 512 * drv->num_secs; + drv->trackdata[i].sync = 0; + drv->trackdata[i].offs = i * 512 * drv->num_secs; + } } drv->buffered_side = 2; /* will force read */ - + drive_fill_bigbuf (drv); return 1; } -static int drive_empty(drive *drv) +static int drive_empty (drive *drv) { - return drv->diskfile == 0; + return drv->diskfile == 0; } -static void drive_step(drive *drv) +static void drive_step (drive *drv) { if (!drive_empty(drv)) - drv->dskchange = 0; + drv->dskchange = 0; else if (drv->dskchange > 1) { -/* emu_printf("Stepping...\n"); +/* printf("Stepping...\n"); drv->dskchange--;*/ } if (direction) { - if (drv->cyl) drv->cyl--; + if (drv->cyl) drv->cyl--; } else { - if (drv->cyl < drv->num_tracks/2) drv->cyl++; + if (drv->cyl < drv->num_tracks/2) drv->cyl++; } } -static int drive_track0(drive *drv) +static int drive_track0 (drive *drv) { - return drv->cyl == 0; + return drv->cyl == 0; } -static int drive_writeprotected(drive *drv) +static int drive_writeprotected (drive *drv) { - return drv->wrprot || drv->diskfile == NULL; + return drv->wrprot || drv->diskfile == NULL; } -static int drive_running(drive *drv) +static int drive_running (drive *drv) { - return !drv->motoroff; + return !drv->motoroff; } -static void drive_motor(drive *drv, int off) +static void drive_motor (drive *drv, int off) { if (drv->motoroff && !off) { - drv->last_cycles = cycles; - drv->mfmpos = 0; - eventtab[ev_diskindex].active = 1; - if (drv->tracklen) - eventtab[ev_diskindex].evtime = FLOPPY_SPEED * drv->tracklen + cycles; - else - eventtab[ev_diskindex].evtime = cycles + 1000; - eventtab[ev_diskindex].oldcycles = cycles; + drv->last_cycles = cycles; + drv->mfmpos = 0; + eventtab[ev_diskindex].active = 1; + if (drv->tracklen) + eventtab[ev_diskindex].evtime = FLOPPY_SPEED * drv->tracklen + cycles; + else + eventtab[ev_diskindex].evtime = cycles + 1000; + eventtab[ev_diskindex].oldcycles = cycles; } else if (off) - eventtab[ev_diskindex].active = 0; + eventtab[ev_diskindex].active = 0; drv->motoroff = off; - events_schedule(); + events_schedule (); } static void drive_fill_bigbuf(drive *drv) @@ -196,93 +221,96 @@ static void drive_fill_bigbuf(drive *drv) int tr = drv->cyl*2 + side; if (!drv->diskfile) { - drv->tracklen = 10; - memset (drv->bigmfmbuf,0xaa,drv->tracklen*2); - return; + drv->tracklen = 2000; + memset (drv->bigmfmbuf,0xaa,drv->tracklen*2); + return; } if (drv->buffered_cyl == drv->cyl && drv->buffered_side == side) - return; + return; +/* if (drv->num_tracks <= tr) { + write_log ("Access beyond end of floppy image!\n"); + }*/ + if (drv->trackdata[tr].sync == 0) { - /* Normal AmigaDOS format track */ - unsigned int sec; - drv->tracklen = drv->num_secs*544 + FLOPPY_GAP_LEN; - memset(drv->bigmfmbuf,0xaa,FLOPPY_GAP_LEN*2); + /* Normal AmigaDOS format track */ + unsigned int sec; + drv->tracklen = drv->num_secs*544 + FLOPPY_GAP_LEN; + memset (drv->bigmfmbuf,0xaa,FLOPPY_GAP_LEN*2); - for (sec = 0; sec < drv->num_secs; sec++) - { - uae_u8 secbuf[544]; - int i; - uae_u16 *mfmbuf = drv->bigmfmbuf + 544*sec + FLOPPY_GAP_LEN; - uae_u32 deven,dodd; - uae_u32 hck=0,dck=0; - - secbuf[0] = secbuf[1] = 0x00; - secbuf[2] = secbuf[3] = 0xa1; - secbuf[4] = 0xff; - secbuf[5] = tr; - secbuf[6] = sec; - secbuf[7] = drv->num_secs-sec; + for (sec = 0; sec < drv->num_secs; sec++) { + uae_u8 secbuf[544]; + int i; + uae_u16 *mfmbuf = drv->bigmfmbuf + 544*sec + FLOPPY_GAP_LEN; + uae_u32 deven,dodd; + uae_u32 hck=0,dck=0; - for(i = 8; i < 24; i++) - secbuf[i] = 0; - - emu_FileSeek(drv->trackdata[tr].offs + sec*512, - SEEK_SET); - emu_FileRead(&secbuf[32],512); + secbuf[0] = secbuf[1] = 0x00; + secbuf[2] = secbuf[3] = 0xa1; + secbuf[4] = 0xff; + secbuf[5] = tr; + secbuf[6] = sec; + secbuf[7] = drv->num_secs-sec; - mfmbuf[0] = mfmbuf[1] = 0xaaaa; - mfmbuf[2] = mfmbuf[3] = 0x4489; + for(i = 8; i < 24; i++) + secbuf[i] = 0; - deven = ((secbuf[4] << 24) | (secbuf[5] << 16) - | (secbuf[6] << 8) | (secbuf[7])); - dodd = deven >> 1; - deven &= 0x55555555; dodd &= 0x55555555; + emu_FileSeek (drv->trackdata[tr].offs + sec*512, + SEEK_SET); + emu_FileRead (&secbuf[32],512); - mfmbuf[4] = dodd >> 16; - mfmbuf[5] = dodd; - mfmbuf[6] = deven>> 16; - mfmbuf[7] = deven; + mfmbuf[0] = mfmbuf[1] = 0xaaaa; + mfmbuf[2] = mfmbuf[3] = 0x4489; - for (i = 8; i < 48; i++) - mfmbuf[i] = 0; - for (i = 0; i < 512; i += 4){ - deven = ((secbuf[i+32] << 24) | (secbuf[i+33] << 16) - | (secbuf[i+34] << 8) | (secbuf[i+35])); - dodd = deven >> 1; - deven &= 0x55555555; dodd &= 0x55555555; - mfmbuf[(i>>1)+32] = dodd >> 16; - mfmbuf[(i>>1)+33] = dodd; - mfmbuf[(i>>1)+256+32] = deven >> 16; - mfmbuf[(i>>1)+256+33] = deven; - } + deven = ((secbuf[4] << 24) | (secbuf[5] << 16) + | (secbuf[6] << 8) | (secbuf[7])); + dodd = deven >> 1; + deven &= 0x55555555; dodd &= 0x55555555; - for(i = 4; i < 24; i += 2) - hck ^= (mfmbuf[i] << 16) | mfmbuf[i+1]; - - deven = dodd = hck; dodd >>= 1; - mfmbuf[24] = dodd >> 16; mfmbuf[25] = dodd; - mfmbuf[26] = deven>> 16; mfmbuf[27] = deven; - - for(i = 32; i < 544; i += 2) - dck ^= (mfmbuf[i] << 16) | mfmbuf[i+1]; - - deven = dodd = dck; dodd >>= 1; - mfmbuf[28] = dodd >> 16; mfmbuf[29] = dodd; - mfmbuf[30] = deven>> 16; mfmbuf[31] = deven; - } + mfmbuf[4] = dodd >> 16; + mfmbuf[5] = dodd; + mfmbuf[6] = deven>> 16; + mfmbuf[7] = deven; + + for (i = 8; i < 48; i++) + mfmbuf[i] = 0xaaaa; + for (i = 0; i < 512; i += 4){ + deven = ((secbuf[i+32] << 24) | (secbuf[i+33] << 16) + | (secbuf[i+34] << 8) | (secbuf[i+35])); + dodd = deven >> 1; + deven &= 0x55555555; dodd &= 0x55555555; + mfmbuf[(i>>1) + 32] = dodd >> 16; + mfmbuf[(i>>1) + 33] = dodd; + mfmbuf[(i>>1) + 256 + 32] = deven >> 16; + mfmbuf[(i>>1) + 256 + 33] = deven; + } + + for(i = 4; i < 24; i += 2) + hck ^= (mfmbuf[i] << 16) | mfmbuf[i+1]; + + deven = dodd = hck; dodd >>= 1; + mfmbuf[24] = dodd >> 16; mfmbuf[25] = dodd; + mfmbuf[26] = deven >> 16; mfmbuf[27] = deven; + + for(i = 32; i < 544; i += 2) + dck ^= (mfmbuf[i] << 16) | mfmbuf[i+1]; + + deven = dodd = dck; dodd >>= 1; + mfmbuf[28] = dodd >> 16; mfmbuf[29] = dodd; + mfmbuf[30] = deven >> 16; mfmbuf[31] = deven; + } } else { int i; - drv->tracklen = drv->trackdata[tr].len/2 + 1; - drv->bigmfmbuf[0] = drv->trackdata[tr].sync; - emu_FileSeek(drv->trackdata[tr].offs, SEEK_SET); - emu_FileRead(drv->bigmfmbuf+1, drv->trackdata[tr].len); - for (i = 0; i < drv->trackdata[tr].len/2; i++) { - uae_u16 *mfm = drv->bigmfmbuf + i + 1; - uae_u8 *data = (uae_u8 *)mfm; - - *mfm = 256 * *data + *(data+1); - } + drv->tracklen = drv->trackdata[tr].len/2 + 1; + drv->bigmfmbuf[0] = drv->trackdata[tr].sync; + emu_FileSeek(drv->trackdata[tr].offs, SEEK_SET); + emu_FileRead((char *)(drv->bigmfmbuf + 1), drv->trackdata[tr].len); + for (i = 0; i < drv->trackdata[tr].len/2; i++) { + uae_u16 *mfm = drv->bigmfmbuf + i + 1; + uae_u8 *data = (uae_u8 *)mfm; + + *mfm = 256 * *data + *(data+1); + } } drv->buffered_side = side; drv->buffered_cyl = drv->cyl; @@ -290,137 +318,374 @@ static void drive_fill_bigbuf(drive *drv) drv->mfmpos = 0; } -static int drive_get_data(drive *drv, uae_u16 *mfm, uae_u16 *byt) +/* Perform DMA for the time interval since the last call. */ +static int drive_update_reads (drive *drv, uaecptr *ptr, int *length, int *syncfound, int sync) { - int offset,mfmpos; + unsigned long maxbytes = (cycles - drv->last_cycles) * 2 / FLOPPY_SPEED; + unsigned long maxcount = maxbytes >> 1; + drv->last_cycles += maxcount * FLOPPY_SPEED; drive_fill_bigbuf(drv); - offset = (cycles - drv->last_cycles) / FLOPPY_SPEED; - mfmpos = (drv->mfmpos + offset) % drv->tracklen; - drv->last_cycles += offset*FLOPPY_SPEED; - drv->mfmpos = mfmpos; - *mfm = drv->bigmfmbuf[mfmpos]; - return offset > 0; + + if (! ptr) { + if (! drv->motoroff) + drv->mfmpos += maxcount; + drv->mfmpos %= drv->tracklen; + } else { + while (maxcount-- > 0 && *length > 0) { + unsigned int word; + if (drv->mfmpos > drv->tracklen) { + write_log ("Bug in disk code - mfmpos too large\n"); + drv->mfmpos = 0; + } + word = drv->bigmfmbuf[drv->mfmpos]; + if (*syncfound) { + put_word (*ptr, word); + (*ptr) += 2; + (*length)--; + } + if (word == sync) + *syncfound = 1; + if (! drv->motoroff) + drv->mfmpos++; + if (drv->mfmpos > drv->tracklen) + drv->mfmpos = 0; + } + } + return ! drv->motoroff && maxbytes >= 1; +} + +/* We assume that drive_update_reads has already been called. */ +static void drive_get_data (drive *drv, uae_u16 *mfm, uae_u16 *byt) +{ + *mfm = drv->bigmfmbuf[drv->mfmpos]; + if (cycles - drv->last_cycles > (FLOPPY_SPEED / 2)) + *byt = *mfm & 0xff; + else + *byt = (*mfm >> 8) & 0xff; } #define MFMMASK 0x55555555 -static __inline__ uae_u32 getmfmlong(uae_u16* mbuf) +STATIC_INLINE uae_u32 getmfmlong (uae_u16* mbuf) { return ((*mbuf << 16) | *(mbuf + 1)) & MFMMASK; } -static void drive_write_data(drive *drv, uae_u16 *mbuf, int length) +static void drive_write_data (drive *drv, uae_u16 *mbuf, int length) { +#ifdef HAS_FLOPPYWRITE int i, secwritten = 0; uae_u32 odd, even, chksum, id, dlong; uae_u8* secdata; uae_u8 secbuf[544]; uae_u16 *mend = mbuf + length; - if (drive_writeprotected(drv)) - return; + if (drive_writeprotected (drv)) + return; - drive_fill_bigbuf(drv); + drive_fill_bigbuf (drv); mend -= (4 + 16 + 8 + 512); while (length > 0) { - int trackoffs; + int trackoffs; - do { - while (*mbuf++ != 0x4489) { - if (mbuf >= mend) return; - } - } while (*mbuf++ != 0x4489); - - odd = getmfmlong(mbuf); - even = getmfmlong(mbuf+2); - mbuf += 4; - id = (odd << 1) | even; + do { + while (*mbuf++ != 0x4489) { + if (mbuf >= mend) + return; + } + } while (*mbuf++ != 0x4489); - trackoffs = (id & 0xff00) >> 8; - if (trackoffs > 10) { - emu_printf("Disk write: weird sector number:"); - emu_printi(trackoffs); - continue; - } - chksum = odd ^ even; - for (i=0; i<4; i++) { - odd = getmfmlong(mbuf); - even = getmfmlong(mbuf+8); - mbuf += 2; - - dlong = (odd << 1) | even; - if (dlong) secwritten = -200; - chksum ^= odd ^ even; - } /* could check here if the label is nonstandard */ - mbuf += 8; - odd = getmfmlong(mbuf); even = getmfmlong(mbuf+2); mbuf += 4; - if ((((odd << 1) | even) != chksum) || - (((id & 0x00ff0000) >> 16) != drv->cyl*2 + side)) { - emu_printf("Disk write: checksum error on sector header\n"); - continue; - } - odd = getmfmlong(mbuf); even = getmfmlong(mbuf+2); mbuf += 4; - chksum = (odd << 1) | even; - secdata = secbuf + 32; - for (i=0; i<128; i++) { - odd = getmfmlong(mbuf); even = getmfmlong(mbuf+256); mbuf += 2; - dlong = (odd << 1) | even; - *secdata++ = dlong >> 24; *secdata++ = (dlong >> 16) & 0xff; - *secdata++ = dlong >> 8; *secdata++ = dlong; - chksum ^= odd ^ even; - } - mbuf += 256; - if (chksum) { - emu_printf("Disk write: data checksum error\n"); - continue; - } - secwritten++; - emu_FileSeek(drv->trackdata[drv->cyl*2 + side].offs + trackoffs*512, - SEEK_SET); - // JMH fwrite(secbuf+32, sizeof(uae_u8), 512, drv->diskfile); + odd = getmfmlong (mbuf); + even = getmfmlong (mbuf + 2); + mbuf += 4; + id = (odd << 1) | even; + + trackoffs = (id & 0xff00) >> 8; + if (trackoffs > 10) { + //write_log ("Disk write: weird sector number %d\n", trackoffs); + continue; + } + chksum = odd ^ even; + for (i = 0; i < 4; i++) { + odd = getmfmlong(mbuf); + even = getmfmlong(mbuf+8); + mbuf += 2; + + dlong = (odd << 1) | even; + if (dlong) + secwritten = -200; + chksum ^= odd ^ even; + } /* could check here if the label is nonstandard */ + mbuf += 8; + odd = getmfmlong (mbuf); even = getmfmlong (mbuf+2); mbuf += 4; + if (((odd << 1) | even) != chksum + || ((id & 0x00ff0000) >> 16) != drv->cyl*2 + side) + { + write_log ("Disk write: checksum error on sector header\n"); + continue; + } + odd = getmfmlong(mbuf); even = getmfmlong(mbuf+2); mbuf += 4; + chksum = (odd << 1) | even; + secdata = secbuf + 32; + for (i=0; i<128; i++) { + odd = getmfmlong(mbuf); even = getmfmlong(mbuf+256); mbuf += 2; + dlong = (odd << 1) | even; + *secdata++ = dlong >> 24; *secdata++ = (dlong >> 16) & 0xff; + *secdata++ = dlong >> 8; *secdata++ = dlong; + chksum ^= odd ^ even; + } + mbuf += 256; + if (chksum) { + write_log ("Disk write: data checksum error\n"); + continue; + } + secwritten++; + emu_FileSeek (drv->trackdata[drv->cyl*2 + side].offs + trackoffs*512, + SEEK_SET); + emu_FileRead (secbuf+32, 512); } drv->buffered_side = 2; /* will force read */ - - if (secwritten == 0) - emu_printf("Disk write in unsupported format\n"); + + if (secwritten == 0) + write_log ("Disk write in unsupported format\n"); if (secwritten < 0) - emu_printf("Disk write: sector labels ignored\n"); + write_log ("Disk write: sector labels ignored\n"); +#endif } -static void drive_eject(drive *drv) +static void drive_eject (drive *drv) { - if (!drive_empty(drv)) - emu_FileClose(); - + if (! drive_empty (drv)) + emu_FileClose(); + drv->dskchange = 4; drv->dskchange_time = 20; -/* emu_printf("setting changed bit %d\n", drv-floppy);*/ +/* printf("setting changed bit %d\n", drv-floppy);*/ drv->diskfile = 0; } -/* We use this function if we have no Kickstart ROM. +/* We use this function if we have no Kickstart ROM. * No error checking - we trust our luck. */ void DISK_ersatz_read (int tr, int sec, uaecptr dest) { - int i; uae_u8 *dptr = get_real_address(dest); - emu_FileSeek(floppy[0].trackdata[tr].offs + sec*512, SEEK_SET); - emu_FileRead(dptr, 512); + emu_FileSeek (floppy[0].trackdata[tr].offs + sec*512, SEEK_SET); + emu_FileRead (dptr, 512); } -void disk_eject(int num) +void disk_eject (int num) { //gui_filename(num, ""); drive_eject(floppy + num); - //*currprefs.df[num] = *changed_prefs.df[num] = 0; + *currprefs.df[num] = *changed_prefs.df[num] = 0; } -void disk_insert(int num, const char *name) +void disk_insert (int num, const char *name) { /* just to be sure */ - drive_eject(floppy + num); - drive_insert(floppy + num, num, name); + drive_eject (floppy + num); + drive_insert (floppy + num, num, name); +} + +void DISK_check_change (void) +{ + int i; + static int count = 0; + count++; + + for (i = 0; i < NB_DRIVE; i++) { + if (strcmp (currprefs.df[i], changed_prefs.df[i]) != 0) { + if (currprefs.df[i][0] != '\0') { + drive_eject(floppy + i); + currprefs.df[i][0] = '\0'; + //gui_filename(i, ""); + } else if (floppy[i].dskchange == 1) { + /* In theory, it should work without the dskchange test. + * In practice, it doesn't. */ + drive_insert (floppy + i, i, changed_prefs.df[i]); + } else if (floppy[i].dskchange > 1 && floppy[i].dskchange_time > 0) { + /* Force the dskchange bit to go to 1 after a given timeout */ + if (--floppy[i].dskchange_time == 0) { + floppy[i].dskchange = 1; + } + } + } + } +} + +int disk_empty (int num) +{ + return drive_empty (floppy + num); +} + +void DISK_init (void) +{ + int i; + for (i = 0; i < NB_DRIVE; i++) + if (!drive_insert (floppy+i, i, currprefs.df[i])) + disk_eject (i); + + if (disk_empty (0)) + write_log ("No disk in drive 0.\n"); +} + +static int ledstate[] = { 0,0,0,0 }; + +void DISK_select (uae_u8 data) +{ + int step_pulse; + int dr; + + if (selected != ((data >> 3) & 15)) + dskready = 0; + selected = (data >> 3) & 15; + side = 1 - ((data >> 2) & 1); + + direction = (data >> 1) & 1; + step_pulse = data & 1; + if (step != step_pulse) { + step = step_pulse; + if (step == 0){ + for (dr = 0; dr < NB_DRIVE; dr++){ + if (!(selected & (1 << dr))) { + drive_step (floppy + dr); + } + } + } + } + for (dr = 0; dr < NB_DRIVE; dr++){ + if (!(selected & (1<> 7); + } + } + for (dr = 0; dr < NB_DRIVE; dr++) { + int state = (!(selected & (1<dskchange) { + /*printf("changed bit set: %d\n",dr); */ + st &= ~0x4; + if (drv->dskchange > 1) + drv->dskchange--; + } + } + } + return st; +} + +void DISK_GetData (uae_u16 *mfm, uae_u16 *byt) +{ + int dr; + for (dr = 0; dr < NB_DRIVE; dr++){ + if (!(selected & (1<mfmpos; + unsigned long missing = FLOPPY_SPEED - (cycles - drv->last_cycles); + unsigned long count = 0; + if (missing == 0) { + write_log ("bug in disk code: missing == 0\n"); + return; + } + + while (missing < cycle_limit) { + count += missing; + cycle_limit -= missing; + missing = FLOPPY_SPEED; + if (drv->bigmfmbuf[offs] == sync) { + eventtab[ev_disksync].active = 1; + eventtab[ev_disksync].oldcycles = cycles; + eventtab[ev_disksync].evtime = cycles + count; + events_schedule (); + } + offs++; + } + } + } +} + +/* Called when DMA gets restarted, so that we don't do DMA for the + parts of the track that went past us while DMA was off. */ +void DISK_reset_cycles (void) +{ + int dr; + for (dr = 0; dr < NB_DRIVE; dr++) { + drive *drv = floppy + dr; + unsigned long count = (cycles - drv->last_cycles) / FLOPPY_SPEED; + drv->mfmpos += count; + drv->mfmpos %= drv->tracklen; + drv->last_cycles += count * FLOPPY_SPEED; + } +} + +void DISK_StartRead () +{ + DISK_reset_cycles (); } static int first = 0; @@ -441,209 +706,4 @@ void disk_swap(const char * disk0, const char * disk1) emu_printf(disk1); drive_insert(floppy + 0, 0, disk1); } -emu_printf("done"); -delay(100); -} - -void DISK_check_change (void) -{ - int i; - static int count = 0; - count++; - - for (i = 0; i < NB_DRIVE; i++) { - if (strcmp (currprefs.df[i], changed_prefs.df[i]) != 0) { - if (currprefs.df[i][0] != '\0') { - drive_eject(floppy + i); - currprefs.df[i][0] = '\0'; - /*emu_printf("Ejecting %d at %d\n", i, count);*/ - } else if (floppy[i].dskchange == 1) { - /* In theory, it should work without the dskchange test. - * In practice, it doesn't. */ - drive_insert (floppy + i, i, changed_prefs.df[i]); - /*emu_printf("Inserting %d at %d\n", i, count);*/ - } else if (floppy[i].dskchange > 1 && floppy[i].dskchange_time > 0) { - /* Force the dskchange bit to go to 1 after a given timeout */ - /*emu_printf("Countdown %d at %d\n", i, count);*/ - if (--floppy[i].dskchange_time == 0) { - /*emu_printf("Timeout %d at %d\n", i, count);*/ - floppy[i].dskchange = 1; - } - } - } - } -} - -int disk_empty(int num) -{ - return drive_empty(floppy + num); -} - -void DISK_init() -{ - int i; - for (i = 0; i < NB_DRIVE; i++) - if (!drive_insert (floppy+i, i, currprefs.df[i])) { - emu_printf("eject"); - disk_eject (i); - } - - if (disk_empty (0)) - emu_printf("No disk in drive 0.\n"); -} - -static int ledstate[] = { 0,0,0,0 }; - -void DISK_select(uae_u8 data) -{ - int step_pulse; - int dr; - - if (selected != ((data >> 3) & 15)) - dskready = 0; - selected = (data >> 3) & 15; - side = 1 - ((data >> 2) & 1); - - direction = (data >> 1) & 1; - step_pulse = data & 1; - if (step != step_pulse) { - step = step_pulse; - if (step == 0){ - for (dr = 0; dr < NB_DRIVE; dr++){ - if (!(selected & (1 << dr))) { - drive_step(floppy + dr); - } - } - } - } - for (dr = 0; dr < NB_DRIVE; dr++){ - if (!(selected & (1<> 7); - } - } - for (dr = 0; dr < NB_DRIVE; dr++) { - int state = (!(selected & (1<dskchange) { - /*emu_printf("changed bit set: %d\n",dr); */ - st &= ~0x4; - if (drv->dskchange > 1) - drv->dskchange--; - } - } - } - return st; -} - -int DISK_GetData(uae_u16 *mfm,uae_u16 *byt) -{ - int dr; - for (dr = 0; dr < NB_DRIVE; dr++){ - if (!(selected & (1<last_cycles) / FLOPPY_SPEED; - mfmpos = (drv->mfmpos + offset) % drv->tracklen; - drv->last_cycles += offset*FLOPPY_SPEED; - drv->mfmpos = mfmpos; - mfmpos++; mfmpos %= drv->tracklen; - while (drv->bigmfmbuf[mfmpos] != sync && mfmpos != drv->mfmpos && use_sync) - mfmpos = (mfmpos + 1) % drv->tracklen, time++; - - if (drv->bigmfmbuf[mfmpos] != sync && use_sync) { - write_log ("warning: sync not found on disk read\n"); - return 0; - } else - mfmpos++; - - mfm_read_length = length; - - while (length--) { - *mfmp++ = drv->bigmfmbuf[mfmpos]; - mfmpos = (mfmpos + 1) % drv->tracklen; - time++; - } - return time*FLOPPY_SPEED; - } - } - return 0; -} - -int DISK_ReadMFM(uaecptr target) -{ - int i; - uae_u8 *mfmp = get_real_address(target); - - if (!chipmem_bank.check(target, mfm_read_length * 2)) { - emu_printf("warning: Bad disk DMA read pointer\n"); - return 0; - } - - for (i = 0; i < mfm_read_length; i++) { - *mfmp++ = mfm_read_buffer[i] >> 8; - *mfmp++ = mfm_read_buffer[i]; - } - return 1; -} - -void DISK_InitWrite() -{ - //JMH: mfmwrite = mfmwrbuffer; -} - -void DISK_WriteData(int length) -{ - int dr; - for (dr=0;dr #include "emuapi.h" +#ifdef HAS_T4_VGA +#include "vga_t_dma.h" +#else #include "tft_t_dma.h" +#endif #include "iopins.h" extern "C" { @@ -79,8 +83,11 @@ char romfile[MAX_FILENAME] = "./kick13.rom"; char prtname[MAX_FILENAME] = "lpr "; char sername[MAX_FILENAME] = ""; char warning_buffer[256]; -static char slinebuf[800]; - +#ifdef HAS_T4_VGA +static char slinebuf[WIN_W]; +#else +static char slinebuf[WIN_W*2]; +#endif #define MOUSE_STEP 3 static int prev_hk = 0; @@ -214,7 +221,11 @@ void write_log (const char *buf) { /*fprintf (stderr, buf); */ } void flush_line(int y) { if(y >= 0 && y < WIN_H) { +#ifdef HAS_T4_VGA + emu_DrawLine8((unsigned char *)slinebuf, WIN_W , 1, y); +#else emu_DrawLine16((unsigned short *)slinebuf, WIN_W , 1, y); +#endif } } @@ -285,13 +296,20 @@ static int hddfound=0; void uae_Init(void) { emu_printf("Init"); +#ifdef HAS_T4_VGA + gfxvidinfo.rowbytes = WIN_W; + gfxvidinfo.pixbytes = 1; +#else gfxvidinfo.rowbytes = WIN_W*2; gfxvidinfo.pixbytes = 2; +#endif gfxvidinfo.maxlinetoscr = WIN_W; gfxvidinfo.maxline = WIN_H; gfxvidinfo.linemem = slinebuf; gfxvidinfo.maxblocklines = 0; - + gfxvidinfo.width = WIN_W; + gfxvidinfo.height = WIN_H; + buttonstate[0] = buttonstate[1] = buttonstate[2] = 0; lastmx = lastmy = 0; newmousecounters = 0; @@ -407,35 +425,5 @@ void uae_Start(char * floppy1, char * floppy2) } void uae_Step(void) { - /* - JoyState = 0; - if (k & MASK_JOY2_DOWN) JoyState|=0x02; - if (k & MASK_JOY2_UP) JoyState|=0x01; - if (k & MASK_JOY2_LEFT) JoyState|=0x04; - if (k & MASK_JOY2_RIGHT) JoyState|=0x08; - if (k & MASK_JOY2_BTN) JoyState|=0x10; - if (k & MASK_KEY_USER2) JoyState|=0x20; -*/ -/* - if (hk != 0) { - emu_printh(hk); - KeyMap[Keys[hk-1].Pos] &=~ Keys[hk-1].Mask; - } - else { - memset(KeyMap,0xFF,16); - } -*/ - - //emu_DrawVsync(); + // not reached! } - - - - - - - - - - - diff --git a/MCUME_teensy/teensyuae41/vga_t_dma.h b/MCUME_teensy/teensyuae41/vga_t_dma.h new file mode 100644 index 0000000..1607a30 --- /dev/null +++ b/MCUME_teensy/teensyuae41/vga_t_dma.h @@ -0,0 +1,53 @@ +/* + Wrapping class to extend VGA_T4 to TFT_T_DMA +*/ + +#ifndef _VGA_T_DMAH_ +#define _VGA_T_DMAH_ + +#ifdef __cplusplus +#include +#endif + + +#define RGBVAL16(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) ) +#define RGBVAL8(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) ) + + + + +#define TFT_WIDTH 320 //640 //320 +#define TFT_REALWIDTH 320 //640 //320 + +#define TFT_HEIGHT 240 +#define TFT_REALHEIGHT 240 + + + +#ifdef __cplusplus + +class TFT_T_DMA: public VGA_T4 +{ + public: + // Fake touch screen functions + bool isTouching(void) { return false; } + void readRaw(uint16_t * oX, uint16_t * oY, uint16_t * oZ) { } + void readCal(uint16_t * oX, uint16_t * oY, uint16_t * oZ) { }; + void callibrateTouch(uint16_t xMin,uint16_t yMin,uint16_t xMax,uint16_t yMax) { } + + // fake DMA functions + void startDMA(void) { }; + void stopDMA(void) { }; + + // fake no DMA functions + void writeScreenNoDma(const vga_pixel *pcolors) { writeScreen(pcolors); } + void fillScreenNoDma(vga_pixel color) { clear(color); } + void drawTextNoDma(int16_t x, int16_t y, const char * text, vga_pixel fgcolor, vga_pixel bgcolor, bool doublesize) { drawText(x,y,text,fgcolor,bgcolor,doublesize); } + void drawRectNoDma(int16_t x, int16_t y, int16_t w, int16_t h, vga_pixel color) { drawRect(x, y, w, h, color); } + void drawSpriteNoDma(int16_t x, int16_t y, const vga_pixel *bitmap) { drawSprite(x, y, bitmap); } + void drawSpriteNoDma(int16_t x, int16_t y, const vga_pixel *bitmap, uint16_t croparx, uint16_t cropary, uint16_t croparw, uint16_t croparh) { drawSprite(x, y, bitmap, croparx, cropary, croparw, croparh); } +}; + + +#endif +#endif diff --git a/MCUME_teensy/teensyuae41/xwin.h b/MCUME_teensy/teensyuae41/xwin.h index b1b4e4e..c661787 100644 --- a/MCUME_teensy/teensyuae41/xwin.h +++ b/MCUME_teensy/teensyuae41/xwin.h @@ -6,7 +6,14 @@ * Copyright 1995-1997 Bernd Schmidt */ +#include "platform_config.h" +#ifdef HAS_T4_VGA +typedef unsigned char xcolnr; +#else typedef unsigned short xcolnr; +#endif + + typedef int (*allocfunc_type)(int, int, int, xcolnr *); @@ -55,6 +62,8 @@ struct vidbuf_description * value than maxline here). */ int can_double; /* Set if the high part of each entry in xcolors contains the same value * as the low part, so that two pixels can be drawn at once. */ + int width; + int height; }; extern struct vidbuf_description gfxvidinfo;