From ddf2b0a4246ca65c23e3f9427e0f6fe6d8e4fa3b Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Thu, 3 Jun 2004 18:13:23 +0300 Subject: [PATCH] imported winuaesrc0827b4.zip --- blitter.c | 12 +- custom.c | 10 +- custom2.c | 5527 ---------------------------------- debug.c | 110 +- drawing.c | 10 +- fdi2raw2.c | 1986 ------------ fdi2raw_old.c | 1835 ----------- identify.c | 440 +-- include/identify.h | 1 + memory.c | 4 +- od-win32/avioutput.c | 6 +- od-win32/drivesound.c | 191 -- od-win32/resources/winuae.rc | 8 +- od-win32/sounddep/sound.c | 6 +- od-win32/win32.h | 2 +- od-win32/win32gui.c | 11 +- 16 files changed, 367 insertions(+), 9792 deletions(-) delete mode 100755 custom2.c delete mode 100755 fdi2raw2.c delete mode 100755 fdi2raw_old.c delete mode 100755 od-win32/drivesound.c diff --git a/blitter.c b/blitter.c index e36dbf20..cfd3b592 100755 --- a/blitter.c +++ b/blitter.c @@ -30,7 +30,6 @@ uae_u32 bltapt,bltbpt,bltcpt,bltdpt; int blinea_shift; static uae_u16 blinea, blineb; -static uaecptr bltcnxlpt,bltdnxlpt; static int blitline, blitfc, blitfill, blitife, blitsing, blitdesc; static int blitonedot,blitsign; static int blit_add; @@ -394,7 +393,7 @@ STATIC_INLINE void blitter_line_incx(void) { if (++blinea_shift == 16) { blinea_shift = 0; - bltcnxlpt += 2; + bltcpt += 2; } } @@ -402,19 +401,19 @@ STATIC_INLINE void blitter_line_decx(void) { if (blinea_shift-- == 0) { blinea_shift = 15; - bltcnxlpt -= 2; + bltcpt -= 2; } } STATIC_INLINE void blitter_line_decy(void) { - bltcnxlpt -= blt_info.bltcmod; + bltcpt -= blt_info.bltcmod; blitonedot = 0; } STATIC_INLINE void blitter_line_incy(void) { - bltcnxlpt += blt_info.bltcmod; + bltcpt += blt_info.bltcmod; blitonedot = 0; } @@ -464,7 +463,6 @@ static void blitter_line(void) STATIC_INLINE void blitter_nxline(void) { - bltdpt = bltcpt = bltcnxlpt; blineb = (blineb << 1) | (blineb >> 15); if (--blt_info.vblitsize == 0) { bltstate = BLT_done; @@ -881,8 +879,6 @@ void do_blitter (int hpos) reset_blit (1|2); if (blitline) { - bltcnxlpt = bltcpt; - bltdnxlpt = bltdpt; blitsing = bltcon1 & 0x2; blinea = blt_info.bltadat; blineb = (blt_info.bltbdat >> blt_info.blitbshift) | (blt_info.bltbdat << (16 - blt_info.blitbshift)); diff --git a/custom.c b/custom.c index a1febcc0..059e69d5 100755 --- a/custom.c +++ b/custom.c @@ -194,7 +194,7 @@ static struct color_entry current_colors; static unsigned int bplcon0, bplcon1, bplcon2, bplcon3, bplcon4; static unsigned int diwstrt, diwstop, diwhigh; static int diwhigh_written; -static unsigned int ddfstrt, ddfstop, ddfstrt_old, ddfstrt_old_hpos, ddfstrt_old_vpos; +static unsigned int ddfstrt, ddfstop, ddfstrt_old_hpos, ddfstrt_old_vpos; static int ddf_change; static unsigned int bplcon0_at_start; @@ -1569,7 +1569,7 @@ STATIC_INLINE void decide_line (int hpos) ok = 1; /* hack warning.. Writing to DDFSTRT when DMA should start must be ignored * (correct fix would be emulate this delay for every custom register, but why bother..) */ - if (ddfstrt_old != ddfstrt && hpos - 2 == ddfstrt_old_hpos && ddfstrt_old_vpos == vpos) + if (hpos - 2 == ddfstrt_old_hpos && ddfstrt_old_vpos == vpos) ok = 0; if (ok) { start_bpl_dma (hpos, plfstrt); @@ -1624,6 +1624,7 @@ static void record_color_change (int hpos, int regno, unsigned long value) typedef int sprbuf_res_t, cclockres_t, hwres_t, bplres_t; +/* handle very rarely needed playfield collision (CLXDAT bit 0) */ static void do_playfield_collisions (void) { int bplres = GET_RES (bplcon0); @@ -2823,11 +2824,10 @@ static void DDFSTRT (int hpos, uae_u16 v) v &= 0xfe; if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) v &= 0xfc; - if (ddfstrt == v) + if (ddfstrt == v && hpos != plfstrt - 2) return; ddf_change = vpos; decide_line (hpos); - ddfstrt_old = ddfstrt; ddfstrt_old_hpos = hpos; ddfstrt_old_vpos = vpos; ddfstrt = v; @@ -3540,7 +3540,7 @@ static void update_copper (int until_hpos) cop_state.state = COP_skip_in2; break; case COP_strobe_delay: - cop_state.state = COP_read1; + cop_state.state = COP_read1_in2; break; default: diff --git a/custom2.c b/custom2.c deleted file mode 100755 index 7d7a8b73..00000000 --- a/custom2.c +++ /dev/null @@ -1,5527 +0,0 @@ - /* - * UAE - The Un*x Amiga Emulator - * - * Custom chip emulation - * - * Copyright 1995-2002 Bernd Schmidt - * Copyright 1995 Alessandro Bissacco - * Copyright 2000-2004 Toni Wilen - */ - -//#define CUSTOM_DEBUG -#define DEBUG_COPPER 0 -#define SPRITE_DEBUG 0 -#define SPRITE_DEBUG_MINY 0 -#define SPRITE_DEBUG_MAXY 400 -//#define DISABLE_SPRITES -#define SPR0_HPOS 0x15 -#define MAX_SPRITES 8 -#define SPRITE_COLLISIONS -#define SPEEDUP - -#include "sysconfig.h" -#include "sysdeps.h" - -#include -#include - -#include "config.h" -#include "options.h" -#include "threaddep/thread.h" -#include "uae.h" -#include "gensound.h" -#include "sounddep/sound.h" -#include "events.h" -#include "memory.h" -#include "custom.h" -#include "newcpu.h" -#include "cia.h" -#include "disk.h" -#include "blitter.h" -#include "xwin.h" -#include "inputdevice.h" -#include "audio.h" -#include "keybuf.h" -#include "serial.h" -#include "osemu.h" -#include "autoconf.h" -#include "gui.h" -#include "picasso96.h" -#include "drawing.h" -#include "savestate.h" -#include "ar.h" -#include "avioutput.h" -#include "debug.h" -#include "akiko.h" -#include "enforcer.h" - -void uae_abort (const char *format,...) -{ - va_list parms; - char buffer[1000]; - - va_start (parms, format); - _vsnprintf( buffer, sizeof (buffer) -1, format, parms ); - va_end (parms); - gui_message (buffer); - activate_debugger (); -} - -#if 0 -void customhack_put (struct customhack *ch, uae_u16 v, int hpos) -{ - ch->v = v; - ch->vpos = vpos; - ch->hpos = hpos; -} - -uae_u16 customhack_get (struct customhack *ch, int hpos) -{ - if (ch->vpos == vpos && ch->hpos == hpos) { - ch->vpos = -1; - return 0xffff; - } - return ch->v; -} -#endif - -static uae_u16 last_custom_value; - -static unsigned int n_consecutive_skipped = 0; -static unsigned int total_skipped = 0; - -STATIC_INLINE void sync_copper (int hpos); - -/* Events */ - -unsigned long int event_cycles, nextevent, is_lastline, currcycle; -long cycles_to_next_event; -long max_cycles_to_next_event; -long cycles_to_hsync_event; - -static int rpt_did_reset; -struct ev eventtab[ev_max]; - -volatile frame_time_t vsynctime, vsyncmintime; - -int ievent_alive = 0; -#ifdef JIT -extern uae_u8* compiled_code; -#endif - -int vpos; -int hack_vpos; -static uae_u16 lof; -static int next_lineno; -static enum nln_how nextline_how; -static int lof_changed = 0; - -static uae_u32 sprtaba[256],sprtabb[256]; -static uae_u32 sprite_ab_merge[256]; -/* Tables for collision detection. */ -static uae_u32 sprclx[16], clxmask[16]; - -/* - * Hardware registers of all sorts. - */ - -static int custom_wput_1 (int, uaecptr, uae_u32, int) REGPARAM; - -static uae_u16 cregs[256]; - -uae_u16 intena,intreq; -uae_u16 dmacon; -uae_u16 adkcon; /* used by audio code */ - -static uae_u32 cop1lc,cop2lc,copcon; - -int maxhpos = MAXHPOS_PAL; -int maxvpos = MAXVPOS_PAL; -int minfirstline = VBLANK_ENDLINE_PAL; -int vblank_hz = VBLANK_HZ_PAL, fake_vblank_hz, vblank_skip; -unsigned long syncbase; -static int fmode; -unsigned int beamcon0, new_beamcon0; -uae_u16 vtotal = MAXVPOS_PAL, htotal = MAXHPOS_PAL; -static uae_u16 hsstop, hbstrt, hbstop, vsstop, vbstrt, vbstop, hsstrt, vsstrt, hcenter; - -#define HSYNCTIME (maxhpos * CYCLE_UNIT); - -/* This is but an educated guess. It seems to be correct, but this stuff - * isn't documented well. */ -struct sprite { - uaecptr pt; - int xpos; - int vstart; - int vstop; - int armed; - int dmastate; - int dmacycle; -}; - -static struct sprite spr[MAX_SPRITES]; - -static int sprite_vblank_endline = VBLANK_SPRITE_PAL; - -static unsigned int sprctl[MAX_SPRITES], sprpos[MAX_SPRITES]; -#ifdef AGA -static uae_u16 sprdata[MAX_SPRITES][4], sprdatb[MAX_SPRITES][4]; -#else -static uae_u16 sprdata[MAX_SPRITES][1], sprdatb[MAX_SPRITES][1]; -#endif -static int sprite_last_drawn_at[MAX_SPRITES]; -static int last_sprite_point, nr_armed; -static int sprite_width, sprres, sprite_buffer_res; - -#ifdef CPUEMU_6 -uae_u8 cycle_line[256]; -#endif - -static uae_u32 bpl1dat, bpl2dat, bpl3dat, bpl4dat, bpl5dat, bpl6dat, bpl7dat, bpl8dat; -static uae_s16 bpl1mod, bpl2mod; - -static uaecptr bplpt[8]; -uae_u8 *real_bplpt[8]; -/* Used as a debugging aid, to offset any bitplane temporarily. */ -int bpl_off[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - -/*static int blitcount[256]; blitter debug */ - -static struct color_entry current_colors; -static unsigned int bplcon0, bplcon1, bplcon2, bplcon3, bplcon4; -static unsigned int diwstrt, diwstop, diwhigh; -static int diwhigh_written; -static unsigned int ddfstrt, ddfstop, ddfstrt_old, ddfstrt_old_hpos, ddfstrt_old_vpos; -static int ddf_change; -static unsigned int bplcon0_at_start; - -/* The display and data fetch windows */ - -enum diw_states -{ - DIW_waiting_start, DIW_waiting_stop -}; - -int plffirstline, plflastline; -int plfstrt, plfstop; -static int last_diw_pix_hpos, last_ddf_pix_hpos, last_decide_line_hpos; -static int last_fetch_hpos, last_sprite_hpos; -int diwfirstword, diwlastword; -static enum diw_states diwstate, hdiwstate, ddfstate; - -/* Sprite collisions */ -static unsigned int clxdat, clxcon, clxcon2, clxcon_bpl_enable, clxcon_bpl_match; - -enum copper_states { - COP_stop, - COP_read1_in2, - COP_read1_wr_in4, - COP_read1_wr_in2, - COP_read1, - COP_read2_wr_in2, - COP_read2, - COP_bltwait, - COP_wait_in4, - COP_wait_in2, - COP_skip_in4, - COP_skip_in2, - COP_wait1, - COP_wait, - COP_skip1, - COP_strobe_delay -}; - -struct copper { - /* The current instruction words. */ - unsigned int i1, i2; - unsigned int saved_i1, saved_i2; - enum copper_states state; - /* Instruction pointer. */ - uaecptr ip, saved_ip; - int hpos, vpos; - unsigned int ignore_next; - int vcmp, hcmp; - - /* When we schedule a copper event, knowing a few things about the future - of the copper list can reduce the number of sync_with_cpu calls - dramatically. */ - unsigned int first_sync; - unsigned int regtypes_modified; - int strobe; /* COPJMP1 / COPJMP2 accessed */ -}; - -#define REGTYPE_NONE 0 -#define REGTYPE_COLOR 1 -#define REGTYPE_SPRITE 2 -#define REGTYPE_PLANE 4 -#define REGTYPE_BLITTER 8 -#define REGTYPE_JOYPORT 16 -#define REGTYPE_DISK 32 -#define REGTYPE_POS 64 -#define REGTYPE_AUDIO 128 - -#define REGTYPE_ALL 255 -/* Always set in regtypes_modified, to enable a forced update when things like - DMACON, BPLCON0, COPJMPx get written. */ -#define REGTYPE_FORCE 256 - - -static unsigned int regtypes[512]; - -static struct copper cop_state; -static int copper_enabled_thisline; -static int cop_min_waittime; - -/* - * Statistics - */ - -/* Used also by bebox.cpp */ -unsigned long int frametime = 0, lastframetime = 0, timeframes = 0, hsync_counter = 0; -unsigned long int idletime; -int bogusframe; - -#if DEBUG_COPPER -/* 10000 isn't enough! */ -#define NR_COPPER_RECORDS 40000 -#else -#define NR_COPPER_RECORDS 1 -#endif - -/* Record copper activity for the debugger. */ -struct cop_record -{ - int hpos, vpos; - uaecptr addr; -}; -static struct cop_record cop_record[2][NR_COPPER_RECORDS]; -static int nr_cop_records[2]; -static int curr_cop_set; - -/* Recording of custom chip register changes. */ -static int current_change_set; - -#ifdef OS_WITHOUT_MEMORY_MANAGEMENT -/* sam: Those arrays uses around 7Mb of BSS... That seems */ -/* too much for AmigaDOS (uae crashes as soon as one loads */ -/* it. So I use a different strategy here (realloc the */ -/* arrays when needed. That strategy might be usefull for */ -/* computer with low memory. */ -struct sprite_entry *sprite_entries[2]; -struct color_change *color_changes[2]; -static int max_sprite_entry = 400; -static int delta_sprite_entry = 0; -static int max_color_change = 400; -static int delta_color_change = 0; -#else -struct sprite_entry sprite_entries[2][MAX_SPR_PIXELS / 16]; -struct color_change color_changes[2][MAX_REG_CHANGE]; -#endif - -struct decision line_decisions[2 * (MAXVPOS + 1) + 1]; -struct draw_info line_drawinfo[2][2 * (MAXVPOS + 1) + 1]; -struct color_entry color_tables[2][(MAXVPOS + 1) * 2]; - -static int next_sprite_entry = 0; -static int prev_next_sprite_entry; -static int next_sprite_forced = 1; - -struct sprite_entry *curr_sprite_entries, *prev_sprite_entries; -struct color_change *curr_color_changes, *prev_color_changes; -struct draw_info *curr_drawinfo, *prev_drawinfo; -struct color_entry *curr_color_tables, *prev_color_tables; - -static int next_color_change; -static int next_color_entry, remembered_color_entry; -static int color_src_match, color_dest_match, color_compare_result; - -static uae_u32 thisline_changed; - -#ifdef SMART_UPDATE -#define MARK_LINE_CHANGED do { thisline_changed = 1; } while (0) -#else -#define MARK_LINE_CHANGED do { ; } while (0) -#endif - -static struct decision thisline_decision; -static int passed_plfstop, fetch_cycle; - -enum fetchstate { - fetch_not_started, - fetch_started, - fetch_was_plane0 -} fetch_state; - -/* - * helper functions - */ - -uae_u32 get_copper_address (int copno) -{ - switch (copno) { - case 1: return cop1lc; - case 2: return cop2lc; - default: return 0; - } -} - -STATIC_INLINE void record_copper (uaecptr addr, int hpos, int vpos) -{ -#if DEBUG_COPPER - int t = nr_cop_records[curr_cop_set]; - if (t < NR_COPPER_RECORDS) { - cop_record[curr_cop_set][t].addr = addr; - cop_record[curr_cop_set][t].hpos = hpos; - cop_record[curr_cop_set][t].vpos = vpos; - nr_cop_records[curr_cop_set] = t + 1; - } -#endif -} - -int find_copper_record (uaecptr addr, int *phpos, int *pvpos) -{ - int s = curr_cop_set ^ 1; - int t = nr_cop_records[s]; - int i; - for (i = 0; i < t; i++) { - if (cop_record[s][i].addr == addr) { - *phpos = cop_record[s][i].hpos; - *pvpos = cop_record[s][i].vpos; - return 1; - } - } - return 0; -} - -int rpt_available = 0; - -void reset_frame_rate_hack (void) -{ - if (currprefs.m68k_speed != -1) - return; - - if (! rpt_available) { - currprefs.m68k_speed = 0; - return; - } - - rpt_did_reset = 1; - is_lastline = 0; - vsyncmintime = read_processor_time() + vsynctime; - write_log ("Resetting frame rate hack\n"); -} - -STATIC_INLINE void setclr (uae_u16 *p, uae_u16 val) -{ - if (val & 0x8000) - *p |= val & 0x7FFF; - else - *p &= ~val; -} - -STATIC_INLINE int current_hpos (void) -{ - return (get_cycles () - eventtab[ev_hsync].oldcycles) / CYCLE_UNIT; -} - -STATIC_INLINE uae_u8 *pfield_xlateptr (uaecptr plpt, int bytecount) -{ - if (!chipmem_bank.check (plpt, bytecount)) { - static int count = 0; - if (!count) - count++, write_log ("Warning: Bad playfield pointer\n"); - return NULL; - } - return chipmem_bank.xlateaddr (plpt); -} - -STATIC_INLINE void docols (struct color_entry *colentry) -{ - int i; - -#ifdef AGA - if (currprefs.chipset_mask & CSMASK_AGA) { - for (i = 0; i < 256; i++) { - int v = color_reg_get (colentry, i); - if (v < 0 || v > 16777215) - continue; - colentry->acolors[i] = CONVERT_RGB (v); - } - } else { -#endif - for (i = 0; i < 32; i++) { - int v = color_reg_get (colentry, i); - if (v < 0 || v > 4095) - continue; - colentry->acolors[i] = xcolors[v]; - } -#ifdef AGA - } -#endif -} - -void notice_new_xcolors (void) -{ - int i; - - docols(¤t_colors); -/* docols(&colors_for_drawing);*/ - for (i = 0; i < (MAXVPOS + 1)*2; i++) { - docols(color_tables[0]+i); - docols(color_tables[1]+i); - } -} - -static void do_sprites (int currhp); - -static void remember_ctable (void) -{ - if (remembered_color_entry == -1) { - /* The colors changed since we last recorded a color map. Record a - * new one. */ - color_reg_cpy (curr_color_tables + next_color_entry, ¤t_colors); - remembered_color_entry = next_color_entry++; - } - thisline_decision.ctable = remembered_color_entry; - if (color_src_match == -1 || color_dest_match != remembered_color_entry - || line_decisions[next_lineno].ctable != color_src_match) - { - /* The remembered comparison didn't help us - need to compare again. */ - int oldctable = line_decisions[next_lineno].ctable; - int changed = 0; - - if (oldctable == -1) { - changed = 1; - color_src_match = color_dest_match = -1; - } else { - color_compare_result = color_reg_cmp (&prev_color_tables[oldctable], ¤t_colors) != 0; - if (color_compare_result) - changed = 1; - color_src_match = oldctable; - color_dest_match = remembered_color_entry; - } - thisline_changed |= changed; - } else { - /* We know the result of the comparison */ - if (color_compare_result) - thisline_changed = 1; - } -} - -static void remember_ctable_for_border (void) -{ - remember_ctable (); -} - -/* 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 (int hpos) -{ - int pix_hpos = coord_diw_to_window_x (hpos == 227 ? 455 : hpos * 2); /* (227.5*2 = 455) */ - if (hdiwstate == DIW_waiting_start && thisline_decision.diwfirstword == -1 - && pix_hpos >= diwfirstword && last_diw_pix_hpos < diwfirstword) - { - thisline_decision.diwfirstword = diwfirstword < 0 ? 0 : diwfirstword; - hdiwstate = DIW_waiting_stop; - } - if (hdiwstate == DIW_waiting_stop && thisline_decision.diwlastword == -1 - && pix_hpos >= diwlastword && last_diw_pix_hpos < diwlastword) - { - thisline_decision.diwlastword = diwlastword < 0 ? 0 : diwlastword; - hdiwstate = DIW_waiting_start; - } - last_diw_pix_hpos = pix_hpos; -} - -/* The HRM says 0xD8, but that can't work... */ -#define HARD_DDF_STOP 0xd4 -#define HARD_DDF_START 0x18 - -static void add_modulos (void) -{ - int m1, m2; - - if (fmode & 0x4000) { - if (((diwstrt >> 8) ^ vpos) & 1) - m1 = m2 = bpl2mod; - else - m1 = m2 = bpl1mod; - } else { - m1 = bpl1mod; - m2 = bpl2mod; - } - - switch (GET_PLANES (bplcon0)) { -#ifdef AGA - case 8: bplpt[7] += m2; - case 7: bplpt[6] += m1; -#endif - case 6: bplpt[5] += m2; - case 5: bplpt[4] += m1; - case 4: bplpt[3] += m2; - case 3: bplpt[2] += m1; - case 2: bplpt[1] += m2; - case 1: bplpt[0] += m1; - } -} - -static void finish_playfield_line (void) -{ - /* The latter condition might be able to happen in interlaced frames. */ - if (vpos >= minfirstline && (thisframe_first_drawn_line == -1 || vpos < thisframe_first_drawn_line)) - thisframe_first_drawn_line = vpos; - thisframe_last_drawn_line = vpos; - - /* These are for comparison. */ - thisline_decision.bplcon0 = bplcon0; - thisline_decision.bplcon2 = bplcon2; -#ifdef AGA - thisline_decision.bplcon3 = bplcon3; - thisline_decision.bplcon4 = bplcon4; -#endif - -#ifdef SMART_UPDATE - if (line_decisions[next_lineno].plflinelen != thisline_decision.plflinelen - || line_decisions[next_lineno].plfleft != thisline_decision.plfleft - || line_decisions[next_lineno].bplcon0 != thisline_decision.bplcon0 - || line_decisions[next_lineno].bplcon2 != thisline_decision.bplcon2 -#ifdef AGA - || line_decisions[next_lineno].bplcon3 != thisline_decision.bplcon3 - || line_decisions[next_lineno].bplcon4 != thisline_decision.bplcon4 -#endif - ) -#endif /* SMART_UPDATE */ - thisline_changed = 1; -} - -static int fetchmode; - -/* The fetch unit mainly controls ddf stop. It's the number of cycles that - are contained in an indivisible block during which ddf is active. E.g. - if DDF starts at 0x30, and fetchunit is 8, then possible DDF stops are - 0x30 + n * 8. */ -static int fetchunit, fetchunit_mask; -/* The delay before fetching the same bitplane again. Can be larger than - the number of bitplanes; in that case there are additional empty cycles - with no data fetch (this happens for high fetchmodes and low - resolutions). */ -static int fetchstart, fetchstart_shift, fetchstart_mask; -/* fm_maxplane holds the maximum number of planes possible with the current - fetch mode. This selects the cycle diagram: - 8 planes: 73516240 - 4 planes: 3120 - 2 planes: 10. */ -static int fm_maxplane, fm_maxplane_shift; - -/* The corresponding values, by fetchmode and display resolution. */ -static int fetchunits[] = { 8,8,8,0, 16,8,8,0, 32,16,8,0 }; -static int fetchstarts[] = { 3,2,1,0, 4,3,2,0, 5,4,3,0 }; -static int fm_maxplanes[] = { 3,2,1,0, 3,3,2,0, 3,3,3,0 }; - -static uae_u8 cycle_diagram_table[3][3][9][32]; -static uae_u8 cycle_diagram_free_cycles[3][3][9]; -static uae_u8 cycle_diagram_total_cycles[3][3][9]; -static uae_u8 *curr_diagram; -static uae_u8 cycle_sequences[3*8] = { 2,1,2,1,2,1,2,1, 4,2,3,1,4,2,3,1, 8,4,6,2,7,3,5,1 }; - -static void debug_cycle_diagram(void) -{ - int fm, res, planes, cycle, v; - char aa; - - for (fm = 0; fm < 3; fm++) { - write_log ("FMODE %d\n=======\n", fm); - for (res = 0; res <= 2; res++) { - for (planes = 0; planes <= 8; planes++) { - write_log("%d: ",planes); - for (cycle = 0; cycle < 32; cycle++) { - v=cycle_diagram_table[fm][res][planes][cycle]; - if (v==0) aa='-'; else if(v>0) aa='1'; else aa='X'; - write_log("%c",aa); - } - write_log(" %d:%d\n", - cycle_diagram_free_cycles[fm][res][planes], cycle_diagram_total_cycles[fm][res][planes]); - } - write_log("\n"); - } - } - fm=0; -} - -static void create_cycle_diagram_table(void) -{ - int fm, res, cycle, planes, v; - int fetch_start, max_planes, freecycles; - uae_u8 *cycle_sequence; - - for (fm = 0; fm <= 2; fm++) { - for (res = 0; res <= 2; res++) { - max_planes = fm_maxplanes[fm * 4 + res]; - fetch_start = 1 << fetchstarts[fm * 4 + res]; - cycle_sequence = &cycle_sequences[(max_planes - 1) * 8]; - max_planes = 1 << max_planes; - for (planes = 0; planes <= 8; planes++) { - freecycles = 0; - for (cycle = 0; cycle < 32; cycle++) - cycle_diagram_table[fm][res][planes][cycle] = -1; - if (planes <= max_planes) { - for (cycle = 0; cycle < fetch_start; cycle++) { - if (cycle < max_planes && planes >= cycle_sequence[cycle & 7]) { - v = 1; - } else { - v = 0; - freecycles++; - } - cycle_diagram_table[fm][res][planes][cycle] = v; - } - } - cycle_diagram_free_cycles[fm][res][planes] = freecycles; - cycle_diagram_total_cycles[fm][res][planes] = fetch_start; - } - } - } -#if 0 - debug_cycle_diagram (); -#endif -} - - -/* Used by the copper. */ -static int estimated_last_fetch_cycle; -static int cycle_diagram_shift; - -static void estimate_last_fetch_cycle (int hpos) -{ - int fetchunit = fetchunits[fetchmode * 4 + GET_RES (bplcon0)]; - - if (! passed_plfstop) { - int stop = plfstop < hpos || plfstop > HARD_DDF_STOP ? HARD_DDF_STOP : plfstop; - /* We know that fetching is up-to-date up until hpos, so we can use fetch_cycle. */ - int fetch_cycle_at_stop = fetch_cycle + (stop - hpos); - int starting_last_block_at = (fetch_cycle_at_stop + fetchunit - 1) & ~(fetchunit - 1); - - estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + fetchunit; - } else { - int starting_last_block_at = (fetch_cycle + fetchunit - 1) & ~(fetchunit - 1); - if (passed_plfstop == 2) - starting_last_block_at -= fetchunit; - - estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + fetchunit; - } -} - -static uae_u32 outword[MAX_PLANES]; -static int out_nbits, out_offs; -static uae_u32 todisplay[MAX_PLANES][4]; -static uae_u32 fetched[MAX_PLANES]; -#ifdef AGA -static uae_u32 fetched_aga0[MAX_PLANES]; -static uae_u32 fetched_aga1[MAX_PLANES]; -#endif - -/* Expansions from bplcon0/bplcon1. */ -static int toscr_res, toscr_res_first, toscr_nr_planes, fetchwidth; -static int toscr_delay1x, toscr_delay2x, toscr_delay1, toscr_delay2; - -/* The number of bits left from the last fetched words. - This is an optimization - conceptually, we have to make sure the result is - the same as if toscr is called in each clock cycle. However, to speed this - up, we accumulate display data; this variable keeps track of how much. - Thus, once we do call toscr_nbits (which happens at least every 16 bits), - we can do more work at once. */ -static int toscr_nbits; - -static int delayoffset; - -STATIC_INLINE void compute_delay_offset (void) -{ - delayoffset = ((plfstrt - HARD_DDF_START) & fetchstart_mask) << 1; - if (delayoffset & 8) - delayoffset = 8; - else if (delayoffset & 16) - delayoffset = 16; - else if (delayoffset & 32) - delayoffset = 32; - else - delayoffset = 0; -} - -static void expand_fmodes (void) -{ - int res = GET_RES(bplcon0); - int fm = fetchmode; - fetchunit = fetchunits[fm * 4 + res]; - fetchunit_mask = fetchunit - 1; - fetchstart_shift = fetchstarts[fm * 4 + res]; - fetchstart = 1 << fetchstart_shift; - fetchstart_mask = fetchstart - 1; - fm_maxplane_shift = fm_maxplanes[fm * 4 + res]; - fm_maxplane = 1 << fm_maxplane_shift; - curr_diagram = cycle_diagram_table[fm][res][GET_PLANES (bplcon0)]; -} - -static int maxplanes_ocs[]={ 6,4,0,0 }; -static int maxplanes_ecs[]={ 6,4,2,0 }; -static int maxplanes_aga[]={ 8,4,2,0, 8,8,4,0, 8,8,8,0 }; - -/* Expand bplcon0/bplcon1 into the toscr_xxx variables. */ -static void compute_toscr_delay_1 (void) -{ - int delay1 = (bplcon1 & 0x0f) | ((bplcon1 & 0x0c00) >> 6); - int delay2 = ((bplcon1 >> 4) & 0x0f) | (((bplcon1 >> 4) & 0x0c00) >> 6); - int delaymask; - int fetchwidth = 16 << fetchmode; - - delay1 += delayoffset; - delay2 += delayoffset; - delaymask = (fetchwidth - 1) >> toscr_res; - toscr_delay1x = (delay1 & delaymask) << toscr_res; - toscr_delay2x = (delay2 & delaymask) << toscr_res; -} - -static int get_maxplanes (int res) -{ - int *planes; - if (currprefs.chipset_mask & CSMASK_AGA) - planes = maxplanes_aga; - else if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE)) - planes = maxplanes_ocs; - else - planes = maxplanes_ecs; - return planes[fetchmode * 4 + res]; -} - -static void compute_toscr_delay (int hpos) -{ - int v = bplcon0; - /* Disable bitplane DMA if planes > maxplanes. This is needed e.g. by the - Sanity WOC demo (at the "Party Effect"). */ - if (GET_PLANES(v) > get_maxplanes (GET_RES(v))) - v &= ~0x7010; - toscr_res = GET_RES (v); - toscr_nr_planes = GET_PLANES (v); - compute_toscr_delay_1 (); -} - -STATIC_INLINE void maybe_first_bpl1dat (int hpos) -{ - if (thisline_decision.plfleft == -1) { - thisline_decision.plfleft = hpos; - compute_delay_offset (); - compute_toscr_delay_1 (); - } -} - -STATIC_INLINE void fetch (int nr, int fm) -{ - uaecptr p; - if (nr >= toscr_nr_planes) - return; - p = bplpt[nr] + bpl_off[nr]; - switch (fm) { - case 0: - fetched[nr] = last_custom_value = chipmem_wget (p); - bplpt[nr] += 2; - break; -#ifdef AGA - case 1: - fetched_aga0[nr] = chipmem_lget (p); - last_custom_value = (uae_u16)fetched_aga0[nr]; - bplpt[nr] += 4; - break; - case 2: - fetched_aga1[nr] = chipmem_lget (p); - fetched_aga0[nr] = chipmem_lget (p + 4); - last_custom_value = (uae_u16)fetched_aga0[nr]; - bplpt[nr] += 8; - break; -#endif - } - if (passed_plfstop == 2 && fetch_cycle >= (fetch_cycle & ~fetchunit_mask) + fetchunit - fetchstart) { - int mod; - if (fmode & 0x4000) { - if (((diwstrt >> 8) ^ vpos) & 1) - mod = bpl2mod; - else - mod = bpl1mod; - } else if (nr & 1) - mod = bpl2mod; - else - mod = bpl1mod; - bplpt[nr] += mod; - } - if (nr == 0) - fetch_state = fetch_was_plane0; -} - -static void clear_fetchbuffer (uae_u32 *ptr, int nwords) -{ - int i; - - if (! thisline_changed) - for (i = 0; i < nwords; i++) - if (ptr[i]) { - thisline_changed = 1; - break; - } - - memset (ptr, 0, nwords * 4); -} - -static void update_toscr_planes (void) -{ - if (toscr_nr_planes > thisline_decision.nr_planes) { - int j; - for (j = thisline_decision.nr_planes; j < toscr_nr_planes; j++) - clear_fetchbuffer ((uae_u32 *)(line_data[next_lineno] + 2 * MAX_WORDS_PER_LINE * j), out_offs); -#if 0 - if (thisline_decision.nr_planes > 0) - printf ("Planes from %d to %d\n", thisline_decision.nr_planes, toscr_nr_planes); -#endif - thisline_decision.nr_planes = toscr_nr_planes; - } -} - -STATIC_INLINE void toscr_3_ecs (int nbits) -{ - int delay1 = toscr_delay1; - int delay2 = toscr_delay2; - int i; - uae_u32 mask = 0xFFFF >> (16 - nbits); - - for (i = 0; i < toscr_nr_planes; i += 2) { - outword[i] <<= nbits; - outword[i] |= (todisplay[i][0] >> (16 - nbits + delay1)) & mask; - todisplay[i][0] <<= nbits; - } - for (i = 1; i < toscr_nr_planes; i += 2) { - outword[i] <<= nbits; - outword[i] |= (todisplay[i][0] >> (16 - nbits + delay2)) & mask; - todisplay[i][0] <<= nbits; - } -} - -STATIC_INLINE void shift32plus (uae_u32 *p, int n) -{ - uae_u32 t = p[1]; - t <<= n; - t |= p[0] >> (32 - n); - p[1] = t; -} - -#ifdef AGA -STATIC_INLINE void aga_shift (uae_u32 *p, int n, int fm) -{ - if (fm == 2) { - shift32plus (p + 2, n); - shift32plus (p + 1, n); - } - shift32plus (p + 0, n); - p[0] <<= n; -} - -STATIC_INLINE void toscr_3_aga (int nbits, int fm) -{ - int delay1 = toscr_delay1; - int delay2 = toscr_delay2; - int i; - uae_u32 mask = 0xFFFF >> (16 - nbits); - - { - int offs = (16 << fm) - nbits + delay1; - int off1 = offs >> 5; - if (off1 == 3) - off1 = 2; - offs -= off1 * 32; - for (i = 0; i < toscr_nr_planes; i += 2) { - uae_u32 t0 = todisplay[i][off1]; - uae_u32 t1 = todisplay[i][off1 + 1]; - uae_u64 t = (((uae_u64)t1) << 32) | t0; - outword[i] <<= nbits; - outword[i] |= (t >> offs) & mask; - aga_shift (todisplay[i], nbits, fm); - } - } - { - int offs = (16 << fm) - nbits + delay2; - int off1 = offs >> 5; - if (off1 == 3) - off1 = 2; - offs -= off1 * 32; - for (i = 1; i < toscr_nr_planes; i += 2) { - uae_u32 t0 = todisplay[i][off1]; - uae_u32 t1 = todisplay[i][off1 + 1]; - uae_u64 t = (((uae_u64)t1) << 32) | t0; - outword[i] <<= nbits; - outword[i] |= (t >> offs) & mask; - aga_shift (todisplay[i], nbits, fm); - } - } -} - -#endif - -static void toscr_2_0 (int nbits) { toscr_3_ecs (nbits); } -#ifdef AGA -static void toscr_2_1 (int nbits) { toscr_3_aga (nbits, 1); } -static void toscr_2_2 (int nbits) { toscr_3_aga (nbits, 2); } -#endif - -STATIC_INLINE void toscr_1 (int nbits, int fm) -{ - switch (fm) { - case 0: - toscr_2_0 (nbits); - break; -#ifdef AGA - case 1: - toscr_2_1 (nbits); - break; - case 2: - toscr_2_2 (nbits); - break; -#endif - } - out_nbits += nbits; - if (out_nbits == 32) { - int i; - uae_u8 *dataptr = line_data[next_lineno] + out_offs * 4; - for (i = 0; i < thisline_decision.nr_planes; i++) { - uae_u32 *dataptr32 = (uae_u32 *)dataptr; - if (i >= toscr_nr_planes) - outword[i] = 0; - if (*dataptr32 != outword[i]) - thisline_changed = 1; - *dataptr32 = outword[i]; - dataptr += MAX_WORDS_PER_LINE * 2; - } - out_offs++; - out_nbits = 0; - } -} - -static void toscr_fm0 (int); -static void toscr_fm1 (int); -static void toscr_fm2 (int); - -STATIC_INLINE void toscr (int nbits, int fm) -{ - switch (fm) { - case 0: toscr_fm0 (nbits); break; -#ifdef AGA - case 1: toscr_fm1 (nbits); break; - case 2: toscr_fm2 (nbits); break; -#endif - } -} - -STATIC_INLINE void toscr_0 (int nbits, int fm) -{ - int t; - - if (nbits > 16) { - toscr (16, fm); - nbits -= 16; - } - - t = 32 - out_nbits; - if (t < nbits) { - toscr_1 (t, fm); - nbits -= t; - } - toscr_1 (nbits, fm); -} - -static void toscr_fm0 (int nbits) { toscr_0 (nbits, 0); } -static void toscr_fm1 (int nbits) { toscr_0 (nbits, 1); } -static void toscr_fm2 (int nbits) { toscr_0 (nbits, 2); } - -static int flush_plane_data (int fm) -{ - int i = 0; - int fetchwidth = 16 << fm; - - if (out_nbits <= 16) { - i += 16; - toscr_1 (16, fm); - } - if (out_nbits != 0) { - i += 32 - out_nbits; - toscr_1 (32 - out_nbits, fm); - } - i += 32; - - toscr_1 (16, fm); - toscr_1 (16, fm); - return i >> (1 + toscr_res); -} - -STATIC_INLINE void flush_display (int fm) -{ - if (toscr_nbits > 0 && thisline_decision.plfleft != -1) - toscr (toscr_nbits, fm); - toscr_nbits = 0; -} - -/* Called when all planes have been fetched, i.e. when a new block - of data is available to be displayed. The data in fetched[] is - moved into todisplay[]. */ -STATIC_INLINE void beginning_of_plane_block (int pos, int fm) -{ - int i; - - flush_display (fm); - if (fm == 0) - for (i = 0; i < MAX_PLANES; i++) - todisplay[i][0] |= fetched[i]; -#ifdef AGA - else - for (i = 0; i < MAX_PLANES; i++) { - if (fm == 2) - todisplay[i][1] = fetched_aga1[i]; - todisplay[i][0] = fetched_aga0[i]; - } -#endif - maybe_first_bpl1dat (pos); - toscr_delay1 = toscr_delay1x; - toscr_delay2 = toscr_delay2x; -} - -#ifdef SPEEDUP - -/* The usual inlining tricks - don't touch unless you know what you are doing. */ -STATIC_INLINE void long_fetch_ecs (int plane, int nwords, int weird_number_of_bits, int dma) -{ - uae_u16 *real_pt = (uae_u16 *)pfield_xlateptr (bplpt[plane] + bpl_off[plane], nwords * 2); - int delay = (plane & 1) ? toscr_delay2 : toscr_delay1; - int tmp_nbits = out_nbits; - uae_u32 shiftbuffer = todisplay[plane][0]; - uae_u32 outval = outword[plane]; - uae_u32 fetchval = fetched[plane]; - uae_u32 *dataptr = (uae_u32 *)(line_data[next_lineno] + 2 * plane * MAX_WORDS_PER_LINE + 4 * out_offs); - - if (dma) - bplpt[plane] += nwords * 2; - - if (real_pt == 0) - /* @@@ Don't do this, fall back on chipmem_wget instead. */ - return; - - while (nwords > 0) { - int bits_left = 32 - tmp_nbits; - uae_u32 t; - - shiftbuffer |= fetchval; - - t = (shiftbuffer >> delay) & 0xFFFF; - - if (weird_number_of_bits && bits_left < 16) { - outval <<= bits_left; - outval |= t >> (16 - bits_left); - thisline_changed |= *dataptr ^ outval; - *dataptr++ = outval; - - outval = t; - tmp_nbits = 16 - bits_left; - shiftbuffer <<= 16; - } else { - outval = (outval << 16) | t; - shiftbuffer <<= 16; - tmp_nbits += 16; - if (tmp_nbits == 32) { - thisline_changed |= *dataptr ^ outval; - *dataptr++ = outval; - tmp_nbits = 0; - } - } - nwords--; - if (dma) { - fetchval = do_get_mem_word (real_pt); - real_pt++; - } - } - fetched[plane] = fetchval; - todisplay[plane][0] = shiftbuffer; - outword[plane] = outval; -} - -#ifdef AGA -STATIC_INLINE void long_fetch_aga (int plane, int nwords, int weird_number_of_bits, int fm, int dma) -{ - uae_u32 *real_pt = (uae_u32 *)pfield_xlateptr (bplpt[plane] + bpl_off[plane], nwords * 2); - int delay = (plane & 1) ? toscr_delay2 : toscr_delay1; - int tmp_nbits = out_nbits; - uae_u32 *shiftbuffer = todisplay[plane]; - uae_u32 outval = outword[plane]; - uae_u32 fetchval0 = fetched_aga0[plane]; - uae_u32 fetchval1 = fetched_aga1[plane]; - uae_u32 *dataptr = (uae_u32 *)(line_data[next_lineno] + 2 * plane * MAX_WORDS_PER_LINE + 4 * out_offs); - int offs = (16 << fm) - 16 + delay; - int off1 = offs >> 5; - if (off1 == 3) - off1 = 2; - offs -= off1 * 32; - - if (dma) - bplpt[plane] += nwords * 2; - - if (real_pt == 0) - /* @@@ Don't do this, fall back on chipmem_wget instead. */ - return; - - while (nwords > 0) { - int i; - - shiftbuffer[0] = fetchval0; - if (fm == 2) - shiftbuffer[1] = fetchval1; - - for (i = 0; i < (1 << fm); i++) { - int bits_left = 32 - tmp_nbits; - - uae_u32 t0 = shiftbuffer[off1]; - uae_u32 t1 = shiftbuffer[off1 + 1]; - uae_u64 t = (((uae_u64)t1) << 32) | t0; - - t0 = (uae_u32)((t >> offs) & 0xFFFF); - - if (weird_number_of_bits && bits_left < 16) { - outval <<= bits_left; - outval |= t0 >> (16 - bits_left); - - thisline_changed |= *dataptr ^ outval; - *dataptr++ = outval; - - outval = t0; - tmp_nbits = 16 - bits_left; - aga_shift (shiftbuffer, 16, fm); - } else { - outval = (outval << 16) | t0; - aga_shift (shiftbuffer, 16, fm); - tmp_nbits += 16; - if (tmp_nbits == 32) { - thisline_changed |= *dataptr ^ outval; - *dataptr++ = outval; - tmp_nbits = 0; - } - } - } - - nwords -= 1 << fm; - - if (dma) { - if (fm == 1) - fetchval0 = do_get_mem_long (real_pt); - else { - fetchval1 = do_get_mem_long (real_pt); - fetchval0 = do_get_mem_long (real_pt + 1); - } - real_pt += fm; - } - } - fetched_aga0[plane] = fetchval0; - fetched_aga1[plane] = fetchval1; - outword[plane] = outval; -} -#endif - -static void long_fetch_ecs_0 (int hpos, int nwords, int dma) { long_fetch_ecs (hpos, nwords, 0, dma); } -static void long_fetch_ecs_1 (int hpos, int nwords, int dma) { long_fetch_ecs (hpos, nwords, 1, dma); } -#ifdef AGA -static void long_fetch_aga_1_0 (int hpos, int nwords, int dma) { long_fetch_aga (hpos, nwords, 0, 1, dma); } -static void long_fetch_aga_1_1 (int hpos, int nwords, int dma) { long_fetch_aga (hpos, nwords, 1, 1, dma); } -static void long_fetch_aga_2_0 (int hpos, int nwords, int dma) { long_fetch_aga (hpos, nwords, 0, 2, dma); } -static void long_fetch_aga_2_1 (int hpos, int nwords, int dma) { long_fetch_aga (hpos, nwords, 1, 2, dma); } -#endif - -static void do_long_fetch (int hpos, int nwords, int dma, int fm) -{ - int i; - - flush_display (fm); - switch (fm) { - case 0: - if (out_nbits & 15) { - for (i = 0; i < toscr_nr_planes; i++) - long_fetch_ecs_1 (i, nwords, dma); - } else { - for (i = 0; i < toscr_nr_planes; i++) - long_fetch_ecs_0 (i, nwords, dma); - } - break; -#ifdef AGA - case 1: - if (out_nbits & 15) { - for (i = 0; i < toscr_nr_planes; i++) - long_fetch_aga_1_1 (i, nwords, dma); - } else { - for (i = 0; i < toscr_nr_planes; i++) - long_fetch_aga_1_0 (i, nwords, dma); - } - break; - case 2: - if (out_nbits & 15) { - for (i = 0; i < toscr_nr_planes; i++) - long_fetch_aga_2_1 (i, nwords, dma); - } else { - for (i = 0; i < toscr_nr_planes; i++) - long_fetch_aga_2_0 (i, nwords, dma); - } - break; -#endif - } - - out_nbits += nwords * 16; - out_offs += out_nbits >> 5; - out_nbits &= 31; - - if (dma && toscr_nr_planes > 0) - fetch_state = fetch_was_plane0; -} - -#endif - -/* make sure fetch that goes beyond maxhpos is finished */ -static void finish_final_fetch (int i, int fm) -{ - if (thisline_decision.plfleft == -1) - return; - if (passed_plfstop == 3) - return; - passed_plfstop = 3; - ddfstate = DIW_waiting_start; - i += flush_plane_data (fm); - thisline_decision.plfright = i; - thisline_decision.plflinelen = out_offs; - thisline_decision.bplres = toscr_res_first; - finish_playfield_line (); -} - -STATIC_INLINE int one_fetch_cycle_0 (int i, int ddfstop_to_test, int dma, int fm) -{ - if (! passed_plfstop && i == ddfstop_to_test) - passed_plfstop = 1; - - if ((fetch_cycle & fetchunit_mask) == 0) { - if (passed_plfstop == 2) { - finish_final_fetch (i, fm); - return 1; - } - if (passed_plfstop) - passed_plfstop++; - } - - if (dma) { - /* fetchstart_mask can be larger than fm_maxplane if FMODE > 0. This means - that the remaining cycles are idle; we'll fall through the whole switch - without doing anything. */ - int cycle_start = fetch_cycle & fetchstart_mask; - switch (fm_maxplane) { - case 8: - switch (cycle_start) { - case 0: fetch (7, fm); break; - case 1: fetch (3, fm); break; - case 2: fetch (5, fm); break; - case 3: fetch (1, fm); break; - case 4: fetch (6, fm); break; - case 5: fetch (2, fm); break; - case 6: fetch (4, fm); break; - case 7: fetch (0, fm); break; - } - break; - case 4: - switch (cycle_start) { - case 0: fetch (3, fm); break; - case 1: fetch (1, fm); break; - case 2: fetch (2, fm); break; - case 3: fetch (0, fm); break; - } - break; - case 2: - switch (cycle_start) { - case 0: fetch (1, fm); break; - case 1: fetch (0, fm); break; - } - break; - } - } - fetch_cycle++; - toscr_nbits += 2 << toscr_res; - - if (toscr_nbits == 16) - flush_display (fm); - if (toscr_nbits > 16) - uae_abort ("toscr_nbits > 16 (%d)", toscr_nbits); - - return 0; -} - -static int one_fetch_cycle_fm0 (int i, int ddfstop_to_test, int dma) { return one_fetch_cycle_0 (i, ddfstop_to_test, dma, 0); } -static int one_fetch_cycle_fm1 (int i, int ddfstop_to_test, int dma) { return one_fetch_cycle_0 (i, ddfstop_to_test, dma, 1); } -static int one_fetch_cycle_fm2 (int i, int ddfstop_to_test, int dma) { return one_fetch_cycle_0 (i, ddfstop_to_test, dma, 2); } - -STATIC_INLINE int one_fetch_cycle (int i, int ddfstop_to_test, int dma, int fm) -{ - switch (fm) { - case 0: return one_fetch_cycle_fm0 (i, ddfstop_to_test, dma); -#ifdef AGA - case 1: return one_fetch_cycle_fm1 (i, ddfstop_to_test, dma); - case 2: return one_fetch_cycle_fm2 (i, ddfstop_to_test, dma); -#endif - default: uae_abort ("fm corrupt"); return 0; - } -} - -STATIC_INLINE void update_fetch (int until, int fm) -{ - int pos; - int dma = dmaen (DMA_BITPLANE); - - int ddfstop_to_test; - - if (framecnt != 0 || passed_plfstop == 3) - return; - - /* We need an explicit test against HARD_DDF_STOP here to guard against - programs that move the DDFSTOP before our current position before we - reach it. */ - ddfstop_to_test = HARD_DDF_STOP; - if (ddfstop >= last_fetch_hpos && plfstop < ddfstop_to_test) - ddfstop_to_test = plfstop; - - compute_toscr_delay (last_fetch_hpos); - update_toscr_planes (); - - pos = last_fetch_hpos; - cycle_diagram_shift = last_fetch_hpos - fetch_cycle; - - /* First, a loop that prepares us for the speedup code. We want to enter - the SPEEDUP case with fetch_state == fetch_was_plane0, and then unroll - whole blocks, so that we end on the same fetch_state again. */ - for (; ; pos++) { - if (pos == until) { - if (until >= maxhpos) { - finish_final_fetch (pos, fm); - return; - } - flush_display (fm); - return; - } - - if (fetch_state == fetch_was_plane0) - break; - - fetch_state = fetch_started; - if (one_fetch_cycle (pos, ddfstop_to_test, dma, fm)) - return; - } - -#ifdef SPEEDUP - /* Unrolled version of the for loop below. */ - if (! passed_plfstop && ddf_change != vpos && ddf_change + 1 != vpos - && dma - && (fetch_cycle & fetchstart_mask) == (fm_maxplane & fetchstart_mask) - && toscr_delay1 == toscr_delay1x && toscr_delay2 == toscr_delay2x - # if 0 - /* @@@ We handle this case, but the code would be simpler if we - * disallowed it - it may even be possible to guarantee that - * this condition never is false. Later. */ - && (out_nbits & 15) == 0 -# endif - && toscr_nr_planes == thisline_decision.nr_planes) - { - int offs = (pos - fetch_cycle) & fetchunit_mask; - int ddf2 = ((ddfstop_to_test - offs + fetchunit - 1) & ~fetchunit_mask) + offs; - int ddf3 = ddf2 + fetchunit; - int stop = until < ddf2 ? until : until < ddf3 ? ddf2 : ddf3; - int count; - - count = stop - pos; - - if (count >= fetchstart) { - count &= ~fetchstart_mask; - - if (thisline_decision.plfleft == -1) { - compute_delay_offset (); - compute_toscr_delay_1 (); - } - do_long_fetch (pos, count >> (3 - toscr_res), dma, fm); - - /* This must come _after_ do_long_fetch so as not to confuse flush_display - into thinking the first fetch has produced any output worth emitting to - the screen. But the calculation of delay_offset must happen _before_. */ - maybe_first_bpl1dat (pos); - - if (pos <= ddfstop_to_test && pos + count > ddfstop_to_test) - passed_plfstop = 1; - if (pos <= ddfstop_to_test && pos + count > ddf2) - passed_plfstop = 2; - if (pos <= ddf2 && pos + count >= ddf2 + fm_maxplane) - add_modulos (); - pos += count; - fetch_cycle += count; - } - } -#endif - for (; pos < until; pos++) { - if (fetch_state == fetch_was_plane0) - beginning_of_plane_block (pos, fm); - fetch_state = fetch_started; - - if (one_fetch_cycle (pos, ddfstop_to_test, dma, fm)) - return; - } - if (until >= maxhpos) { - finish_final_fetch (pos, fm); - return; - } - flush_display (fm); -} - -static void update_fetch_0 (int hpos) { update_fetch (hpos, 0); } -static void update_fetch_1 (int hpos) { update_fetch (hpos, 1); } -static void update_fetch_2 (int hpos) { update_fetch (hpos, 2); } - -STATIC_INLINE void decide_fetch (int hpos) -{ - if (fetch_state != fetch_not_started && hpos > last_fetch_hpos) { - switch (fetchmode) { - case 0: update_fetch_0 (hpos); break; -#ifdef AGA - case 1: update_fetch_1 (hpos); break; - case 2: update_fetch_2 (hpos); break; -#endif - default: uae_abort ("fetchmode corrupt"); - } - } - last_fetch_hpos = hpos; -} - -static void start_bpl_dma (int hpos, int hstart) -{ - fetch_state = fetch_started; - fetch_cycle = 0; - last_fetch_hpos = hstart; - out_nbits = 0; - out_offs = 0; - toscr_nbits = 0; - toscr_res_first = GET_RES (bplcon0); - - ddfstate = DIW_waiting_stop; - compute_toscr_delay (last_fetch_hpos); - - /* If someone already wrote BPL1DAT, clear the area between that point and - the real fetch start. */ - if (framecnt == 0) { - if (thisline_decision.plfleft != -1) { - out_nbits = (plfstrt - thisline_decision.plfleft) << (1 + toscr_res); - out_offs = out_nbits >> 5; - out_nbits &= 31; - } - update_toscr_planes (); - } -} - -/* this may turn on datafetch if program turns dma on during the ddf */ -static void maybe_start_bpl_dma (int hpos) -{ - /* OCS: BPL DMA never restarts if DMA is turned on during DDF - * ECS/AGA: BPL DMA restarts but only if DMA was turned off - outside of DDF or during current line, otherwise display - processing jumps immediately to "DDFSTOP passed"-condition */ - if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - return; - if (fetch_state != fetch_not_started) - return; - if (diwstate != DIW_waiting_stop) - return; - if (hpos <= plfstrt) - return; - if (hpos > plfstop) - return; - if (ddfstate != DIW_waiting_start) - passed_plfstop = 1; - start_bpl_dma (hpos, hpos); -} - -/* This function is responsible for turning on datafetch if necessary. */ -STATIC_INLINE void decide_line (int hpos) -{ - /* Take care of the vertical DIW. */ - if (vpos == plffirstline) - diwstate = DIW_waiting_stop; - if (vpos == plflastline) - diwstate = DIW_waiting_start; - - if (hpos <= last_decide_line_hpos) - return; - if (fetch_state != fetch_not_started) - return; - - if (dmaen (DMA_BITPLANE) && diwstate == DIW_waiting_stop) { - int ok = 0; - /* Test if we passed the start of the DDF window. */ - if (last_decide_line_hpos < plfstrt && hpos >= plfstrt) { - ok = 1; - /* hack warning.. Writing to DDFSTRT when DMA should start must be ignored - * (correct fix would be emulate this delay for every custom register, but why bother..) */ - if (ddfstrt_old != ddfstrt && hpos - 2 == ddfstrt_old_hpos && ddfstrt_old_vpos == vpos) - ok = 0; - if (ok) { - start_bpl_dma (hpos, plfstrt); - estimate_last_fetch_cycle (plfstrt); - last_decide_line_hpos = hpos; -#ifndef CUSTOM_SIMPLE - do_sprites (plfstrt); -#endif - return; - } - } - } - -#ifndef CUSTOM_SIMPLE - if (last_decide_line_hpos < SPR0_HPOS + 4 * MAX_SPRITES) - do_sprites (hpos); -#endif - last_decide_line_hpos = hpos; -} - -/* 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 hpos, int regno, unsigned long value) -{ - if (regno == -1 && value) { - thisline_decision.ham_seen = 1; - if (hpos < HARD_DDF_START) - thisline_decision.ham_at_start = 1; - } - - /* Early positions don't appear on-screen. */ - if (framecnt != 0 || vpos < minfirstline || hpos < HARD_DDF_START - /*|| currprefs.emul_accuracy == 0*/) - return; - - decide_diw (hpos); - decide_line (hpos); - - if (thisline_decision.ctable == -1) - remember_ctable (); - -#ifdef OS_WITHOUT_MEMORY_MANAGEMENT - if (next_color_change >= max_color_change) { - ++delta_color_change; - return; - } -#endif - curr_color_changes[next_color_change].linepos = hpos; - curr_color_changes[next_color_change].regno = regno; - curr_color_changes[next_color_change++].value = value; -} - -typedef int sprbuf_res_t, cclockres_t, hwres_t, bplres_t; - -static void do_playfield_collisions (void) -{ - uae_u8 *ld = line_data[next_lineno]; - int i; - - if (clxcon_bpl_enable == 0) { - clxdat |= 1; - return; - } - - for (i = thisline_decision.plfleft; i < thisline_decision.plfright; i += 2) { - int j; - uae_u32 total = 0xFFFFFFFF; - for (j = 0; j < 8; j++) { - uae_u32 t = 0; - if ((clxcon_bpl_enable & (1 << j)) == 0) - t = 0xFFFFFFFF; - else if (j < thisline_decision.nr_planes) { - t = *(uae_u32 *)(line_data[next_lineno] + 2 * i + 2 * j * MAX_WORDS_PER_LINE); - t ^= ~(((clxcon_bpl_match >> j) & 1) - 1); - } - total &= t; - } - if (total) - clxdat |= 1; - } -} - -/* Sprite-to-sprite collisions are taken care of in record_sprite. This one does - playfield/sprite collisions. - That's the theory. In practice this doesn't work yet. I also suspect this code - is way too slow. */ -static void do_sprite_collisions (void) -{ - int nr_sprites = curr_drawinfo[next_lineno].nr_sprites; - int first = curr_drawinfo[next_lineno].first_sprite_entry; - int i; - unsigned int collision_mask = clxmask[clxcon >> 12]; - int bplres = GET_RES (bplcon0); - hwres_t ddf_left = thisline_decision.plfleft * 2 << bplres; - hwres_t hw_diwlast = coord_window_to_diw_x (thisline_decision.diwlastword); - hwres_t hw_diwfirst = coord_window_to_diw_x (thisline_decision.diwfirstword); - - if (clxcon_bpl_enable == 0) { - clxdat |= 0x1FE; - return; - } - - for (i = 0; i < nr_sprites; i++) { - struct sprite_entry *e = curr_sprite_entries + first + i; - sprbuf_res_t j; - sprbuf_res_t minpos = e->pos; - sprbuf_res_t maxpos = e->max; - hwres_t minp1 = minpos >> sprite_buffer_res; - hwres_t maxp1 = maxpos >> sprite_buffer_res; - - if (maxp1 > hw_diwlast) - maxpos = hw_diwlast << sprite_buffer_res; - if (maxp1 > thisline_decision.plfright * 2) - maxpos = thisline_decision.plfright * 2 << sprite_buffer_res; - if (minp1 < hw_diwfirst) - minpos = hw_diwfirst << sprite_buffer_res; - if (minp1 < thisline_decision.plfleft * 2) - minpos = thisline_decision.plfleft * 2 << sprite_buffer_res; - - for (j = minpos; j < maxpos; j++) { - int sprpix = spixels[e->first_pixel + j - e->pos] & collision_mask; - int k, offs, match = 1; - - if (sprpix == 0) - continue; - - offs = ((j << bplres) >> sprite_buffer_res) - ddf_left; - sprpix = sprite_ab_merge[sprpix & 255] | (sprite_ab_merge[sprpix >> 8] << 2); - sprpix <<= 1; - - /* Loop over number of playfields. */ - for (k = 1; k >= 0; k--) { - int l; -#ifdef AGA - int planes = (currprefs.chipset_mask & CSMASK_AGA) ? 8 : 6; -#else - int planes = 6; -#endif - if (bplcon0 & 0x400) - match = 1; - for (l = k; match && l < planes; l += 2) { - int t = 0; - if (l < thisline_decision.nr_planes) { - uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + 2 * l * MAX_WORDS_PER_LINE); - uae_u32 word = ldata[offs >> 5]; - t = (word >> (31 - (offs & 31))) & 1; -#if 0 /* debug: draw collision mask */ - if (1) { - int m; - for (m = 0; m < 5; m++) { - ldata = (uae_u32 *)(line_data[next_lineno] + 2 * m * MAX_WORDS_PER_LINE); - ldata[(offs >> 5) + 1] |= 15 << (31 - (offs & 31)); - } - } -#endif - } - if (clxcon_bpl_enable & (1 << l)) { - if (t != ((clxcon_bpl_match >> l) & 1)) - match = 0; - } - } - if (match) { -#if 0 /* debug: mark lines where collisions are detected */ - if (0) { - int l; - for (l = 0; l < 5; l++) { - uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + 2 * l * MAX_WORDS_PER_LINE); - ldata[(offs >> 5) + 1] |= 15 << (31 - (offs & 31)); - } - } -#endif - clxdat |= sprpix << (k * 4); - } - } - } - } -#if 0 - { - static int olx; - if (clxdat != olx) - write_log ("%d: %04.4X\n", vpos, clxdat); - olx = clxdat; - } -#endif -} - -static void expand_sprres (void) -{ - switch ((bplcon3 >> 6) & 3) { - case 0: /* ECS defaults (LORES,HIRES=140ns,SHRES=70ns) */ - if ((currprefs.chipset_mask & CSMASK_ECS_DENISE) && GET_RES (bplcon0) == RES_SUPERHIRES) - sprres = RES_HIRES; - else - sprres = RES_LORES; - break; - case 1: - sprres = RES_LORES; - break; - case 2: - sprres = RES_HIRES; - break; - case 3: - sprres = RES_SUPERHIRES; - break; - } -} - -STATIC_INLINE void record_sprite_1 (uae_u16 *buf, uae_u32 datab, int num, int dbl, - unsigned int mask, int do_collisions, uae_u32 collision_mask) -{ - int j = 0; - while (datab) { - unsigned int tmp = *buf; - unsigned int col = (datab & 3) << (2 * num); - tmp |= col; - if ((j & mask) == 0) - *buf++ = tmp; - if (dbl) - *buf++ = tmp; - j++; - datab >>= 2; - if (do_collisions) { - tmp &= collision_mask; - if (tmp) { - unsigned int shrunk_tmp = sprite_ab_merge[tmp & 255] | (sprite_ab_merge[tmp >> 8] << 2); - clxdat |= sprclx[shrunk_tmp]; - } - } - } -} - -/* DATAB contains the sprite data; 16 pixels in two-bit packets. Bits 0/1 - determine the color of the leftmost pixel, bits 2/3 the color of the next - etc. - This function assumes that for all sprites in a given line, SPRXP either - stays equal or increases between successive calls. - - The data is recorded either in lores pixels (if ECS), or in hires pixels - (if AGA). No support for SHRES sprites. */ - -static void record_sprite (int line, int num, int sprxp, uae_u16 *data, uae_u16 *datb, unsigned int ctl) -{ - struct sprite_entry *e = curr_sprite_entries + next_sprite_entry; - int i; - int word_offs; - uae_u16 *buf; - uae_u32 collision_mask; - int width = sprite_width; - int dbl = 0, half = 0; - unsigned int mask = 0; - - if (sprres != RES_LORES) - thisline_decision.any_hires_sprites = 1; - -#ifdef AGA - if (currprefs.chipset_mask & CSMASK_AGA) { - width = (width << 1) >> sprres; - dbl = sprite_buffer_res - sprres; - if (dbl < 0) { - half = -dbl; - dbl = 0; - } - mask = sprres == RES_SUPERHIRES ? 1 : 0; - } -#endif - - /* Try to coalesce entries if they aren't too far apart. */ - if (! next_sprite_forced && e[-1].max + 16 >= sprxp) { - e--; - } else { - next_sprite_entry++; - e->pos = sprxp; - e->has_attached = 0; - } - - if (sprxp < e->pos) - uae_abort ("sprxp < e->pos"); - - e->max = sprxp + width; - e[1].first_pixel = e->first_pixel + ((e->max - e->pos + 3) & ~3); - next_sprite_forced = 0; - - collision_mask = clxmask[clxcon >> 12]; - word_offs = e->first_pixel + sprxp - e->pos; - - for (i = 0; i < sprite_width; i += 16) { - unsigned int da = *data; - unsigned int db = *datb; - uae_u32 datab = ((sprtaba[da & 0xFF] << 16) | sprtaba[da >> 8] - | (sprtabb[db & 0xFF] << 16) | sprtabb[db >> 8]); - - buf = spixels + word_offs + ((i << dbl) >> half); - if (currprefs.collision_level > 0 && collision_mask) - record_sprite_1 (buf, datab, num, dbl, mask, 1, collision_mask); - else - record_sprite_1 (buf, datab, num, dbl, mask, 0, collision_mask); - data++; - datb++; - } - - /* We have 8 bits per pixel in spixstate, two for every sprite pair. The - low order bit records whether the attach bit was set for this pair. */ - - if (ctl & 0x80) { - uae_u32 state = 0x01010101 << (num & ~1); - uae_u32 *stbuf = spixstate.words + (word_offs >> 2); - uae_u8 *stb1 = spixstate.bytes + word_offs; - for (i = 0; i < width; i += 8) { - stb1[0] |= state; - stb1[1] |= state; - stb1[2] |= state; - stb1[3] |= state; - stb1[4] |= state; - stb1[5] |= state; - stb1[6] |= state; - stb1[7] |= state; - stb1 += 8; - } - e->has_attached = 1; - } -} - -static void decide_sprites (int hpos) -{ - int nrs[MAX_SPRITES], posns[MAX_SPRITES]; - int count, i; - int point = hpos * 2; - int width = sprite_width; - int window_width = (width << lores_shift) >> sprres; - - if (framecnt != 0 || hpos < 0x14 || nr_armed == 0 || point == last_sprite_point) - return; -#ifdef DISABLE_SPRITES - return; -#endif - - decide_diw (hpos); - decide_line (hpos); - -#if 0 - /* This tries to detect whether the line is border, but that doesn't work, it's too early. */ - if (thisline_decision.plfleft == -1) - return; -#endif - count = 0; - for (i = 0; i < MAX_SPRITES; i++) { - int sprxp = spr[i].xpos; - int hw_xp = (sprxp >> sprite_buffer_res); - int window_xp = coord_hw_to_window_x (hw_xp) + (DIW_DDF_OFFSET << lores_shift); - int j, bestp; - - if (! spr[i].armed || sprxp < 0 || hw_xp <= last_sprite_point || hw_xp > point) - continue; - if ( !(bplcon3 & 2) && /* sprites outside playfields enabled? */ - ((thisline_decision.diwfirstword >= 0 && window_xp + window_width < thisline_decision.diwfirstword) - || (thisline_decision.diwlastword >= 0 && window_xp > thisline_decision.diwlastword))) - continue; - - /* Sort the sprites in order of ascending X position before recording them. */ - 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++; - } - for (i = 0; i < count; i++) { - int nr = nrs[i]; - record_sprite (next_lineno, nr, spr[nr].xpos, sprdata[nr], sprdatb[nr], sprctl[nr]); - } - last_sprite_point = point; -} - -STATIC_INLINE int sprites_differ (struct draw_info *dip, struct draw_info *dip_old) -{ - struct sprite_entry *this_first = curr_sprite_entries + dip->first_sprite_entry; - struct sprite_entry *this_last = curr_sprite_entries + dip->last_sprite_entry; - struct sprite_entry *prev_first = prev_sprite_entries + dip_old->first_sprite_entry; - int npixels; - int i; - - if (dip->nr_sprites != dip_old->nr_sprites) - return 1; - - if (dip->nr_sprites == 0) - return 0; - - for (i = 0; i < dip->nr_sprites; i++) - if (this_first[i].pos != prev_first[i].pos - || this_first[i].max != prev_first[i].max - || this_first[i].has_attached != prev_first[i].has_attached) - return 1; - - npixels = this_last->first_pixel + (this_last->max - this_last->pos) - this_first->first_pixel; - if (memcmp (spixels + this_first->first_pixel, spixels + prev_first->first_pixel, - npixels * sizeof (uae_u16)) != 0) - return 1; - if (memcmp (spixstate.bytes + this_first->first_pixel, spixstate.bytes + prev_first->first_pixel, npixels) != 0) - return 1; - return 0; -} - -STATIC_INLINE int color_changes_differ (struct draw_info *dip, struct draw_info *dip_old) -{ - if (dip->nr_color_changes != dip_old->nr_color_changes) - return 1; - - if (dip->nr_color_changes == 0) - return 0; - if (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) - return 1; - return 0; -} - -/* End of a horizontal scan line. Finish off all decisions that were not - * made yet. */ -static void finish_decisions (void) -{ - struct draw_info *dip; - struct draw_info *dip_old; - struct decision *dp; - int changed; - int hpos = current_hpos (); - - if (framecnt != 0) - return; - - decide_diw (hpos); - decide_line (hpos); - decide_fetch (hpos); - - if (thisline_decision.plfleft != -1 && thisline_decision.plflinelen == -1) { - if (fetch_state != fetch_not_started) { - write_log("fetch_state=%d plfleft=%d\n",fetch_state,thisline_decision.plfleft); - uae_abort ("fetch_state != fetch_not_started"); - } - thisline_decision.plfright = thisline_decision.plfleft; - thisline_decision.plflinelen = 0; - thisline_decision.bplres = RES_LORES; - } - - /* 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) - thisline_decision.diwlastword = max_diwlastword; - - if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword) - MARK_LINE_CHANGED; - if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword) - MARK_LINE_CHANGED; - - dip = curr_drawinfo + next_lineno; - dip_old = prev_drawinfo + next_lineno; - dp = line_decisions + next_lineno; - changed = thisline_changed; - - if (thisline_decision.plfleft != -1) { - record_diw_line (thisline_decision.diwfirstword, thisline_decision.diwlastword); - - decide_sprites (hpos); - } - - dip->last_sprite_entry = next_sprite_entry; - dip->last_color_change = next_color_change; - - if (thisline_decision.ctable == -1) { - if (thisline_decision.plfleft == -1) - remember_ctable_for_border (); - else - remember_ctable (); - } - - dip->nr_color_changes = next_color_change - dip->first_color_change; - dip->nr_sprites = next_sprite_entry - dip->first_sprite_entry; - - if (thisline_decision.plfleft != line_decisions[next_lineno].plfleft) - changed = 1; - if (! changed && color_changes_differ (dip, dip_old)) - changed = 1; - if (!changed && thisline_decision.plfleft != -1 && sprites_differ (dip, dip_old)) - changed = 1; - - if (changed) { - thisline_changed = 1; - *dp = thisline_decision; - } else - /* The only one that may differ: */ - 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) - return; - toscr_res_first = 0; - - thisline_decision.any_hires_sprites = 0; - thisline_decision.nr_planes = 0; - - thisline_decision.plfleft = -1; - thisline_decision.plflinelen = -1; - thisline_decision.ham_seen = !! (bplcon0 & 0x800); - thisline_decision.ham_at_start = !! (bplcon0 & 0x800); - - /* decided_res shouldn't be touched before it's initialized by decide_line(). */ - thisline_decision.diwfirstword = -1; - thisline_decision.diwlastword = -1; - if (hdiwstate == DIW_waiting_stop) { - thisline_decision.diwfirstword = 0; - if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword) - MARK_LINE_CHANGED; - } - thisline_decision.ctable = -1; - - thisline_changed = 0; - curr_drawinfo[next_lineno].first_color_change = next_color_change; - curr_drawinfo[next_lineno].first_sprite_entry = next_sprite_entry; - next_sprite_forced = 1; - - /* memset(sprite_last_drawn_at, 0, sizeof sprite_last_drawn_at); */ - last_sprite_point = 0; - fetch_state = fetch_not_started; - passed_plfstop = 0; - - memset (todisplay, 0, sizeof todisplay); - memset (fetched, 0, sizeof fetched); -#ifdef AGA - memset (fetched_aga0, 0, sizeof fetched_aga0); - memset (fetched_aga1, 0, sizeof fetched_aga1); -#endif - memset (outword, 0, sizeof outword); - - last_decide_line_hpos = -1; - last_diw_pix_hpos = -1; - last_ddf_pix_hpos = -1; - last_sprite_hpos = -1; - last_fetch_hpos = -1; - -} - -int vsynctime_orig; -int turbo_emulation; - -void compute_vsynctime (void) -{ - fake_vblank_hz = 0; - if (currprefs.gfx_vsync && currprefs.gfx_afullscreen && currprefs.gfx_refreshrate) { - vblank_hz = currprefs.gfx_refreshrate; - vblank_skip = 1; -#if 0 - if (vblank_hz == 75) { - fake_vblank_hz = 50; - vblank_skip = 2; - } - if (vblank_hz == 90) { - fake_vblank_hz = 60; - vblank_skip = 2; - } -#endif - if (!fake_vblank_hz && vblank_hz > 85) { - vblank_hz /= 2; - vblank_skip = -1; - } - } - if (!fake_vblank_hz) - fake_vblank_hz = vblank_hz; - if (turbo_emulation) - vsynctime = vsynctime_orig = 1; - else - vsynctime = vsynctime_orig = syncbase / fake_vblank_hz; -#ifdef OPENGL - OGL_refresh (); -#endif -#ifdef D3D - D3D_refresh (); -#endif - if (currprefs.produce_sound > 1) - update_sound (fake_vblank_hz); -} - - -/* set PAL or NTSC timing variables */ -void init_hz (void) -{ - int isntsc; - - beamcon0 = new_beamcon0; - isntsc = beamcon0 & 0x20 ? 0 : 1; - if (hack_vpos > 0) { - if (maxvpos == hack_vpos) return; - maxvpos = hack_vpos; - vblank_hz = 15600 / hack_vpos; - hack_vpos = -1; - } else if (hack_vpos < 0) { - hack_vpos = 0; - } - if (hack_vpos == 0) { - if (!isntsc) { - maxvpos = MAXVPOS_PAL; - maxhpos = MAXHPOS_PAL; - minfirstline = VBLANK_ENDLINE_PAL; - vblank_hz = VBLANK_HZ_PAL; - sprite_vblank_endline = VBLANK_SPRITE_PAL; - } else { - maxvpos = MAXVPOS_NTSC; - maxhpos = MAXHPOS_NTSC; - minfirstline = VBLANK_ENDLINE_NTSC; - vblank_hz = VBLANK_HZ_NTSC; - sprite_vblank_endline = VBLANK_SPRITE_NTSC; - } - } - if (beamcon0 & 0x80) { - if (vtotal >= MAXVPOS) - vtotal = MAXVPOS - 1; - maxvpos = vtotal + 1; - if (htotal >= MAXHPOS) - htotal = MAXHPOS - 1; - maxhpos = htotal + 1; - vblank_hz = 227 * 312 * 50 / (maxvpos * maxhpos); - } - /* limit to sane values */ - if (vblank_hz < 10) - vblank_hz = 10; - if (vblank_hz > 300) - vblank_hz = 300; - eventtab[ev_hsync].oldcycles = get_cycles (); - eventtab[ev_hsync].evtime = get_cycles() + HSYNCTIME; - events_schedule (); - compute_vsynctime (); -#ifdef OPENGL - OGL_refresh (); -#endif -#ifdef PICASSO96 - init_hz_p96 (); -#endif - write_log ("%s mode, %dHz\n", isntsc ? "NTSC" : "PAL", vblank_hz); -} - -static void calcdiw (void) -{ - int hstrt = diwstrt & 0xFF; - int hstop = diwstop & 0xFF; - int vstrt = diwstrt >> 8; - int vstop = diwstop >> 8; - - if (diwhigh_written) { - hstrt |= ((diwhigh >> 5) & 1) << 8; - hstop |= ((diwhigh >> 13) & 1) << 8; - vstrt |= (diwhigh & 7) << 8; - vstop |= ((diwhigh >> 8) & 7) << 8; - } else { - hstop += 0x100; - if ((vstop & 0x80) == 0) - vstop |= 0x100; - } - - diwfirstword = coord_diw_to_window_x (hstrt); - diwlastword = coord_diw_to_window_x (hstop); - if (diwfirstword < 0) - diwfirstword = 0; - - plffirstline = vstrt; - plflastline = vstop; - -#if 0 - /* This happens far too often. */ - if (plffirstline < minfirstline_bpl) { - write_log ("Warning: Playfield begins before line %d (%d)!\n", minfirstline_bpl, plffirstline); - } -#endif - -#if 0 /* this comparison is not needed but previous is.. */ - if (plflastline > 313) { - /* Turrican does this */ - write_log ("Warning: Playfield out of range!\n"); - plflastline = 313; - } -#endif - - plfstrt = ddfstrt; - plfstop = ddfstop; - /* probably not the correct place.. */ - if ((currprefs.chipset_mask & CSMASK_ECS_AGNUS) && ddfstop > maxhpos) - plfstrt = 0; - if (plfstrt < HARD_DDF_START) - plfstrt = HARD_DDF_START; -} - -static int timehack_alive = 0; - -static uae_u32 timehack_helper (void) -{ -#ifdef HAVE_GETTIMEOFDAY - struct timeval tv; - if (m68k_dreg (regs, 0) == 0) - return timehack_alive; - - timehack_alive = 10; - - gettimeofday (&tv, NULL); - put_long (m68k_areg (regs, 0), tv.tv_sec - (((365 * 8 + 2) * 24) * 60 * 60)); - put_long (m68k_areg (regs, 0) + 4, tv.tv_usec); - return 0; -#else - return 2; -#endif -} - - /* - * register functions - */ -STATIC_INLINE uae_u16 DENISEID (void) -{ -#ifdef AGA - if (currprefs.chipset_mask & CSMASK_AGA) - return 0xF8; -#endif - if (currprefs.chipset_mask & CSMASK_ECS_DENISE) - return 0xFC; - return 0xffff; -} -STATIC_INLINE uae_u16 DMACONR (void) -{ - uae_u16 v; - decide_blitter (current_hpos ()); - v = dmacon | (bltstate == BLT_done ? 0 : 0x4000) - | (blt_info.blitzero ? 0x2000 : 0); - return v; -} -STATIC_INLINE uae_u16 INTENAR (void) -{ - return intena; -} -uae_u16 INTREQR (void) -{ - return intreq; -} -STATIC_INLINE uae_u16 ADKCONR (void) -{ - return adkcon; -} -STATIC_INLINE uae_u16 VPOSR (void) -{ - unsigned int csbit = currprefs.ntscmode ? 0x1000 : 0; - int vp = (vpos >> 8) & 7; -#ifdef AGA - csbit |= (currprefs.chipset_mask & CSMASK_AGA) ? 0x2300 : 0; -#else - csbit |= (currprefs.chipset_mask & CSMASK_ECS_AGNUS) ? 0x2000 : 0; -#endif - if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - vp &= 1; - vp = vp | lof | csbit; - return vp; -} -static void VPOSW (uae_u16 v) -{ -#if 0 - write_log ("vposw %x at %x\n", v, m68k_getpc()); -#endif - if (lof != (v & 0x8000)) - lof_changed = 1; - lof = v & 0x8000; - if ( (v & 1) && vpos > 0) - hack_vpos = vpos; -} - -STATIC_INLINE uae_u16 VHPOSR (void) -{ - uae_u16 v = (vpos << 8) | current_hpos (); - return 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 COPJMP (int num) -{ - int was_active = eventtab[ev_copper].active; - eventtab[ev_copper].active = 0; - if (was_active) - events_schedule (); - - cop_state.ignore_next = 0; - cop_state.state = COP_read1; - cop_state.vpos = vpos; - cop_state.hpos = current_hpos () & ~1; - cop_state.strobe = num; - copper_enabled_thisline = 0; - - if (dmaen (DMA_COPPER)) { - copper_enabled_thisline = 1; - set_special (SPCFLAG_COPPER); - } -} - -STATIC_INLINE void COPCON (uae_u16 a) -{ - copcon = a; -} - -static void compute_spcflag_copper (void); -static void DMACON (int hpos, uae_u16 v) -{ - int oldcop, newcop; - uae_u16 changed; - - uae_u16 oldcon = dmacon; - - decide_line (hpos); - decide_fetch (hpos); - decide_blitter (hpos); - - setclr (&dmacon, v); - dmacon &= 0x1FFF; - - changed = dmacon ^ oldcon; - - oldcop = (oldcon & DMA_COPPER) && (oldcon & DMA_MASTER); - newcop = (dmacon & DMA_COPPER) && (dmacon & DMA_MASTER); - - if (oldcop != newcop) { - eventtab[ev_copper].active = 0; - if (newcop && !oldcop) { - compute_spcflag_copper (); - } else if (!newcop) { - copper_enabled_thisline = 0; - unset_special (SPCFLAG_COPPER); - } - } - if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done) { - static int count = 0; - if (!count) { - count = 1; - write_log ("warning: program is doing blitpri hacks.\n"); - } - set_special (SPCFLAG_BLTNASTY); - decide_blitter (hpos); - } - if (dmaen (DMA_BLITTER) && bltstate == BLT_init) - bltstate = BLT_work; - if ((dmacon & (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER)) != (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER)) { - unset_special (SPCFLAG_BLTNASTY); - decide_blitter (hpos); - } - if (changed & (DMA_MASTER | 0x0f)) - audio_hsync (0); - if (changed & (DMA_MASTER | DMA_BITPLANE)) { - ddf_change = vpos; - if (dmaen (DMA_BITPLANE)) - maybe_start_bpl_dma (hpos); - } - - events_schedule(); -} - - -static int intlev_2 (void) -{ - uae_u16 imask = intreq & intena; - unsigned long cycles = get_cycles (); - int c = currprefs.cpu_level >= 2 ? 20 : 4; - int i; - - if (!(imask && (intena & 0x4000))) { - unset_special (SPCFLAG_INT); - return -1; - } - for (i = 14; i >= 0; i--) { - if (imask & (1 << i)) { - if (!(irqdelay[i] && (cycles - irqcycles[i]) < c * CYCLE_UNIT)) { - irqdelay[i] = 0; - if (i == 13 || i == 14) - return 6; - else if (i == 11 || i == 12) - return 5; - else if (i >= 7 && i <= 10) - return 4; - else if (i >= 4 && i <= 6) - return 3; - else if (i == 3) - return 2; - else - return 1; - } - } - } - return -1; -} - -int intlev (void) -{ - int il = intlev_2 (); - if (il >= 0 && il <= regs.intmask) - unset_special (SPCFLAG_INT); - return il; -} - -static void doint (void) -{ - int i; - uae_u16 imask = intreq & intena; - - set_special (SPCFLAG_INT); - if (imask && (intena & 0x4000)) { - for (i = 0; i < 14; i++) { - if ((imask & (1 << i)) && irqdelay[i] == 0) { - irqdelay[i] = 1; - irqcycles[i] = get_cycles (); - } - } - } -} - -STATIC_INLINE void INTENA (uae_u16 v) -{ - setclr (&intena,v); -#if 0 - if (v & 0x100) - write_log("INTENA %04.4X (%04.4X) %p\n", intena, v, m68k_getpc()); -#endif - if (v & 0x8000) - doint (); -} - -void INTREQ_0 (uae_u16 v) -{ - setclr (&intreq,v); - doint (); -} - -void INTREQ (uae_u16 v) -{ - INTREQ_0 (v); - serial_check_irq (); - rethink_cias (); -#if 0 - if (v & 0x100) - write_log("INTREQ %04.4X (%04.4X) %p\n", intreq, v, m68k_getpc()); -#endif -} - -static void ADKCON (int hpos, uae_u16 v) -{ - if (currprefs.produce_sound > 0) - update_audio (); - - setclr (&adkcon,v); - update_adkmasks (); - DISK_update (hpos); - if ((v >> 11) & 1) - serial_uartbreak ((adkcon >> 11) & 1); -} - -static void dumpsync (void) -{ -#if 0 - write_log ("BEAMCON0 = %04.4X VTOTAL=%04.4X HTOTAL=%04.4X\n", new_beamcon0, vtotal, htotal); - write_log ("HSSTOP=%04.4X HBSTRT=%04.4X HBSTOP=%04.4X\n", hsstop, hbstrt, hbstop); - write_log ("VSSTOP=%04.4X VBSTRT=%04.4X VBSTOP=%04.4X\n", vsstop, vbstrt, vbstop); - write_log ("HSSTRT=%04.4X VSSTRT=%04.4X HCENTER=%04.4X\n", hsstrt, vsstrt, hcenter); -#endif -} - -static void BEAMCON0 (uae_u16 v) -{ - if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) { - if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE)) - v &= 0x20; - if (v != new_beamcon0) { - new_beamcon0 = v; - if (v & ~0x20) - write_log ("warning: %04.4X written to BEAMCON0\n", v); - } - } -} - -static void varsync (void) -{ -#ifdef PICASSO96 - if (p96refresh_active) - { - extern int p96hack_vpos2; - static int p96hack_vpos_old; - if (p96hack_vpos_old == p96hack_vpos2) return; - vtotal = p96hack_vpos2; - p96hack_vpos_old = p96hack_vpos2; - hack_vpos = -1; - return; - } -#endif - if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE)) - return; - if (!(beamcon0 & 0x80)) - return; - hack_vpos = -1; - dumpsync (); -} - - -static void BPLxPTH (int hpos, uae_u16 v, int num) -{ - decide_line (hpos); - decide_fetch (hpos); - bplpt[num] = (bplpt[num] & 0xffff) | ((uae_u32)v << 16); - //write_log("%d:%d:BPL%dPTH %08.8X\n", hpos, vpos, num, v); -} -static void BPLxPTL (int hpos, uae_u16 v, int num) -{ - decide_line (hpos); - decide_fetch (hpos); - bplpt[num] = (bplpt[num] & ~0xffff) | (v & 0xfffe); - //write_log("%d:%d:BPL%dPTL %08.8X\n", hpos, vpos, num, v); -} - -static void BPLCON0 (int hpos, uae_u16 v) -{ - if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE)) - v &= ~0x00F1; - else if (! (currprefs.chipset_mask & CSMASK_AGA)) - v &= ~0x00B1; - - if (bplcon0 == v) - return; - - ddf_change = vpos; - decide_line (hpos); - decide_fetch (hpos); - decide_blitter (hpos); - - /* HAM change? */ - if ((bplcon0 ^ v) & 0x800) { - record_color_change (hpos, -1, !! (v & 0x800)); - } - bplcon0 = v; - -#ifdef AGA - if (currprefs.chipset_mask & CSMASK_AGA) { - decide_sprites (hpos); - expand_sprres (); - } -#endif - - expand_fmodes (); - calcdiw (); - estimate_last_fetch_cycle (hpos); -} - -STATIC_INLINE void BPLCON1 (int hpos, uae_u16 v) -{ - if (!(currprefs.chipset_mask & CSMASK_AGA)) - v &= 0xff; - if (bplcon1 == v) - return; - decide_line (hpos); - decide_fetch (hpos); - bplcon1 = v; -} - -STATIC_INLINE void BPLCON2 (int hpos, uae_u16 v) -{ - if (!(currprefs.chipset_mask & CSMASK_AGA)) - v &= 0x7f; - if (bplcon2 == v) - return; - decide_line (hpos); - bplcon2 = v; -} - -#ifdef AGA -STATIC_INLINE void BPLCON3 (int hpos, uae_u16 v) -{ - if (! (currprefs.chipset_mask & CSMASK_AGA)) - return; - if (bplcon3 == v) - return; - decide_line (hpos); - decide_sprites (hpos); - bplcon3 = v; - expand_sprres (); -} - -STATIC_INLINE void BPLCON4 (int hpos, uae_u16 v) -{ - if (! (currprefs.chipset_mask & CSMASK_AGA)) - return; - if (bplcon4 == v) - return; - decide_line (hpos); - bplcon4 = v; -} -#endif - -static void BPL1MOD (int hpos, uae_u16 v) -{ - v &= ~1; - if ((uae_s16)bpl1mod == (uae_s16)v) - return; - decide_line (hpos); - decide_fetch (hpos); - bpl1mod = v; -} - -static void BPL2MOD (int hpos, uae_u16 v) -{ - v &= ~1; - if ((uae_s16)bpl2mod == (uae_s16)v) - return; - decide_line (hpos); - decide_fetch (hpos); - bpl2mod = v; -} - -STATIC_INLINE void BPL1DAT (int hpos, uae_u16 v) -{ - decide_line (hpos); - bpl1dat = v; - - maybe_first_bpl1dat (hpos); -} -/* We could do as well without those... */ -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_INLINE void BPL7DAT (uae_u16 v) { bpl7dat = v; } -STATIC_INLINE void BPL8DAT (uae_u16 v) { bpl8dat = v; } - -static void DIWSTRT (int hpos, uae_u16 v) -{ - if (diwstrt == v && ! diwhigh_written) - return; - decide_line (hpos); - diwhigh_written = 0; - diwstrt = v; - calcdiw (); -} - -static void DIWSTOP (int hpos, uae_u16 v) -{ - if (diwstop == v && ! diwhigh_written) - return; - decide_line (hpos); - diwhigh_written = 0; - diwstop = v; - calcdiw (); -} - -static void DIWHIGH (int hpos, uae_u16 v) -{ - if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - return; - if (diwhigh_written && diwhigh == v) - return; - decide_line (hpos); - diwhigh_written = 1; - diwhigh = v; - calcdiw (); -} - -static void DDFSTRT (int hpos, uae_u16 v) -{ - v &= 0xfe; - if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - v &= 0xfc; - if (ddfstrt == v) - return; - ddf_change = vpos; - decide_line (hpos); - ddfstrt_old = ddfstrt; - ddfstrt_old_hpos = hpos; - ddfstrt_old_vpos = vpos; - ddfstrt = v; - calcdiw (); - if (ddfstop > 0xD4 && (ddfstrt & 4) == 4) { - static int last_warned; - last_warned = (last_warned + 1) & 4095; - if (last_warned == 0) - write_log ("WARNING! Very strange DDF values.\n"); - } -} - -int test_cnt = 0x80; - -static void DDFSTOP (int hpos, uae_u16 v) -{ - v &= 0xfe; - if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - v &= 0xfc; - if (ddfstop == v) - return; - decide_line (hpos); - decide_fetch (hpos); - decide_blitter (hpos); - ddfstop = v; - calcdiw (); - if (fetch_state != fetch_not_started) - estimate_last_fetch_cycle (hpos); - if (ddfstop > 0xD4 && (ddfstrt & 4) == 4) { - static int last_warned; - if (last_warned == 0) - write_log ("WARNING! Very strange DDF values (%x).\n", ddfstop); - last_warned = (last_warned + 1) & 4095; - } -} - -static void FMODE (uae_u16 v) -{ - if (! (currprefs.chipset_mask & CSMASK_AGA)) - v = 0; - ddf_change = vpos; - fmode = v; - sprite_width = GET_SPRITEWIDTH (fmode); - switch (fmode & 3) { - case 0: - fetchmode = 0; - break; - case 1: - case 2: - fetchmode = 1; - break; - case 3: - fetchmode = 2; - break; - } - expand_fmodes (); - calcdiw (); -} - -static void BLTADAT (uae_u16 v) -{ - maybe_blit (current_hpos(), 0); - - blt_info.bltadat = v; -} -/* - * "Loading data shifts it immediately" says the HRM. Well, that may - * be true for BLTBDAT, but not for BLTADAT - it appears the A data must be - * loaded for every word so that AFWM and ALWM can be applied. - */ -static void BLTBDAT (uae_u16 v) -{ - maybe_blit (current_hpos(), 0); - - if (bltcon1 & 2) - blt_info.bltbhold = v << (bltcon1 >> 12); - else - blt_info.bltbhold = v >> (bltcon1 >> 12); - blt_info.bltbdat = v; -} -static void BLTCDAT (uae_u16 v) { maybe_blit (current_hpos(), 0); blt_info.bltcdat = v; reset_blit (0); } - -static void BLTAMOD (uae_u16 v) { maybe_blit (current_hpos(), 1); blt_info.bltamod = (uae_s16)(v & 0xFFFE); reset_blit (0); } -static void BLTBMOD (uae_u16 v) { maybe_blit (current_hpos(), 1); blt_info.bltbmod = (uae_s16)(v & 0xFFFE); reset_blit (0); } -static void BLTCMOD (uae_u16 v) { maybe_blit (current_hpos(), 1); blt_info.bltcmod = (uae_s16)(v & 0xFFFE); reset_blit (0); } -static void BLTDMOD (uae_u16 v) { maybe_blit (current_hpos(), 1); blt_info.bltdmod = (uae_s16)(v & 0xFFFE); reset_blit (0); } - -static void BLTCON0 (uae_u16 v) { maybe_blit (current_hpos(), 2); bltcon0 = v; blinea_shift = v >> 12; reset_blit (1); } -/* The next category is "Most useless hardware register". - * And the winner is... */ -static void BLTCON0L (uae_u16 v) -{ - if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - return; - maybe_blit (current_hpos(), 2); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF); - reset_blit (1); -} -static void BLTCON1 (uae_u16 v) { maybe_blit (current_hpos(), 2); bltcon1 = v; reset_blit (2); } - -static void BLTAFWM (uae_u16 v) { maybe_blit (current_hpos(), 2); blt_info.bltafwm = v; reset_blit (0); } -static void BLTALWM (uae_u16 v) { maybe_blit (current_hpos(), 2); blt_info.bltalwm = v; reset_blit (0); } - -static void BLTAPTH (uae_u16 v) { maybe_blit (current_hpos(), 0); bltapt = (bltapt & 0xffff) | ((uae_u32)v << 16); } -static void BLTAPTL (uae_u16 v) { maybe_blit (current_hpos(), 0); bltapt = (bltapt & ~0xffff) | (v & 0xFFFE); } -static void BLTBPTH (uae_u16 v) { maybe_blit (current_hpos(), 0); bltbpt = (bltbpt & 0xffff) | ((uae_u32)v << 16); } -static void BLTBPTL (uae_u16 v) { maybe_blit (current_hpos(), 0); bltbpt = (bltbpt & ~0xffff) | (v & 0xFFFE); } -static void BLTCPTH (uae_u16 v) { maybe_blit (current_hpos(), 0); bltcpt = (bltcpt & 0xffff) | ((uae_u32)v << 16); } -static void BLTCPTL (uae_u16 v) { maybe_blit (current_hpos(), 0); bltcpt = (bltcpt & ~0xffff) | (v & 0xFFFE); } -static void BLTDPTH (uae_u16 v) { maybe_blit (current_hpos(), 0); bltdpt = (bltdpt & 0xffff) | ((uae_u32)v << 16); } -static void BLTDPTL (uae_u16 v) { maybe_blit (current_hpos(), 0); bltdpt = (bltdpt & ~0xffff) | (v & 0xFFFE); } - -static void BLTSIZE (uae_u16 v) -{ - maybe_blit (current_hpos(), 0); - - blt_info.vblitsize = v >> 6; - blt_info.hblitsize = v & 0x3F; - if (!blt_info.vblitsize) blt_info.vblitsize = 1024; - if (!blt_info.hblitsize) blt_info.hblitsize = 64; - do_blitter (current_hpos()); -} - -static void BLTSIZV (uae_u16 v) -{ - if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - return; - maybe_blit (current_hpos(), 0); - blt_info.vblitsize = v & 0x7FFF; -} - -static void BLTSIZH (uae_u16 v) -{ - if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - return; - maybe_blit (current_hpos(), 0); - blt_info.hblitsize = v & 0x7FF; - if (!blt_info.vblitsize) blt_info.vblitsize = 32768; - if (!blt_info.hblitsize) blt_info.hblitsize = 0x800; - do_blitter (current_hpos()); -} - -STATIC_INLINE void SPRxCTLPOS (int num) -{ - int sprxp; - struct sprite *s = &spr[num]; - - sprxp = (sprpos[num] & 0xFF) * 2 + (sprctl[num] & 1); - /* Quite a bit salad in this register... */ -#ifdef AGA - if (currprefs.chipset_mask & CSMASK_AGA) { - /* We ignore the SHRES 35ns increment for now; SHRES support doesn't - work anyway, so we may as well restrict AGA sprites to a 70ns - resolution. */ - sprxp <<= 1; - sprxp |= (sprctl[num] >> 4) & 1; - } -#endif - s->xpos = sprxp; - s->vstart = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100); - s->vstop = (sprctl[num] >> 8) | ((sprctl[num] << 7) & 0x100); - if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) { - s->vstart |= (sprctl[num] << 3) & 0x200; - s->vstop |= (sprctl[num] << 4) & 0x200; - } - if (vpos == s->vstart) - s->dmastate = 1; - if (vpos == s->vstop) - s->dmastate = 0; -} - -STATIC_INLINE void SPRxCTL_1 (uae_u16 v, int num, int hpos) -{ - struct sprite *s = &spr[num]; - sprctl[num] = v; - nr_armed -= s->armed; - s->armed = 0; - SPRxCTLPOS (num); -#if SPRITE_DEBUG > 0 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) { - write_log ("%d:%d:SPR%dCTL %04.4X VSTRT=%d VSTOP=%d HSTRT=%d DMA=%d ARM=%d COP=%x PC=%x\n", - vpos, hpos, num, v, s->vstart, s->vstop, s->xpos, spr[num].dmastate, spr[num].armed, cop_state.ip, m68k_getpc()); - } -#endif - -} -STATIC_INLINE void SPRxPOS_1 (uae_u16 v, int num, int hpos) -{ - struct sprite *s = &spr[num]; - sprpos[num] = v; - SPRxCTLPOS (num); -#if SPRITE_DEBUG > 0 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) { - write_log ("%d:%d:SPR%dPOS %04.4X VSTRT=%d VSTOP=%d HSTRT=%d DMA=%d ARM=%d COP=%x PC=%x\n", - vpos, hpos, num, v, s->vstart, s->vstop, s->xpos, spr[num].dmastate, spr[num].armed, cop_state.ip, m68k_getpc()); - } -#endif -} -STATIC_INLINE void SPRxDATA_1 (uae_u16 v, int num, int hpos) -{ - sprdata[num][0] = v; -#ifdef AGA - sprdata[num][1] = v; - sprdata[num][2] = v; - sprdata[num][3] = v; -#endif - nr_armed += 1 - spr[num].armed; - spr[num].armed = 1; -#if SPRITE_DEBUG > 1 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) { - write_log ("%d:%d:SPR%dDATA %04.4X DMA=%d ARM=%d PC=%x\n", - vpos, hpos, num, v, spr[num].dmastate, spr[num].armed, m68k_getpc()); - } -#endif -} -STATIC_INLINE void SPRxDATB_1 (uae_u16 v, int num, int hpos) -{ - sprdatb[num][0] = v; -#ifdef AGA - sprdatb[num][1] = v; - sprdatb[num][2] = v; - sprdatb[num][3] = v; -#endif -#if SPRITE_DEBUG > 1 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) { - write_log ("%d:%d:SPR%dDATB %04.4X DMA=%d ARM=%d PC=%x\n", - vpos, hpos, num, v, spr[num].dmastate, spr[num].armed, m68k_getpc()); - } -#endif -} -static void SPRxDATA (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxDATA_1 (v, num, hpos); } -static void SPRxDATB (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxDATB_1 (v, num, hpos); } -static void SPRxCTL (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxCTL_1 (v, num, hpos); } -static void SPRxPOS (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxPOS_1 (v, num, hpos); } -static void SPRxPTH (int hpos, uae_u16 v, int num) -{ - decide_sprites (hpos); - spr[num].pt &= 0xffff; - spr[num].pt |= (uae_u32)v << 16; -#if SPRITE_DEBUG > 0 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) { - write_log ("%d:%d:SPR%dPTH %08.8X\n", vpos, hpos, num, spr[num].pt); - } -#endif -} -static void SPRxPTL (int hpos, uae_u16 v, int num) -{ - decide_sprites (hpos); - spr[num].pt &= ~0xffff; - spr[num].pt |= v; -#if SPRITE_DEBUG > 0 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) { - write_log ("%d:%d:SPR%dPTL %08.8X\n", vpos, hpos, num, spr[num].pt); - } -#endif -} - -static void CLXCON (uae_u16 v) -{ - clxcon = v; - clxcon_bpl_enable = (v >> 6) & 63; - clxcon_bpl_match = v & 63; - //write_log("CLXCON: %04.4X PC=%x\n", v, m68k_getpc()); -} - -static void CLXCON2 (uae_u16 v) -{ - if (!(currprefs.chipset_mask & CSMASK_AGA)) - return; - clxcon2 = v; - clxcon_bpl_enable |= v & (0x40|0x80); - clxcon_bpl_match |= (v & (0x01|0x02)) << 6; - //write_log("CLXCON2: %04.4X\n", v); -} - -static uae_u16 CLXDAT (void) -{ - uae_u16 v = clxdat | 0x8000; - //write_log("%d:CLXDAT %04.4X PC=%x\n", vpos, v, m68k_getpc()); - clxdat = 0; - return v; -} - -#ifdef AGA -static uae_u16 COLOR_READ (int num) -{ - int cr, cg, cb, colreg; - uae_u16 cval; - - if (!(currprefs.chipset_mask & CSMASK_AGA) || !(bplcon2 & 0x0100)) - return 0xffff; - - colreg = ((bplcon3 >> 13) & 7) * 32 + num; - cr = current_colors.color_regs_aga[colreg] >> 16; - cg = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF; - cb = current_colors.color_regs_aga[colreg] & 0xFF; - if (bplcon3 & 0x200) - cval = ((cr & 15) << 8) | ((cg & 15) << 4) | ((cb & 15) << 0); - else - cval = ((cr >> 4) << 8) | ((cg >> 4) << 4) | ((cb >> 4) << 0); - return cval; -} -#endif - -static void COLOR_WRITE (int hpos, uae_u16 v, int num) -{ - v &= 0xFFF; -#ifdef AGA - if (currprefs.chipset_mask & CSMASK_AGA) { - int r,g,b; - int cr,cg,cb; - int colreg; - uae_u32 cval; - - /* writing is disabled when RDRAM=1 */ - if (bplcon2 & 0x0100) - return; - - colreg = ((bplcon3 >> 13) & 7) * 32 + num; - r = (v & 0xF00) >> 8; - g = (v & 0xF0) >> 4; - b = (v & 0xF) >> 0; - cr = current_colors.color_regs_aga[colreg] >> 16; - cg = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF; - cb = current_colors.color_regs_aga[colreg] & 0xFF; - - if (bplcon3 & 0x200) { - cr &= 0xF0; cr |= r; - cg &= 0xF0; cg |= g; - cb &= 0xF0; cb |= b; - } else { - cr = r + (r << 4); - cg = g + (g << 4); - cb = b + (b << 4); - } - cval = (cr << 16) | (cg << 8) | cb; - if (cval == current_colors.color_regs_aga[colreg]) - return; - - /* Call this with the old table still intact. */ - record_color_change (hpos, colreg, cval); - remembered_color_entry = -1; - current_colors.color_regs_aga[colreg] = cval; - current_colors.acolors[colreg] = CONVERT_RGB (cval); - } else { -#endif - if (current_colors.color_regs_ecs[num] == v) - return; - /* Call this with the old table still intact. */ - record_color_change (hpos, num, v); - remembered_color_entry = -1; - current_colors.color_regs_ecs[num] = v; - current_colors.acolors[num] = xcolors[v]; -#ifdef AGA - } -#endif -} - -/* The copper code. The biggest nightmare in the whole emulator. - - Alright. The current theory: - 1. Copper moves happen 2 cycles after state READ2 is reached. - It can't happen immediately when we reach READ2, because the - data needs time to get back from the bus. An additional 2 - cycles are needed for non-Agnus registers, to take into account - the delay for moving data from chip to chip. - 2. As stated in the HRM, a WAIT really does need an extra cycle - to wake up. This is implemented by _not_ falling through from - a successful wait to READ1, but by starting the next cycle. - (Note: the extra cycle for the WAIT apparently really needs a - free cycle; i.e. contention with the bitplane fetch can slow - it down). - 3. Apparently, to compensate for the extra wake up cycle, a WAIT - will use the _incremented_ horizontal position, so the WAIT - cycle normally finishes two clocks earlier than the position - it was waiting for. The extra cycle then takes us to the - position that was waited for. - If the earlier cycle is busy with a bitplane, things change a bit. - E.g., waiting for position 0x50 in a 6 plane display: In cycle - 0x4e, we fetch BPL5, so the wait wakes up in 0x50, the extra cycle - takes us to 0x54 (since 0x52 is busy), then we have READ1/READ2, - and the next register write is at 0x5c. - 4. The last cycle in a line is not usable for the copper. - 5. A 4 cycle delay also applies to the WAIT instruction. This means - that the second of two back-to-back WAITs (or a WAIT whose - condition is immediately true) takes 8 cycles. - 6. This also applies to a SKIP instruction. The copper does not - fetch the next instruction while waiting for the second word of - a WAIT or a SKIP to arrive. - 7. A SKIP also seems to need an unexplained additional two cycles - after its second word arrives; this is _not_ a memory cycle (I - think, the documentation is pretty clear on this). - 8. Two additional cycles are inserted when writing to COPJMP1/2. */ - -/* Determine which cycles are available for the copper in a display - * with a agiven number of planes. */ - -int is_bitplane_dma (int hpos) -{ - if (fetch_state == fetch_not_started || hpos < thisline_decision.plfleft) - return 0; - if ((passed_plfstop == 3 && hpos >= thisline_decision.plfright) - || hpos >= estimated_last_fetch_cycle) - return 0; - return curr_diagram[(hpos - cycle_diagram_shift) & fetchstart_mask]; -} - -STATIC_INLINE int is_bitplane_dma_inline (int hpos) -{ - if (fetch_state == fetch_not_started || hpos < thisline_decision.plfleft) - return 0; - if ((passed_plfstop == 3 && hpos >= thisline_decision.plfright) - || hpos >= estimated_last_fetch_cycle) - return 0; - return curr_diagram[(hpos - cycle_diagram_shift) & fetchstart_mask]; -} - -STATIC_INLINE int copper_cant_read (int hpos) -{ - if (hpos + 1 >= maxhpos) - return 1; - return is_bitplane_dma_inline (hpos); -} - -STATIC_INLINE int dangerous_reg (int reg) -{ - /* Safe: - * Bitplane pointers, control registers, modulos and data. - * Sprite pointers, control registers, and data. - * Color registers. */ - if (reg >= 0xE0 && reg < 0x1C0) - return 0; - return 1; -} - -#define FAST_COPPER 1 - -/* The future, Conan? - We try to look ahead in the copper list to avoid doing continuous calls - to updat_copper (which is what happens when SPCFLAG_COPPER is set). If - we find that the same effect can be achieved by setting a delayed event - and then doing multiple copper insns in one batch, we can get a massive - speedup. - - We don't try to be precise here. All copper reads take exactly 2 cycles, - the effect of bitplane contention is ignored. Trying to get it exactly - right would be much more complex and as such carry a huge risk of getting - it subtly wrong; and it would also be more expensive - we want this code - to be fast. */ -static void predict_copper (void) -{ - uaecptr ip = cop_state.ip; - unsigned int c_hpos = cop_state.hpos; - enum copper_states state = cop_state.state; - unsigned int w1, w2, cycle_count; - - switch (state) { - case COP_read1_wr_in2: - case COP_read2_wr_in2: - case COP_read1_wr_in4: - if (dangerous_reg (cop_state.saved_i1)) - return; - state = state == COP_read2_wr_in2 ? COP_read2 : COP_read1; - break; - - case COP_read1_in2: - c_hpos += 2; - state = COP_read1; - break; - - case COP_stop: - case COP_bltwait: - case COP_wait1: - case COP_skip_in4: - case COP_skip_in2: - case COP_skip1: - case COP_strobe_delay: - return; - - case COP_wait_in4: - c_hpos += 2; - /* fallthrough */ - case COP_wait_in2: - c_hpos += 2; - /* fallthrough */ - case COP_wait: - state = COP_wait; - break; - - default: - break; - } - - /* Only needed for COP_wait, but let's shut up the compiler. */ - w1 = cop_state.saved_i1; - w2 = cop_state.saved_i2; - cop_state.first_sync = c_hpos; - cop_state.regtypes_modified = REGTYPE_FORCE; - - /* Get this case out of the way, so that the loop below only has to deal - with read1 and wait. */ - if (state == COP_read2) { - w1 = cop_state.i1; - if (w1 & 1) { - w2 = chipmem_wget (ip); - if (w2 & 1) - goto done; - state = COP_wait; - c_hpos += 4; - } else if (dangerous_reg (w1)) { - c_hpos += 4; - goto done; - } else { - cop_state.regtypes_modified |= regtypes[w1 & 0x1FE]; - state = COP_read1; - c_hpos += 2; - } - ip += 2; - } - - while (c_hpos + 1 < maxhpos) { - if (state == COP_read1) { - w1 = chipmem_wget (ip); - if (w1 & 1) { - w2 = chipmem_wget (ip + 2); - if (w2 & 1) - break; - state = COP_wait; - c_hpos += 6; - } else if (dangerous_reg (w1)) { - c_hpos += 6; - break; - } else { - cop_state.regtypes_modified |= regtypes[w1 & 0x1FE]; - c_hpos += 4; - } - ip += 4; - } else if (state == COP_wait) { - if ((w2 & 0xFE) != 0xFE) - break; - else { - unsigned int vcmp = (w1 & (w2 | 0x8000)) >> 8; - unsigned int hcmp = (w1 & 0xFE); - - unsigned int vp = vpos & (((w2 >> 8) & 0x7F) | 0x80); - if (vp < vcmp) { - /* Whee. We can wait until the end of the line! */ - c_hpos = maxhpos; - } else if (vp > vcmp || hcmp <= c_hpos) { - state = COP_read1; - /* minimum wakeup time */ - c_hpos += 2; - } else { - state = COP_read1; - c_hpos = hcmp; - } - /* If this is the current instruction, remember that we don't - need to sync CPU and copper anytime soon. */ - if (cop_state.ip == ip) { - cop_state.first_sync = c_hpos; - } - } - } else - uae_abort ("predict copper %d", state); - } - - done: - cycle_count = c_hpos - cop_state.hpos; - if (cycle_count >= 8) { - unset_special (SPCFLAG_COPPER); - eventtab[ev_copper].active = 1; - eventtab[ev_copper].oldcycles = get_cycles (); - eventtab[ev_copper].evtime = get_cycles () + cycle_count * CYCLE_UNIT; - events_schedule (); - } -} - -static int test_copper_dangerous (unsigned int address) -{ - if ((address & 0x1fe) < (copcon & 2 ? ((currprefs.chipset_mask & CSMASK_AGA) ? 0 : 0x40u) : 0x80u)) { - cop_state.state = COP_stop; - copper_enabled_thisline = 0; - unset_special (SPCFLAG_COPPER); - return 1; - } - return 0; -} - -static void perform_copper_write (int old_hpos) -{ - unsigned int address = cop_state.saved_i1 & 0x1FE; - - record_copper (cop_state.saved_ip - 4, old_hpos, vpos); - - if (test_copper_dangerous (address)) - return; - if (address == 0x88) { - cop_state.ip = cop1lc; - cop_state.state = COP_strobe_delay; - } else if (address == 0x8A) { - cop_state.ip = cop2lc; - cop_state.state = COP_strobe_delay; - } else - custom_wput_1 (old_hpos, cop_state.saved_i1, cop_state.saved_i2, 0); -} - -static int isagnus[]= { - 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* 32 0x00 - 0x3e */ - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 27 0x40 - 0x74 */ - 0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0, /* 21 */ - 1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0, /* 32 0xa0 - 0xde - /* BPLxPTH/BPLxPTL */ - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 16 */ - 0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0, /* 16 */ - /* SPRxPTH/SPRxPTL */ - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 16 */ - /* SPRxPOS/SPRxCTL/SPRxDATA/SPRxDATB */ - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - /* COLORxx */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - /* RESERVED */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -}; - -static void dump_copper (char *error, int until_hpos) -{ - write_log("%s: vpos=%d until_hpos=%d\n", - error, vpos, until_hpos); - write_log("cvcmp=%d chcmp=%d chpos=%d cvpos=%d ci1=%04.4X ci2=%04.4X\n", - cop_state.vcmp,cop_state.hcmp,cop_state.hpos,cop_state.vpos,cop_state.saved_i1,cop_state.saved_i2); - write_log("cstate=%d ip=%08.8X ev_copper=%d\n", - cop_state.state,cop_state.ip,eventtab[ev_copper].active); -} - -static void update_copper (int until_hpos) -{ - int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80); - int c_hpos = cop_state.hpos; - - if (eventtab[ev_copper].active) { - static int warned; - if (!warned) { - dump_copper ("error1",until_hpos); - warned = 1; - } - eventtab[ev_copper].active = 0; - return; - uae_abort ("update_copper1"); - } - - if (cop_state.state == COP_wait && vp < cop_state.vcmp) { - static int warned; - if (!warned) { - dump_copper ("error2",until_hpos); - warned = 1; - } - copper_enabled_thisline = 0; - return; - uae_abort ("update_copper2"); - } - - until_hpos &= ~1; - - if (until_hpos > (maxhpos & ~1)) - until_hpos = maxhpos & ~1; - - until_hpos += 2; - for (;;) { - int old_hpos = c_hpos; - int hp; - - if (c_hpos >= until_hpos) - break; - - /* So we know about the fetch state. */ - decide_line (c_hpos); - - switch (cop_state.state) { - case COP_read1_in2: - cop_state.state = COP_read1; - break; - case COP_read1_wr_in2: - cop_state.state = COP_read1; - perform_copper_write (old_hpos); - /* That could have turned off the copper. */ - if (! copper_enabled_thisline) - goto out; - - break; - case COP_read1_wr_in4: - cop_state.state = COP_read1_wr_in2; - break; - case COP_read2_wr_in2: - cop_state.state = COP_read2; - perform_copper_write (old_hpos); - /* That could have turned off the copper. */ - if (! copper_enabled_thisline) - goto out; - - break; - case COP_wait_in2: - cop_state.state = COP_wait1; - break; - case COP_wait_in4: - cop_state.state = COP_wait_in2; - break; - case COP_skip_in2: - cop_state.state = COP_skip1; - break; - case COP_skip_in4: - cop_state.state = COP_skip_in2; - break; - case COP_strobe_delay: - cop_state.state = COP_read1; - break; - - default: - break; - } - - c_hpos += 2; -#if 0 - if (copper_cant_read (old_hpos)) - continue; -#endif - if (cop_state.strobe) { - cop_state.ip = cop_state.strobe == 1 ? cop1lc : cop2lc; - cop_state.strobe = 0; - } - - switch (cop_state.state) { - - case COP_read1_wr_in4: - uae_abort ("COP_read1_wr_in4"); - - case COP_read1_wr_in2: - case COP_read1: - if (copper_cant_read (old_hpos)) - continue; - cop_state.i1 = chipmem_wget (cop_state.ip); -#ifdef CPUEMU_6 - cycle_line[old_hpos] |= CYCLE_COPPER; -#endif - cop_state.ip += 2; - cop_state.state = cop_state.state == COP_read1 ? COP_read2 : COP_read2_wr_in2; - break; - - case COP_read2_wr_in2: - uae_abort ("read2_wr_in2"); - - case COP_read2: - if (copper_cant_read (old_hpos)) - continue; - cop_state.i2 = chipmem_wget (cop_state.ip); -#ifdef CPUEMU_6 - cycle_line[old_hpos] |= CYCLE_COPPER; -#endif - cop_state.ip += 2; - if (cop_state.ignore_next) { - cop_state.ignore_next = 0; - cop_state.state = COP_read1; - break; - } - - cop_state.saved_i1 = cop_state.i1; - cop_state.saved_i2 = cop_state.i2; - cop_state.saved_ip = cop_state.ip; - - if (cop_state.i1 & 1) { - if (cop_state.i2 & 1) - cop_state.state = COP_skip_in4; - else - cop_state.state = COP_wait_in4; - } else { - unsigned int reg = cop_state.i1 & 0x1FE; - cop_state.state = isagnus[reg >> 1] ? COP_read1_wr_in2 : COP_read1_wr_in4; - } - break; - - case COP_wait1: - /* There's a nasty case here. As stated in the "Theory" comment above, we - test against the incremented copper position. I believe this means that - we have to increment the _vertical_ position at the last cycle in the line, - and set the horizontal position to 0. - Normally, this isn't going to make a difference, since we consider these - last cycles unavailable for the copper, so waking up in the last cycle has - the same effect as waking up at the start of the line. However, there is - one possible problem: If we're at 0xFFE0, any wait for an earlier position - must _not_ complete (since, in effect, the current position will be back - at 0/0). This can be seen in the Superfrog copper list. - Things get monstrously complicated if we try to handle this "properly" by - incrementing vpos and setting c_hpos to 0. Especially the various speedup - hacks really assume that vpos remains constant during one line. Hence, - this hack: defer the entire decision until the next line if necessary. */ - if (c_hpos >= (maxhpos & ~1)) - break; - - cop_state.state = COP_wait; - - cop_state.vcmp = (cop_state.saved_i1 & (cop_state.saved_i2 | 0x8000)) >> 8; - cop_state.hcmp = (cop_state.saved_i1 & cop_state.saved_i2 & 0xFE); - - vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80); - - if (cop_state.saved_i1 == 0xFFFF && cop_state.saved_i2 == 0xFFFE) { - cop_state.state = COP_stop; - copper_enabled_thisline = 0; - unset_special (SPCFLAG_COPPER); - goto out; - } - if (vp < cop_state.vcmp) { - copper_enabled_thisline = 0; - unset_special (SPCFLAG_COPPER); - goto out; - } - - /* fall through */ - case COP_wait: - if (vp < cop_state.vcmp) - uae_abort ("vp < cop_state.vcmp"); - if (copper_cant_read (old_hpos)) - continue; - - hp = c_hpos & (cop_state.saved_i2 & 0xFE); - if (vp == cop_state.vcmp && hp < cop_state.hcmp) { - /* Position not reached yet. */ - if (currprefs.fast_copper && FAST_COPPER && (cop_state.saved_i2 & 0xFE) == 0xFE) { - int wait_finish = cop_state.hcmp - 2; - /* This will leave c_hpos untouched if it's equal to wait_finish. */ - if (wait_finish < c_hpos) - uae_abort ("wait_finish < c_hpos"); - else if (wait_finish <= until_hpos) { - c_hpos = wait_finish; - } else - c_hpos = until_hpos; - } - break; - } - - /* Now we know that the comparisons were successful. We might still - have to wait for the blitter though. */ - if ((cop_state.saved_i2 & 0x8000) == 0 && (DMACONR() & 0x4000)) { - /* We need to wait for the blitter. */ - cop_state.state = COP_bltwait; - copper_enabled_thisline = 0; - unset_special (SPCFLAG_COPPER); - goto out; - } - - record_copper (cop_state.ip - 4, old_hpos, vpos); - - cop_state.state = COP_read1; - break; - - case COP_skip1: - { - static int skipped_before; - unsigned int vcmp, hcmp, vp1, hp1; - - if (! skipped_before) { - skipped_before = 1; - write_log ("Program uses Copper SKIP instruction.\n"); - } - - if (c_hpos >= (maxhpos & ~1)) - break; - - vcmp = (cop_state.saved_i1 & (cop_state.saved_i2 | 0x8000)) >> 8; - hcmp = (cop_state.saved_i1 & cop_state.saved_i2 & 0xFE); - vp1 = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80); - hp1 = c_hpos & (cop_state.saved_i2 & 0xFE); - - if ((vp1 > vcmp || (vp1 == vcmp && hp1 >= hcmp)) - && ((cop_state.saved_i2 & 0x8000) != 0 || ! (DMACONR() & 0x4000))) - cop_state.ignore_next = 1; - if (chipmem_wget (cop_state.ip) & 1) { /* FIXME: HACK!!! */ - /* copper never skips if following instruction is WAIT or another SKIP... */ - cop_state.ignore_next = 0; - } - - cop_state.state = COP_read1; - - if (cop_state.ignore_next && (chipmem_wget (cop_state.ip) & 1) == 0) { - /* another undocumented copper feature: - copper stops if skipped instruction is MOVE to dangerous register... - */ - test_copper_dangerous (chipmem_wget(cop_state.ip)); - } - - record_copper (cop_state.ip - 4, old_hpos, vpos); - - break; - } - default: - break; - } - } - - out: - cop_state.hpos = c_hpos; - - /* The test against maxhpos also prevents us from calling predict_copper - when we are being called from hsync_handler, which would not only be - stupid, but actively harmful. */ - if (currprefs.fast_copper && FAST_COPPER && (regs.spcflags & SPCFLAG_COPPER) && c_hpos + 8 < maxhpos) - predict_copper (); -} - -static void compute_spcflag_copper (void) -{ - copper_enabled_thisline = 0; - unset_special (SPCFLAG_COPPER); - if (! dmaen (DMA_COPPER) || cop_state.state == COP_stop || cop_state.state == COP_bltwait) - return; - - if (cop_state.state == COP_wait) { - int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80); - - if (vp < cop_state.vcmp) - return; - } - copper_enabled_thisline = 1; - - if (currprefs.fast_copper && FAST_COPPER) - predict_copper (); - - if (! eventtab[ev_copper].active) - set_special (SPCFLAG_COPPER); -} - -static void copper_handler (void) -{ - /* This will take effect immediately, within the same cycle. */ - set_special (SPCFLAG_COPPER); - - if (! copper_enabled_thisline) - uae_abort ("copper_handler"); - - eventtab[ev_copper].active = 0; -} - -void blitter_done_notify (void) -{ - if (cop_state.state != COP_bltwait) - return; - - cop_state.hpos = current_hpos () & ~1; - cop_state.vpos = vpos; - cop_state.state = COP_wait; - compute_spcflag_copper (); -} - -void do_copper (void) -{ - int hpos = current_hpos (); - update_copper (hpos); -} - -/* ADDR is the address that is going to be read/written; this access is - the reason why we want to update the copper. This function is also - used from hsync_handler to finish up the line; for this case, we check - hpos against maxhpos. */ -STATIC_INLINE void sync_copper_with_cpu (int hpos, int do_schedule, unsigned int addr) -{ - /* Need to let the copper advance to the current position. */ - if (eventtab[ev_copper].active) { - if (hpos != maxhpos) { - /* There might be reasons why we don't actually need to bother - updating the copper. */ - if (hpos < cop_state.first_sync) - return; - - if ((cop_state.regtypes_modified & regtypes[addr & 0x1FE]) == 0) - return; - } - - eventtab[ev_copper].active = 0; - if (do_schedule) - events_schedule (); - set_special (SPCFLAG_COPPER); - } - if (copper_enabled_thisline) - update_copper (hpos); -} - -STATIC_INLINE uae_u16 sprite_fetch (struct sprite *s, int dma, int hpos) -{ - uae_u16 data = last_custom_value; - if (dma) { - data = last_custom_value = chipmem_wget (s->pt); -#ifdef CPUEMU_6 - cycle_line[hpos] |= CYCLE_SPRITE; -#endif - } - s->pt += 2; - return data; -} - -STATIC_INLINE void do_sprites_1 (int num, int cycle, int hpos) -{ - struct sprite *s = &spr[num]; - int dma, posctl = 0; - uae_u16 data; - - if (vpos == s->vstart) { - s->dmastate = 1; -#if SPRITE_DEBUG > 0 - write_log ("%d:SPR%d START\n", vpos, num); -#endif - } - if (vpos == s->vstop || vpos == sprite_vblank_endline) { - s->dmastate = 0; -#if SPRITE_DEBUG > 0 - write_log ("%d:SPR%d STOP\n", vpos, num); -#endif - } - if (!dmaen (DMA_SPRITE)) - return; - dma = hpos < plfstrt || diwstate != DIW_waiting_stop || !dmaen (DMA_BITPLANE); - if (vpos == s->vstop || vpos == sprite_vblank_endline) { - s->dmastate = 0; - posctl = 1; - if (dma) { - data = sprite_fetch (s, dma, hpos); - s->pt += (sprite_width >> 3) - 2; - } else { - data = cycle == 0 ? sprpos[num] : sprctl[num]; - } -#if SPRITE_DEBUG > 1 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) { - write_log ("dma:"); - } -#endif - if (cycle == 0) - SPRxPOS_1 (data, num, hpos); - else - SPRxCTL_1 (data, num, hpos); - } - if (s->dmastate && !posctl) { - uae_u16 data = sprite_fetch (s, dma, hpos); - /* Hack for X mouse auto-calibration */ - if (num == 0 && cycle == 0) - mousehack_handle (sprctl[0], sprpos[0]); -#if SPRITE_DEBUG > 1 - if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY) { - write_log ("dma:"); - } -#endif - if (cycle == 0) - SPRxDATA_1 (dma ? data : sprdata[num][0], num, hpos); - else - SPRxDATB_1 (dma ? data : sprdatb[num][0], num, hpos); -#ifdef AGA - switch (sprite_width) - { - case 64: - { - uae_u16 data32 = sprite_fetch (s, dma, hpos); - uae_u16 data641 = sprite_fetch (s, dma, hpos); - uae_u16 data642 = sprite_fetch (s, dma, hpos); - if (dma) { - if (cycle == 0) { - sprdata[num][3] = data642; - sprdata[num][2] = data641; - sprdata[num][1] = data32; - } else { - sprdatb[num][3] = data642; - sprdatb[num][2] = data641; - sprdatb[num][1] = data32; - } - } - } - break; - case 32: - { - uae_u16 data32 = sprite_fetch (s, dma, hpos); - if (dma) { - if (cycle == 0) - sprdata[num][1] = data32; - else - sprdatb[num][1] = data32; - } - } - break; - } -#endif - } -} - -static void do_sprites (int hpos) -{ - int maxspr, minspr; - int i; - - /* I don't know whether this is right. Some programs write the sprite pointers - * directly at the start of the copper list. With the test against currvp, the - * first two words of data are read on the second line in the frame. The problem - * occurs when the program jumps to another copperlist a few lines further down - * which _also_ writes the sprite pointer registers. This means that a) writing - * to the sprite pointers sets the state to SPR_restart; or b) that sprite DMA - * 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 - * 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. */ - /* Another update: seems like we have to use the NTSC value here (see Sanity Turmoil - * demo). */ - /* Maximum for Sanity Turmoil: 27. - Minimum for Sanity Arte: 22. */ - if (vpos < sprite_vblank_endline) - return; - -#ifndef CUSTOM_SIMPLE - maxspr = hpos; - minspr = last_sprite_hpos; - - if (minspr >= SPR0_HPOS + MAX_SPRITES * 4 || maxspr < SPR0_HPOS) - return; - - if (maxspr > SPR0_HPOS + MAX_SPRITES * 4) - maxspr = SPR0_HPOS + MAX_SPRITES * 4; - if (minspr < SPR0_HPOS) - minspr = SPR0_HPOS; - - for (i = minspr; i < maxspr; i++) { - int cycle = -1; - switch ((i - SPR0_HPOS) & 3) - { - case 0: - cycle = 0; - break; - case 2: - cycle = 1; - break; - } - if (cycle >= 0) - do_sprites_1 ((i - SPR0_HPOS) / 4, cycle, i); - } - last_sprite_hpos = hpos; -#else - for (i = 0; i < MAX_SPRITES * 2; i++) - do_sprites_1 (i / 2, i & 1, 0); -#endif -} - -static void init_sprites (void) -{ - memset (sprpos, 0, sizeof sprpos); - memset (sprctl, 0, sizeof sprctl); -} - -static void adjust_array_sizes (void) -{ -#ifdef OS_WITHOUT_MEMORY_MANAGEMENT - if (delta_sprite_entry) { - void *p1,*p2; - int mcc = max_sprite_entry + 50 + delta_sprite_entry; - delta_sprite_entry = 0; - p1 = realloc (sprite_entries[0], mcc * sizeof (struct sprite_entry)); - p2 = realloc (sprite_entries[1], mcc * sizeof (struct sprite_entry)); - if (p1) sprite_entries[0] = p1; - if (p2) sprite_entries[1] = p2; - if (p1 && p2) { - write_log ("new max_sprite_entry=%d\n",mcc); - max_sprite_entry = 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) { - write_log ("new max_color_change=%d\n",mcc); - max_color_change = mcc; - } - } -#endif -} - -static void init_hardware_frame (void) -{ - next_lineno = 0; - nextline_how = nln_normal; - diwstate = DIW_waiting_start; - hdiwstate = DIW_waiting_start; - ddfstate = DIW_waiting_start; -} - -void init_hardware_for_drawing_frame (void) -{ - adjust_array_sizes (); - - /* Avoid this code in the first frame after a customreset. */ - if (prev_sprite_entries) { - int first_pixel = prev_sprite_entries[0].first_pixel; - int npixels = prev_sprite_entries[prev_next_sprite_entry].first_pixel - first_pixel; - memset (spixels + first_pixel, 0, npixels * sizeof *spixels); - memset (spixstate.bytes + first_pixel, 0, npixels * sizeof *spixstate.bytes); - } - prev_next_sprite_entry = next_sprite_entry; - - next_color_change = 0; - next_sprite_entry = 0; - next_color_entry = 0; - remembered_color_entry = -1; - - prev_sprite_entries = sprite_entries[current_change_set]; - curr_sprite_entries = sprite_entries[current_change_set ^ 1]; - prev_color_changes = color_changes[current_change_set]; - 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]; - current_change_set ^= 1; - - color_src_match = color_dest_match = -1; - - /* Use both halves of the array in alternating fashion. */ - curr_sprite_entries[0].first_pixel = current_change_set * MAX_SPR_PIXELS; - next_sprite_forced = 1; -} - -static void do_savestate(void); - -static int rpt_vsync (void) -{ - int v = read_processor_time () - vsyncmintime; - if (v > (int)syncbase || v < -((int)syncbase)) { - vsyncmintime = read_processor_time(); - v = 0; - } - return v; -} - -static void framewait (void) -{ - frame_time_t curr_time; - int start; - - for (;;) { - double v = rpt_vsync () / (syncbase / 1000.0); - if (v >= -4) - break; - sleep_millis_busy (1); - } - start = read_processor_time(); - do { - curr_time = read_processor_time (); - } while (rpt_vsync () < 0); - vsyncmintime = curr_time + vsynctime; - idletime += read_processor_time() - start; -} - -static int frametime2; - -void fpscounter_reset (void) -{ - timeframes = 0; - frametime2 = 0; - bogusframe = 2; - lastframetime = read_processor_time (); - idletime = 0; -} - -static void fpscounter (void) -{ - int now, last; - - now = read_processor_time (); - last = now - lastframetime; - lastframetime = now; - - if (bogusframe) - return; - - frametime += last; - frametime2 += last; - timeframes++; - if ((timeframes & 31) == 0) { - double idle = 1000 - (idletime == 0 ? 0.0 : (double)idletime * 1000.0 / (vsynctime * 32.0)); - int fps = frametime2 == 0 ? 0 : syncbase * 32 / (frametime2 / 10); - if (fps > 9999) - fps = 9999; - if (idle < 0) - idle = 0; - if (idle > 100 * 10) - idle = 100 * 10; - if (fake_vblank_hz * 10 > fps) { - double mult = (double)fake_vblank_hz * 10.0 / fps; - idle *= mult; - } - if (turbo_emulation && idle < 100 * 10) - idle = 100 * 10; - gui_fps (fps, (int)idle); - frametime2 = 0; - idletime = 0; - } -} - -static void vsync_handler (void) -{ - fpscounter (); - - if ((!currprefs.gfx_vsync || !currprefs.gfx_afullscreen) -#ifdef AVIOUTPUT - && ((avioutput_framelimiter && avioutput_enabled) || !avioutput_enabled) -#endif - ) { -#ifdef JIT - if (!compiled_code) { -#endif - if (currprefs.m68k_speed == -1) { - 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 || rpt_did_reset) - vsyncmintime = curr_time + vsynctime; - rpt_did_reset = 0; - } else if (rpt_available) { - framewait (); - } -#ifdef JIT - } else { - if (rpt_available && currprefs.m68k_speed == 0) { - framewait (); - } - } -#endif - } - - if (bogusframe > 0) - bogusframe--; - - handle_events (); - - INTREQ (0x8020); - if (bplcon0 & 4) - lof ^= 0x8000; - -#ifdef PICASSO96 - /* And now let's update the Picasso palette, if required */ - DX_SetPalette_vsync(); - if (picasso_on) - picasso_handle_vsync (); -#endif - - vsync_handle_redraw (lof, lof_changed); - - if (quit_program > 0) { - /* prevent possible infinite loop at wait_cycles().. */ - framecnt = 0; - reset_decisions (); - return; - } - - { - static int cnt = 0; - if (cnt == 0) { - /* resolution_check_change (); */ - DISK_check_change (); - cnt = 5; - } - cnt--; - } - - /* Start a new set of copper records. */ - curr_cop_set ^= 1; - nr_cop_records[curr_cop_set] = 0; - - /* For now, let's only allow this to change at vsync time. It gets too - * hairy otherwise. */ - if ((beamcon0 & (0x20|0x80)) != (new_beamcon0 & (0x20|0x80)) || hack_vpos) - init_hz (); - - lof_changed = 0; - - eventtab[ev_copper].active = 0; - COPJMP (1); - - init_hardware_frame (); - - if (ievent_alive > 0) - ievent_alive--; - if (timehack_alive > 0) - timehack_alive--; - inputdevice_vsync (); - -} - -#ifdef JIT - -#define N_LINES 8 - -static __inline__ int trigger_frh(int v) -{ - return (v & (N_LINES - 1)) == 0; -} - -extern int gonebad; - -static long int diff32(frame_time_t x, frame_time_t y) -{ - return (long int)(x-y); -} -static void frh_handler(void) -{ - if (currprefs.m68k_speed == -1) { - frame_time_t curr_time = read_processor_time (); - vsyncmintime += vsynctime * N_LINES / maxvpos; - /* @@@ 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 (rpt_did_reset) { - vsyncmintime = curr_time + vsynctime; - rpt_did_reset = 0; - } - /* Allow this to be one frame's worth of cycles out */ - while (diff32 (curr_time, vsyncmintime + vsynctime) > 0) { - vsyncmintime += vsynctime * N_LINES / maxvpos; - gonebad++; - if (turbo_emulation) - break; - } - } -} -#endif - -static void copper_check (int n) -{ - if (cop_state.state == COP_wait) { - int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80); - if (vp < cop_state.vcmp) { - if (eventtab[ev_copper].active || copper_enabled_thisline) - write_log ("COPPER BUG %d: vp=%d vpos=%d vcmp=%d act=%d thisline=%d\n", n, vp, vpos, cop_state.vcmp, eventtab[ev_copper].active, copper_enabled_thisline); - } - } -} - -static void hsync_handler (void) -{ - static int ciahsync; - int hpos = current_hpos (); - - /* Using 0x8A makes sure that we don't accidentally trip over the - modified_regtypes check. */ - sync_copper_with_cpu (maxhpos, 0, 0x8A); - - //copper_check (1); - - finish_decisions (); - if (thisline_decision.plfleft != -1) { - if (currprefs.collision_level > 1) - do_sprite_collisions (); - if (currprefs.collision_level > 2) - do_playfield_collisions (); - } - hsync_record_line_state (next_lineno, nextline_how, thisline_changed); - - eventtab[ev_hsync].evtime += get_cycles () - eventtab[ev_hsync].oldcycles; - eventtab[ev_hsync].oldcycles = get_cycles (); - CIA_hsync_handler (); -#ifdef CD32 - AKIKO_hsync_handler (); -#endif - -#ifdef PICASSO96 - picasso_handle_hsync (); -#endif - ciahsync++; - if (ciahsync >= (currprefs.ntscmode ? MAXVPOS_NTSC : MAXVPOS_PAL) * MAXHPOS_PAL / maxhpos) { /* not so perfect.. */ - CIA_vsync_handler (); - ciahsync = 0; - } - -#ifdef CPUEMU_6 - if (currprefs.cpu_cycle_exact || currprefs.blitter_cycle_exact) { - decide_blitter (hpos); - memset (cycle_line, 0, MAXHPOS); - cycle_line[maxhpos - 1] = CYCLE_REFRESH; - cycle_line[0] = CYCLE_REFRESH; - cycle_line[2] = CYCLE_REFRESH; - cycle_line[4] = CYCLE_REFRESH; - } -#endif - if ((currprefs.chipset_mask & CSMASK_AGA) || (!currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - last_custom_value = rand (); - else - last_custom_value = 0xffff; - - if (!currprefs.blitter_cycle_exact && bltstate != BLT_done && dmaen (DMA_BITPLANE) && diwstate == DIW_waiting_stop) - blitter_slowdown (ddfstrt, ddfstop, cycle_diagram_total_cycles[fmode][GET_RES (bplcon0)][GET_PLANES (bplcon0)], - cycle_diagram_free_cycles[fmode][GET_RES (bplcon0)][GET_PLANES (bplcon0)]); - - if (currprefs.produce_sound) - audio_hsync (1); - - hardware_line_completed (next_lineno); - - /* In theory only an equality test is needed here - but if a program - goes haywire with the VPOSW register, it can cause us to miss this, - with vpos going into the thousands (and all the nasty consequences - this has). */ - - if (++vpos >= (maxvpos + (lof == 0 ? 0 : 1))) { - vpos = 0; - vsync_handler (); - } - - DISK_update (maxhpos); - -#ifdef JIT - if (compiled_code) { - if (currprefs.m68k_speed == -1) { - static int count=0; - - count++; - if (trigger_frh(count)) { - frh_handler(); - } - is_lastline = trigger_frh(count+1) && ! rpt_did_reset; - } - else - is_lastline=0; - } else { -#endif - is_lastline = vpos + 1 == maxvpos + (lof == 0 ? 0 : 1) && currprefs.m68k_speed == -1 && ! rpt_did_reset; -#ifdef JIT - } -#endif - - if ((bplcon0 & 4) && currprefs.gfx_linedbl) - notice_interlace_seen (); - - if (framecnt == 0) { - int lineno = vpos; - nextline_how = nln_normal; - if (currprefs.gfx_linedbl) { - lineno *= 2; - nextline_how = currprefs.gfx_linedbl == 1 ? nln_doubled : nln_nblack; - if (bplcon0 & 4) { - if (!lof) { - lineno++; - nextline_how = nln_lower; - } else { - nextline_how = nln_upper; - } - } - } - next_lineno = lineno; - reset_decisions (); - } -#ifdef FILESYS - if (uae_int_requested) { - set_uae_int_flag (); - INTREQ (0x8000 | 0x0008); - } -#endif - /* See if there's a chance of a copper wait ending this line. */ - cop_state.hpos = 0; - compute_spcflag_copper (); - inputdevice_hsync (); - serial_hsynchandler (); -#ifdef CUSTOM_SIMPLE - do_sprites (0); -#endif - //copper_check (2); -} - -static void init_regtypes (void) -{ - int i; - for (i = 0; i < 512; i += 2) { - regtypes[i] = REGTYPE_ALL; - if ((i >= 0x20 && i < 0x28) || i == 0x08 || i == 0x7E) - regtypes[i] = REGTYPE_DISK; - else if (i >= 0x68 && i < 0x70) - regtypes[i] = REGTYPE_NONE; - else if (i >= 0x40 && i < 0x78) - regtypes[i] = REGTYPE_BLITTER; - else if (i >= 0xA0 && i < 0xE0 && (i & 0xF) < 0xE) - regtypes[i] = REGTYPE_AUDIO; - else if (i >= 0xA0 && i < 0xE0) - regtypes[i] = REGTYPE_NONE; - else if (i >= 0xE0 && i < 0x100) - regtypes[i] = REGTYPE_PLANE; - else if (i >= 0x120 && i < 0x180) - regtypes[i] = REGTYPE_SPRITE; - else if (i >= 0x180 && i < 0x1C0) - regtypes[i] = REGTYPE_COLOR; - else switch (i) { - case 0x02: - /* DMACONR - setting this to REGTYPE_BLITTER will cause it to - conflict with DMACON (since that is REGTYPE_ALL), and the - blitter registers (for the BBUSY bit), but nothing else, - which is (I think) what we want. */ - regtypes[i] = REGTYPE_BLITTER; - break; - case 0x04: case 0x06: case 0x2A: case 0x2C: - regtypes[i] = REGTYPE_POS; - break; - case 0x0A: case 0x0C: - case 0x12: case 0x14: case 0x16: - case 0x36: - regtypes[i] = REGTYPE_JOYPORT; - break; - case 0x104: - case 0x102: - regtypes[i] = REGTYPE_PLANE; - break; - case 0x88: case 0x8A: - case 0x8E: case 0x90: case 0x92: case 0x94: - case 0x96: - case 0x100: - regtypes[i] |= REGTYPE_FORCE; - break; - } - } -} - -void init_eventtab (void) -{ - int i; - - nextevent = 0; - set_cycles (0); - for (i = 0; i < ev_max; i++) { - eventtab[i].active = 0; - eventtab[i].oldcycles = 0; - } - - eventtab[ev_cia].handler = CIA_handler; - eventtab[ev_hsync].handler = hsync_handler; - eventtab[ev_hsync].evtime = get_cycles () + HSYNCTIME; - eventtab[ev_hsync].active = 1; - - eventtab[ev_copper].handler = copper_handler; - eventtab[ev_copper].active = 0; - eventtab[ev_blitter].handler = blitter_handler; - eventtab[ev_blitter].active = 0; - eventtab[ev_disk].handler = DISK_handler; - eventtab[ev_disk].active = 0; - eventtab[ev_audio].handler = audio_evhandler; - eventtab[ev_audio].active = 0; - events_schedule (); -} - -void customreset (void) -{ - int i; - int zero = 0; - - write_log ("reset at %x\n", m68k_getpc()); - if (! savestate_state) { - currprefs.chipset_mask = changed_prefs.chipset_mask; - if ((currprefs.chipset_mask & CSMASK_AGA) == 0) { - for (i = 0; i < 32; i++) { - current_colors.color_regs_ecs[i] = 0; - current_colors.acolors[i] = xcolors[0]; - } -#ifdef AGA - } else { - for (i = 0; i < 256; i++) { - current_colors.color_regs_aga[i] = 0; - current_colors.acolors[i] = CONVERT_RGB (zero); - } -#endif - } - - clxdat = 0; - - /* Clear the armed flags of all sprites. */ - memset (spr, 0, sizeof spr); - nr_armed = 0; - - dmacon = intena = 0; - - copcon = 0; - DSKLEN (0, 0); - - bplcon0 = 0; - bplcon4 = 0x11; /* Get AGA chipset into ECS compatibility mode */ - bplcon3 = 0xC00; - - FMODE (0); - CLXCON (0); - } - -#ifdef AUTOCONFIG - expamem_reset (); -#endif - a1000_reset (); - DISK_reset (); - CIA_reset (); -#ifdef JIT - compemu_reset (); -#endif - unset_special (~(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)); - - vpos = 0; - - if (needmousehack ()) { -#if 0 - mousehack_set (mousehack_follow); -#else - mousehack_set (mousehack_dontcare); -#endif - } else { - mousehack_set (mousehack_normal); - } - ievent_alive = 0; - timehack_alive = 0; - - curr_sprite_entries = 0; - prev_sprite_entries = 0; - sprite_entries[0][0].first_pixel = 0; - sprite_entries[1][0].first_pixel = MAX_SPR_PIXELS; - sprite_entries[0][1].first_pixel = 0; - sprite_entries[1][1].first_pixel = MAX_SPR_PIXELS; - memset (spixels, 0, sizeof spixels); - memset (&spixstate, 0, sizeof spixstate); - - bltstate = BLT_done; - cop_state.state = COP_stop; - diwstate = DIW_waiting_start; - hdiwstate = DIW_waiting_start; - set_cycles (0); - - new_beamcon0 = currprefs.ntscmode ? 0x00 : 0x20; - hack_vpos = 0; - init_hz (); - - audio_reset (); - if (savestate_state != STATE_RESTORE) { - /* must be called after audio_reset */ - adkcon = 0; - serial_uartbreak (0); - update_adkmasks (); - } - - init_sprites (); - - init_hardware_frame (); - drawing_init (); - - reset_decisions (); - - bogusframe = 1; - - init_regtypes (); - - sprite_buffer_res = currprefs.chipset_mask & CSMASK_AGA ? RES_HIRES : RES_LORES; - if (savestate_state == STATE_RESTORE) { - uae_u16 v; - uae_u32 vv; - - update_adkmasks (); - INTENA (0); - INTREQ (0); -#if 0 - DMACON (0, 0); -#endif - COPJMP (1); - v = bplcon0; - BPLCON0 (0, 0); - BPLCON0 (0, v); - FMODE (fmode); - if (!(currprefs.chipset_mask & CSMASK_AGA)) { - for(i = 0 ; i < 32 ; i++) { - vv = current_colors.color_regs_ecs[i]; - current_colors.color_regs_ecs[i] = -1; - record_color_change (0, i, vv); - remembered_color_entry = -1; - current_colors.color_regs_ecs[i] = vv; - current_colors.acolors[i] = xcolors[vv]; - } -#ifdef AGA - } else { - for(i = 0 ; i < 256 ; i++) { - vv = current_colors.color_regs_aga[i]; - current_colors.color_regs_aga[i] = -1; - record_color_change (0, i, vv); - remembered_color_entry = -1; - current_colors.color_regs_aga[i] = vv; - current_colors.acolors[i] = CONVERT_RGB(vv); - } -#endif - } - CLXCON (clxcon); - CLXCON2 (clxcon2); - calcdiw (); - write_log ("State restored\n"); - dumpcustom (); - for (i = 0; i < 8; i++) - nr_armed += spr[i].armed != 0; - } - expand_sprres (); - - #ifdef ACTION_REPLAY - /* Doing this here ensures we can use the 'reset' command from within AR */ - action_replay_reset (); - #endif - #ifdef WIN32 - #ifndef UAE_MINI - enforcer_disable(); - #endif - #endif -} - -void dumpcustom (void) -{ - write_log ("DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR(), - (unsigned int)intena, (unsigned int)intreq, (unsigned int)vpos, (unsigned int)current_hpos()); - write_log ("COP1LC: %08lx, COP2LC: %08lx COPPTR: %08lx\n", (unsigned long)cop1lc, (unsigned long)cop2lc, cop_state.ip); - write_log ("DIWSTRT: %04x DIWSTOP: %04x DDFSTRT: %04x DDFSTOP: %04x\n", - (unsigned int)diwstrt, (unsigned int)diwstop, (unsigned int)ddfstrt, (unsigned int)ddfstop); - write_log ("BPLCON 0: %04x 1: %04x 2: %04x 3: %04x 4: %04x\n", bplcon0, bplcon1, bplcon2, bplcon3, bplcon4); - if (timeframes) { - write_log ("Average frame time: %f ms [frames: %d time: %d]\n", - (double)frametime / timeframes, timeframes, frametime); - if (total_skipped) - write_log ("Skipped frames: %d\n", total_skipped); - } - /*for (i=0; i<256; i++) if (blitcount[i]) write_log ("minterm %x = %d\n",i,blitcount[i]); blitter debug */ -} - -static void gen_custom_tables (void) -{ - int i; - for (i = 0; i < 256; i++) { - sprtaba[i] = ((((i >> 7) & 1) << 0) - | (((i >> 6) & 1) << 2) - | (((i >> 5) & 1) << 4) - | (((i >> 4) & 1) << 6) - | (((i >> 3) & 1) << 8) - | (((i >> 2) & 1) << 10) - | (((i >> 1) & 1) << 12) - | (((i >> 0) & 1) << 14)); - sprtabb[i] = sprtaba[i] * 2; - sprite_ab_merge[i] = (((i & 15) ? 1 : 0) - | ((i & 240) ? 2 : 0)); - } - for (i = 0; i < 16; i++) { - clxmask[i] = (((i & 1) ? 0xF : 0x3) - | ((i & 2) ? 0xF0 : 0x30) - | ((i & 4) ? 0xF00 : 0x300) - | ((i & 8) ? 0xF000 : 0x3000)); - sprclx[i] = (((i & 0x3) == 0x3 ? 1 : 0) - | ((i & 0x5) == 0x5 ? 2 : 0) - | ((i & 0x9) == 0x9 ? 4 : 0) - | ((i & 0x6) == 0x6 ? 8 : 0) - | ((i & 0xA) == 0xA ? 16 : 0) - | ((i & 0xC) == 0xC ? 32 : 0)) << 9; - } -} - -void custom_init (void) -{ - -#ifdef OS_WITHOUT_MEMORY_MANAGEMENT - int num; - - for (num = 0; num < 2; num++) { - sprite_entries[num] = xmalloc (max_sprite_entry * sizeof (struct sprite_entry)); - color_changes[num] = xmalloc (max_color_change * sizeof (struct color_change)); - } -#endif - -#ifdef AUTOCONFIG - { - uaecptr pos; - pos = here (); - - org (RTAREA_BASE+0xFF70); - calltrap (deftrap (mousehack_helper)); - dw (RTS); - - org (RTAREA_BASE+0xFFA0); - calltrap (deftrap (timehack_helper)); - dw (RTS); - - org (pos); - } -#endif - - gen_custom_tables (); - build_blitfilltable (); - - drawing_init (); - - mousehack_set (mousehack_unknown); - if (needmousehack ()) - mousehack_set (mousehack_follow); - - create_cycle_diagram_table (); -} - -/* Custom chip memory bank */ - -static uae_u32 custom_lget (uaecptr) REGPARAM; -static uae_u32 custom_wget (uaecptr) REGPARAM; -static uae_u32 custom_bget (uaecptr) REGPARAM; -static void custom_lput (uaecptr, uae_u32) REGPARAM; -static void custom_wput (uaecptr, uae_u32) REGPARAM; -static void custom_bput (uaecptr, uae_u32) REGPARAM; - -addrbank custom_bank = { - custom_lget, custom_wget, custom_bget, - custom_lput, custom_wput, custom_bput, - default_xlate, default_check, NULL -}; - -STATIC_INLINE uae_u32 REGPARAM2 custom_wget_1 (uaecptr addr, int noput) -{ - uae_u16 v; -#ifdef JIT - special_mem |= S_READ; -#endif - addr &= 0xfff; -#ifdef CUSTOM_DEBUG - write_log ("%d:%d:wget: %04.4X=%04.4X pc=%p\n", current_hpos(), vpos, addr, addr & 0x1fe, m68k_getpc()); -#endif - switch (addr & 0x1fe) { - case 0x002: v = DMACONR (); break; - case 0x004: v = VPOSR (); break; - case 0x006: v = VHPOSR (); break; - - case 0x00A: v = JOY0DAT (); break; - case 0x00C: v = JOY1DAT (); break; - case 0x00E: v = CLXDAT (); break; - case 0x010: v = ADKCONR (); break; - - case 0x012: v = POT0DAT (); break; - case 0x014: v = POT1DAT (); break; - case 0x016: v = POTGOR (); break; - case 0x018: v = SERDATR (); break; - case 0x01A: v = DSKBYTR (current_hpos ()); break; - case 0x01C: v = INTENAR (); break; - case 0x01E: v = INTREQR (); break; - case 0x07C: v = DENISEID (); break; - - case 0x02E: v = 0xffff; break; /* temporary hack */ - -#ifdef AGA - 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: - v = COLOR_READ ((addr & 0x3E) / 2); - break; -#endif - - default: - /* reading write-only register causes write with last value in bus */ - v = last_custom_value; - if (!noput) { - int r; - int hpos = current_hpos (); - decide_line (hpos); - decide_fetch (hpos); - decide_blitter (hpos); - v = last_custom_value; - r = custom_wput_1 (hpos, addr, v, 1); - } - return v; - } - return v; -} - - STATIC_INLINE custom_wget2 (uaecptr addr) - { - uae_u32 v; - sync_copper_with_cpu (current_hpos (), 1, addr); - if (currprefs.cpu_level >= 2) { - if(addr > 0xde0000 && addr <= 0xdeffff) - return 0x7f7f; - if(addr > 0xdd0000 && addr <= 0xddffff) - return 0xffff; - } - v = custom_wget_1 (addr, 0); -#ifdef ACTION_REPLAY -#ifdef ACTION_REPLAY_COMMON - addr &= 0x1ff; - ar_custom[addr + 0] = (uae_u8)(v >> 8); - ar_custom[addr + 1] = (uae_u8)(v); -#endif -#endif - return v; -} - -uae_u32 REGPARAM2 custom_wget (uaecptr addr) -{ - uae_u32 v; - - if (addr & 1) { - /* think about move.w $dff005,d0.. (68020+ only) */ - addr &= ~1; - v = custom_wget2 (addr) << 8; - v |= custom_wget2 (addr + 2) >> 8; - return v; - } - return custom_wget2 (addr); - } - -uae_u32 REGPARAM2 custom_bget (uaecptr addr) -{ -#ifdef JIT - special_mem |= S_READ; -#endif - return custom_wget2 (addr & ~1) >> (addr & 1 ? 0 : 8); -} - -uae_u32 REGPARAM2 custom_lget (uaecptr addr) -{ -#ifdef JIT - special_mem |= S_READ; -#endif - return ((uae_u32)custom_wget (addr) << 16) | custom_wget (addr + 2); -} - -int REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value, int noget) -{ - addr &= 0x1FE; - value &= 0xffff; -#ifdef ACTION_REPLAY -#ifdef ACTION_REPLAY_COMMON - ar_custom[addr+0]=(uae_u8)(value>>8); - ar_custom[addr+1]=(uae_u8)(value); -#endif -#endif - last_custom_value = value; - switch (addr) { - case 0x00E: CLXDAT (); break; - - case 0x020: DSKPTH (value); break; - case 0x022: DSKPTL (value); break; - case 0x024: DSKLEN (value, hpos); break; - case 0x026: DSKDAT (value); break; - - case 0x02A: VPOSW (value); break; - case 0x02E: COPCON (value); break; - case 0x030: SERDAT (value); break; - case 0x032: SERPER (value); break; - case 0x034: 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 (hpos, value); break; - - case 0x080: COP1LCH (value); break; - case 0x082: COP1LCL (value); break; - case 0x084: COP2LCH (value); break; - case 0x086: COP2LCL (value); break; - - case 0x088: COPJMP (1); break; - case 0x08A: COPJMP (2); break; - - case 0x08E: DIWSTRT (hpos, value); break; - case 0x090: DIWSTOP (hpos, value); break; - case 0x092: DDFSTRT (hpos, value); break; - case 0x094: DDFSTOP (hpos, value); break; - - case 0x096: DMACON (hpos, value); break; - case 0x098: CLXCON (value); break; - case 0x09A: INTENA (value); break; - case 0x09C: INTREQ (value); break; - case 0x09E: ADKCON (hpos, 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: BPLxPTH (hpos, value, 0); break; - case 0x0E2: BPLxPTL (hpos, value, 0); break; - case 0x0E4: BPLxPTH (hpos, value, 1); break; - case 0x0E6: BPLxPTL (hpos, value, 1); break; - case 0x0E8: BPLxPTH (hpos, value, 2); break; - case 0x0EA: BPLxPTL (hpos, value, 2); break; - case 0x0EC: BPLxPTH (hpos, value, 3); break; - case 0x0EE: BPLxPTL (hpos, value, 3); break; - case 0x0F0: BPLxPTH (hpos, value, 4); break; - case 0x0F2: BPLxPTL (hpos, value, 4); break; - case 0x0F4: BPLxPTH (hpos, value, 5); break; - case 0x0F6: BPLxPTL (hpos, value, 5); break; - case 0x0F8: BPLxPTH (hpos, value, 6); break; - case 0x0FA: BPLxPTL (hpos, value, 6); break; - case 0x0FC: BPLxPTH (hpos, value, 7); break; - case 0x0FE: BPLxPTL (hpos, value, 7); break; - - case 0x100: BPLCON0 (hpos, value); break; - case 0x102: BPLCON1 (hpos, value); break; - case 0x104: BPLCON2 (hpos, value); break; -#ifdef AGA - case 0x106: BPLCON3 (hpos, value); break; -#endif - - case 0x108: BPL1MOD (hpos, value); break; - case 0x10A: BPL2MOD (hpos, value); break; -#ifdef AGA - case 0x10E: CLXCON2 (value); break; -#endif - - case 0x110: BPL1DAT (hpos, 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 0x11C: BPL7DAT (value); break; - case 0x11E: BPL8DAT (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_WRITE (hpos, value & 0xFFF, (addr & 0x3E) / 2); - break; - case 0x120: case 0x124: case 0x128: case 0x12C: - case 0x130: case 0x134: case 0x138: case 0x13C: - SPRxPTH (hpos, value, (addr - 0x120) / 4); - break; - case 0x122: case 0x126: case 0x12A: case 0x12E: - case 0x132: case 0x136: case 0x13A: case 0x13E: - SPRxPTL (hpos, value, (addr - 0x122) / 4); - break; - case 0x140: case 0x148: case 0x150: case 0x158: - case 0x160: case 0x168: case 0x170: case 0x178: - SPRxPOS (hpos, value, (addr - 0x140) / 8); - break; - case 0x142: case 0x14A: case 0x152: case 0x15A: - case 0x162: case 0x16A: case 0x172: case 0x17A: - SPRxCTL (hpos, value, (addr - 0x142) / 8); - break; - case 0x144: case 0x14C: case 0x154: case 0x15C: - case 0x164: case 0x16C: case 0x174: case 0x17C: - SPRxDATA (hpos, value, (addr - 0x144) / 8); - break; - case 0x146: case 0x14E: case 0x156: case 0x15E: - case 0x166: case 0x16E: case 0x176: case 0x17E: - SPRxDATB (hpos, value, (addr - 0x146) / 8); - break; - - case 0x36: JOYTEST (value); break; - case 0x5A: BLTCON0L (value); break; - case 0x5C: BLTSIZV (value); break; - case 0x5E: BLTSIZH (value); break; - case 0x1E4: DIWHIGH (hpos, value); break; -#ifdef AGA - case 0x10C: BPLCON4 (hpos, value); break; -#endif - - case 0x1DC: BEAMCON0 (value); break; - case 0x1C0: if (htotal != value) { htotal = value; varsync (); } break; - case 0x1C2: if (hsstop != value) { hsstop = value; varsync (); } break; - case 0x1C4: if (hbstrt != value) { hbstrt = value; varsync (); } break; - case 0x1C6: if (hbstop != value) { hbstop = value; varsync (); } break; - case 0x1C8: if (vtotal != value) { vtotal = value; varsync (); } break; - case 0x1CA: if (vsstop != value) { vsstop = value; varsync (); } break; - case 0x1CC: if (vbstrt != value) { vbstrt = value; varsync (); } break; - case 0x1CE: if (vbstop != value) { vbstop = value; varsync (); } break; - case 0x1DE: if (hsstrt != value) { hsstrt = value; varsync (); } break; - case 0x1E0: if (vsstrt != value) { vsstrt = value; varsync (); } break; - case 0x1E2: if (hcenter != value) { hcenter = value; varsync (); } break; - -#ifdef AGA - case 0x1FC: FMODE (value); break; -#endif - - /* writing to read-only register causes read access */ - default: - if (!noget) - custom_wget_1 (addr, 1); - if (!(currprefs.chipset_mask & CSMASK_AGA) && (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - last_custom_value = 0xffff; - return 1; - } - return 0; -} - -void REGPARAM2 custom_wput (uaecptr addr, uae_u32 value) -{ - int hpos = current_hpos (); -#ifdef JIT - special_mem |= S_WRITE; -#endif -#ifdef CUSTOM_DEBUG - write_log ("%d:%d:wput: %04.4X %04.4X pc=%p\n", hpos, vpos, addr & 0x01fe, value & 0xffff, m68k_getpc()); -#endif - sync_copper_with_cpu (hpos, 1, addr); - custom_wput_1 (hpos, addr, value, 0); -} - -void REGPARAM2 custom_bput (uaecptr addr, uae_u32 value) -{ - static int warned; - /* Is this correct now? (There are people who bput things to the upper byte of AUDxVOL). */ - uae_u16 rval = (value << 8) | (value & 0xFF); -#ifdef JIT - special_mem |= S_WRITE; -#endif - custom_wput (addr & ~1, rval); - if (warned < 10) { - write_log ("Byte put to custom register %04.4X PC=%08.8X\n", addr, m68k_getpc()); - warned++; - } -} - -void REGPARAM2 custom_lput(uaecptr addr, uae_u32 value) -{ -#ifdef JIT - special_mem |= S_WRITE; -#endif - custom_wput (addr & 0xfffe, value >> 16); - custom_wput ((addr + 2) & 0xfffe, (uae_u16)value); -} - -void custom_prepare_savestate (void) -{ -} - -#define RB restore_u8 () -#define RW restore_u16 () -#define RL restore_u32 () - -uae_u8 *restore_custom (uae_u8 *src) -{ - uae_u16 dsklen, dskbytr; - int dskpt; - int i; - - audio_reset (); - - changed_prefs.chipset_mask = currprefs.chipset_mask = RL; - RW; /* 000 ? */ - RW; /* 002 DMACONR */ - RW; /* 004 VPOSR */ - RW; /* 006 VHPOSR */ - RW; /* 008 DSKDATR (dummy register) */ - RW; /* 00A JOY0DAT */ - RW; /* 00C JOY1DAT */ - clxdat = RW; /* 00E CLXDAT */ - RW; /* 010 ADKCONR */ - RW; /* 012 POT0DAT* */ - RW; /* 014 POT1DAT* */ - RW; /* 016 POTINP* */ - RW; /* 018 SERDATR* */ - dskbytr = RW; /* 01A DSKBYTR */ - RW; /* 01C INTENAR */ - RW; /* 01E INTREQR */ - dskpt = RL; /* 020-022 DSKPT */ - dsklen = RW; /* 024 DSKLEN */ - RW; /* 026 DSKDAT */ - RW; /* 028 REFPTR */ - lof = RW; /* 02A VPOSW */ - RW; /* 02C VHPOSW */ - COPCON(RW); /* 02E COPCON */ - RW; /* 030 SERDAT* */ - RW; /* 032 SERPER* */ - POTGO(RW); /* 034 POTGO */ - RW; /* 036 JOYTEST* */ - RW; /* 038 STREQU */ - RW; /* 03A STRVHBL */ - RW; /* 03C STRHOR */ - RW; /* 03E STRLONG */ - BLTCON0(RW); /* 040 BLTCON0 */ - BLTCON1(RW); /* 042 BLTCON1 */ - BLTAFWM(RW); /* 044 BLTAFWM */ - BLTALWM(RW); /* 046 BLTALWM */ - BLTCPTH(RL); /* 048-04B BLTCPT */ - BLTBPTH(RL); /* 04C-04F BLTBPT */ - BLTAPTH(RL); /* 050-053 BLTAPT */ - BLTDPTH(RL); /* 054-057 BLTDPT */ - RW; /* 058 BLTSIZE */ - RW; /* 05A BLTCON0L */ - blt_info.vblitsize = RW; /* 05C BLTSIZV */ - blt_info.hblitsize = RW; /* 05E BLTSIZH */ - BLTCMOD(RW); /* 060 BLTCMOD */ - BLTBMOD(RW); /* 062 BLTBMOD */ - BLTAMOD(RW); /* 064 BLTAMOD */ - BLTDMOD(RW); /* 066 BLTDMOD */ - RW; /* 068 ? */ - RW; /* 06A ? */ - RW; /* 06C ? */ - RW; /* 06E ? */ - BLTCDAT(RW); /* 070 BLTCDAT */ - BLTBDAT(RW); /* 072 BLTBDAT */ - BLTADAT(RW); /* 074 BLTADAT */ - RW; /* 076 ? */ - RW; /* 078 ? */ - RW; /* 07A ? */ - RW; /* 07C LISAID */ - DSKSYNC(-1, RW); /* 07E DSKSYNC */ - cop1lc = RL; /* 080/082 COP1LC */ - cop2lc = RL; /* 084/086 COP2LC */ - RW; /* 088 ? */ - RW; /* 08A ? */ - RW; /* 08C ? */ - diwstrt = RW; /* 08E DIWSTRT */ - diwstop = RW; /* 090 DIWSTOP */ - ddfstrt = RW; /* 092 DDFSTRT */ - ddfstop = RW; /* 094 DDFSTOP */ - dmacon = RW & ~(0x2000|0x4000); /* 096 DMACON */ - CLXCON(RW); /* 098 CLXCON */ - intena = RW; /* 09A INTENA */ - intreq = RW; /* 09C INTREQ */ - adkcon = RW; /* 09E ADKCON */ - for (i = 0; i < 8; i++) - bplpt[i] = RL; - bplcon0 = RW; /* 100 BPLCON0 */ - bplcon1 = RW; /* 102 BPLCON1 */ - bplcon2 = RW; /* 104 BPLCON2 */ - bplcon3 = RW; /* 106 BPLCON3 */ - bpl1mod = RW; /* 108 BPL1MOD */ - bpl2mod = RW; /* 10A BPL2MOD */ - bplcon4 = RW; /* 10C BPLCON4 */ - clxcon2 = RW; /* 10E CLXCON2* */ - for(i = 0; i < 8; i++) - RW; /* BPLXDAT */ - for(i = 0; i < 32; i++) - current_colors.color_regs_ecs[i] = RW; /* 180 COLORxx */ - htotal = RW; /* 1C0 HTOTAL */ - RW; /* 1C2 ? */ - RW; /* 1C4 ? */ - RW; /* 1C6 ? */ - vtotal = RW; /* 1C8 VTOTAL */ - RW; /* 1CA ? */ - RW; /* 1CC ? */ - RW; /* 1CE ? */ - RW; /* 1D0 ? */ - RW; /* 1D2 ? */ - RW; /* 1D4 ? */ - RW; /* 1D6 ? */ - RW; /* 1D8 ? */ - RW; /* 1DA ? */ - new_beamcon0 = RW; /* 1DC BEAMCON0 */ - RW; /* 1DE ? */ - RW; /* 1E0 ? */ - RW; /* 1E2 ? */ - diwhigh = RW; /* 1E4 ? */ - if (diwhigh & 0x8000) - diwhigh_written = 1; - diwhigh &= 0x7fff; - RW; /* 1E6 ? */ - RW; /* 1E8 ? */ - RW; /* 1EA ? */ - RW; /* 1EC ? */ - RW; /* 1EE ? */ - RW; /* 1F0 ? */ - RW; /* 1F2 ? */ - RW; /* 1F4 ? */ - RW; /* 1F6 ? */ - RW; /* 1F8 ? */ - RW; /* 1FA ? */ - fmode = RW; /* 1FC FMODE */ - last_custom_value = RW; /* 1FE ? */ - - DISK_restore_custom (dskpt, dsklen, dskbytr); - - return src; -} - - -#define SB save_u8 -#define SW save_u16 -#define SL save_u32 - -extern uae_u16 serper; - -uae_u8 *save_custom (int *len, uae_u8 *dstptr, int full) -{ - uae_u8 *dstbak, *dst; - int i; - uae_u32 dskpt; - uae_u16 dsklen, dsksync, dskbytr; - - DISK_save_custom (&dskpt, &dsklen, &dsksync, &dskbytr); - - if (dstptr) - dstbak = dst = dstptr; - else - dstbak = dst = malloc (8+256*2); - - SL (currprefs.chipset_mask); - SW (0); /* 000 ? */ - SW (dmacon); /* 002 DMACONR */ - SW (VPOSR()); /* 004 VPOSR */ - SW (VHPOSR()); /* 006 VHPOSR */ - SW (0); /* 008 DSKDATR */ - SW (JOY0DAT()); /* 00A JOY0DAT */ - SW (JOY1DAT()); /* 00C JOY1DAT */ - SW (clxdat); /* 00E CLXDAT */ - SW (ADKCONR()); /* 010 ADKCONR */ - SW (POT0DAT()); /* 012 POT0DAT */ - SW (POT0DAT()); /* 014 POT1DAT */ - SW (0) ; /* 016 POTINP * */ - SW (0); /* 018 SERDATR * */ - SW (dskbytr); /* 01A DSKBYTR */ - SW (INTENAR()); /* 01C INTENAR */ - SW (INTREQR()); /* 01E INTREQR */ - SL (dskpt); /* 020-023 DSKPT */ - SW (dsklen); /* 024 DSKLEN */ - SW (0); /* 026 DSKDAT */ - SW (0); /* 028 REFPTR */ - SW (lof); /* 02A VPOSW */ - SW (0); /* 02C VHPOSW */ - SW (copcon); /* 02E COPCON */ - SW (serper); /* 030 SERDAT * */ - SW (serdat); /* 032 SERPER * */ - SW (potgo_value); /* 034 POTGO */ - SW (0); /* 036 JOYTEST * */ - SW (0); /* 038 STREQU */ - SW (0); /* 03A STRVBL */ - SW (0); /* 03C STRHOR */ - SW (0); /* 03E STRLONG */ - SW (bltcon0); /* 040 BLTCON0 */ - SW (bltcon1); /* 042 BLTCON1 */ - SW (blt_info.bltafwm); /* 044 BLTAFWM */ - SW (blt_info.bltalwm); /* 046 BLTALWM */ - SL (bltcpt); /* 048-04B BLTCPT */ - SL (bltbpt); /* 04C-04F BLTCPT */ - SL (bltapt); /* 050-053 BLTCPT */ - SL (bltdpt); /* 054-057 BLTCPT */ - SW (0); /* 058 BLTSIZE */ - SW (0); /* 05A BLTCON0L (use BLTCON0 instead) */ - SW (blt_info.vblitsize); /* 05C BLTSIZV */ - SW (blt_info.hblitsize); /* 05E BLTSIZH */ - SW (blt_info.bltcmod); /* 060 BLTCMOD */ - SW (blt_info.bltbmod); /* 062 BLTBMOD */ - SW (blt_info.bltamod); /* 064 BLTAMOD */ - SW (blt_info.bltdmod); /* 066 BLTDMOD */ - SW (0); /* 068 ? */ - SW (0); /* 06A ? */ - SW (0); /* 06C ? */ - SW (0); /* 06E ? */ - SW (blt_info.bltcdat); /* 070 BLTCDAT */ - SW (blt_info.bltbdat); /* 072 BLTBDAT */ - SW (blt_info.bltadat); /* 074 BLTADAT */ - SW (0); /* 076 ? */ - SW (0); /* 078 ? */ - SW (0); /* 07A ? */ - SW (DENISEID()); /* 07C DENISEID/LISAID */ - SW (dsksync); /* 07E DSKSYNC */ - SL (cop1lc); /* 080-083 COP1LC */ - SL (cop2lc); /* 084-087 COP2LC */ - SW (0); /* 088 ? */ - SW (0); /* 08A ? */ - SW (0); /* 08C ? */ - SW (diwstrt); /* 08E DIWSTRT */ - SW (diwstop); /* 090 DIWSTOP */ - SW (ddfstrt); /* 092 DDFSTRT */ - SW (ddfstop); /* 094 DDFSTOP */ - SW (dmacon); /* 096 DMACON */ - SW (clxcon); /* 098 CLXCON */ - SW (intena); /* 09A INTENA */ - SW (intreq); /* 09C INTREQ */ - SW (adkcon); /* 09E ADKCON */ - for (i = 0; full && i < 32; i++) - SW (0); - for (i = 0; i < 8; i++) - SL (bplpt[i]); /* 0E0-0FE BPLxPT */ - SW (bplcon0); /* 100 BPLCON0 */ - SW (bplcon1); /* 102 BPLCON1 */ - SW (bplcon2); /* 104 BPLCON2 */ - SW (bplcon3); /* 106 BPLCON3 */ - SW (bpl1mod); /* 108 BPL1MOD */ - SW (bpl2mod); /* 10A BPL2MOD */ - SW (bplcon4); /* 10C BPLCON4 */ - SW (clxcon2); /* 10E CLXCON2 */ - for (i = 0;i < 8; i++) - SW (0); /* 110 BPLxDAT */ - if (full) { - for (i = 0; i < 8; i++) { - SL (spr[i].pt); /* 120-13E SPRxPT */ - SW (sprpos[i]); /* 1x0 SPRxPOS */ - SW (sprctl[i]); /* 1x2 SPRxPOS */ - SW (sprdata[i][0]); /* 1x4 SPRxDATA */ - SW (sprdatb[i][0]); /* 1x6 SPRxDATB */ - } - } - for ( i = 0; i < 32; i++) - SW (current_colors.color_regs_ecs[i]); /* 180-1BE COLORxx */ - SW (htotal); /* 1C0 HTOTAL */ - SW (0); /* 1C2 */ - SW (0); /* 1C4 */ - SW (0); /* 1C6 */ - SW (vtotal); /* 1C8 VTOTAL */ - SW (0); /* 1CA */ - SW (0); /* 1CC */ - SW (0); /* 1CE */ - SW (0); /* 1D0 */ - SW (0); /* 1D2 */ - SW (0); /* 1D4 */ - SW (0); /* 1D6 */ - SW (0); /* 1D8 */ - SW (0); /* 1DA */ - SW (beamcon0); /* 1DC BEAMCON0 */ - SW (0); /* 1DE */ - SW (0); /* 1E0 */ - SW (0); /* 1E2 */ - SW (diwhigh | (diwhigh_written ? 0x8000 : 0)); /* 1E4 */ - SW (0); /* 1E6 */ - SW (0); /* 1E8 */ - SW (0); /* 1EA */ - SW (0); /* 1EC */ - SW (0); /* 1EE */ - SW (0); /* 1F0 */ - SW (0); /* 1F2 */ - SW (0); /* 1F4 */ - SW (0); /* 1F6 */ - SW (0); /* 1F8 */ - SW (0); /* 1FA */ - SW (fmode); /* 1FC FMODE */ - SW (last_custom_value); /* 1FE */ - - *len = dst - dstbak; - return dstbak; -} - -uae_u8 *restore_custom_agacolors (uae_u8 *src) -{ - int i; - - for (i = 0; i < 256; i++) -#ifdef AGA - current_colors.color_regs_aga[i] = RL; -#else - RL; -#endif - return src; -} - -uae_u8 *save_custom_agacolors (int *len, uae_u8 *dstptr) -{ - uae_u8 *dstbak, *dst; - int i; - - if (dstptr) - dstbak = dst = dstptr; - else - dstbak = dst = malloc (256*4); - for (i = 0; i < 256; i++) -#ifdef AGA - SL (current_colors.color_regs_aga[i]); -#else - SL (0); -#endif - *len = dst - dstbak; - return dstbak; -} - -uae_u8 *restore_custom_sprite (int num, uae_u8 *src) -{ - spr[num].pt = RL; /* 120-13E SPRxPT */ - sprpos[num] = RW; /* 1x0 SPRxPOS */ - sprctl[num] = RW; /* 1x2 SPRxPOS */ - sprdata[num][0] = RW; /* 1x4 SPRxDATA */ - sprdatb[num][0] = RW; /* 1x6 SPRxDATB */ - sprdata[num][1] = RW; - sprdatb[num][1] = RW; - sprdata[num][2] = RW; - sprdatb[num][2] = RW; - sprdata[num][3] = RW; - sprdatb[num][3] = RW; - spr[num].armed = RB; - return src; -} - -uae_u8 *save_custom_sprite(int num, int *len, uae_u8 *dstptr) -{ - uae_u8 *dstbak, *dst; - - if (dstptr) - dstbak = dst = dstptr; - else - dstbak = dst = malloc (25); - SL (spr[num].pt); /* 120-13E SPRxPT */ - SW (sprpos[num]); /* 1x0 SPRxPOS */ - SW (sprctl[num]); /* 1x2 SPRxPOS */ - SW (sprdata[num][0]); /* 1x4 SPRxDATA */ - SW (sprdatb[num][0]); /* 1x6 SPRxDATB */ - SW (sprdata[num][1]); - SW (sprdatb[num][1]); - SW (sprdata[num][2]); - SW (sprdatb[num][2]); - SW (sprdata[num][3]); - SW (sprdatb[num][3]); - SB (spr[num].armed ? 1 : 0); - *len = dst - dstbak; - return dstbak; -} - -void check_prefs_changed_custom (void) -{ - currprefs.gfx_framerate = changed_prefs.gfx_framerate; - if (inputdevice_config_change_test ()) { - inputdevice_copyconfig (&changed_prefs, &currprefs); - inputdevice_updateconfig (&currprefs); - } - currprefs.immediate_blits = changed_prefs.immediate_blits; - currprefs.collision_level = changed_prefs.collision_level; - currprefs.fast_copper = changed_prefs.fast_copper; - - if (currprefs.chipset_mask != changed_prefs.chipset_mask || - currprefs.gfx_vsync != changed_prefs.gfx_vsync || - currprefs.ntscmode != changed_prefs.ntscmode) { - currprefs.gfx_vsync = changed_prefs.gfx_vsync; - currprefs.chipset_mask = changed_prefs.chipset_mask; - if (currprefs.ntscmode != changed_prefs.ntscmode) { - currprefs.ntscmode = changed_prefs.ntscmode; - new_beamcon0 = currprefs.ntscmode ? 0x00 : 0x20; - } - init_hz (); - calcdiw (); - } - currprefs.gfx_filter_horiz_zoom = changed_prefs.gfx_filter_horiz_zoom; - currprefs.gfx_filter_vert_zoom = changed_prefs.gfx_filter_vert_zoom; - currprefs.gfx_filter_horiz_offset = changed_prefs.gfx_filter_horiz_offset; - currprefs.gfx_filter_vert_offset = changed_prefs.gfx_filter_vert_offset; - currprefs.gfx_filter_scanlines = changed_prefs.gfx_filter_scanlines; - currprefs.gfx_filter_filtermode = changed_prefs.gfx_filter_filtermode; -} - -#ifdef CPUEMU_6 - -STATIC_INLINE void sync_copper (int hpos) -{ - if (eventtab[ev_copper].active) { - eventtab[ev_copper].active = 0; - update_copper (hpos); - return; - } - if (copper_enabled_thisline) - update_copper (hpos); -} - -STATIC_INLINE int dma_cycle(void) -{ - int hpos, cycles = 0, bnasty = 0; - - for (;;) { - int bpldma; - int blitpri = dmaen (DMA_BLITPRI); - do_cycles (1 * CYCLE_UNIT); - cycles += CYCLE_UNIT; - hpos = current_hpos (); - sync_copper (hpos); - decide_line (hpos); - bpldma = is_bitplane_dma (hpos); - if (cycle_line[hpos] == 0 && !bpldma) { - if (bltstate == BLT_done || bnasty >= 3) - break; - decide_blitter (hpos); - if (cycle_line[hpos] == 0) - break; - if (!blitpri || blit_singlechannel) - bnasty++; - } else if (bpldma && (blit_singlechannel || !blitpri)) { - bnasty++; - } - /* bus was allocated to dma channel, wait for next cycle.. */ - } - cycle_line[hpos] |= CYCLE_CPU; - return cycles; -} - -uae_u32 wait_cpu_cycle_read (uaecptr addr, int mode) -{ - uae_u32 v = 0; - dma_cycle (); - if (mode > 0) - v = get_word (addr); - else if (mode == 0) - v = get_byte (addr); - do_cycles (1 * CYCLE_UNIT); - return v; -} - -uae_u32 wait_cpu_cycle_read_cycles (uaecptr addr, int mode, int *cycles) -{ - uae_u32 v = 0; - *cycles = dma_cycle () + CYCLE_UNIT; - if (mode > 0) - v = get_word (addr); - else if (mode == 0) - v = get_byte (addr); - do_cycles (1 * CYCLE_UNIT); - return v; -} - -void wait_cpu_cycle_write (uaecptr addr, int mode, uae_u32 v) -{ - dma_cycle (); - if (mode > 0) - put_word (addr, v); - else if (mode == 0) - put_byte (addr, v); - do_cycles (1 * CYCLE_UNIT); -} - -void do_cycles_ce (long cycles) -{ - int hpos, bpldma; - while (cycles > 0) { - do_cycles (1 * CYCLE_UNIT); - cycles -= CYCLE_UNIT; - hpos = current_hpos (); - sync_copper (hpos); - decide_line (hpos); - bpldma = is_bitplane_dma (hpos); - if (cycle_line[hpos] == 0 && !bpldma) - decide_blitter (hpos); - } -} - -#endif diff --git a/debug.c b/debug.c index 30104e6d..0c6a7515 100755 --- a/debug.c +++ b/debug.c @@ -30,6 +30,7 @@ #include "disk.h" #include "savestate.h" #include "autoconf.h" +#include "akiko.h" static int debugger_active; static uaecptr skipaddr_start, skipaddr_end, skipaddr_doskip; @@ -94,9 +95,10 @@ static char help[] = { " W
Write into Amiga memory\n" " w
[]\n" " Add/remove memory watchpoints\n" + " wd Enable illegal access logger\n" " S Save a block of Amiga memory\n" " s / [] []\n" - " search for string/bytes\n" + " Search for string/bytes\n" " T Show exec tasks and their PCs\n" " h,? Show this help page\n" " b Step to previous state capture position\n" @@ -538,6 +540,86 @@ struct memwatch_node { static struct memwatch_node mwnodes[MEMWATCH_TOTAL]; static struct memwatch_node mwhit; +static uae_u8 *illgdebug; +extern int cdtv_enabled, cd32_enabled; + +static void illg_init (void) +{ + int i; + + free (illgdebug); + illgdebug = xmalloc (0x1000000); + if (!illgdebug) + return; + memset (illgdebug, 3, 0x1000000); + memset (illgdebug, 0, currprefs.chipmem_size); + memset (illgdebug + 0xc00000, 0, currprefs.bogomem_size); + memset (illgdebug + 0x200000, 0, currprefs.fastmem_size); + i = 0; + while (custd[i].name) { + int rw = custd[i].rw; + illgdebug[custd[i].adr] = rw; + illgdebug[custd[i].adr + 1] = rw; + i++; + } + for (i = 0; i < 16; i++) { /* CIAs */ + if (i == 11) + continue; + illgdebug[0xbfe001 + i * 0x100] = 0; + illgdebug[0xbfd000 + i * 0x100] = 0; + } + memset (illgdebug + 0xf80000, 1, 512 * 1024); /* KS ROM */ + memset (illgdebug + 0xdc0000, 0, 0x3f); /* clock */ + if (cdtv_enabled) { + memset (illgdebug + 0xf00000, 1, 256 * 1024); /* CDTV ext ROM */ + memset (illgdebug + 0xdc8000, 0, 4096); /* CDTV batt RAM */ + } + if (cd32_enabled || cloanto_rom) { + memset (illgdebug + 0xe00000, 1, 512 * 1024); /* CD32 ext ROM */ + if (cd32_enabled) + memset (illgdebug + AKIKO_BASE, 0, AKIKO_BASE_END - AKIKO_BASE); + } + if (nr_units (currprefs.mountinfo) > 0) /* filesys "rom" */ + memset (illgdebug + RTAREA_BASE, 1, 0x10000); +} + +/* add special custom register check here */ +static void illg_debug_check (uaecptr addr, int rw, int size, uae_u32 val) +{ + return; +} + +static void illg_debug_do (uaecptr addr, int rw, int size, uae_u32 val) +{ + uae_u8 mask; + uae_u32 pc = m68k_getpc (); + char rws = rw ? 'W' : 'R'; + int i; + + for (i = size - 1; i >= 0; i--) { + uae_u8 v = val >> (i * 8); + uae_u32 ad = addr + i; + if (ad >= 0x1000000) + mask = 3; + else + mask = illgdebug[ad]; + if (!mask) + continue; + if (mask & 0x80) { + illg_debug_check (ad, rw, size, val); + } else if ((mask & 3) == 3) { + if (rw) + write_log ("RW: %08.8X=%02.2X %c PC=%08.8X\n", ad, v, rws, pc); + else + write_log ("RW: %08.8X %c PC=%08.8X\n", ad, rws, pc); + } else if ((mask & 1) && rw) { + write_log ("RO: %08.8X=%02.2X %c PC=%08.8X\n", ad, v, rws, pc); + } else if ((mask & 2) && !rw) { + write_log ("WO: %08.8X %c PC=%08.8X\n", ad, rws, pc); + } + } +} + static int debug_mem_off (uaecptr addr) { return (munge24 (addr) >> 16) & 0xff; @@ -547,6 +629,8 @@ static void memwatch_func (uaecptr addr, int rw, int size, uae_u32 val) { int i, brk; + if (illgdebug) + illg_debug_do (addr, rw, size, val); addr = munge24 (addr); for (i = 0; i < MEMWATCH_TOTAL; i++) { uaecptr addr2 = mwnodes[i].addr; @@ -659,6 +743,8 @@ static void deinitialize_memwatch (void) free (debug_mem_banks); debug_mem_banks = 0; memwatch_enabled = 0; + free (illgdebug); + illgdebug = 0; } static int initialize_memwatch (void) @@ -735,6 +821,28 @@ static void memwatch (char **c) console_out ("Memwatch breakpoints disabled\n"); return; } + if (nc == 'd') { + if (illgdebug) { + ignore_ws (c); + if (more_params (c)) { + uae_u32 addr = readhex (c); + uae_u32 len = 1; + if (more_params (c)) + len = readhex (c); + write_log ("cleared logging addresses %08.8X - %08.8X\n", addr, addr + len); + while (len > 0) { + addr &= 0xffffff; + illgdebug[addr] = 0; + addr++; + len--; + } + } + } else { + illg_init (); + console_out ("Illegal memory access logging enabled\n"); + } + return; + } num = nc - '0'; if (num < 0 || num >= MEMWATCH_TOTAL) return; diff --git a/drawing.c b/drawing.c index 433de995..854373ac 100755 --- a/drawing.c +++ b/drawing.c @@ -141,12 +141,12 @@ static char linestate[(MAXVPOS + 1)*2 + 1]; uae_u8 line_data[(MAXVPOS + 1) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2]; /* Centering variables. */ -static int min_diwstart, max_diwstop, prev_x_adjust; +static int min_diwstart, max_diwstop; /* The visible window: VISIBLE_LEFT_BORDER contains the left border of the visible area, VISIBLE_RIGHT_BORDER the right border. These are in window coordinates. */ static int visible_left_border, visible_right_border; static int linetoscr_x_adjust_bytes; -static int thisframe_y_adjust, prev_y_adjust; +static int thisframe_y_adjust; static int thisframe_y_adjust_real, max_ypos_thisframe, min_ypos_for_screen; static int extra_y_adjust; int thisframe_first_drawn_line, thisframe_last_drawn_line; @@ -1526,8 +1526,8 @@ STATIC_INLINE void pfield_draw_line (int lineno, int gfx_ypos, int follow_ypos) static void center_image (void) { - prev_x_adjust = visible_left_border; - prev_y_adjust = thisframe_y_adjust; + int prev_x_adjust = visible_left_border; + int prev_y_adjust = thisframe_y_adjust; if (currprefs.gfx_xcenter) { @@ -1540,7 +1540,7 @@ static void center_image (void) /* Would the old value be good enough? If so, leave it as it is if we want to * be clever. */ if (currprefs.gfx_xcenter == 2) { - if (visible_left_border < prev_x_adjust && prev_x_adjust < min_diwstart) + if (visible_left_border < prev_x_adjust && prev_x_adjust < min_diwstart && min_diwstart - visible_left_border <= 32) visible_left_border = prev_x_adjust; } } else diff --git a/fdi2raw2.c b/fdi2raw2.c deleted file mode 100755 index 3c2dc194..00000000 --- a/fdi2raw2.c +++ /dev/null @@ -1,1986 +0,0 @@ -/* - - FDI to raw bit stream converter - Copyright (c) 2001 by Toni Wilen - FDI 2.0 support - Copyright (c) 2003-2004 by Toni Wilen - and Vincent Joguin - - FDI format created by Vincent "ApH" Joguin - - Tiny changes - function type fixes, multiple drives, addition of - get_last_head and C++ callability - by Thomas Harte, 2001, - T.Harte@excite.co.uk - - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - -*/ - -#include -#include -#include - -/* IF UAE */ -#include "sysconfig.h" -#include "sysdeps.h" -#include "zfile.h" -/* ELSE */ -//#include "types.h" - -#include "fdi2raw.h" - -#undef DEBUG -#define VERBOSE -//#undef VERBOSE - -#include - -#ifdef DEBUG -static char *datalog(uae_u8 *src, int len) -{ - static char buf[1000]; - static int offset; - int i = 0, offset2; - - offset2 = offset; - buf[offset++]='\''; - while(len--) { - sprintf (buf + offset, "%02.2X", src[i]); - offset += 2; - i++; - if (i > 10) break; - } - buf[offset++]='\''; - buf[offset++] = 0; - if (offset >= 900) offset = 0; - return buf + offset2; -} -#else -static char *datalog(uae_u8 *src, int len) { return ""; } -#endif - -#ifdef DEBUG -#define debuglog write_log -#else -#define debuglog -#endif -#ifdef VERBOSE -#define outlog write_log -#else -#define outlog -#endif - -static int fdi_allocated; -#ifdef DEBUG -static void fdi_free (void *p) -{ - int size; - if (!p) - return; - size = ((int*)p)[-1]; - fdi_allocated -= size; - write_log ("%d freed (%d)\n", size, fdi_allocated); - free ((int*)p - 1); -} -static void *fdi_malloc (int size) -{ - void *p = xmalloc (size + sizeof (int)); - ((int*)p)[0] = size; - fdi_allocated += size; - write_log ("%d allocated (%d)\n", size, fdi_allocated); - return (int*)p + 1; -} -#else -#define fdi_free free -#define fdi_malloc xmalloc -#endif - -#define MAX_SRC_BUFFER 4194304 -#define MAX_DST_BUFFER 40000 -#define MAX_MFM_SYNC_BUFFER 60000 -#define MAX_TIMING_BUFFER 400000 -#define MAX_TRACKS 166 - -struct fdi_cache { - uae_u32 *avgp, *minp, *maxp; - uae_u8 *idxp; - int avg_free, idx_free, min_free, max_free; - uae_u32 totalavg, pulses, maxidx, indexoffset; - int weakbits; - int lowlevel; -}; - -struct fdi { - uae_u8 *track_src_buffer; - uae_u8 *track_src; - int track_src_len; - uae_u8 *track_dst_buffer; - uae_u8 *track_dst; - uae_u16 *track_dst_buffer_timing; - uae_u8 track_len; - uae_u8 track_type; - int current_track; - int last_track; - int last_head; - int rotation_speed; - int bit_rate; - int disk_type; - int write_protect; - int err; - uae_u8 header[2048]; - int track_offsets[MAX_TRACKS]; - struct zfile *file; - int out; - int mfmsync_offset; - int *mfmsync_buffer; - /* sector described only */ - int index_offset; - int encoding_type; - /* bit handling */ - int nextdrop; - struct fdi_cache cache[MAX_TRACKS]; -}; - -#define get_u32(x) ((((x)[0])<<24)|(((x)[1])<<16)|(((x)[2])<<8)|((x)[3])) -#define get_u24(x) ((((x)[0])<<16)|(((x)[1])<<8)|((x)[2])) -STATIC_INLINE put_u32 (uae_u8 *d, uae_u32 v) -{ - d[0] = v >> 24; - d[1] = v >> 16; - d[2] = v >> 8; - d[3] = v; -} - -struct node { - uae_u16 v; - struct node *left; - struct node *right; -}; -typedef struct node NODE; - -static uae_u8 temp, temp2; - -static uae_u8 *expand_tree (uae_u8 *stream, NODE *node) -{ - if (temp & temp2) { - fdi_free (node->left); - node->left = 0; - fdi_free (node->right); - node->right = 0; - temp2 >>= 1; - if (!temp2) { - temp = *stream++; - temp2 = 0x80; - } - return stream; - } else { - uae_u8 *stream_temp; - temp2 >>= 1; - if (!temp2) { - temp = *stream++; - temp2 = 0x80; - } - node->left = fdi_malloc (sizeof (NODE)); - memset (node->left, 0, sizeof (NODE)); - stream_temp = expand_tree (stream, node->left); - node->right = fdi_malloc (sizeof (NODE)); - memset (node->right, 0, sizeof (NODE)); - return expand_tree (stream_temp, node->right); - } -} - -static uae_u8 *values_tree8 (uae_u8 *stream, NODE *node) -{ - if (node->left == 0) { - node->v = *stream++; - return stream; - } else { - uae_u8 *stream_temp = values_tree8 (stream, node->left); - return values_tree8 (stream_temp, node->right); - } -} - -static uae_u8 *values_tree16 (uae_u8 *stream, NODE *node) -{ - if (node->left == 0) { - uae_u16 high_8_bits = (*stream++) << 8; - node->v = high_8_bits | (*stream++); - return stream; - } else { - uae_u8 *stream_temp = values_tree16 (stream, node->left); - return values_tree16 (stream_temp, node->right); - } -} - -static void free_nodes (NODE *node) -{ - if (node) { - free_nodes (node->left); - free_nodes (node->right); - fdi_free (node); - } -} - -static uae_u32 sign_extend16 (uae_u32 v) -{ - if (v & 0x8000) - v |= 0xffff0000; - return v; -} - -static uae_u32 sign_extend8 (uae_u32 v) -{ - if (v & 0x80) - v |= 0xffffff00; - return v; -} - -static void fdi_decode (uae_u8 *stream, int size, uae_u8 *out) -{ - int i; - uae_u8 sign_extend, sixteen_bit, sub_stream_shift; - NODE root; - NODE *current_node; - - memset (out, 0, size * 4); - sub_stream_shift = 1; - while (sub_stream_shift) { - - //sub-stream header decode - sign_extend = *stream++; - sub_stream_shift = sign_extend & 0x7f; - sign_extend &= 0x80; - sixteen_bit = (*stream++) & 0x80; - - //huffman tree architecture decode - temp = *stream++; - temp2 = 0x80; - stream = expand_tree (stream, &root); - if (temp2 == 0x80) - stream--; - - //huffman output values decode - if (sixteen_bit) - stream = values_tree16 (stream, &root); - else - stream = values_tree8 (stream, &root); - - //sub-stream data decode - temp2 = 0; - for (i = 0; i < size; i++) { - uae_u32 v; - uae_u8 decode = 1; - current_node = &root; - while (decode) { - if (current_node->left == 0) { - decode = 0; - } else { - temp2 >>= 1; - if (!temp2) { - temp2 = 0x80; - temp = *stream++; - } - if (temp & temp2) - current_node = current_node->right; - else - current_node = current_node->left; - } - } - v = ((uae_u32*)out)[i]; - if (sign_extend) { - if (sixteen_bit) - v |= sign_extend16 (current_node->v) << sub_stream_shift; - else - v |= sign_extend8 (current_node->v) << sub_stream_shift; - } else { - v |= current_node->v << sub_stream_shift; - } - ((uae_u32*)out)[i] = v; - } - free_nodes (root.left); - free_nodes (root.right); - } -} - - -static int decode_raw_track (FDI *fdi) -{ - int size = get_u32(fdi->track_src); - memcpy (fdi->track_dst, fdi->track_src, (size + 7) >> 3); - fdi->track_src += (size + 7) >> 3; - return size; -} - -/* unknown track */ -static void zxx (FDI *fdi) -{ - outlog ("track %d: unknown track type 0x%02.2X\n", fdi->current_track, fdi->track_type); -// return -1; -} -/* unsupported track */ -static void zyy (FDI *fdi) -{ - outlog ("track %d: unsupported track type 0x%02.2X\n", fdi->current_track, fdi->track_type); -// return -1; -} -/* empty track */ -static void track_empty (FDI *fdi) -{ -// return 0; -} - -/* unknown sector described type */ -static void dxx (FDI *fdi) -{ - outlog ("\ntrack %d: unknown sector described type 0x%02.2X\n", fdi->current_track, fdi->track_type); - fdi->err = 1; -} -/* unsupported sector described type */ -static void dyy (FDI *fdi) -{ - outlog ("\ntrack %d: unsupported sector described 0x%02.2X\n", fdi->current_track, fdi->track_type); - fdi->err = 1; -} -/* add position of mfm sync bit */ -static void add_mfm_sync_bit (FDI *fdi) -{ - if (fdi->nextdrop) { - fdi->nextdrop = 0; - return; - } - fdi->mfmsync_buffer[fdi->mfmsync_offset++] = fdi->out; - if (fdi->out == 0) { - outlog ("illegal position for mfm sync bit, offset=%d\n",fdi->out); - fdi->err = 1; - } - if (fdi->mfmsync_offset >= MAX_MFM_SYNC_BUFFER) { - fdi->mfmsync_offset = 0; - outlog ("mfmsync buffer overflow\n"); - fdi->err = 1; - } - fdi->out++; -} - -#define BIT_BYTEOFFSET ((fdi->out) >> 3) -#define BIT_BITOFFSET (7-((fdi->out)&7)) - -/* add one bit */ -static void bit_add (FDI *fdi, int bit) -{ - if (fdi->nextdrop) { - fdi->nextdrop = 0; - return; - } - fdi->track_dst[BIT_BYTEOFFSET] &= ~(1 << BIT_BITOFFSET); - if (bit) - fdi->track_dst[BIT_BYTEOFFSET] |= (1 << BIT_BITOFFSET); - fdi->out++; - if (fdi->out >= MAX_DST_BUFFER * 8) { - outlog ("destination buffer overflow\n"); - fdi->err = 1; - fdi->out = 1; - } -} -/* add bit and mfm sync bit */ -static void bit_mfm_add (FDI *fdi, int bit) -{ - add_mfm_sync_bit (fdi); - bit_add (fdi, bit); -} -/* remove following bit */ -static void bit_drop_next (FDI *fdi) -{ - if (fdi->nextdrop > 0) { - outlog("multiple bit_drop_next() called"); - } else if (fdi->nextdrop < 0) { - fdi->nextdrop = 0; - debuglog(":DNN:"); - return; - } - debuglog(":DN:"); - fdi->nextdrop = 1; -} - -/* ignore next bit_drop_next() */ -static void bit_dedrop (FDI *fdi) -{ - if (fdi->nextdrop) { - outlog("bit_drop_next called before bit_dedrop"); - } - fdi->nextdrop = -1; - debuglog(":BDD:"); -} - -/* add one byte */ -static void byte_add (FDI *fdi, uae_u8 v) -{ - int i; - for (i = 7; i >= 0; i--) - bit_add (fdi, v & (1 << i)); -} -/* add one word */ -static void word_add (FDI *fdi, uae_u16 v) -{ - byte_add (fdi, (uae_u8)(v >> 8)); - byte_add (fdi, (uae_u8)v); -} -/* add one byte and mfm encode it */ -static void byte_mfm_add (FDI *fdi, uae_u8 v) -{ - int i; - for (i = 7; i >= 0; i--) - bit_mfm_add (fdi, v & (1 << i)); -} -/* add multiple bytes and mfm encode them */ -static void bytes_mfm_add (FDI *fdi, uae_u8 v, int len) -{ - int i; - for (i = 0; i < len; i++) byte_mfm_add (fdi, v); -} -/* add one mfm encoded word and re-mfm encode it */ -static void word_post_mfm_add (FDI *fdi, uae_u16 v) -{ - int i; - for (i = 14; i >= 0; i -= 2) - bit_mfm_add (fdi, v & (1 << i)); -} - -/* bit 0 */ -static void s00(FDI *fdi) { bit_add (fdi, 0); } -/* bit 1*/ -static void s01(FDI *fdi) { bit_add (fdi, 1); } -/* 4489 */ -static void s02(FDI *fdi) { word_add (fdi, 0x4489); } -/* 5224 */ -static void s03(FDI *fdi) { word_add (fdi, 0x5224); } -/* mfm sync bit */ -static void s04(FDI *fdi) { add_mfm_sync_bit (fdi); } -/* RLE MFM-encoded data */ -static void s08(FDI *fdi) -{ - int bytes = *fdi->track_src++; - uae_u8 byte = *fdi->track_src++; - if (bytes == 0) bytes = 256; - debuglog ("s08:len=%d,data=%02.2X",bytes,byte); - while(bytes--) byte_add (fdi, byte); -} -/* RLE MFM-decoded data */ -static void s09(FDI *fdi) -{ - int bytes = *fdi->track_src++; - uae_u8 byte = *fdi->track_src++; - if (bytes == 0) bytes = 256; - bit_drop_next (fdi); - debuglog ("s09:len=%d,data=%02.2X",bytes,byte); - while(bytes--) byte_mfm_add (fdi, byte); -} -/* MFM-encoded data */ -static void s0a(FDI *fdi) -{ - int i, bits = (fdi->track_src[0] << 8) | fdi->track_src[1]; - uae_u8 b; - fdi->track_src += 2; - debuglog ("s0a:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); - while (bits >= 8) { - byte_add (fdi, *fdi->track_src++); - bits -= 8; - } - if (bits > 0) { - i = 7; - b = *fdi->track_src++; - while (bits--) { - bit_add (fdi, b & (1 << i)); - i--; - } - } -} -/* MFM-encoded data */ -static void s0b(FDI *fdi) -{ - int i, bits = ((fdi->track_src[0] << 8) | fdi->track_src[1]) + 65536; - uae_u8 b; - fdi->track_src += 2; - debuglog ("s0b:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); - while (bits >= 8) { - byte_add (fdi, *fdi->track_src++); - bits -= 8; - } - if (bits > 0) { - i = 7; - b = *fdi->track_src++; - while (bits--) { - bit_add (fdi, b & (1 << i)); - i--; - } - } -} -/* MFM-decoded data */ -static void s0c(FDI *fdi) -{ - int i, bits = (fdi->track_src[0] << 8) | fdi->track_src[1]; - uae_u8 b; - fdi->track_src += 2; - bit_drop_next (fdi); - debuglog ("s0c:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); - while (bits >= 8) { - byte_mfm_add (fdi, *fdi->track_src++); - bits -= 8; - } - if (bits > 0) { - i = 7; - b = *fdi->track_src++; - while(bits--) { - bit_mfm_add (fdi, b & (1 << i)); - i--; - } - } -} -/* MFM-decoded data */ -static void s0d(FDI *fdi) -{ - int i, bits = ((fdi->track_src[0] << 8) | fdi->track_src[1]) + 65536; - uae_u8 b; - fdi->track_src += 2; - bit_drop_next (fdi); - debuglog ("s0d:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); - while (bits >= 8) { - byte_mfm_add (fdi, *fdi->track_src++); - bits -= 8; - } - if (bits > 0) { - i = 7; - b = *fdi->track_src++; - while(bits--) { - bit_mfm_add (fdi, b & (1 << i)); - i--; - } - } -} - -/* ***** */ -/* AMIGA */ -/* ***** */ - -/* just for testing integrity of Amiga sectors */ - -static void rotateonebit (uae_u8 *start, uae_u8 *end, int shift) -{ - if (shift == 0) - return; - while (start <= end) { - start[0] <<= shift; - start[0] |= start[1] >> (8 - shift); - start++; - } -} - -static int check_offset; -static uae_u16 getmfmword (uae_u8 *mbuf) -{ - uae_u32 v; - - v = (mbuf[0] << 8) | (mbuf[1] << 0); - if (check_offset == 0) - return v; - v <<= 8; - v |= mbuf[2]; - v >>= check_offset; - return v; -} - -#define MFMMASK 0x55555555 -static uae_u32 getmfmlong (uae_u8 * mbuf) -{ - return ((getmfmword (mbuf) << 16) | getmfmword (mbuf + 2)) & MFMMASK; -} - -static int amiga_check_track (FDI *fdi) -{ - int i, j, secwritten = 0; - int fwlen = fdi->out / 8; - int length = 2 * fwlen; - int drvsec = 11; - uae_u32 odd, even, chksum, id, dlong; - uae_u8 *secdata; - uae_u8 secbuf[544]; - uae_u8 bigmfmbuf[60000]; - uae_u8 *mbuf, *mbuf2, *mend; - char sectable[22]; - uae_u8 *raw = fdi->track_dst_buffer; - int slabel, off; - int ok = 1; - - memset (bigmfmbuf, 0, sizeof (bigmfmbuf)); - mbuf = bigmfmbuf; - check_offset = 0; - for (i = 0; i < (fdi->out + 7) / 8; i++) - *mbuf++ = raw[i]; - off = fdi->out & 7; -#if 1 - if (off > 0) { - mbuf--; - *mbuf &= ~((1 << (8 - off)) - 1); - } - j = 0; - while (i < (fdi->out + 7) / 8 + 600) { - *mbuf++ |= (raw[j] >> off) | ((raw[j + 1]) << (8 - off)); - j++; - i++; - } -#endif - mbuf = bigmfmbuf; - - memset (sectable, 0, sizeof (sectable)); - //memcpy (mbuf + fwlen, mbuf, fwlen * sizeof (uae_u16)); - mend = bigmfmbuf + length; - mend -= (4 + 16 + 8 + 512); - - while (secwritten < drvsec) { - int trackoffs; - - for (;;) { - rotateonebit (bigmfmbuf, mend, 1); - if (getmfmword (mbuf) == 0) - break; - if (secwritten == 10) { - mbuf[0] = 0x44; - mbuf[1] = 0x89; - } -// check_offset++; - if (check_offset > 7) { - check_offset = 0; - mbuf++; - if (mbuf >= mend || *mbuf == 0) - break; - } - if (getmfmword (mbuf) == 0x4489) - break; - } - if (mbuf >= mend || *mbuf == 0) - break; - - rotateonebit (bigmfmbuf, mend, check_offset); - check_offset = 0; - - while (getmfmword (mbuf) == 0x4489) - mbuf+= 1 * 2; - mbuf2 = mbuf + 8; - - odd = getmfmlong (mbuf); - even = getmfmlong (mbuf + 2 * 2); - mbuf += 4 * 2; - id = (odd << 1) | even; - - trackoffs = (id & 0xff00) >> 8; - if (trackoffs + 1 > drvsec) { - outlog("illegal sector offset %d\n",trackoffs); - ok = 0; - mbuf = mbuf2; - continue; - } - if ((id >> 24) != 0xff) { - outlog ("sector %d format type %02.2X?\n", trackoffs, id >> 24); - ok = 0; - } - chksum = odd ^ even; - slabel = 0; - for (i = 0; i < 4; i++) { - odd = getmfmlong (mbuf); - even = getmfmlong (mbuf + 8 * 2); - mbuf += 2* 2; - - dlong = (odd << 1) | even; - if (dlong) slabel = 1; - chksum ^= odd ^ even; - } - mbuf += 8 * 2; - odd = getmfmlong (mbuf); - even = getmfmlong (mbuf + 2 * 2); - mbuf += 4 * 2; - if (((odd << 1) | even) != chksum) { - outlog("sector %d header crc error\n", trackoffs); - ok = 0; - mbuf = mbuf2; - continue; - } - outlog("sector %d header crc ok\n", trackoffs); - if (((id & 0x00ff0000) >> 16) != (uae_u32)fdi->current_track) { - outlog("illegal track number %d <> %d\n",fdi->current_track,(id & 0x00ff0000) >> 16); - ok++; - mbuf = mbuf2; - continue; - } - odd = getmfmlong (mbuf); - even = getmfmlong (mbuf + 2 * 2); - mbuf += 4 * 2; - chksum = (odd << 1) | even; - secdata = secbuf + 32; - for (i = 0; i < 128; i++) { - odd = getmfmlong (mbuf); - even = getmfmlong (mbuf + 256 * 2); - mbuf += 2 * 2; - dlong = (odd << 1) | even; - *secdata++ = (uae_u8) (dlong >> 24); - *secdata++ = (uae_u8) (dlong >> 16); - *secdata++ = (uae_u8) (dlong >> 8); - *secdata++ = (uae_u8) dlong; - chksum ^= odd ^ even; - } - mbuf += 256 * 2; - if (chksum) { - outlog("sector %d data checksum error\n",trackoffs); - ok = 0; - } else if (sectable[trackoffs]) { - outlog("sector %d already found?\n", trackoffs); - mbuf = mbuf2; - } else { - outlog("sector %d ok\n",trackoffs); - if (slabel) outlog("(non-empty sector header)\n"); - sectable[trackoffs] = 1; - secwritten++; - if (trackoffs == 9) - mbuf += 0x228; - } - } - for (i = 0; i < drvsec; i++) { - if (!sectable[i]) { - outlog ("sector %d missing\n", i); - ok = 0; - } - } - return ok; -} - -static void amiga_data_raw (FDI *fdi, uae_u8 *secbuf, uae_u8 *crc, int len) -{ - int i; - uae_u8 crcbuf[4]; - - if (!crc) { - memset (crcbuf, 0, 4); - } else { - memcpy (crcbuf, crc ,4); - } - for (i = 0; i < 4; i++) - byte_mfm_add (fdi, crcbuf[i]); - for (i = 0; i < len; i++) - byte_mfm_add (fdi, secbuf[i]); -} - -static void amiga_data (FDI *fdi, uae_u8 *secbuf) -{ - uae_u16 mfmbuf[4 + 512]; - uae_u32 dodd, deven, dck; - int i; - - for (i = 0; i < 512; i += 4) { - deven = ((secbuf[i + 0] << 24) | (secbuf[i + 1] << 16) - | (secbuf[i + 2] << 8) | (secbuf[i + 3])); - dodd = deven >> 1; - deven &= 0x55555555; - dodd &= 0x55555555; - mfmbuf[(i >> 1) + 4] = (uae_u16) (dodd >> 16); - mfmbuf[(i >> 1) + 5] = (uae_u16) dodd; - mfmbuf[(i >> 1) + 256 + 4] = (uae_u16) (deven >> 16); - mfmbuf[(i >> 1) + 256 + 5] = (uae_u16) deven; - } - dck = 0; - for (i = 4; i < 4 + 512; i += 2) - dck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1]; - deven = dodd = dck; - dodd >>= 1; - deven &= 0x55555555; - dodd &= 0x55555555; - mfmbuf[0] = (uae_u16) (dodd >> 16); - mfmbuf[1] = (uae_u16) dodd; - mfmbuf[2] = (uae_u16) (deven >> 16); - mfmbuf[3] = (uae_u16) deven; - - for (i = 0; i < 4 + 512; i ++) - word_post_mfm_add (fdi, mfmbuf[i]); -} - -static void amiga_sector_header (FDI *fdi, uae_u8 *header, uae_u8 *data, int sector, int untilgap) -{ - uae_u8 headerbuf[4], databuf[16]; - uae_u32 deven, dodd, hck; - uae_u16 mfmbuf[24]; - int i; - - byte_mfm_add (fdi, 0); - byte_mfm_add (fdi, 0); - word_add (fdi, 0x4489); - word_add (fdi, 0x4489); - if (header) { - memcpy (headerbuf, header, 4); - } else { - headerbuf[0] = 0xff; - headerbuf[1] = (uae_u8)fdi->current_track; - headerbuf[2] = (uae_u8)sector; - headerbuf[3] = (uae_u8)untilgap; - } - if (data) - memcpy (databuf, data, 16); - else - memset (databuf, 0, 16); - - deven = ((headerbuf[0] << 24) | (headerbuf[1] << 16) - | (headerbuf[2] << 8) | (headerbuf[3])); - dodd = deven >> 1; - deven &= 0x55555555; - dodd &= 0x55555555; - mfmbuf[0] = (uae_u16) (dodd >> 16); - mfmbuf[1] = (uae_u16) dodd; - mfmbuf[2] = (uae_u16) (deven >> 16); - mfmbuf[3] = (uae_u16) deven; - for (i = 0; i < 16; i += 4) { - deven = ((databuf[i] << 24) | (databuf[i + 1] << 16) - | (databuf[i + 2] << 8) | (databuf[i + 3])); - dodd = deven >> 1; - deven &= 0x55555555; - dodd &= 0x55555555; - mfmbuf[(i >> 1) + 0 + 4] = (uae_u16) (dodd >> 16); - mfmbuf[(i >> 1) + 0 + 5] = (uae_u16) dodd; - mfmbuf[(i >> 1) + 8 + 4] = (uae_u16) (deven >> 16); - mfmbuf[(i >> 1) + 8 + 5] = (uae_u16) deven; - } - hck = 0; - for (i = 0; i < 4 + 16; i += 2) - hck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1]; - deven = dodd = hck; - dodd >>= 1; - deven &= 0x55555555; - dodd &= 0x55555555; - mfmbuf[20] = (uae_u16) (dodd >> 16); - mfmbuf[21] = (uae_u16) dodd; - mfmbuf[22] = (uae_u16) (deven >> 16); - mfmbuf[23] = (uae_u16) deven; - - for (i = 0; i < 4 + 16 + 4; i ++) - word_post_mfm_add (fdi, mfmbuf[i]); -} - -/* standard super-extended Amiga sector header */ -static void s20(FDI *fdi) -{ - bit_drop_next (fdi); - debuglog ("s20:header=%s,data=%s", datalog(fdi->track_src, 4), datalog(fdi->track_src + 4, 16)); - amiga_sector_header (fdi, fdi->track_src, fdi->track_src + 4, 0, 0); - fdi->track_src += 4 + 16; -} -/* standard extended Amiga sector header */ -static void s21(FDI *fdi) -{ - bit_drop_next (fdi); - debuglog ("s21:header=%s", datalog(fdi->track_src, 4)); - amiga_sector_header (fdi, fdi->track_src, 0, 0, 0); - fdi->track_src += 4; -} -/* standard Amiga sector header */ -static void s22(FDI *fdi) -{ - bit_drop_next (fdi); - debuglog("s22:sector=%d,untilgap=%d", fdi->track_src[0], fdi->track_src[1]); - amiga_sector_header (fdi, 0, 0, fdi->track_src[0], fdi->track_src[1]); - fdi->track_src += 2; -} -/* standard 512-byte, CRC-correct Amiga data */ -static void s23(FDI *fdi) -{ - debuglog("s23:data=%s", datalog (fdi->track_src, 512)); - amiga_data (fdi, fdi->track_src); - fdi->track_src += 512; -} -/* not-decoded, 128*2^x-byte, CRC-correct Amiga data */ -static void s24(FDI *fdi) -{ - int shift = *fdi->track_src++; - debuglog("s24:shift=%d,data=%s", shift, datalog (fdi->track_src, 128 << shift)); - amiga_data_raw (fdi, fdi->track_src, 0, 128 << shift); - fdi->track_src += 128 << shift; -} -/* not-decoded, 128*2^x-byte, CRC-incorrect Amiga data */ -static void s25(FDI *fdi) -{ - int shift = *fdi->track_src++; - debuglog("s25:shift=%d,crc=%s,data=%s", shift, datalog (fdi->track_src, 4), datalog (fdi->track_src + 4, 128 << shift)); - amiga_data_raw (fdi, fdi->track_src + 4, fdi->track_src, 128 << shift); - fdi->track_src += 4 + (128 << shift); -} -/* standard extended Amiga sector */ -static void s26(FDI *fdi) -{ - s21 (fdi); - debuglog("s26:data=%s", datalog (fdi->track_src, 512)); - amiga_data (fdi, fdi->track_src); - fdi->track_src += 512; -} -/* standard short Amiga sector */ -static void s27(FDI *fdi) -{ - s22 (fdi); - debuglog("s27:data=%s", datalog (fdi->track_src, 512)); - amiga_data (fdi, fdi->track_src); - fdi->track_src += 512; -} - -/* *** */ -/* IBM */ -/* *** */ - -static uae_u16 ibm_crc (uae_u8 byte, int reset) -{ - static uae_u16 crc; - int i; - - if (reset) crc = 0xcdb4; - for (i = 0; i < 8; i++) { - if (crc & 0x8000) { - crc <<= 1; - if (!(byte & 0x80)) crc ^= 0x1021; - } else { - crc <<= 1; - if (byte & 0x80) crc ^= 0x1021; - } - byte <<= 1; - } - return crc; -} - -static void ibm_data (FDI *fdi, uae_u8 *data, uae_u8 *crc, int len) -{ - int i; - uae_u8 crcbuf[2]; - uae_u16 crcv; - - word_add (fdi, 0x4489); - word_add (fdi, 0x4489); - word_add (fdi, 0x4489); - byte_mfm_add (fdi, 0xfb); - ibm_crc (0xfb, 1); - for (i = 0; i < len; i++) { - byte_mfm_add (fdi, data[i]); - crcv = ibm_crc (data[i], 0); - } - if (!crc) { - crc = crcbuf; - crc[0] = (uae_u8)(crcv >> 8); - crc[1] = (uae_u8)crcv; - } - byte_mfm_add (fdi, crc[0]); - byte_mfm_add (fdi, crc[1]); -} - -static void ibm_sector_header (FDI *fdi, uae_u8 *data, uae_u8 *crc, int secnum, int pre) -{ - uae_u8 secbuf[5]; - uae_u8 crcbuf[2]; - uae_u16 crcv; - int i; - - if (pre) - bytes_mfm_add (fdi, 0, 12); - word_add (fdi, 0x4489); - word_add (fdi, 0x4489); - word_add (fdi, 0x4489); - secbuf[0] = 0xfe; - if (secnum >= 0) { - secbuf[1] = (uae_u8)(fdi->current_track/2); - secbuf[2] = (uae_u8)(fdi->current_track%2); - secbuf[3] = (uae_u8)secnum; - secbuf[4] = 2; - } else { - memcpy (secbuf + 1, data, 4); - } - ibm_crc (secbuf[0], 1); - ibm_crc (secbuf[1], 0); - ibm_crc (secbuf[2], 0); - ibm_crc (secbuf[3], 0); - crcv = ibm_crc (secbuf[4], 0); - if (crc) { - memcpy (crcbuf, crc, 2); - } else { - crcbuf[0] = (uae_u8)(crcv >> 8); - crcbuf[1] = (uae_u8)crcv; - } - /* data */ - for (i = 0;i < 5; i++) - byte_mfm_add (fdi, secbuf[i]); - /* crc */ - byte_mfm_add (fdi, crcbuf[0]); - byte_mfm_add (fdi, crcbuf[1]); -} - -/* standard IBM index address mark */ -static void s10(FDI *fdi) -{ - bit_drop_next (fdi); - bytes_mfm_add (fdi, 0, 12); - word_add (fdi, 0x5224); - word_add (fdi, 0x5224); - word_add (fdi, 0x5224); - byte_mfm_add (fdi, 0xfc); -} -/* standard IBM pre-gap */ -static void s11(FDI *fdi) -{ - bit_drop_next (fdi); - bytes_mfm_add (fdi, 0x4e, 78); - bit_dedrop (fdi); - s10 (fdi); - bytes_mfm_add (fdi, 0x4e, 50); -} -/* standard ST pre-gap */ -static void s12(FDI *fdi) -{ - bit_drop_next (fdi); - bytes_mfm_add (fdi, 0x4e, 78); -} -/* standard extended IBM sector header */ -static void s13(FDI *fdi) -{ - bit_drop_next (fdi); - debuglog ("s13:header=%s", datalog (fdi->track_src, 4)); - ibm_sector_header (fdi, fdi->track_src, 0, -1, 1); - fdi->track_src += 4; -} -/* standard mini-extended IBM sector header */ -static void s14(FDI *fdi) -{ - debuglog ("s14:header=%s", datalog (fdi->track_src, 4)); - ibm_sector_header (fdi, fdi->track_src, 0, -1, 0); - fdi->track_src += 4; -} -/* standard short IBM sector header */ -static void s15(FDI *fdi) -{ - bit_drop_next (fdi); - debuglog ("s15:sector=%d", *fdi->track_src); - ibm_sector_header (fdi, 0, 0, *fdi->track_src++, 1); -} -/* standard mini-short IBM sector header */ -static void s16(FDI *fdi) -{ - debuglog ("s16:track=%d", *fdi->track_src); - ibm_sector_header (fdi, 0, 0, *fdi->track_src++, 0); -} -/* standard CRC-incorrect mini-extended IBM sector header */ -static void s17(FDI *fdi) -{ - debuglog ("s17:header=%s,crc=%s", datalog (fdi->track_src, 4), datalog (fdi->track_src + 4, 2)); - ibm_sector_header (fdi, fdi->track_src, fdi->track_src + 4, -1, 0); - fdi->track_src += 4 + 2; -} -/* standard CRC-incorrect mini-short IBM sector header */ -static void s18(FDI *fdi) -{ - debuglog ("s18:sector=%d,header=%s", *fdi->track_src, datalog (fdi->track_src + 1, 4)); - ibm_sector_header (fdi, 0, fdi->track_src + 1, *fdi->track_src, 0); - fdi->track_src += 1 + 4; -} -/* standard 512-byte CRC-correct IBM data */ -static void s19(FDI *fdi) -{ - debuglog ("s19:data=%s", datalog (fdi->track_src , 512)); - ibm_data (fdi, fdi->track_src, 0, 512); - fdi->track_src += 512; -} -/* standard 128*2^x-byte-byte CRC-correct IBM data */ -static void s1a(FDI *fdi) -{ - int shift = *fdi->track_src++; - debuglog ("s1a:shift=%d,data=%s", shift, datalog (fdi->track_src , 128 << shift)); - ibm_data (fdi, fdi->track_src, 0, 128 << shift); - fdi->track_src += 128 << shift; -} -/* standard 128*2^x-byte-byte CRC-incorrect IBM data */ -static void s1b(FDI *fdi) -{ - int shift = *fdi->track_src++; - debuglog ("s1b:shift=%d,crc=%s,data=%s", shift, datalog (fdi->track_src + (128 << shift), 2), datalog (fdi->track_src , 128 << shift)); - ibm_data (fdi, fdi->track_src, fdi->track_src + (128 << shift), 128 << shift); - fdi->track_src += (128 << shift) + 2; -} -/* standard extended IBM sector */ -static void s1c(FDI *fdi) -{ - int shift = fdi->track_src[3]; - s13 (fdi); - bytes_mfm_add (fdi, 0x4e, 22); - bytes_mfm_add (fdi, 0x00, 12); - ibm_data (fdi, fdi->track_src, 0, 128 << shift); - fdi->track_src += 128 << shift; -} -/* standard short IBM sector */ -static void s1d(FDI *fdi) -{ - s15 (fdi); - bytes_mfm_add (fdi, 0x4e, 22); - bytes_mfm_add (fdi, 0x00, 12); - s19 (fdi); -} - -/* end marker */ -static void sff(FDI *fdi) -{ -} - -typedef void (*decode_described_track_func)(FDI*); - -static decode_described_track_func decode_sectors_described_track[] = -{ - s00,s01,s02,s03,s04,dxx,dxx,dxx,s08,s09,s0a,s0b,s0c,s0d,dxx,dxx, /* 00-0F */ - s10,s11,s12,s13,s14,s15,s16,s17,s18,s19,s1a,s1b,s1c,s1d,dxx,dxx, /* 10-1F */ - s20,s21,s22,s23,s24,s25,s26,s27,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 20-2F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 30-3F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 40-4F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 50-5F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 60-6F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 70-7F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 80-8F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 90-9F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* A0-AF */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* B0-BF */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* C0-CF */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* D0-DF */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* E0-EF */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,sff /* F0-FF */ -}; - -static void track_amiga (struct fdi *fdi, int first_sector, int max_sector) -{ - int i; - - bit_add (fdi, 0); - bit_drop_next (fdi); - for (i = 0; i < max_sector; i++) { - amiga_sector_header (fdi, 0, 0, first_sector, max_sector - i); - amiga_data (fdi, fdi->track_src + first_sector * 512); - first_sector++; - if (first_sector >= max_sector) first_sector = 0; - } - bytes_mfm_add (fdi, 0, 260); /* gap */ -} -static void track_atari_st (struct fdi *fdi, int max_sector) -{ - int i, gap3; - uae_u8 *p = fdi->track_src; - - switch (max_sector) - { - case 9: - gap3 = 40; - break; - case 10: - gap3 = 24; - break; - } - s15 (fdi); - for (i = 0; i < max_sector; i++) { - byte_mfm_add (fdi, 0x4e); - byte_mfm_add (fdi, 0x4e); - ibm_sector_header (fdi, 0, 0, fdi->current_track, 1); - ibm_data (fdi, p + i * 512, 0, 512); - bytes_mfm_add (fdi, 0x4e, gap3); - } - bytes_mfm_add (fdi, 0x4e, 660 - gap3); - fdi->track_src += fdi->track_len * 256; -} -static void track_pc (struct fdi *fdi, int max_sector) -{ - int i, gap3; - uae_u8 *p = fdi->track_src; - - switch (max_sector) - { - case 8: - gap3 = 116; - break; - case 9: - gap3 = 54; - break; - default: - gap3 = 100; /* fixme */ - break; - } - s11 (fdi); - for (i = 0; i < max_sector; i++) { - byte_mfm_add (fdi, 0x4e); - byte_mfm_add (fdi, 0x4e); - ibm_sector_header (fdi, 0, 0, fdi->current_track, 1); - ibm_data (fdi, p + i * 512, 0, 512); - bytes_mfm_add (fdi, 0x4e, gap3); - } - bytes_mfm_add (fdi, 0x4e, 600 - gap3); - fdi->track_src += fdi->track_len * 256; -} - -/* amiga dd */ -static void track_amiga_dd (struct fdi *fdi) -{ - uae_u8 *p = fdi->track_src; - track_amiga (fdi, fdi->track_len >> 4, 11); - fdi->track_src = p + (fdi->track_len & 15) * 512; -} -/* amiga hd */ -static void track_amiga_hd (struct fdi *fdi) -{ - uae_u8 *p = fdi->track_src; - track_amiga (fdi, 0, 22); - fdi->track_src = p + fdi->track_len * 256; -} -/* atari st 9 sector */ -static void track_atari_st_9 (struct fdi *fdi) -{ - track_atari_st (fdi, 9); -} -/* atari st 10 sector */ -static void track_atari_st_10 (struct fdi *fdi) -{ - track_atari_st (fdi, 10); -} -/* pc 8 sector */ -static void track_pc_8 (struct fdi *fdi) -{ - track_pc (fdi, 8); -} -/* pc 9 sector */ -static void track_pc_9 (struct fdi *fdi) -{ - track_pc (fdi, 9); -} -/* pc 15 sector */ -static void track_pc_15 (struct fdi *fdi) -{ - track_pc (fdi, 15); -} -/* pc 18 sector */ -static void track_pc_18 (struct fdi *fdi) -{ - track_pc (fdi, 18); -} -/* pc 36 sector */ -static void track_pc_36 (struct fdi *fdi) -{ - track_pc (fdi, 36); -} - -typedef void (*decode_normal_track_func)(FDI*); - -static decode_normal_track_func decode_normal_track[] = -{ - track_empty, /* 0 */ - track_amiga_dd, track_amiga_hd, /* 1-2 */ - track_atari_st_9, track_atari_st_10, /* 3-4 */ - track_pc_8, track_pc_9, track_pc_15, track_pc_18, track_pc_36, /* 5-9 */ - zxx,zxx,zxx,zxx,zxx /* A-F */ -}; - -static void fix_mfm_sync (FDI *fdi) -{ - int i, pos, off1, off2, off3, mask1, mask2, mask3; - - for (i = 0; i < fdi->mfmsync_offset; i++) { - pos = fdi->mfmsync_buffer[i]; - off1 = (pos - 1) >> 3; - off2 = (pos + 1) >> 3; - off3 = pos >> 3; - mask1 = 1 << (7 - ((pos - 1) & 7)); - mask2 = 1 << (7 - ((pos + 1) & 7)); - mask3 = 1 << (7 - (pos & 7)); - if (!(fdi->track_dst[off1] & mask1) && !(fdi->track_dst[off2] & mask2)) - fdi->track_dst[off3] |= mask3; - else - fdi->track_dst[off3] &= ~mask3; - } -} - -static int handle_sectors_described_track (FDI *fdi) -{ - int oldout; - uae_u8 *start_src = fdi->track_src ; - fdi->encoding_type = *fdi->track_src++; - fdi->index_offset = get_u32(fdi->track_src); - fdi->index_offset >>= 8; - fdi->track_src += 3; - outlog ("sectors_described, index offset: %d\n",fdi->index_offset); - - do { - fdi->track_type = *fdi->track_src++; - outlog ("%06.6X %06.6X %02.2X:",fdi->track_src - start_src + 0x200, fdi->out/8, fdi->track_type); - oldout = fdi->out; - decode_sectors_described_track[fdi->track_type](fdi); - outlog(" %d\n", fdi->out - oldout); - oldout = fdi->out; - if (fdi->out < 0 || fdi->err) { - outlog ("\nin %d bytes, out %d bits\n", fdi->track_src - fdi->track_src_buffer, fdi->out); - return -1; - } - if (fdi->track_src - fdi->track_src_buffer >= fdi->track_src_len) { - outlog ("source buffer overrun, previous type: %02.2X\n", fdi->track_type); - return -1; - } - } while (fdi->track_type != 0xff); - outlog("\n"); - fix_mfm_sync (fdi); - return fdi->out; -} - -static uae_u8 *fdi_decompress (int pulses, uae_u8 *sizep, uae_u8 *src, int *dofree) -{ - uae_u32 size = get_u24 (sizep); - uae_u32 *dst2; - int len = size & 0x3fffff; - uae_u8 *dst; - int mode = size >> 22, i; - - *dofree = 0; - if (mode == 0 && pulses * 2 > len) - mode = 1; - if (mode == 0) { - dst2 = (uae_u32*)src; - dst = src; - for (i = 0; i < pulses; i++) { - *dst2++ = get_u32 (src); - src += 4; - } - } else if (mode == 1) { - dst = fdi_malloc (pulses *4); - *dofree = 1; - fdi_decode (src, pulses, dst); - } else { - dst = 0; - } - return dst; -} - -static void dumpstream(int track, uae_u8 *stream, int len) -{ -#if 0 - char name[100]; - FILE *f; - - sprintf (name, "track_%d.raw", track); - f = fopen(name, "wb"); - fwrite (stream, 1, len * 4, f); - fclose (f); -#endif -} - -static int bitoffset; - -STATIC_INLINE void addbit (uae_u8 *p, int bit) -{ - int off1 = bitoffset / 8; - int off2 = bitoffset % 8; - p[off1] |= bit << (7 - off2); - bitoffset++; -} - - -struct pulse_sample { - unsigned long size; - int number_of_bits; -}; - -#define FDI_MAX_ARRAY 10 /* change this value as you want */ -static int pulse_limitval = 15; /* tolerance of 15% */ -static struct pulse_sample psarray[FDI_MAX_ARRAY]; -static int array_index; -static unsigned long total; -static int totaldiv; - -static void init_array(unsigned long standard_MFM_2_bit_cell_size, int nb_of_bits) -{ - int i; - - for (i = 0; i < FDI_MAX_ARRAY; i++) { - psarray[i].size = standard_MFM_2_bit_cell_size; // That is (total track length / 50000) for Amiga double density - total += psarray[i].size; - psarray[i].number_of_bits = nb_of_bits; - totaldiv += psarray[i].number_of_bits; - } - array_index = 0; -} - -static void fdi2_mfm_decode(FDI *fdi, unsigned long totalavg, uae_u32 *avgp, uae_u32 *minp, uae_u32 *maxp, uae_u8 *idx, int maxidx, int pulses) -{ - unsigned long adjust; - unsigned long adjusted_pulse; - unsigned long standard_MFM_2_bit_cell_size = totalavg / 50000; - unsigned long standard_MFM_8_bit_cell_size = totalavg / 12500; - int real_size, i, j, nexti, eodat, outstep, randval; - uae_u8 *d = fdi->track_dst_buffer; - uae_u16 *pt = fdi->track_dst_buffer_timing; - uae_u32 ref_pulse, pulse; - long jitter; - - /* detects a long-enough stable pulse coming just after another stable pulse */ - i = 1; - while ( (i < pulses) && ( (idx[i] < maxidx) - || (idx[i - 1] < maxidx) - || (minp[i] < (standard_MFM_2_bit_cell_size - (standard_MFM_2_bit_cell_size / 4))) ) ) - i++; - if (i == pulses) { - outlog ("No stable and long-enough pulse in track.\n"); - return; - } - nexti = i; - eodat = i; - i--; - adjust = 0; - total = 0; - totaldiv = 0; - init_array(standard_MFM_2_bit_cell_size, 2); - bitoffset = 0; - ref_pulse = 0; - jitter = 0; - outstep = -1; - while (outstep < 2) { - - /* calculates the current average bitrate from previous decoded data */ - uae_u32 avg_size = (total << 3) / totaldiv; /* this is the new average size for one MFM bit */ - /* uae_u32 avg_size = (uae_u32)((((float)total)*8.0) / ((float)totaldiv)); */ - /* you can try tighter ranges than 25%, or wider ranges. I would probably go for tighter... */ - if ((avg_size < (standard_MFM_8_bit_cell_size - (pulse_limitval * standard_MFM_8_bit_cell_size / 100))) || - (avg_size > (standard_MFM_8_bit_cell_size + (pulse_limitval * standard_MFM_8_bit_cell_size / 100)))) { - //init_array(standard_MFM_2_bit_cell_size, 2); - avg_size = standard_MFM_8_bit_cell_size; - } - /* this is to prevent the average value from going too far - * from the theoretical value, otherwise it could progressively go to (2 * - * real value), or (real value / 2), etc. */ - - /* gets the next long-enough pulse (this may require more than one pulse) */ - pulse = 0; - while (pulse < ((avg_size / 4) - (avg_size / 16))) { - uae_u32 avg_pulse, min_pulse, max_pulse; - i++; - if (i >= pulses) - i = 0; - if (i == nexti) { - do { - nexti++; - if (nexti >= pulses) - nexti = 0; - } while (idx[nexti] < maxidx); - } - if (idx[i] >= maxidx) { /* stable pulse */ - avg_pulse = avgp[i] - jitter; - min_pulse = minp[i]; - max_pulse = maxp[i]; - if (jitter >= 0) - min_pulse -= jitter; - else - max_pulse -= jitter; - if ((maxp[nexti] - avgp[nexti]) < (avg_pulse - min_pulse)) - min_pulse = avg_pulse - (maxp[nexti] - avgp[nexti]); - if ((avgp[nexti] - minp[nexti]) < (max_pulse - avg_pulse)) - max_pulse = avg_pulse + (avgp[nexti] - minp[nexti]); - if (min_pulse < ref_pulse) - min_pulse = ref_pulse; - randval = rand(); - if (randval < (RAND_MAX / 2)) { - if (randval > (RAND_MAX / 4)) { - if (randval <= (3 * RAND_MAX / 8)) - randval = (2 * randval) - (RAND_MAX /4); - else - randval = (4 * randval) - RAND_MAX; - } - jitter = 0 - (randval * (avg_pulse - min_pulse)) / RAND_MAX; - } else { - randval -= RAND_MAX / 2; - if (randval > (RAND_MAX / 4)) { - if (randval <= (3 * RAND_MAX / 8)) - randval = (2 * randval) - (RAND_MAX /4); - else - randval = (4 * randval) - RAND_MAX; - } - jitter = (randval * (max_pulse - avg_pulse)) / RAND_MAX; - } - avg_pulse += jitter; - if ((avg_pulse < min_pulse) || (avg_pulse > max_pulse)) { - outlog ("avg_pulse outside bounds! avg=%u min=%u max=%u\n", avg_pulse, min_pulse, max_pulse); - outlog("avgp=%u (%u) minp=%u (%u) maxp=%u (%u) jitter=%d i=%d ni=%d\n", - avgp[i], avgp[nexti], minp[i], minp[nexti], maxp[i], maxp[nexti], jitter, i, nexti); - } - if (avg_pulse < ref_pulse) - outlog ("avg_pulse < ref_pulse! (%u < %u)\n", avg_pulse, ref_pulse); - pulse += avg_pulse - ref_pulse; - ref_pulse = 0; - if (i == eodat) - outstep++; - } else if (rand() <= ((idx[i] * RAND_MAX) / maxidx)) { - avg_pulse = avgp[i]; - min_pulse = minp[i]; - max_pulse = maxp[i]; - randval = rand(); - if (randval < (RAND_MAX / 2)) { - if (randval > (RAND_MAX / 4)) { - if (randval <= (3 * RAND_MAX / 8)) - randval = (2 * randval) - (RAND_MAX /4); - else - randval = (4 * randval) - RAND_MAX; - } - avg_pulse -= (randval * (avg_pulse - min_pulse)) / RAND_MAX; - } else { - randval -= RAND_MAX / 2; - if (randval > (RAND_MAX / 4)) { - if (randval <= (3 * RAND_MAX / 8)) - randval = (2 * randval) - (RAND_MAX /4); - else - randval = (4 * randval) - RAND_MAX; - } - avg_pulse += (randval * (max_pulse - avg_pulse)) / RAND_MAX; - } - if ((avg_pulse > ref_pulse) && (avg_pulse < (avgp[nexti] - jitter))) { - pulse += avg_pulse - ref_pulse; - ref_pulse = avg_pulse; - } - } - } - - /* gets the size in bits from the pulse width, considering the current average bitrate */ - adjusted_pulse = pulse; - real_size = 0; - while (adjusted_pulse >= avg_size) { - real_size += 4; - adjusted_pulse -= avg_size / 2; - } - adjusted_pulse <<= 3; - while (adjusted_pulse >= ((avg_size * 4) + (avg_size / 4))) { - real_size += 2; - adjusted_pulse -= avg_size * 2; - } - if (adjusted_pulse >= ((avg_size * 3) + (avg_size / 4))) { - if (adjusted_pulse <= ((avg_size * 4) - (avg_size / 4))) { - if ((2 * ((adjusted_pulse >> 2) - adjust)) <= ((2 * avg_size) - (avg_size / 4))) - real_size += 3; - else - real_size += 4; - } else - real_size += 4; - } else { - if (adjusted_pulse > ((avg_size * 3) - (avg_size / 4))) { - real_size += 3; - } else { - if (adjusted_pulse >= ((avg_size * 2) + (avg_size / 4))) { - if ((2 * ((adjusted_pulse >> 2) - adjust)) < (avg_size + (avg_size / 4))) - real_size += 2; - else - real_size += 3; - } else - real_size += 2; - } - } - - if (outstep == 1) { - for (j = real_size; j > 1; j--) - addbit (d, 0); - addbit (d, 1); - for (j = 0; j < real_size; j++) - *pt++ = (uae_u16)(pulse / real_size); - } - - /* prepares for the next pulse */ - adjust = ((real_size * avg_size)/8) - pulse; - total -= psarray[array_index].size; - totaldiv -= psarray[array_index].number_of_bits; - psarray[array_index].size = pulse; - psarray[array_index].number_of_bits = real_size; - total += pulse; - totaldiv += real_size; - array_index++; - if (array_index >= FDI_MAX_ARRAY) - array_index = 0; - } - - fdi->out = bitoffset; -} - -static void fdi2_celltiming (FDI *fdi, unsigned long totalavg, int bitoffset, uae_u16 *out) -{ - uae_u16 *pt2, *pt; - double avg_bit_len; - int i; - - avg_bit_len = (double)totalavg / (double)bitoffset; - pt2 = fdi->track_dst_buffer_timing; - pt = out; - for (i = 0; i < bitoffset / 8; i++) { - double v = (pt2[0] + pt2[1] + pt2[2] + pt2[3] + pt2[4] + pt2[5] + pt2[6] + pt2[7]) / 8.0; - v = 1000.0 * v / avg_bit_len; - *pt++ = (uae_u16)v; - pt2 += 8; - } - *out++ = *pt; - *out = *pt; -} - -static int decode_lowlevel_track (FDI *fdi, int *indexoffsetp, int track, struct fdi_cache *cache) -{ - uae_u8 *p1, *d; - uae_u32 *p2; - uae_u32 *avgp, *minp = 0, *maxp = 0; - uae_u8 *idxp = 0; - uae_u32 maxidx, minidx, totalavg, weakbits; - int i, len, pulses, indexoffset; - int avg_free, min_free = 0, max_free = 0, idx_free; - int idx_off1, idx_off2, idx_off3; - - d = fdi->track_dst; - p1 = fdi->track_src; - pulses = get_u32 (p1); - if (!pulses) - return -1; - p1 += 4; - len = 12; - avgp = (uae_u32*)fdi_decompress (pulses, p1 + 0, p1 + len, &avg_free); - dumpstream(track, (uae_u8*)avgp, pulses); - len += get_u24 (p1 + 0) & 0x3fffff; - if (!avgp) - return -1; - if (get_u24 (p1 + 3) && get_u24 (p1 + 6)) { - minp = (uae_u32*)fdi_decompress (pulses, p1 + 3, p1 + len, &min_free); - len += get_u24 (p1 + 3) & 0x3fffff; - maxp = (uae_u32*)fdi_decompress (pulses, p1 + 6, p1 + len, &max_free); - len += get_u24 (p1 + 6) & 0x3fffff; - /* Computes the real min and max values */ - for (i = 0; i < pulses; i++) { - maxp[i] = avgp[i] + minp[i] - maxp[i]; - minp[i] = avgp[i] - minp[i]; - } - } else { - minp = avgp; - maxp = avgp; - } - if (get_u24 (p1 + 9)) { - idx_off1 = 0; - idx_off2 = 1; - idx_off3 = 2; - idxp = fdi_decompress (pulses, p1 + 9, p1 + len, &idx_free); - if (idx_free) { - if (idxp[0] == 0 && idxp[1] == 0) { - idx_off1 = 2; - idx_off2 = 3; - } else { - idx_off1 = 1; - idx_off2 = 0; - } - idx_off3 = 4; - } - } else { - idxp = fdi_malloc (pulses * 2); - idx_free = 1; - for (i = 0; i < pulses; i++) { - idxp[i * 2 + 0] = 2; - idxp[i * 2 + 1] = 0; - } - idxp[0] = 1; - idxp[1] = 1; - } - - maxidx = 0; - minidx = 255; - indexoffset = 0; - p1 = idxp; - for (i = 0; i < pulses; i++) { - if (p1[idx_off1] + p1[idx_off2] > maxidx) - maxidx = p1[idx_off1] + p1[idx_off2]; - if (abs (p1[idx_off1] - p1[idx_off2]) < minidx) { - minidx = abs (p1[idx_off1] - p1[idx_off2]); - indexoffset = i; - } - p1 += idx_off3; - } - p1 = idxp; - p2 = avgp; - totalavg = 0; - weakbits = 0; - for (i = 0; i < pulses; i++) { - int sum = p1[idx_off1] + p1[idx_off2]; - if (sum >= maxidx) { - totalavg += *p2; - } else { - weakbits++; - } - p2++; - p1 += idx_off3; - idxp[i] = sum; - } - len = totalavg / 100000; - outlog("totalavg=%u index=%d maxidx=%d weakbits=%d len=%d\n", - totalavg, indexoffset, maxidx, weakbits, len); - cache->avgp = avgp; - cache->idxp = idxp; - cache->minp = minp; - cache->maxp = maxp; - cache->avg_free = avg_free; - cache->idx_free = idx_free; - cache->min_free = min_free; - cache->max_free = max_free; - cache->totalavg = totalavg; - cache->pulses = pulses; - cache->maxidx = maxidx; - cache->indexoffset = indexoffset; - cache->weakbits = weakbits; - cache->lowlevel = 1; - - return 1; -} - -static unsigned char fdiid[]={"Formatted Disk Image file"}; -static int bit_rate_table[16] = { 125,150,250,300,500,1000 }; - -void fdi2raw_header_free (FDI *fdi) -{ - int i; - - fdi_free (fdi->mfmsync_buffer); - fdi_free (fdi->track_src_buffer); - fdi_free (fdi->track_dst_buffer); - fdi_free (fdi->track_dst_buffer_timing); - for (i = 0; i < MAX_TRACKS; i++) { - struct fdi_cache *c = &fdi->cache[i]; - if (c->idx_free) - fdi_free (c->idxp); - if (c->avg_free) - fdi_free (c->avgp); - if (c->min_free) - fdi_free (c->minp); - if (c->max_free) - fdi_free (c->maxp); - } - fdi_free (fdi); - debuglog ("FREE: memory allocated %d\n", fdi_allocated); -} - -int fdi2raw_get_last_track (FDI *fdi) -{ - return fdi->last_track; -} - -int fdi2raw_get_num_sector (FDI *fdi) -{ - if (fdi->header[152] == 0x02) - return 22; - return 11; -} - -int fdi2raw_get_last_head (FDI *fdi) -{ - return fdi->last_head; -} - -int fdi2raw_get_rotation (FDI *fdi) -{ - return fdi->rotation_speed; -} - -int fdi2raw_get_bit_rate (FDI *fdi) -{ - return fdi->bit_rate; -} - -int fdi2raw_get_type (FDI *fdi) -{ - return fdi->disk_type; -} - -int fdi2raw_get_write_protect (FDI *fdi) -{ - return fdi->write_protect; -} - -FDI *fdi2raw_header(struct zfile *f) -{ - int i, offset, oldseek; - uae_u8 type, size; - FDI *fdi; - - debuglog ("ALLOC: memory allocated %d\n", fdi_allocated); - fdi = fdi_malloc(sizeof(FDI)); - memset (fdi, 0, sizeof (FDI)); - fdi->file = f; - oldseek = zfile_ftell (fdi->file); - zfile_fseek (fdi->file, 0, SEEK_SET); - zfile_fread (fdi->header, 2048, 1, fdi->file); - zfile_fseek (fdi->file, oldseek, SEEK_SET); - if (memcmp (fdiid, fdi->header, strlen (fdiid)) ) { - fdi_free(fdi); - return NULL; - } - if ((fdi->header[140] != 1 && fdi->header[140] != 2) || fdi->header[141] != 0) { - fdi_free(fdi); - return NULL; - } - - fdi->mfmsync_buffer = fdi_malloc (MAX_MFM_SYNC_BUFFER * sizeof(int)); - fdi->track_src_buffer = fdi_malloc (MAX_SRC_BUFFER); - fdi->track_dst_buffer = fdi_malloc (MAX_DST_BUFFER); - fdi->track_dst_buffer_timing = fdi_malloc (MAX_TIMING_BUFFER); - - fdi->last_track = ((fdi->header[142] << 8) + fdi->header[143]) + 1; - fdi->last_track *= fdi->header[144] + 1; - if (fdi->last_track > MAX_TRACKS) - fdi->last_track = MAX_TRACKS; - fdi->last_head = fdi->header[144]; - fdi->disk_type = fdi->header[145]; - fdi->rotation_speed = fdi->header[146] + 128; - fdi->write_protect = fdi->header[147] & 1; - outlog ("FDI version %d.%d\n", fdi->header[140], fdi->header[141]); - outlog ("last_track=%d rotation_speed=%d\n",fdi->last_track,fdi->rotation_speed); - - offset = 512; - i = fdi->last_track; - if (i > 180) { - offset += 512; - i -= 180; - while (i > 256) { - offset += 512; - i -= 256; - } - } - for (i = 0; i < fdi->last_track; i++) { - fdi->track_offsets[i] = offset; - type = fdi->header[152 + i * 2]; - size = fdi->header[152 + i * 2 + 1]; - if (type == 1) - offset += (size & 15) * 512; - else if ((type & 0xc0) == 0x80) - offset += (((type & 0x3f) << 8) | size) * 256; - else - offset += size * 256; - } - fdi->track_offsets[i] = offset; - - return fdi; -} - - -int fdi2raw_loadrevolution_2 (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, int track, int *tracklength, int *indexoffsetp, int *multirev) -{ - struct fdi_cache *cache = &fdi->cache[track]; - int len, i; - - memset (fdi->track_dst_buffer, 0, MAX_DST_BUFFER); - fdi2_mfm_decode (fdi, cache->totalavg, - cache->avgp, cache->minp, cache->maxp, cache->idxp, - cache->maxidx, cache->pulses); - //fdi2_gcr_decode (fdi, totalavg, avgp, minp, maxp, idxp, idx_off1, idx_off2, idx_off3, maxidx, pulses); - outlog("track %d: number of bits=%d avg len=%.2f weakbits=%d\n", - track, bitoffset, (double)cache->totalavg / bitoffset, cache->weakbits); - len = fdi->out; - if (cache->weakbits >= 10 && multirev) - *multirev = 1; - *tracklength = len; - - for (i = 0; i < (len + 15) / (2 * 8); i++) { - uae_u8 *data = fdi->track_dst_buffer + i * 2; - *mfmbuf++ = 256 * *data + *(data + 1); - } - fdi2_celltiming (fdi, cache->totalavg, len, tracktiming); - if (indexoffsetp) - *indexoffsetp = cache->indexoffset; - return 1; -} - -int fdi2raw_loadrevolution (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, int track, int *tracklength) -{ - return fdi2raw_loadrevolution_2 (fdi, mfmbuf, tracktiming, track, tracklength, 0, 0); -} - -int fdi2raw_loadtrack (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, int track, int *tracklength, int *indexoffsetp, int *multirev) -{ - uae_u8 *p; - int outlen, i, indexoffset = 0; - struct fdi_cache *cache = &fdi->cache[track]; - - if (cache->lowlevel) - return fdi2raw_loadrevolution_2 (fdi, mfmbuf, tracktiming, track, tracklength, indexoffsetp, multirev); - - fdi->err = 0; - fdi->track_src_len = fdi->track_offsets[track + 1] - fdi->track_offsets[track]; - zfile_fseek (fdi->file, fdi->track_offsets[track], SEEK_SET); - zfile_fread (fdi->track_src_buffer, fdi->track_src_len, 1, fdi->file); - memset (fdi->track_dst_buffer, 0, MAX_DST_BUFFER); - fdi->track_dst_buffer_timing[0] = 0; - - fdi->current_track = track; - fdi->track_src = fdi->track_src_buffer; - fdi->track_dst = fdi->track_dst_buffer; - p = fdi->header + 152 + fdi->current_track * 2; - fdi->track_type = *p++; - fdi->track_len = *p++; - fdi->bit_rate = 0; - fdi->out = 0; - fdi->mfmsync_offset = 0; - - if ((fdi->track_type & 0xf0) == 0xf0 || (fdi->track_type & 0xf0) == 0xe0) - fdi->bit_rate = bit_rate_table[fdi->track_type & 0x0f]; - else - fdi->bit_rate = 250; - - outlog ("track %d: srclen: %d track_type: %02.2X, bitrate: %d\n", - fdi->current_track, fdi->track_src_len, fdi->track_type, fdi->bit_rate); - - if ((fdi->track_type & 0xc0) == 0x80) { - - outlen = decode_lowlevel_track (fdi, &indexoffset, track, cache); - - } else if ((fdi->track_type & 0xf0) == 0xf0) { - - outlen = decode_raw_track (fdi); - - } else if ((fdi->track_type & 0xf0) == 0xe0) { - - outlen = handle_sectors_described_track (fdi); - - } else if ((fdi->track_type & 0xf0)) { - - zxx (fdi); - outlen = -1; - - } else if (fdi->track_type < 0x10) { - - decode_normal_track[fdi->track_type](fdi); - fix_mfm_sync (fdi); - outlen = fdi->out; - - } else { - - zxx (fdi); - outlen = -1; - - } - -// amiga_check_track (fdi); - - if (fdi->err) - return 0; - - if (outlen > 0) { - if (cache->lowlevel) - return fdi2raw_loadrevolution_2 (fdi, mfmbuf, tracktiming, track, tracklength, indexoffsetp, multirev); - *tracklength = fdi->out; - for (i = 0; i < ((*tracklength) + 15) / (2 * 8); i++) { - uae_u8 *data = fdi->track_dst_buffer + i * 2; - *mfmbuf++ = 256 * *data + *(data + 1); - } - } - return outlen; -} - diff --git a/fdi2raw_old.c b/fdi2raw_old.c deleted file mode 100755 index 42efc71b..00000000 --- a/fdi2raw_old.c +++ /dev/null @@ -1,1835 +0,0 @@ -/* - - FDI to raw bit stream converter - Copyright (c) 2001 by Toni Wilen - FDI 2.0 support - Copyright (c) 2003-2004 by Toni Wilen - and Vincent Joguin - - FDI format created by Vincent "ApH" Joguin - - Tiny changes - function type fixes, multiple drives, addition of - get_last_head and C++ callability - by Thomas Harte, 2001, - T.Harte@excite.co.uk - - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - -*/ - -#include -#include -#include - -/* IF UAE */ -#include "sysconfig.h" -#include "sysdeps.h" -#include "zfile.h" -/* ELSE */ -//#include "types.h" - -#include "fdi2raw.h" - -#undef DEBUG -#define VERBOSE - -#include - -#ifdef DEBUG -static char *datalog(uae_u8 *src, int len) -{ - static char buf[1000]; - static int offset; - int i = 0, offset2; - - offset2 = offset; - buf[offset++]='\''; - while(len--) { - sprintf (buf + offset, "%02.2X", src[i]); - offset += 2; - i++; - if (i > 10) break; - } - buf[offset++]='\''; - buf[offset++] = 0; - if (offset >= 900) offset = 0; - return buf + offset2; -} -#else -static char *datalog(uae_u8 *src, int len) { return ""; } -#endif - -#ifdef DEBUG -#define debuglog write_log -#else -#define debuglog -#endif -#ifdef VERBOSE -#define outlog write_log -#else -#define outlog -#endif - -static int fdi_allocated; -#ifdef DEBUG -static void fdi_free (void *p) -{ - int size; - if (!p) - return; - size = ((int*)p)[-1]; - fdi_allocated -= size; - write_log ("%d freed (%d)\n", size, fdi_allocated); - free ((int*)p - 1); -} -static void *fdi_malloc (int size) -{ - void *p = xmalloc (size + sizeof (int)); - ((int*)p)[0] = size; - fdi_allocated += size; - write_log ("%d allocated (%d)\n", size, fdi_allocated); - return (int*)p + 1; -} -#else -#define fdi_free free -#define fdi_malloc xmalloc -#endif - -#define MAX_SRC_BUFFER 4194304 -#define MAX_DST_BUFFER 40000 -#define MAX_MFM_SYNC_BUFFER 60000 -#define MAX_TIMING_BUFFER 400000 -#define MAX_TRACKS 166 -#define MAX_REVOLUTIONS 4 - -struct fdi_cache { - uae_u8 *cache_buffer[MAX_REVOLUTIONS]; - uae_u8 *cache_buffer_timing; - int length[MAX_REVOLUTIONS]; - int indexoffset; -}; - -struct fdi { - uae_u8 *track_src_buffer; - uae_u8 *track_src; - int track_src_len; - uae_u8 *track_dst_buffer; - uae_u8 *track_dst; - uae_u16 *track_dst_buffer_timing; - uae_u8 track_len; - uae_u8 track_type; - int current_track; - int last_track; - int last_head; - int rotation_speed; - int bit_rate; - int disk_type; - int write_protect; - int err; - uae_u8 header[2048]; - int track_offsets[MAX_TRACKS]; - struct zfile *file; - int out; - int mfmsync_offset; - int *mfmsync_buffer; - /* sector described only */ - int index_offset; - int encoding_type; - /* bit handling */ - int nextdrop; - struct fdi_cache cache[MAX_TRACKS]; -}; - -#define get_u32(x) ((((x)[0])<<24)|(((x)[1])<<16)|(((x)[2])<<8)|((x)[3])) -#define get_u24(x) ((((x)[0])<<16)|(((x)[1])<<8)|((x)[2])) -STATIC_INLINE put_u32 (uae_u8 *d, uae_u32 v) -{ - d[0] = v >> 24; - d[1] = v >> 16; - d[2] = v >> 8; - d[3] = v; -} - -struct node { - uae_u16 v; - struct node *left; - struct node *right; -}; -typedef struct node NODE; - -static uae_u8 temp, temp2; - -static uae_u8 *expand_tree (uae_u8 *stream, NODE *node) -{ - if (temp & temp2) { - fdi_free (node->left); - node->left = 0; - fdi_free (node->right); - node->right = 0; - temp2 >>= 1; - if (!temp2) { - temp = *stream++; - temp2 = 0x80; - } - return stream; - } else { - uae_u8 *stream_temp; - temp2 >>= 1; - if (!temp2) { - temp = *stream++; - temp2 = 0x80; - } - node->left = fdi_malloc (sizeof (NODE)); - memset (node->left, 0, sizeof (NODE)); - stream_temp = expand_tree (stream, node->left); - node->right = fdi_malloc (sizeof (NODE)); - memset (node->right, 0, sizeof (NODE)); - return expand_tree (stream_temp, node->right); - } -} - -static uae_u8 *values_tree8 (uae_u8 *stream, NODE *node) -{ - if (node->left == 0) { - node->v = *stream++; - return stream; - } else { - uae_u8 *stream_temp = values_tree8 (stream, node->left); - return values_tree8 (stream_temp, node->right); - } -} - -static uae_u8 *values_tree16 (uae_u8 *stream, NODE *node) -{ - if (node->left == 0) { - uae_u16 high_8_bits = (*stream++) << 8; - node->v = high_8_bits | (*stream++); - return stream; - } else { - uae_u8 *stream_temp = values_tree16 (stream, node->left); - return values_tree16 (stream_temp, node->right); - } -} - -static void free_nodes (NODE *node) -{ - if (node) { - free_nodes (node->left); - free_nodes (node->right); - fdi_free (node); - } -} - -static uae_u32 sign_extend16 (uae_u32 v) -{ - if (v & 0x8000) - v |= 0xffff0000; - return v; -} - -static uae_u32 sign_extend8 (uae_u32 v) -{ - if (v & 0x80) - v |= 0xffffff00; - return v; -} - -static void fdi_decode (uae_u8 *stream, int size, uae_u8 *out) -{ - int i; - uae_u8 sign_extend, sixteen_bit, sub_stream_shift; - NODE root; - NODE *current_node; - - memset (out, 0, size * 4); - sub_stream_shift = 1; - while (sub_stream_shift) { - - //sub-stream header decode - sign_extend = *stream++; - sub_stream_shift = sign_extend & 0x7f; - sign_extend &= 0x80; - sixteen_bit = (*stream++) & 0x80; - - //huffman tree architecture decode - temp = *stream++; - temp2 = 0x80; - stream = expand_tree (stream, &root); - if (temp2 == 0x80) - stream--; - - //huffman output values decode - if (sixteen_bit) - stream = values_tree16 (stream, &root); - else - stream = values_tree8 (stream, &root); - - //sub-stream data decode - temp2 = 0; - for (i = 0; i < size; i++) { - uae_u32 v; - uae_u8 decode = 1; - current_node = &root; - while (decode) { - if (current_node->left == 0) { - decode = 0; - } else { - temp2 >>= 1; - if (!temp2) { - temp2 = 0x80; - temp = *stream++; - } - if (temp & temp2) - current_node = current_node->right; - else - current_node = current_node->left; - } - } - v = ((uae_u32*)out)[i]; - if (sign_extend) { - if (sixteen_bit) - v |= sign_extend16 (current_node->v) << sub_stream_shift; - else - v |= sign_extend8 (current_node->v) << sub_stream_shift; - } else { - v |= current_node->v << sub_stream_shift; - } - ((uae_u32*)out)[i] = v; - } - free_nodes (root.left); - free_nodes (root.right); - } -} - - -static int decode_raw_track (FDI *fdi) -{ - int size = get_u32(fdi->track_src); - memcpy (fdi->track_dst, fdi->track_src, (size + 7) >> 3); - fdi->track_src += (size + 7) >> 3; - return size; -} - -/* unknown track */ -static void zxx (FDI *fdi) -{ - outlog ("track %d: unknown track type 0x%02.2X\n", fdi->current_track, fdi->track_type); -// return -1; -} -/* unsupported track */ -static void zyy (FDI *fdi) -{ - outlog ("track %d: unsupported track type 0x%02.2X\n", fdi->current_track, fdi->track_type); -// return -1; -} -/* empty track */ -static void track_empty (FDI *fdi) -{ -// return 0; -} - -/* unknown sector described type */ -static void dxx (FDI *fdi) -{ - outlog ("\ntrack %d: unknown sector described type 0x%02.2X\n", fdi->current_track, fdi->track_type); - fdi->err = 1; -} -/* unsupported sector described type */ -static void dyy (FDI *fdi) -{ - outlog ("\ntrack %d: unsupported sector described 0x%02.2X\n", fdi->current_track, fdi->track_type); - fdi->err = 1; -} -/* add position of mfm sync bit */ -static void add_mfm_sync_bit (FDI *fdi) -{ - if (fdi->nextdrop) { - fdi->nextdrop = 0; - return; - } - fdi->mfmsync_buffer[fdi->mfmsync_offset++] = fdi->out; - if (fdi->out == 0) { - outlog ("illegal position for mfm sync bit, offset=%d\n",fdi->out); - fdi->err = 1; - } - if (fdi->mfmsync_offset >= MAX_MFM_SYNC_BUFFER) { - fdi->mfmsync_offset = 0; - outlog ("mfmsync buffer overflow\n"); - fdi->err = 1; - } - fdi->out++; -} - -#define BIT_BYTEOFFSET ((fdi->out) >> 3) -#define BIT_BITOFFSET (7-((fdi->out)&7)) - -/* add one bit */ -static void bit_add (FDI *fdi, int bit) -{ - if (fdi->nextdrop) { - fdi->nextdrop = 0; - return; - } - fdi->track_dst[BIT_BYTEOFFSET] &= ~(1 << BIT_BITOFFSET); - if (bit) - fdi->track_dst[BIT_BYTEOFFSET] |= (1 << BIT_BITOFFSET); - fdi->out++; - if (fdi->out >= MAX_DST_BUFFER * 8) { - outlog ("destination buffer overflow\n"); - fdi->err = 1; - fdi->out = 1; - } -} -/* add bit and mfm sync bit */ -static void bit_mfm_add (FDI *fdi, int bit) -{ - add_mfm_sync_bit (fdi); - bit_add (fdi, bit); -} -/* remove following bit */ -static void bit_drop_next (FDI *fdi) -{ - if (fdi->nextdrop > 0) { - outlog("multiple bit_drop_next() called"); - } else if (fdi->nextdrop < 0) { - fdi->nextdrop = 0; - debuglog(":DNN:"); - return; - } - debuglog(":DN:"); - fdi->nextdrop = 1; -} - -/* ignore next bit_drop_next() */ -static void bit_dedrop (FDI *fdi) -{ - if (fdi->nextdrop) { - outlog("bit_drop_next called before bit_dedrop"); - } - fdi->nextdrop = -1; - debuglog(":BDD:"); -} - -/* add one byte */ -static void byte_add (FDI *fdi, uae_u8 v) -{ - int i; - for (i = 7; i >= 0; i--) - bit_add (fdi, v & (1 << i)); -} -/* add one word */ -static void word_add (FDI *fdi, uae_u16 v) -{ - byte_add (fdi, (uae_u8)(v >> 8)); - byte_add (fdi, (uae_u8)v); -} -/* add one byte and mfm encode it */ -static void byte_mfm_add (FDI *fdi, uae_u8 v) -{ - int i; - for (i = 7; i >= 0; i--) - bit_mfm_add (fdi, v & (1 << i)); -} -/* add multiple bytes and mfm encode them */ -static void bytes_mfm_add (FDI *fdi, uae_u8 v, int len) -{ - int i; - for (i = 0; i < len; i++) byte_mfm_add (fdi, v); -} -/* add one mfm encoded word and re-mfm encode it */ -static void word_post_mfm_add (FDI *fdi, uae_u16 v) -{ - int i; - for (i = 14; i >= 0; i -= 2) - bit_mfm_add (fdi, v & (1 << i)); -} - -/* bit 0 */ -static void s00(FDI *fdi) { bit_add (fdi, 0); } -/* bit 1*/ -static void s01(FDI *fdi) { bit_add (fdi, 1); } -/* 4489 */ -static void s02(FDI *fdi) { word_add (fdi, 0x4489); } -/* 5224 */ -static void s03(FDI *fdi) { word_add (fdi, 0x5224); } -/* mfm sync bit */ -static void s04(FDI *fdi) { add_mfm_sync_bit (fdi); } -/* RLE MFM-encoded data */ -static void s08(FDI *fdi) -{ - int bytes = *fdi->track_src++; - uae_u8 byte = *fdi->track_src++; - if (bytes == 0) bytes = 256; - debuglog ("s08:len=%d,data=%02.2X",bytes,byte); - while(bytes--) byte_add (fdi, byte); -} -/* RLE MFM-decoded data */ -static void s09(FDI *fdi) -{ - int bytes = *fdi->track_src++; - uae_u8 byte = *fdi->track_src++; - if (bytes == 0) bytes = 256; - bit_drop_next (fdi); - debuglog ("s09:len=%d,data=%02.2X",bytes,byte); - while(bytes--) byte_mfm_add (fdi, byte); -} -/* MFM-encoded data */ -static void s0a(FDI *fdi) -{ - int i, bits = (fdi->track_src[0] << 8) | fdi->track_src[1]; - uae_u8 b; - fdi->track_src += 2; - debuglog ("s0a:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); - while (bits >= 8) { - byte_add (fdi, *fdi->track_src++); - bits -= 8; - } - if (bits > 0) { - i = 7; - b = *fdi->track_src++; - while (bits--) { - bit_add (fdi, b & (1 << i)); - i--; - } - } -} -/* MFM-encoded data */ -static void s0b(FDI *fdi) -{ - int i, bits = ((fdi->track_src[0] << 8) | fdi->track_src[1]) + 65536; - uae_u8 b; - fdi->track_src += 2; - debuglog ("s0b:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); - while (bits >= 8) { - byte_add (fdi, *fdi->track_src++); - bits -= 8; - } - if (bits > 0) { - i = 7; - b = *fdi->track_src++; - while (bits--) { - bit_add (fdi, b & (1 << i)); - i--; - } - } -} -/* MFM-decoded data */ -static void s0c(FDI *fdi) -{ - int i, bits = (fdi->track_src[0] << 8) | fdi->track_src[1]; - uae_u8 b; - fdi->track_src += 2; - bit_drop_next (fdi); - debuglog ("s0c:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); - while (bits >= 8) { - byte_mfm_add (fdi, *fdi->track_src++); - bits -= 8; - } - if (bits > 0) { - i = 7; - b = *fdi->track_src++; - while(bits--) { - bit_mfm_add (fdi, b & (1 << i)); - i--; - } - } -} -/* MFM-decoded data */ -static void s0d(FDI *fdi) -{ - int i, bits = ((fdi->track_src[0] << 8) | fdi->track_src[1]) + 65536; - uae_u8 b; - fdi->track_src += 2; - bit_drop_next (fdi); - debuglog ("s0d:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); - while (bits >= 8) { - byte_mfm_add (fdi, *fdi->track_src++); - bits -= 8; - } - if (bits > 0) { - i = 7; - b = *fdi->track_src++; - while(bits--) { - bit_mfm_add (fdi, b & (1 << i)); - i--; - } - } -} - -/* ***** */ -/* AMIGA */ -/* ***** */ - -/* just for testing integrity of Amiga sectors */ - -static void rotateonebit (uae_u8 *start, uae_u8 *end, int shift) -{ - if (shift == 0) - return; - while (start <= end) { - start[0] <<= shift; - start[0] |= start[1] >> (8 - shift); - start++; - } -} - -static int check_offset; -static uae_u16 getmfmword (uae_u8 *mbuf) -{ - uae_u32 v; - - v = (mbuf[0] << 8) | (mbuf[1] << 0); - if (check_offset == 0) - return v; - v <<= 8; - v |= mbuf[2]; - v >>= check_offset; - return v; -} - -#define MFMMASK 0x55555555 -static uae_u32 getmfmlong (uae_u8 * mbuf) -{ - return ((getmfmword (mbuf) << 16) | getmfmword (mbuf + 2)) & MFMMASK; -} - -static int amiga_check_track (FDI *fdi) -{ - int i, j, secwritten = 0; - int fwlen = fdi->out / 8; - int length = 2 * fwlen; - int drvsec = 11; - uae_u32 odd, even, chksum, id, dlong; - uae_u8 *secdata; - uae_u8 secbuf[544]; - uae_u8 bigmfmbuf[60000]; - uae_u8 *mbuf, *mbuf2, *mend; - char sectable[22]; - uae_u8 *raw = fdi->track_dst_buffer; - int slabel, off; - int ok = 1; - - memset (bigmfmbuf, 0, sizeof (bigmfmbuf)); - mbuf = bigmfmbuf; - check_offset = 0; - for (i = 0; i < (fdi->out + 7) / 8; i++) - *mbuf++ = raw[i]; - off = fdi->out & 7; -#if 1 - if (off > 0) { - mbuf--; - *mbuf &= ~((1 << (8 - off)) - 1); - } - j = 0; - while (i < (fdi->out + 7) / 8 + 600) { - *mbuf++ |= (raw[j] >> off) | ((raw[j + 1]) << (8 - off)); - j++; - i++; - } -#endif - mbuf = bigmfmbuf; - - memset (sectable, 0, sizeof (sectable)); - //memcpy (mbuf + fwlen, mbuf, fwlen * sizeof (uae_u16)); - mend = bigmfmbuf + length; - mend -= (4 + 16 + 8 + 512); - - while (secwritten < drvsec) { - int trackoffs; - - for (;;) { - rotateonebit (bigmfmbuf, mend, 1); - if (getmfmword (mbuf) == 0) - break; - if (secwritten == 10) { - mbuf[0] = 0x44; - mbuf[1] = 0x89; - } -// check_offset++; - if (check_offset > 7) { - check_offset = 0; - mbuf++; - if (mbuf >= mend || *mbuf == 0) - break; - } - if (getmfmword (mbuf) == 0x4489) - break; - } - if (mbuf >= mend || *mbuf == 0) - break; - - rotateonebit (bigmfmbuf, mend, check_offset); - check_offset = 0; - mbuf2 = mbuf; - - while (getmfmword (mbuf) == 0x4489) - mbuf+= 1 * 2; - - odd = getmfmlong (mbuf); - even = getmfmlong (mbuf + 2 * 2); - mbuf += 4 * 2; - id = (odd << 1) | even; - - trackoffs = (id & 0xff00) >> 8; - if (trackoffs + 1 > drvsec) { - debuglog("illegal sector offset %d\n",trackoffs); - ok = 0; - mbuf = mbuf2; - continue; - } - if ((id >> 24) != 0xff) { - debuglog ("sector %d format type %02.2X?\n", trackoffs, id >> 24); - ok = 0; - } - chksum = odd ^ even; - slabel = 0; - for (i = 0; i < 4; i++) { - odd = getmfmlong (mbuf); - even = getmfmlong (mbuf + 8 * 2); - mbuf += 2* 2; - - dlong = (odd << 1) | even; - if (dlong) slabel = 1; - chksum ^= odd ^ even; - } - mbuf += 8 * 2; - odd = getmfmlong (mbuf); - even = getmfmlong (mbuf + 2 * 2); - mbuf += 4 * 2; - if (((odd << 1) | even) != chksum) { - debuglog("sector %d header crc error\n", trackoffs); - ok = 0; - mbuf = mbuf2; - continue; - } - debuglog("sector %d header crc ok\n", trackoffs); - if (((id & 0x00ff0000) >> 16) != (uae_u32)fdi->current_track) { - debuglog("illegal track number %d <> %d\n",fdi->current_track,(id & 0x00ff0000) >> 16); - ok++; - mbuf = mbuf2; - continue; - } - odd = getmfmlong (mbuf); - even = getmfmlong (mbuf + 2 * 2); - mbuf += 4 * 2; - chksum = (odd << 1) | even; - secdata = secbuf + 32; - for (i = 0; i < 128; i++) { - odd = getmfmlong (mbuf); - even = getmfmlong (mbuf + 256 * 2); - mbuf += 2 * 2; - dlong = (odd << 1) | even; - *secdata++ = (uae_u8) (dlong >> 24); - *secdata++ = (uae_u8) (dlong >> 16); - *secdata++ = (uae_u8) (dlong >> 8); - *secdata++ = (uae_u8) dlong; - chksum ^= odd ^ even; - } - mbuf += 256 * 2; - if (chksum) { - debuglog("sector %d data checksum error\n",trackoffs); - ok = 0; - } else if (sectable[trackoffs]) { - debuglog("sector %d already found?\n", trackoffs); - mbuf = mbuf2; - } else { - debuglog("sector %d ok\n",trackoffs); - if (slabel) debuglog("(non-empty sector header)\n"); - sectable[trackoffs] = 1; - secwritten++; - if (trackoffs == 9) - mbuf += 0x228; - } - } - for (i = 0; i < drvsec; i++) { - if (!sectable[i]) { - debuglog ("sector %d missing\n", i); - ok = 0; - } - } - return ok; -} - -static void amiga_data_raw (FDI *fdi, uae_u8 *secbuf, uae_u8 *crc, int len) -{ - int i; - uae_u8 crcbuf[4]; - - if (!crc) { - memset (crcbuf, 0, 4); - } else { - memcpy (crcbuf, crc ,4); - } - for (i = 0; i < 4; i++) - byte_mfm_add (fdi, crcbuf[i]); - for (i = 0; i < len; i++) - byte_mfm_add (fdi, secbuf[i]); -} - -static void amiga_data (FDI *fdi, uae_u8 *secbuf) -{ - uae_u16 mfmbuf[4 + 512]; - uae_u32 dodd, deven, dck; - int i; - - for (i = 0; i < 512; i += 4) { - deven = ((secbuf[i + 0] << 24) | (secbuf[i + 1] << 16) - | (secbuf[i + 2] << 8) | (secbuf[i + 3])); - dodd = deven >> 1; - deven &= 0x55555555; - dodd &= 0x55555555; - mfmbuf[(i >> 1) + 4] = (uae_u16) (dodd >> 16); - mfmbuf[(i >> 1) + 5] = (uae_u16) dodd; - mfmbuf[(i >> 1) + 256 + 4] = (uae_u16) (deven >> 16); - mfmbuf[(i >> 1) + 256 + 5] = (uae_u16) deven; - } - dck = 0; - for (i = 4; i < 4 + 512; i += 2) - dck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1]; - deven = dodd = dck; - dodd >>= 1; - deven &= 0x55555555; - dodd &= 0x55555555; - mfmbuf[0] = (uae_u16) (dodd >> 16); - mfmbuf[1] = (uae_u16) dodd; - mfmbuf[2] = (uae_u16) (deven >> 16); - mfmbuf[3] = (uae_u16) deven; - - for (i = 0; i < 4 + 512; i ++) - word_post_mfm_add (fdi, mfmbuf[i]); -} - -static void amiga_sector_header (FDI *fdi, uae_u8 *header, uae_u8 *data, int sector, int untilgap) -{ - uae_u8 headerbuf[4], databuf[16]; - uae_u32 deven, dodd, hck; - uae_u16 mfmbuf[24]; - int i; - - byte_mfm_add (fdi, 0); - byte_mfm_add (fdi, 0); - word_add (fdi, 0x4489); - word_add (fdi, 0x4489); - if (header) { - memcpy (headerbuf, header, 4); - } else { - headerbuf[0] = 0xff; - headerbuf[1] = (uae_u8)fdi->current_track; - headerbuf[2] = (uae_u8)sector; - headerbuf[3] = (uae_u8)untilgap; - } - if (data) - memcpy (databuf, data, 16); - else - memset (databuf, 0, 16); - - deven = ((headerbuf[0] << 24) | (headerbuf[1] << 16) - | (headerbuf[2] << 8) | (headerbuf[3])); - dodd = deven >> 1; - deven &= 0x55555555; - dodd &= 0x55555555; - mfmbuf[0] = (uae_u16) (dodd >> 16); - mfmbuf[1] = (uae_u16) dodd; - mfmbuf[2] = (uae_u16) (deven >> 16); - mfmbuf[3] = (uae_u16) deven; - for (i = 0; i < 16; i += 4) { - deven = ((databuf[i] << 24) | (databuf[i + 1] << 16) - | (databuf[i + 2] << 8) | (databuf[i + 3])); - dodd = deven >> 1; - deven &= 0x55555555; - dodd &= 0x55555555; - mfmbuf[(i >> 1) + 0 + 4] = (uae_u16) (dodd >> 16); - mfmbuf[(i >> 1) + 0 + 5] = (uae_u16) dodd; - mfmbuf[(i >> 1) + 8 + 4] = (uae_u16) (deven >> 16); - mfmbuf[(i >> 1) + 8 + 5] = (uae_u16) deven; - } - hck = 0; - for (i = 0; i < 4 + 16; i += 2) - hck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1]; - deven = dodd = hck; - dodd >>= 1; - deven &= 0x55555555; - dodd &= 0x55555555; - mfmbuf[20] = (uae_u16) (dodd >> 16); - mfmbuf[21] = (uae_u16) dodd; - mfmbuf[22] = (uae_u16) (deven >> 16); - mfmbuf[23] = (uae_u16) deven; - - for (i = 0; i < 4 + 16 + 4; i ++) - word_post_mfm_add (fdi, mfmbuf[i]); -} - -/* standard super-extended Amiga sector header */ -static void s20(FDI *fdi) -{ - bit_drop_next (fdi); - debuglog ("s20:header=%s,data=%s", datalog(fdi->track_src, 4), datalog(fdi->track_src + 4, 16)); - amiga_sector_header (fdi, fdi->track_src, fdi->track_src + 4, 0, 0); - fdi->track_src += 4 + 16; -} -/* standard extended Amiga sector header */ -static void s21(FDI *fdi) -{ - bit_drop_next (fdi); - debuglog ("s21:header=%s", datalog(fdi->track_src, 4)); - amiga_sector_header (fdi, fdi->track_src, 0, 0, 0); - fdi->track_src += 4; -} -/* standard Amiga sector header */ -static void s22(FDI *fdi) -{ - bit_drop_next (fdi); - debuglog("s22:sector=%d,untilgap=%d", fdi->track_src[0], fdi->track_src[1]); - amiga_sector_header (fdi, 0, 0, fdi->track_src[0], fdi->track_src[1]); - fdi->track_src += 2; -} -/* standard 512-byte, CRC-correct Amiga data */ -static void s23(FDI *fdi) -{ - debuglog("s23:data=%s", datalog (fdi->track_src, 512)); - amiga_data (fdi, fdi->track_src); - fdi->track_src += 512; -} -/* not-decoded, 128*2^x-byte, CRC-correct Amiga data */ -static void s24(FDI *fdi) -{ - int shift = *fdi->track_src++; - debuglog("s24:shift=%d,data=%s", shift, datalog (fdi->track_src, 128 << shift)); - amiga_data_raw (fdi, fdi->track_src, 0, 128 << shift); - fdi->track_src += 128 << shift; -} -/* not-decoded, 128*2^x-byte, CRC-incorrect Amiga data */ -static void s25(FDI *fdi) -{ - int shift = *fdi->track_src++; - debuglog("s25:shift=%d,crc=%s,data=%s", shift, datalog (fdi->track_src, 4), datalog (fdi->track_src + 4, 128 << shift)); - amiga_data_raw (fdi, fdi->track_src + 4, fdi->track_src, 128 << shift); - fdi->track_src += 4 + (128 << shift); -} -/* standard extended Amiga sector */ -static void s26(FDI *fdi) -{ - s21 (fdi); - debuglog("s26:data=%s", datalog (fdi->track_src, 512)); - amiga_data (fdi, fdi->track_src); - fdi->track_src += 512; -} -/* standard short Amiga sector */ -static void s27(FDI *fdi) -{ - s22 (fdi); - debuglog("s27:data=%s", datalog (fdi->track_src, 512)); - amiga_data (fdi, fdi->track_src); - fdi->track_src += 512; -} - -/* *** */ -/* IBM */ -/* *** */ - -static uae_u16 ibm_crc (uae_u8 byte, int reset) -{ - static uae_u16 crc; - int i; - - if (reset) crc = 0xcdb4; - for (i = 0; i < 8; i++) { - if (crc & 0x8000) { - crc <<= 1; - if (!(byte & 0x80)) crc ^= 0x1021; - } else { - crc <<= 1; - if (byte & 0x80) crc ^= 0x1021; - } - byte <<= 1; - } - return crc; -} - -static void ibm_data (FDI *fdi, uae_u8 *data, uae_u8 *crc, int len) -{ - int i; - uae_u8 crcbuf[2]; - uae_u16 crcv; - - word_add (fdi, 0x4489); - word_add (fdi, 0x4489); - word_add (fdi, 0x4489); - byte_mfm_add (fdi, 0xfb); - ibm_crc (0xfb, 1); - for (i = 0; i < len; i++) { - byte_mfm_add (fdi, data[i]); - crcv = ibm_crc (data[i], 0); - } - if (!crc) { - crc = crcbuf; - crc[0] = (uae_u8)(crcv >> 8); - crc[1] = (uae_u8)crcv; - } - byte_mfm_add (fdi, crc[0]); - byte_mfm_add (fdi, crc[1]); -} - -static void ibm_sector_header (FDI *fdi, uae_u8 *data, uae_u8 *crc, int secnum, int pre) -{ - uae_u8 secbuf[5]; - uae_u8 crcbuf[2]; - uae_u16 crcv; - int i; - - if (pre) - bytes_mfm_add (fdi, 0, 12); - word_add (fdi, 0x4489); - word_add (fdi, 0x4489); - word_add (fdi, 0x4489); - secbuf[0] = 0xfe; - if (secnum >= 0) { - secbuf[1] = (uae_u8)(fdi->current_track/2); - secbuf[2] = (uae_u8)(fdi->current_track%2); - secbuf[3] = (uae_u8)secnum; - secbuf[4] = 2; - } else { - memcpy (secbuf + 1, data, 4); - } - ibm_crc (secbuf[0], 1); - ibm_crc (secbuf[1], 0); - ibm_crc (secbuf[2], 0); - ibm_crc (secbuf[3], 0); - crcv = ibm_crc (secbuf[4], 0); - if (crc) { - memcpy (crcbuf, crc, 2); - } else { - crcbuf[0] = (uae_u8)(crcv >> 8); - crcbuf[1] = (uae_u8)crcv; - } - /* data */ - for (i = 0;i < 5; i++) - byte_mfm_add (fdi, secbuf[i]); - /* crc */ - byte_mfm_add (fdi, crcbuf[0]); - byte_mfm_add (fdi, crcbuf[1]); -} - -/* standard IBM index address mark */ -static void s10(FDI *fdi) -{ - bit_drop_next (fdi); - bytes_mfm_add (fdi, 0, 12); - word_add (fdi, 0x5224); - word_add (fdi, 0x5224); - word_add (fdi, 0x5224); - byte_mfm_add (fdi, 0xfc); -} -/* standard IBM pre-gap */ -static void s11(FDI *fdi) -{ - bit_drop_next (fdi); - bytes_mfm_add (fdi, 0x4e, 78); - bit_dedrop (fdi); - s10 (fdi); - bytes_mfm_add (fdi, 0x4e, 50); -} -/* standard ST pre-gap */ -static void s12(FDI *fdi) -{ - bit_drop_next (fdi); - bytes_mfm_add (fdi, 0x4e, 78); -} -/* standard extended IBM sector header */ -static void s13(FDI *fdi) -{ - bit_drop_next (fdi); - debuglog ("s13:header=%s", datalog (fdi->track_src, 4)); - ibm_sector_header (fdi, fdi->track_src, 0, -1, 1); - fdi->track_src += 4; -} -/* standard mini-extended IBM sector header */ -static void s14(FDI *fdi) -{ - debuglog ("s14:header=%s", datalog (fdi->track_src, 4)); - ibm_sector_header (fdi, fdi->track_src, 0, -1, 0); - fdi->track_src += 4; -} -/* standard short IBM sector header */ -static void s15(FDI *fdi) -{ - bit_drop_next (fdi); - debuglog ("s15:sector=%d", *fdi->track_src); - ibm_sector_header (fdi, 0, 0, *fdi->track_src++, 1); -} -/* standard mini-short IBM sector header */ -static void s16(FDI *fdi) -{ - debuglog ("s16:track=%d", *fdi->track_src); - ibm_sector_header (fdi, 0, 0, *fdi->track_src++, 0); -} -/* standard CRC-incorrect mini-extended IBM sector header */ -static void s17(FDI *fdi) -{ - debuglog ("s17:header=%s,crc=%s", datalog (fdi->track_src, 4), datalog (fdi->track_src + 4, 2)); - ibm_sector_header (fdi, fdi->track_src, fdi->track_src + 4, -1, 0); - fdi->track_src += 4 + 2; -} -/* standard CRC-incorrect mini-short IBM sector header */ -static void s18(FDI *fdi) -{ - debuglog ("s18:sector=%d,header=%s", *fdi->track_src, datalog (fdi->track_src + 1, 4)); - ibm_sector_header (fdi, 0, fdi->track_src + 1, *fdi->track_src, 0); - fdi->track_src += 1 + 4; -} -/* standard 512-byte CRC-correct IBM data */ -static void s19(FDI *fdi) -{ - debuglog ("s19:data=%s", datalog (fdi->track_src , 512)); - ibm_data (fdi, fdi->track_src, 0, 512); - fdi->track_src += 512; -} -/* standard 128*2^x-byte-byte CRC-correct IBM data */ -static void s1a(FDI *fdi) -{ - int shift = *fdi->track_src++; - debuglog ("s1a:shift=%d,data=%s", shift, datalog (fdi->track_src , 128 << shift)); - ibm_data (fdi, fdi->track_src, 0, 128 << shift); - fdi->track_src += 128 << shift; -} -/* standard 128*2^x-byte-byte CRC-incorrect IBM data */ -static void s1b(FDI *fdi) -{ - int shift = *fdi->track_src++; - debuglog ("s1b:shift=%d,crc=%s,data=%s", shift, datalog (fdi->track_src + (128 << shift), 2), datalog (fdi->track_src , 128 << shift)); - ibm_data (fdi, fdi->track_src, fdi->track_src + (128 << shift), 128 << shift); - fdi->track_src += (128 << shift) + 2; -} -/* standard extended IBM sector */ -static void s1c(FDI *fdi) -{ - int shift = fdi->track_src[3]; - s13 (fdi); - bytes_mfm_add (fdi, 0x4e, 22); - bytes_mfm_add (fdi, 0x00, 12); - ibm_data (fdi, fdi->track_src, 0, 128 << shift); - fdi->track_src += 128 << shift; -} -/* standard short IBM sector */ -static void s1d(FDI *fdi) -{ - s15 (fdi); - bytes_mfm_add (fdi, 0x4e, 22); - bytes_mfm_add (fdi, 0x00, 12); - s19 (fdi); -} - -/* end marker */ -static void sff(FDI *fdi) -{ -} - -typedef void (*decode_described_track_func)(FDI*); - -static decode_described_track_func decode_sectors_described_track[] = -{ - s00,s01,s02,s03,s04,dxx,dxx,dxx,s08,s09,s0a,s0b,s0c,s0d,dxx,dxx, /* 00-0F */ - s10,s11,s12,s13,s14,s15,s16,s17,s18,s19,s1a,s1b,s1c,s1d,dxx,dxx, /* 10-1F */ - s20,s21,s22,s23,s24,s25,s26,s27,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 20-2F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 30-3F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 40-4F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 50-5F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 60-6F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 70-7F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 80-8F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 90-9F */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* A0-AF */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* B0-BF */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* C0-CF */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* D0-DF */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* E0-EF */ - dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,sff /* F0-FF */ -}; - -static void track_amiga (struct fdi *fdi, int first_sector, int max_sector) -{ - int i; - - bit_add (fdi, 0); - bit_drop_next (fdi); - for (i = 0; i < max_sector; i++) { - amiga_sector_header (fdi, 0, 0, first_sector, max_sector - i); - amiga_data (fdi, fdi->track_src + first_sector * 512); - first_sector++; - if (first_sector >= max_sector) first_sector = 0; - } - bytes_mfm_add (fdi, 0, 260); /* gap */ -} -static void track_atari_st (struct fdi *fdi, int max_sector) -{ - int i, gap3; - uae_u8 *p = fdi->track_src; - - switch (max_sector) - { - case 9: - gap3 = 40; - break; - case 10: - gap3 = 24; - break; - } - s15 (fdi); - for (i = 0; i < max_sector; i++) { - byte_mfm_add (fdi, 0x4e); - byte_mfm_add (fdi, 0x4e); - ibm_sector_header (fdi, 0, 0, fdi->current_track, 1); - ibm_data (fdi, p + i * 512, 0, 512); - bytes_mfm_add (fdi, 0x4e, gap3); - } - bytes_mfm_add (fdi, 0x4e, 660 - gap3); - fdi->track_src += fdi->track_len * 256; -} -static void track_pc (struct fdi *fdi, int max_sector) -{ - int i, gap3; - uae_u8 *p = fdi->track_src; - - switch (max_sector) - { - case 8: - gap3 = 116; - break; - case 9: - gap3 = 54; - break; - default: - gap3 = 100; /* fixme */ - break; - } - s11 (fdi); - for (i = 0; i < max_sector; i++) { - byte_mfm_add (fdi, 0x4e); - byte_mfm_add (fdi, 0x4e); - ibm_sector_header (fdi, 0, 0, fdi->current_track, 1); - ibm_data (fdi, p + i * 512, 0, 512); - bytes_mfm_add (fdi, 0x4e, gap3); - } - bytes_mfm_add (fdi, 0x4e, 600 - gap3); - fdi->track_src += fdi->track_len * 256; -} - -/* amiga dd */ -static void track_amiga_dd (struct fdi *fdi) -{ - uae_u8 *p = fdi->track_src; - track_amiga (fdi, fdi->track_len >> 4, 11); - fdi->track_src = p + (fdi->track_len & 15) * 512; -} -/* amiga hd */ -static void track_amiga_hd (struct fdi *fdi) -{ - uae_u8 *p = fdi->track_src; - track_amiga (fdi, 0, 22); - fdi->track_src = p + fdi->track_len * 256; -} -/* atari st 9 sector */ -static void track_atari_st_9 (struct fdi *fdi) -{ - track_atari_st (fdi, 9); -} -/* atari st 10 sector */ -static void track_atari_st_10 (struct fdi *fdi) -{ - track_atari_st (fdi, 10); -} -/* pc 8 sector */ -static void track_pc_8 (struct fdi *fdi) -{ - track_pc (fdi, 8); -} -/* pc 9 sector */ -static void track_pc_9 (struct fdi *fdi) -{ - track_pc (fdi, 9); -} -/* pc 15 sector */ -static void track_pc_15 (struct fdi *fdi) -{ - track_pc (fdi, 15); -} -/* pc 18 sector */ -static void track_pc_18 (struct fdi *fdi) -{ - track_pc (fdi, 18); -} -/* pc 36 sector */ -static void track_pc_36 (struct fdi *fdi) -{ - track_pc (fdi, 36); -} - -typedef void (*decode_normal_track_func)(FDI*); - -static decode_normal_track_func decode_normal_track[] = -{ - track_empty, /* 0 */ - track_amiga_dd, track_amiga_hd, /* 1-2 */ - track_atari_st_9, track_atari_st_10, /* 3-4 */ - track_pc_8, track_pc_9, track_pc_15, track_pc_18, track_pc_36, /* 5-9 */ - zxx,zxx,zxx,zxx,zxx /* A-F */ -}; - -static void fix_mfm_sync (FDI *fdi) -{ - int i, pos, off1, off2, off3, mask1, mask2, mask3; - - for (i = 0; i < fdi->mfmsync_offset; i++) { - pos = fdi->mfmsync_buffer[i]; - off1 = (pos - 1) >> 3; - off2 = (pos + 1) >> 3; - off3 = pos >> 3; - mask1 = 1 << (7 - ((pos - 1) & 7)); - mask2 = 1 << (7 - ((pos + 1) & 7)); - mask3 = 1 << (7 - (pos & 7)); - if (!(fdi->track_dst[off1] & mask1) && !(fdi->track_dst[off2] & mask2)) - fdi->track_dst[off3] |= mask3; - else - fdi->track_dst[off3] &= ~mask3; - } -} - -static int handle_sectors_described_track (FDI *fdi) -{ - int oldout; - uae_u8 *start_src = fdi->track_src ; - fdi->encoding_type = *fdi->track_src++; - fdi->index_offset = get_u32(fdi->track_src); - fdi->index_offset >>= 8; - fdi->track_src += 3; - outlog ("sectors_described, index offset: %d\n",fdi->index_offset); - - do { - fdi->track_type = *fdi->track_src++; - outlog ("%06.6X %06.6X %02.2X:",fdi->track_src - start_src + 0x200, fdi->out/8, fdi->track_type); - oldout = fdi->out; - decode_sectors_described_track[fdi->track_type](fdi); - outlog(" %d\n", fdi->out - oldout); - oldout = fdi->out; - if (fdi->out < 0 || fdi->err) { - outlog ("\nin %d bytes, out %d bits\n", fdi->track_src - fdi->track_src_buffer, fdi->out); - return -1; - } - if (fdi->track_src - fdi->track_src_buffer >= fdi->track_src_len) { - outlog ("source buffer overrun, previous type: %02.2X\n", fdi->track_type); - return -1; - } - } while (fdi->track_type != 0xff); - outlog("\n"); - fix_mfm_sync (fdi); - return fdi->out; -} - -static uae_u8 *fdi_decompress (int pulses, uae_u8 *sizep, uae_u8 *src, int *dofree) -{ - uae_u32 size = get_u24 (sizep); - uae_u32 *dst2; - int len = size & 0x3fffff; - uae_u8 *dst; - int mode = size >> 22, i; - - *dofree = 0; - if (mode == 0 && pulses * 2 > len) - mode = 1; - if (mode == 0) { - dst2 = (uae_u32*)src; - for (i = 0; i < pulses; i++) { - *dst2++ = get_u32 (src); - src += 4; - } - dst = src; - } else if (mode == 1) { - dst = fdi_malloc (pulses *4); - *dofree = 1; - fdi_decode (src, pulses, dst); - } else { - dst = 0; - } - return dst; -} - -static void dumpstream(int track, uae_u8 *stream, int len) -{ - char name[100]; - FILE *f; - - sprintf (name, "track_%d.raw", track); - f = fopen(name, "wb"); - fwrite (stream, 1, len * 4, f); - fclose (f); -} - -static int bitoffset; - -STATIC_INLINE void addbit (uae_u8 *p, int bit) -{ - int off1 = bitoffset / 8; - int off2 = bitoffset % 8; - p[off1] |= bit << (7 - off2); - bitoffset++; -} - - -struct pulse_sample { - unsigned long size; - int number_of_bits; -}; - -#define FDI_MAX_ARRAY 6 /* change this value as you want */ -static int pulse_limitval = 20; -static struct pulse_sample psarray[FDI_MAX_ARRAY]; -static int array_index; -static unsigned long total; -static int totaldiv; - -static void init_array(unsigned long standard_MFM_2_bit_cell_size) -{ - int i; - - for (i = 0; i < FDI_MAX_ARRAY; i++) { - psarray[i].size = standard_MFM_2_bit_cell_size; // That is (total track length / 50000) for Amiga double density - total += psarray[i].size; - psarray[i].number_of_bits = 2; - totaldiv += psarray[i].number_of_bits; - } - array_index = 0; -} - -static void fdi2_mfm_decode(FDI *fdi, unsigned long totalavg, uae_u32 *avgp, uae_u8 *idx, int idx_off1, int idx_off2, int idx_off3, int maxidx, int pulses) -{ - unsigned long adjust; - unsigned long adjusted_pulse; - unsigned long standard_MFM_2_bit_cell_size = totalavg / 50000; - int real_size, i, j; - uae_u8 *d = fdi->track_dst_buffer; - uae_u16 *pt = fdi->track_dst_buffer_timing; - - adjust = 0; - total = 0; - totaldiv = 0; - init_array(standard_MFM_2_bit_cell_size); - bitoffset = 0; - for (i = 0; i < pulses; i++) - { - if (idx[idx_off1] + idx[idx_off2] >= maxidx) { - uae_u32 pulse = avgp[i]; - uae_u32 avg_size = total / totaldiv; /* this is the new average size for one MFM bit */ - /* you can try tighter ranges than 25%, or wider ranges. I would probably go for tighter... */ - if ((avg_size < ((standard_MFM_2_bit_cell_size / 2) - (pulse_limitval * standard_MFM_2_bit_cell_size / 200))) || - (avg_size > ((standard_MFM_2_bit_cell_size / 2) + (pulse_limitval * standard_MFM_2_bit_cell_size /200)))) - init_array(standard_MFM_2_bit_cell_size); - /* this is to prevent the average value from going too far - * from the theoretical value, otherwise it could progressively go to (2 * - * real value), or (real value / 2), etc. */ - if ((pulse > adjust) && (adjust < avg_size)) - adjusted_pulse = pulse - adjust; - else - adjusted_pulse = pulse; - adjusted_pulse = pulse; - real_size = 1; - do { - addbit (d, 0); - real_size++; - } while (adjusted_pulse > avg_size * real_size + avg_size / 2); - addbit (d, 1); -#if 1 - for (j = 0; j < real_size; j++) - *pt++ = (uae_u16)(adjusted_pulse / real_size); -#endif - /* Note that you should also consider values above 4! Too lazy to do it here ;-) */ - adjust = (real_size * avg_size) - pulse; - /* function to transform the value in real_size to '01', '001' or '0001', and append this to the decoded MFM stream */ - total -= psarray[array_index].size; - totaldiv -= psarray[array_index].number_of_bits; - psarray[array_index].size = pulse; - psarray[array_index].number_of_bits = real_size; - total += pulse; - totaldiv += real_size; - array_index++; - if (array_index >= FDI_MAX_ARRAY) - array_index = 0; - } - idx += idx_off3; - } - fdi->out = bitoffset; - write_log ("result bits: %d\n", bitoffset); -} - -static void fdi2_celltiming (FDI *fdi, unsigned long totalavg, int bitoffset) -{ - uae_u16 *pt2, *pt; - double avg_bit_len; - int timed = 0; - int i; - - avg_bit_len = (double)totalavg / (double)bitoffset; - pt2 = pt = fdi->track_dst_buffer_timing; - for (i = 0; i < bitoffset / 8; i++) { - double v = (pt2[0] + pt2[1] + pt2[2] + pt2[3] + pt2[4] + pt2[5] + pt2[6] + pt2[7]) / 8.0; - uae_u16 vv; - v = 1000.0 * v / avg_bit_len; - vv = (uae_u16)v; - *pt++ = vv; - if (vv > 1030 || vv < 970) - timed = 1; - pt2 += 8; - if (vv > 1030 || vv < 970) - write_log ("%d ", vv); - } - *pt++ = fdi->track_dst_buffer_timing[0]; - *pt = fdi->track_dst_buffer_timing[0]; - if (!timed) - fdi->track_dst_buffer_timing[0] = 0; -} - -static int decode_lowlevel_track (FDI *fdi, int *indexoffsetp, int track) -{ - uae_u8 *p1, *d; - uae_u32 *p2; - uae_u32 *avgp, *minp = 0, *maxp = 0; - uae_u8 *idxp = 0; - uae_u32 maxidx, minidx, totalavg, weakbits; - int i, len, pulses, indexoffset; - int avg_free, min_free = 0, max_free = 0, idx_free; - int idx_off1, idx_off2, idx_off3; - - d = fdi->track_dst; - p1 = fdi->track_src; - pulses = get_u32 (p1); - if (!pulses) - return -1; - p1 += 4; - len = 12; - avgp = (uae_u32*)fdi_decompress (pulses, p1 + 0, p1 + len, &avg_free); - //dumpstream(track, (uae_u8*)avgp, pulses); - len += get_u24 (p1 + 0) & 0x3fffff; - if (!avgp) - return -1; - if (get_u24 (p1 + 3) && get_u24 (p1 + 6)) { -#if 0 - minp = (uae_u32*)fdi_decompress (pulses, p1 + 3, p1 + len, &min_free); -#endif - len += get_u24 (p1 + 3) & 0x3fffff; -#if 0 - maxp = (uae_u32*)fdi_decompress (pulses, p1 + 6, p1 + len, &max_free); -#endif - len += get_u24 (p1 + 6) & 0x3fffff; - } - if (get_u24 (p1 + 9)) { - idx_off1 = 0; - idx_off2 = 1; - idx_off3 = 2; - idxp = fdi_decompress (pulses, p1 + 9, p1 + len, &idx_free); - if (idx_free) { - if (idxp[0] == 0 && idxp[1] == 0) { - idx_off1 = 2; - idx_off2 = 3; - } else { - idx_off1 = 1; - idx_off2 = 0; - } - idx_off3 = 4; - } - } else { - idxp = fdi_malloc (pulses * 2); - idx_free = 1; - for (i = 0; i < pulses; i++) { - idxp[i * 2 + 0] = 2; - idxp[i * 2 + 1] = 0; - } - idxp[0] = 1; - idxp[1] = 1; - } - - maxidx = 0; - minidx = 255; - indexoffset = 0; - p1 = idxp; - for (i = 0; i < pulses; i++) { - if (p1[idx_off1] + p1[idx_off2] > maxidx) - maxidx = p1[idx_off1] + p1[idx_off2]; - if (abs (p1[idx_off1] - p1[idx_off2]) < minidx) { - minidx = abs (p1[idx_off1] - p1[idx_off2]); - indexoffset = i; - } - p1 += idx_off3; - } - p1 = idxp; - p2 = avgp; - totalavg = 0; - weakbits = 0; - for (i = 0; i < pulses; i++) { - if (p1[idx_off1] + p1[idx_off2] >= maxidx) { - totalavg += *p2; - } else { - weakbits++; - } - p2++; - p1 += idx_off3; - } - len = totalavg / 100000; - outlog("totalavg=%d index=%d maxidx=%d weakbits=%d len=%d\n", - totalavg, indexoffset, maxidx, weakbits, len); - fdi2_mfm_decode (fdi, totalavg, avgp, idxp, idx_off1, idx_off2, idx_off3, maxidx, pulses); - outlog("number of bits=%d avg len=%.2f\n", bitoffset, (double)totalavg / bitoffset); - fdi2_celltiming (fdi, totalavg, bitoffset); - - *indexoffsetp = indexoffset; - if (avg_free) - fdi_free (avgp); - if (min_free) - fdi_free (minp); - if (max_free) - fdi_free (maxp); - if (idx_free) - fdi_free (idxp); - return bitoffset; -} - -static unsigned char fdiid[]={"Formatted Disk Image file"}; -static int bit_rate_table[16] = { 125,150,250,300,500,1000 }; - -void fdi2raw_header_free (FDI *fdi) -{ - int i, j; - - fdi_free (fdi->mfmsync_buffer); - fdi_free (fdi->track_src_buffer); - fdi_free (fdi->track_dst_buffer); - fdi_free (fdi->track_dst_buffer_timing); - for (i = 0; i < MAX_TRACKS; i++) { - struct fdi_cache *c = &fdi->cache[i]; - for (j = 0; j < MAX_REVOLUTIONS; j++) - fdi_free (c->cache_buffer[j]); - fdi_free (c->cache_buffer_timing); - } - fdi_free (fdi); -#ifdef DEBUG - write_log ("FREE: memory allocated %d\n", fdi_allocated); -#endif -} - -int fdi2raw_get_last_track (FDI *fdi) -{ - return fdi->last_track; -} - -int fdi2raw_get_num_sector (FDI *fdi) -{ - if (fdi->header[152] == 0x02) - return 22; - return 11; -} - -int fdi2raw_get_last_head (FDI *fdi) -{ - return fdi->last_head; -} - -int fdi2raw_get_rotation (FDI *fdi) -{ - return fdi->rotation_speed; -} - -int fdi2raw_get_bit_rate (FDI *fdi) -{ - return fdi->bit_rate; -} - -int fdi2raw_get_type (FDI *fdi) -{ - return fdi->disk_type; -} - -int fdi2raw_get_write_protect (FDI *fdi) -{ - return fdi->write_protect; -} - -FDI *fdi2raw_header(struct zfile *f) -{ - int i, offset, oldseek; - uae_u8 type, size; - FDI *fdi; - -#ifdef DEBUG - write_log ("ALLOC: memory allocated %d\n", fdi_allocated); -#endif - fdi = fdi_malloc(sizeof(FDI)); - memset (fdi, 0, sizeof (FDI)); - fdi->file = f; - oldseek = zfile_ftell (fdi->file); - zfile_fseek (fdi->file, 0, SEEK_SET); - zfile_fread (fdi->header, 2048, 1, fdi->file); - zfile_fseek (fdi->file, oldseek, SEEK_SET); - if (memcmp (fdiid, fdi->header, strlen (fdiid)) ) { - fdi_free(fdi); - return NULL; - } - if ((fdi->header[140] != 1 && fdi->header[140] != 2) || fdi->header[141] != 0) { - fdi_free(fdi); - return NULL; - } - - fdi->mfmsync_buffer = fdi_malloc (MAX_MFM_SYNC_BUFFER * sizeof(int)); - fdi->track_src_buffer = fdi_malloc (MAX_SRC_BUFFER); - fdi->track_dst_buffer = fdi_malloc (MAX_DST_BUFFER); - fdi->track_dst_buffer_timing = fdi_malloc (MAX_TIMING_BUFFER); - - fdi->last_track = ((fdi->header[142] << 8) + fdi->header[143]) + 1; - fdi->last_track *= fdi->header[144] + 1; - if (fdi->last_track > MAX_TRACKS) - fdi->last_track = MAX_TRACKS; - fdi->last_head = fdi->header[144]; - fdi->disk_type = fdi->header[145]; - fdi->rotation_speed = fdi->header[146] + 128; - fdi->write_protect = fdi->header[147] & 1; - outlog ("FDI version %d.%d\n", fdi->header[140], fdi->header[141]); - outlog ("last_track=%d rotation_speed=%d\n",fdi->last_track,fdi->rotation_speed); - - offset = 512; - i = fdi->last_track; - if (i > 180) { - offset += 512; - i -= 180; - while (i > 256) { - offset += 512; - i -= 256; - } - } - for (i = 0; i < fdi->last_track; i++) { - fdi->track_offsets[i] = offset; - type = fdi->header[152 + i * 2]; - size = fdi->header[152 + i * 2 + 1]; - if (type == 1) - offset += (size & 15) * 512; - else if ((type & 0xc0) == 0x80) - offset += (((type & 0x3f) << 8) | size) * 256; - else - offset += size * 256; - } - fdi->track_offsets[i] = offset; - - return fdi; -} - - -int fdi2raw_loadrevolution (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, int track, int *tracklength) -{ - return 0; -} - -int fdi2raw_loadtrack (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, int track, int *tracklength, int *indexoffsetp, int *multirev) -{ - uae_u8 *p; - int outlen, i, j, indexoffset = 0; - struct fdi_cache *cache; - - cache = &fdi->cache[track]; - if (cache->cache_buffer[0]) { - *tracklength = cache->length[0]; - for (i = 0; i < (tracklength[0] + 15) / (2 * 8); i++) { - uae_u8 *data = cache->cache_buffer[0] + i * 2; - *mfmbuf++ = 256 * *data + *(data + 1); - } - if (cache->cache_buffer_timing) - memcpy (tracktiming, cache->cache_buffer_timing, (tracklength[0] + 7) / 8 * sizeof (uae_u16)); - *indexoffsetp = cache->indexoffset; - return 1; - } - - fdi->err = 0; - fdi->track_src_len = fdi->track_offsets[track + 1] - fdi->track_offsets[track]; - zfile_fseek (fdi->file, fdi->track_offsets[track], SEEK_SET); - zfile_fread (fdi->track_src_buffer, fdi->track_src_len, 1, fdi->file); - memset (fdi->track_dst_buffer, 0, MAX_DST_BUFFER); - fdi->track_dst_buffer_timing[0] = 0; - - fdi->current_track = track; - fdi->track_src = fdi->track_src_buffer; - fdi->track_dst = fdi->track_dst_buffer; - p = fdi->header + 152 + fdi->current_track * 2; - fdi->track_type = *p++; - fdi->track_len = *p++; - fdi->bit_rate = 0; - fdi->out = 0; - fdi->mfmsync_offset = 0; - - if ((fdi->track_type & 0xf0) == 0xf0 || (fdi->track_type & 0xf0) == 0xe0) - fdi->bit_rate = bit_rate_table[fdi->track_type & 0x0f]; - else - fdi->bit_rate = 250; - - outlog ("track %d: srclen: %d track_type: %02.2X, bitrate: %d\n", - fdi->current_track, fdi->track_src_len, fdi->track_type, fdi->bit_rate); - - if ((fdi->track_type & 0xc0) == 0x80) { - - outlen = decode_lowlevel_track (fdi, &indexoffset, track); - - } else if ((fdi->track_type & 0xf0) == 0xf0) { - - outlen = decode_raw_track (fdi); - - } else if ((fdi->track_type & 0xf0) == 0xe0) { - - outlen = handle_sectors_described_track (fdi); - - } else if ((fdi->track_type & 0xf0)) { - - zxx (fdi); - outlen = -1; - - } else if (fdi->track_type < 0x10) { - - decode_normal_track[fdi->track_type](fdi); - fix_mfm_sync (fdi); - outlen = fdi->out; - - } else { - - zxx (fdi); - outlen = -1; - - } - - if (fdi->err) - return 0; - - if (outlen > 0) { - for (j = 0; j < MAX_REVOLUTIONS; j++) { - fdi_free (cache->cache_buffer[j]); - cache->cache_buffer[j] = 0; - } - fdi_free (cache->cache_buffer_timing); - cache->cache_buffer_timing = 0; - cache->indexoffset = indexoffset; - cache->length[0] = outlen; - cache->cache_buffer[0] = fdi_malloc ((outlen + 7) / 8); - memcpy (cache->cache_buffer[0], fdi->track_dst_buffer, (outlen + 7) / 8); - if (fdi->track_dst_buffer_timing[0] > 0) { - cache->cache_buffer_timing = fdi_malloc ((outlen + 7) / 8 * sizeof (uae_u16)); - memcpy (cache->cache_buffer_timing, fdi->track_dst_buffer_timing, (outlen + 7) / 8 * sizeof (uae_u16)); - } - return fdi2raw_loadtrack (fdi, mfmbuf, tracktiming, track, tracklength, indexoffsetp, multirev); - } - return 0; -} - diff --git a/identify.c b/identify.c index 6d39ab97..792e075a 100755 --- a/identify.c +++ b/identify.c @@ -119,255 +119,255 @@ struct customData custd[] = #if 0 { "BLTDDAT", 0xdff000 }, /* Blitter dest. early read (dummy address) */ #endif - { "DMACONR", 0xdff002 }, /* Dma control (and blitter status) read */ - { "VPOSR", 0xdff004 }, /* Read vert most sig. bits (and frame flop */ - { "VHPOSR", 0xdff006 }, /* Read vert and horiz position of beam */ + { "DMACONR", 0xdff002, 1, 0 }, /* Dma control (and blitter status) read */ + { "VPOSR", 0xdff004, 1, 0 }, /* Read vert most sig. bits (and frame flop */ + { "VHPOSR", 0xdff006, 1, 0 }, /* Read vert and horiz position of beam */ #if 0 { "DSKDATR", 0xdff008 }, /* Disk data early read (dummy address) */ #endif - { "JOY0DAT", 0xdff00A }, /* Joystick-mouse 0 data (vert,horiz) */ - { "JOT1DAT", 0xdff00C }, /* Joystick-mouse 1 data (vert,horiz) */ - { "CLXDAT", 0xdff00E }, /* Collision data reg. (read and clear) */ - { "ADKCONR", 0xdff010 }, /* Audio,disk control register read */ - { "POT0DAT", 0xdff012 }, /* Pot counter pair 0 data (vert,horiz) */ - { "POT1DAT", 0xdff014 }, /* Pot counter pair 1 data (vert,horiz) */ - { "POTGOR", 0xdff016 }, /* Pot pin data read */ - { "SERDATR", 0xdff018 }, /* Serial port data and status read */ - { "DSKBYTR", 0xdff01A }, /* Disk data byte and status read */ - { "INTENAR", 0xdff01C }, /* Interrupt enable bits read */ - { "INTREQR", 0xdff01E }, /* Interrupt request bits read */ - { "DSKPTH", 0xdff020 }, /* Disk pointer (high 5 bits) */ - { "DSKPTL", 0xdff022 }, /* Disk pointer (low 15 bits) */ - { "DSKLEN", 0xdff024 }, /* Disk lentgh */ - { "DSKDAT", 0xdff026 }, /* Disk DMA data write */ + { "JOY0DAT", 0xdff00A, 1, 0 }, /* Joystick-mouse 0 data (vert,horiz) */ + { "JOT1DAT", 0xdff00C, 1, 0 }, /* Joystick-mouse 1 data (vert,horiz) */ + { "CLXDAT", 0xdff00E, 1, 0 }, /* Collision data reg. (read and clear) */ + { "ADKCONR", 0xdff010, 1, 0 }, /* Audio,disk control register read */ + { "POT0DAT", 0xdff012, 1, 0 }, /* Pot counter pair 0 data (vert,horiz) */ + { "POT1DAT", 0xdff014, 1, 0 }, /* Pot counter pair 1 data (vert,horiz) */ + { "POTGOR", 0xdff016, 1, 0 }, /* Pot pin data read */ + { "SERDATR", 0xdff018, 1, 0 }, /* Serial port data and status read */ + { "DSKBYTR", 0xdff01A, 1, 0 }, /* Disk data byte and status read */ + { "INTENAR", 0xdff01C, 1, 0 }, /* Interrupt enable bits read */ + { "INTREQR", 0xdff01E, 1, 0 }, /* Interrupt request bits read */ + { "DSKPTH", 0xdff020, 2, 1 }, /* Disk pointer (high 5 bits) */ + { "DSKPTL", 0xdff022, 2, 2 }, /* Disk pointer (low 15 bits) */ + { "DSKLEN", 0xdff024, 2, 0 }, /* Disk lentgh */ #if 0 + { "DSKDAT", 0xdff026 }, /* Disk DMA data write */ { "REFPTR", 0xdff028 }, /* Refresh pointer */ #endif - { "VPOSW", 0xdff02A }, /* Write vert most sig. bits(and frame flop) */ - { "VHPOSW", 0xdff02C }, /* Write vert and horiz pos of beam */ - { "COPCON", 0xdff02e }, /* Coprocessor control reg (CDANG) */ - { "SERDAT", 0xdff030 }, /* Serial port data and stop bits write */ - { "SERPER", 0xdff032 }, /* Serial port period and control */ - { "POTGO", 0xdff034 }, /* Pot count start,pot pin drive enable data */ - { "JOYTEST", 0xdff036 }, /* Write to all 4 joystick-mouse counters at once */ - { "STREQU", 0xdff038 }, /* Strobe for horiz sync with VB and EQU */ - { "STRVBL", 0xdff03A }, /* Strobe for horiz sync with VB (vert blank) */ - { "STRHOR", 0xdff03C }, /* Strobe for horiz sync */ - { "STRLONG", 0xdff03E }, /* Strobe for identification of long horiz line */ - { "BLTCON0", 0xdff040 }, /* Blitter control reg 0 */ - { "BLTCON1", 0xdff042 }, /* Blitter control reg 1 */ - { "BLTAFWM", 0xdff044 }, /* Blitter first word mask for source A */ - { "BLTALWM", 0xdff046 }, /* Blitter last word mask for source A */ - { "BLTCPTH", 0xdff048 }, /* Blitter pointer to source C (high 5 bits) */ - { "BLTCPTL", 0xdff04A }, /* Blitter pointer to source C (low 15 bits) */ - { "BLTBPTH", 0xdff04C }, /* Blitter pointer to source B (high 5 bits) */ - { "BLTBPTL", 0xdff04E }, /* Blitter pointer to source B (low 15 bits) */ - { "BLTAPTH", 0xdff050 }, /* Blitter pointer to source A (high 5 bits) */ - { "BLTAPTL", 0xdff052 }, /* Blitter pointer to source A (low 15 bits) */ - { "BPTDPTH", 0xdff054 }, /* Blitter pointer to destn D (high 5 bits) */ - { "BLTDPTL", 0xdff056 }, /* Blitter pointer to destn D (low 15 bits) */ - { "BLTSIZE", 0xdff058 }, /* Blitter start and size (win/width,height) */ - { "BLTCON0L", 0xdff05A }, /* Blitter control 0 lower 8 bits (minterms) */ - { "BLTSIZV", 0xdff05C }, /* Blitter V size (for 15 bit vert size) */ - { "BLTSIZH", 0xdff05E }, /* Blitter H size & start (for 11 bit H size) */ - { "BLTCMOD", 0xdff060 }, /* Blitter modulo for source C */ - { "BLTBMOD", 0xdff062 }, /* Blitter modulo for source B */ - { "BLTAMOD", 0xdff064 }, /* Blitter modulo for source A */ - { "BLTDMOD", 0xdff066 }, /* Blitter modulo for destn D */ + { "VPOSW", 0xdff02A, 2, 0 }, /* Write vert most sig. bits(and frame flop) */ + { "VHPOSW", 0xdff02C, 2, 0 }, /* Write vert and horiz pos of beam */ + { "COPCON", 0xdff02e, 2, 0 }, /* Coprocessor control reg (CDANG) */ + { "SERDAT", 0xdff030, 2, 0 }, /* Serial port data and stop bits write */ + { "SERPER", 0xdff032, 2, 0 }, /* Serial port period and control */ + { "POTGO", 0xdff034, 2, 0 }, /* Pot count start,pot pin drive enable data */ + { "JOYTEST", 0xdff036, 2, 0 }, /* Write to all 4 joystick-mouse counters at once */ + { "STREQU", 0xdff038, 2, 0 }, /* Strobe for horiz sync with VB and EQU */ + { "STRVBL", 0xdff03A, 2, 0 }, /* Strobe for horiz sync with VB (vert blank) */ + { "STRHOR", 0xdff03C, 2, 0 }, /* Strobe for horiz sync */ + { "STRLONG", 0xdff03E, 2, 0 }, /* Strobe for identification of long horiz line */ + { "BLTCON0", 0xdff040, 2, 0 }, /* Blitter control reg 0 */ + { "BLTCON1", 0xdff042, 2, 0 }, /* Blitter control reg 1 */ + { "BLTAFWM", 0xdff044, 2, 0 }, /* Blitter first word mask for source A */ + { "BLTALWM", 0xdff046, 2, 0 }, /* Blitter last word mask for source A */ + { "BLTCPTH", 0xdff048, 2, 1 }, /* Blitter pointer to source C (high 5 bits) */ + { "BLTCPTL", 0xdff04A, 2, 2 }, /* Blitter pointer to source C (low 15 bits) */ + { "BLTBPTH", 0xdff04C, 2, 1 }, /* Blitter pointer to source B (high 5 bits) */ + { "BLTBPTL", 0xdff04E, 2, 2 }, /* Blitter pointer to source B (low 15 bits) */ + { "BLTAPTH", 0xdff050, 2, 1 }, /* Blitter pointer to source A (high 5 bits) */ + { "BLTAPTL", 0xdff052, 2, 2 }, /* Blitter pointer to source A (low 15 bits) */ + { "BPTDPTH", 0xdff054, 2, 1 }, /* Blitter pointer to destn D (high 5 bits) */ + { "BLTDPTL", 0xdff056, 2, 2 }, /* Blitter pointer to destn D (low 15 bits) */ + { "BLTSIZE", 0xdff058, 2, 0 }, /* Blitter start and size (win/width,height) */ + { "BLTCON0L", 0xdff05A, 2, 0 }, /* Blitter control 0 lower 8 bits (minterms) */ + { "BLTSIZV", 0xdff05C, 2, 0 }, /* Blitter V size (for 15 bit vert size) */ + { "BLTSIZH", 0xdff05E, 2, 0 }, /* Blitter H size & start (for 11 bit H size) */ + { "BLTCMOD", 0xdff060, 2, 0 }, /* Blitter modulo for source C */ + { "BLTBMOD", 0xdff062, 2, 0 }, /* Blitter modulo for source B */ + { "BLTAMOD", 0xdff064, 2, 0 }, /* Blitter modulo for source A */ + { "BLTDMOD", 0xdff066, 2, 0 }, /* Blitter modulo for destn D */ #if 0 { "Unknown", 0xdff068 }, /* Unknown or Unused */ { "Unknown", 0xdff06a }, /* Unknown or Unused */ { "Unknown", 0xdff06c }, /* Unknown or Unused */ { "Unknown", 0xdff06e }, /* Unknown or Unused */ #endif - { "BLTCDAT", 0xdff070 }, /* Blitter source C data reg */ - { "BLTBDAT", 0xdff072 }, /* Blitter source B data reg */ - { "BLTADAT", 0xdff074 }, /* Blitter source A data reg */ - { "BLTDDAT", 0xdff076 }, /* Blitter destination reg */ + { "BLTCDAT", 0xdff070, 2, 0 }, /* Blitter source C data reg */ + { "BLTBDAT", 0xdff072, 2, 0 }, /* Blitter source B data reg */ + { "BLTADAT", 0xdff074, 2, 0 }, /* Blitter source A data reg */ + { "BLTDDAT", 0xdff076, 2, 0 }, /* Blitter destination reg */ #if 0 { "SPRHDAT", 0xdff078 }, /* Ext logic UHRES sprite pointer and data identifier */ { "BPLHDAT", 0xdff07A }, /* Ext logic UHRES bit plane identifier */ #endif - { "LISAID", 0xdff07C }, /* Chip revision level for Denise/Lisa */ - { "DSKSYNC", 0xdff07E }, /* Disk sync pattern reg for disk read */ - { "COP1LCH", 0xdff080 }, /* Coprocessor first location reg (high 5 bits) */ - { "COP1LCL", 0xdff082 }, /* Coprocessor first location reg (low 15 bits) */ - { "COP2LCH", 0xdff084 }, /* Coprocessor second reg (high 5 bits) */ - { "COP2LCL", 0xdff086 }, /* Coprocessor second reg (low 15 bits) */ - { "COPJMP1", 0xdff088 }, /* Coprocessor restart at first location */ - { "COPJMP2", 0xdff08A }, /* Coprocessor restart at second location */ + { "LISAID", 0xdff07C, 1, 0 }, /* Chip revision level for Denise/Lisa */ + { "DSKSYNC", 0xdff07E, 2, 0 }, /* Disk sync pattern reg for disk read */ + { "COP1LCH", 0xdff080, 2, 1 }, /* Coprocessor first location reg (high 5 bits) */ + { "COP1LCL", 0xdff082, 2, 2 }, /* Coprocessor first location reg (low 15 bits) */ + { "COP2LCH", 0xdff084, 2, 1 }, /* Coprocessor second reg (high 5 bits) */ + { "COP2LCL", 0xdff086, 2, 2 }, /* Coprocessor second reg (low 15 bits) */ + { "COPJMP1", 0xdff088, 2, 0 }, /* Coprocessor restart at first location */ + { "COPJMP2", 0xdff08A, 2, 0 }, /* Coprocessor restart at second location */ #if 0 { "COPINS", 0xdff08C }, /* Coprocessor inst fetch identify */ #endif - { "DIWSTRT", 0xdff08E }, /* Display window start (upper left vert-hor pos) */ - { "DIWSTOP", 0xdff090 }, /* Display window stop (lower right vert-hor pos) */ - { "DDFSTRT", 0xdff092 }, /* Display bit plane data fetch start.hor pos */ - { "DDFSTOP", 0xdff094 }, /* Display bit plane data fetch stop.hor pos */ - { "DMACON", 0xdff096 }, /* DMA control write (clear or set) */ - { "CLXCON", 0xdff098 }, /* Collision control */ - { "INTENA", 0xdff09A }, /* Interrupt enable bits (clear or set bits) */ - { "INTREQ", 0xdff09C }, /* Interrupt request bits (clear or set bits) */ - { "ADKCON", 0xdff09E }, /* Audio,disk,UART,control */ - { "AUD0LCH", 0xdff0A0 }, /* Audio channel 0 location (high 5 bits) */ - { "AUD0LCL", 0xdff0A2 }, /* Audio channel 0 location (low 15 bits) */ - { "AUD0LEN", 0xdff0A4 }, /* Audio channel 0 lentgh */ - { "AUD0PER", 0xdff0A6 }, /* Audio channel 0 period */ - { "AUD0VOL", 0xdff0A8 }, /* Audio channel 0 volume */ - { "AUD0DAT", 0xdff0AA }, /* Audio channel 0 data */ + { "DIWSTRT", 0xdff08E, 2, 0 }, /* Display window start (upper left vert-hor pos) */ + { "DIWSTOP", 0xdff090, 2, 0 }, /* Display window stop (lower right vert-hor pos) */ + { "DDFSTRT", 0xdff092, 2, 0 }, /* Display bit plane data fetch start.hor pos */ + { "DDFSTOP", 0xdff094, 2, 0 }, /* Display bit plane data fetch stop.hor pos */ + { "DMACON", 0xdff096, 2, 0 }, /* DMA control write (clear or set) */ + { "CLXCON", 0xdff098, 2, 0 }, /* Collision control */ + { "INTENA", 0xdff09A, 2, 0 }, /* Interrupt enable bits (clear or set bits) */ + { "INTREQ", 0xdff09C, 2, 0 }, /* Interrupt request bits (clear or set bits) */ + { "ADKCON", 0xdff09E, 2, 0 }, /* Audio,disk,UART,control */ + { "AUD0LCH", 0xdff0A0, 2, 1 }, /* Audio channel 0 location (high 5 bits) */ + { "AUD0LCL", 0xdff0A2, 2, 2 }, /* Audio channel 0 location (low 15 bits) */ + { "AUD0LEN", 0xdff0A4, 2, 0 }, /* Audio channel 0 lentgh */ + { "AUD0PER", 0xdff0A6, 2, 0 }, /* Audio channel 0 period */ + { "AUD0VOL", 0xdff0A8, 2, 0 }, /* Audio channel 0 volume */ + { "AUD0DAT", 0xdff0AA, 2, 0 }, /* Audio channel 0 data */ #if 0 { "Unknown", 0xdff0AC }, /* Unknown or Unused */ { "Unknown", 0xdff0AE }, /* Unknown or Unused */ #endif - { "AUD1LCH", 0xdff0B0 }, /* Audio channel 1 location (high 5 bits) */ - { "AUD1LCL", 0xdff0B2 }, /* Audio channel 1 location (low 15 bits) */ - { "AUD1LEN", 0xdff0B4 }, /* Audio channel 1 lentgh */ - { "AUD1PER", 0xdff0B6 }, /* Audio channel 1 period */ - { "AUD1VOL", 0xdff0B8 }, /* Audio channel 1 volume */ - { "AUD1DAT", 0xdff0BA }, /* Audio channel 1 data */ + { "AUD1LCH", 0xdff0B0, 2, 0 }, /* Audio channel 1 location (high 5 bits) */ + { "AUD1LCL", 0xdff0B2, 2, 0 }, /* Audio channel 1 location (low 15 bits) */ + { "AUD1LEN", 0xdff0B4, 2, 0 }, /* Audio channel 1 lentgh */ + { "AUD1PER", 0xdff0B6, 2, 0 }, /* Audio channel 1 period */ + { "AUD1VOL", 0xdff0B8, 2, 0 }, /* Audio channel 1 volume */ + { "AUD1DAT", 0xdff0BA, 2, 0 }, /* Audio channel 1 data */ #if 0 { "Unknown", 0xdff0BC }, /* Unknown or Unused */ { "Unknown", 0xdff0BE }, /* Unknown or Unused */ #endif - { "AUD2LCH", 0xdff0C0 }, /* Audio channel 2 location (high 5 bits) */ - { "AUD2LCL", 0xdff0C2 }, /* Audio channel 2 location (low 15 bits) */ - { "AUD2LEN", 0xdff0C4 }, /* Audio channel 2 lentgh */ - { "AUD2PER", 0xdff0C6 }, /* Audio channel 2 period */ - { "AUD2VOL", 0xdff0C8 }, /* Audio channel 2 volume */ - { "AUD2DAT", 0xdff0CA }, /* Audio channel 2 data */ + { "AUD2LCH", 0xdff0C0, 2, 0 }, /* Audio channel 2 location (high 5 bits) */ + { "AUD2LCL", 0xdff0C2, 2, 0 }, /* Audio channel 2 location (low 15 bits) */ + { "AUD2LEN", 0xdff0C4, 2, 0 }, /* Audio channel 2 lentgh */ + { "AUD2PER", 0xdff0C6, 2, 0 }, /* Audio channel 2 period */ + { "AUD2VOL", 0xdff0C8, 2, 0 }, /* Audio channel 2 volume */ + { "AUD2DAT", 0xdff0CA, 2, 0 }, /* Audio channel 2 data */ #if 0 { "Unknown", 0xdff0CC }, /* Unknown or Unused */ { "Unknown", 0xdff0CE }, /* Unknown or Unused */ #endif - { "AUD3LCH", 0xdff0D0 }, /* Audio channel 3 location (high 5 bits) */ - { "AUD3LCL", 0xdff0D2 }, /* Audio channel 3 location (low 15 bits) */ - { "AUD3LEN", 0xdff0D4 }, /* Audio channel 3 lentgh */ - { "AUD3PER", 0xdff0D6 }, /* Audio channel 3 period */ - { "AUD3VOL", 0xdff0D8 }, /* Audio channel 3 volume */ - { "AUD3DAT", 0xdff0DA }, /* Audio channel 3 data */ + { "AUD3LCH", 0xdff0D0, 2, 0 }, /* Audio channel 3 location (high 5 bits) */ + { "AUD3LCL", 0xdff0D2, 2, 0 }, /* Audio channel 3 location (low 15 bits) */ + { "AUD3LEN", 0xdff0D4, 2, 0 }, /* Audio channel 3 lentgh */ + { "AUD3PER", 0xdff0D6, 2, 0 }, /* Audio channel 3 period */ + { "AUD3VOL", 0xdff0D8, 2, 0 }, /* Audio channel 3 volume */ + { "AUD3DAT", 0xdff0DA, 2, 0 }, /* Audio channel 3 data */ #if 0 { "Unknown", 0xdff0DC }, /* Unknown or Unused */ { "Unknown", 0xdff0DE }, /* Unknown or Unused */ #endif - { "BPL1PTH", 0xdff0E0 }, /* Bit plane pointer 1 (high 5 bits) */ - { "BPL1PTL", 0xdff0E2 }, /* Bit plane pointer 1 (low 15 bits) */ - { "BPL2PTH", 0xdff0E4 }, /* Bit plane pointer 2 (high 5 bits) */ - { "BPL2PTL", 0xdff0E6 }, /* Bit plane pointer 2 (low 15 bits) */ - { "BPL3PTH", 0xdff0E8 }, /* Bit plane pointer 3 (high 5 bits) */ - { "BPL3PTL", 0xdff0EA }, /* Bit plane pointer 3 (low 15 bits) */ - { "BPL4PTH", 0xdff0EC }, /* Bit plane pointer 4 (high 5 bits) */ - { "BPL4PTL", 0xdff0EE }, /* Bit plane pointer 4 (low 15 bits) */ - { "BPL5PTH", 0xdff0F0 }, /* Bit plane pointer 5 (high 5 bits) */ - { "BPL5PTL", 0xdff0F2 }, /* Bit plane pointer 5 (low 15 bits) */ - { "BPL6PTH", 0xdff0F4 }, /* Bit plane pointer 6 (high 5 bits) */ - { "BPL6PTL", 0xdff0F6 }, /* Bit plane pointer 6 (low 15 bits) */ - { "BPL7PTH", 0xdff0F8 }, /* Bit plane pointer 7 (high 5 bits) */ - { "BPL7PTL", 0xdff0FA }, /* Bit plane pointer 7 (low 15 bits) */ - { "BPL8PTH", 0xdff0FC }, /* Bit plane pointer 8 (high 5 bits) */ - { "BPL8PTL", 0xdff0FE }, /* Bit plane pointer 8 (low 15 bits) */ - { "BPLCON0", 0xdff100 }, /* Bit plane control reg (misc control bits) */ - { "BPLCON1", 0xdff102 }, /* Bit plane control reg (scroll val PF1,PF2) */ - { "BPLCON2", 0xdff104 }, /* Bit plane control reg (priority control) */ - { "BPLCON3", 0xdff106 }, /* Bit plane control reg (enhanced features) */ - { "BPL1MOD", 0xdff108 }, /* Bit plane modulo (odd planes,or active- fetch lines if bitplane scan-doubling is enabled */ - { "BPL2MOD", 0xdff10A }, /* Bit plane modulo (even planes or inactive- fetch lines if bitplane scan-doubling is enabled */ - { "BPLCON4", 0xdff10C }, /* Bit plane control reg (bitplane and sprite masks) */ - { "CLXCON2", 0xdff10e }, /* Extended collision control reg */ - { "BPL1DAT", 0xdff110 }, /* Bit plane 1 data (parallel to serial con- vert) */ - { "BPL2DAT", 0xdff112 }, /* Bit plane 2 data (parallel to serial con- vert) */ - { "BPL3DAT", 0xdff114 }, /* Bit plane 3 data (parallel to serial con- vert) */ - { "BPL4DAT", 0xdff116 }, /* Bit plane 4 data (parallel to serial con- vert) */ - { "BPL5DAT", 0xdff118 }, /* Bit plane 5 data (parallel to serial con- vert) */ - { "BPL6DAT", 0xdff11a }, /* Bit plane 6 data (parallel to serial con- vert) */ - { "BPL7DAT", 0xdff11c }, /* Bit plane 7 data (parallel to serial con- vert) */ - { "BPL8DAT", 0xdff11e }, /* Bit plane 8 data (parallel to serial con- vert) */ - { "SPR0PTH", 0xdff120 }, /* Sprite 0 pointer (high 5 bits) */ - { "SPR0PTL", 0xdff122 }, /* Sprite 0 pointer (low 15 bits) */ - { "SPR1PTH", 0xdff124 }, /* Sprite 1 pointer (high 5 bits) */ - { "SPR1PTL", 0xdff126 }, /* Sprite 1 pointer (low 15 bits) */ - { "SPR2PTH", 0xdff128 }, /* Sprite 2 pointer (high 5 bits) */ - { "SPR2PTL", 0xdff12A }, /* Sprite 2 pointer (low 15 bits) */ - { "SPR3PTH", 0xdff12C }, /* Sprite 3 pointer (high 5 bits) */ - { "SPR3PTL", 0xdff12E }, /* Sprite 3 pointer (low 15 bits) */ - { "SPR4PTH", 0xdff130 }, /* Sprite 4 pointer (high 5 bits) */ - { "SPR4PTL", 0xdff132 }, /* Sprite 4 pointer (low 15 bits) */ - { "SPR5PTH", 0xdff134 }, /* Sprite 5 pointer (high 5 bits) */ - { "SPR5PTL", 0xdff136 }, /* Sprite 5 pointer (low 15 bits) */ - { "SPR6PTH", 0xdff138 }, /* Sprite 6 pointer (high 5 bits) */ - { "SPR6PTL", 0xdff13A }, /* Sprite 6 pointer (low 15 bits) */ - { "SPR7PTH", 0xdff13C }, /* Sprite 7 pointer (high 5 bits) */ - { "SPR7PTL", 0xdff13E }, /* Sprite 7 pointer (low 15 bits) */ - { "SPR0POS", 0xdff140 }, /* Sprite 0 vert-horiz start pos data */ - { "SPR0CTL", 0xdff142 }, /* Sprite 0 position and control data */ - { "SPR0DATA", 0xdff144 }, /* Sprite 0 image data register A */ - { "SPR0DATB", 0xdff146 }, /* Sprite 0 image data register B */ - { "SPR1POS", 0xdff148 }, /* Sprite 1 vert-horiz start pos data */ - { "SPR1CTL", 0xdff14A }, /* Sprite 1 position and control data */ - { "SPR1DATA", 0xdff14C }, /* Sprite 1 image data register A */ - { "SPR1DATB", 0xdff14E }, /* Sprite 1 image data register B */ - { "SPR2POS", 0xdff150 }, /* Sprite 2 vert-horiz start pos data */ - { "SPR2CTL", 0xdff152 }, /* Sprite 2 position and control data */ - { "SPR2DATA", 0xdff154 }, /* Sprite 2 image data register A */ - { "SPR2DATB", 0xdff156 }, /* Sprite 2 image data register B */ - { "SPR3POS", 0xdff158 }, /* Sprite 3 vert-horiz start pos data */ - { "SPR3CTL", 0xdff15A }, /* Sprite 3 position and control data */ - { "SPR3DATA", 0xdff15C }, /* Sprite 3 image data register A */ - { "SPR3DATB", 0xdff15E }, /* Sprite 3 image data register B */ - { "SPR4POS", 0xdff160 }, /* Sprite 4 vert-horiz start pos data */ - { "SPR4CTL", 0xdff162 }, /* Sprite 4 position and control data */ - { "SPR4DATA", 0xdff164 }, /* Sprite 4 image data register A */ - { "SPR4DATB", 0xdff166 }, /* Sprite 4 image data register B */ - { "SPR5POS", 0xdff168 }, /* Sprite 5 vert-horiz start pos data */ - { "SPR5CTL", 0xdff16A }, /* Sprite 5 position and control data */ - { "SPR5DATA", 0xdff16C }, /* Sprite 5 image data register A */ - { "SPR5DATB", 0xdff16E }, /* Sprite 5 image data register B */ - { "SPR6POS", 0xdff170 }, /* Sprite 6 vert-horiz start pos data */ - { "SPR6CTL", 0xdff172 }, /* Sprite 6 position and control data */ - { "SPR6DATA", 0xdff174 }, /* Sprite 6 image data register A */ - { "SPR6DATB", 0xdff176 }, /* Sprite 6 image data register B */ - { "SPR7POS", 0xdff178 }, /* Sprite 7 vert-horiz start pos data */ - { "SPR7CTL", 0xdff17A }, /* Sprite 7 position and control data */ - { "SPR7DATA", 0xdff17C }, /* Sprite 7 image data register A */ - { "SPR7DATB", 0xdff17E }, /* Sprite 7 image data register B */ - { "COLOR00", 0xdff180 }, /* Color table 00 */ - { "COLOR01", 0xdff182 }, /* Color table 01 */ - { "COLOR02", 0xdff184 }, /* Color table 02 */ - { "COLOR03", 0xdff186 }, /* Color table 03 */ - { "COLOR04", 0xdff188 }, /* Color table 04 */ - { "COLOR05", 0xdff18A }, /* Color table 05 */ - { "COLOR06", 0xdff18C }, /* Color table 06 */ - { "COLOR07", 0xdff18E }, /* Color table 07 */ - { "COLOR08", 0xdff190 }, /* Color table 08 */ - { "COLOR09", 0xdff192 }, /* Color table 09 */ - { "COLOR10", 0xdff194 }, /* Color table 10 */ - { "COLOR11", 0xdff196 }, /* Color table 11 */ - { "COLOR12", 0xdff198 }, /* Color table 12 */ - { "COLOR13", 0xdff19A }, /* Color table 13 */ - { "COLOR14", 0xdff19C }, /* Color table 14 */ - { "COLOR15", 0xdff19E }, /* Color table 15 */ - { "COLOR16", 0xdff1A0 }, /* Color table 16 */ - { "COLOR17", 0xdff1A2 }, /* Color table 17 */ - { "COLOR18", 0xdff1A4 }, /* Color table 18 */ - { "COLOR19", 0xdff1A6 }, /* Color table 19 */ - { "COLOR20", 0xdff1A8 }, /* Color table 20 */ - { "COLOR21", 0xdff1AA }, /* Color table 21 */ - { "COLOR22", 0xdff1AC }, /* Color table 22 */ - { "COLOR23", 0xdff1AE }, /* Color table 23 */ - { "COLOR24", 0xdff1B0 }, /* Color table 24 */ - { "COLOR25", 0xdff1B2 }, /* Color table 25 */ - { "COLOR26", 0xdff1B4 }, /* Color table 26 */ - { "COLOR27", 0xdff1B6 }, /* Color table 27 */ - { "COLOR28", 0xdff1B8 }, /* Color table 28 */ - { "COLOR29", 0xdff1BA }, /* Color table 29 */ - { "COLOR30", 0xdff1BC }, /* Color table 30 */ - { "COLOR31", 0xdff1BE }, /* Color table 31 */ - { "HTOTAL", 0xdff1C0 }, /* Highest number count in horiz line (VARBEAMEN = 1) */ - { "HSSTOP", 0xdff1C2 }, /* Horiz line pos for HSYNC stop */ - { "HBSTRT", 0xdff1C4 }, /* Horiz line pos for HBLANK start */ - { "HBSTOP", 0xdff1C6 }, /* Horiz line pos for HBLANK stop */ - { "VTOTAL", 0xdff1C8 }, /* Highest numbered vertical line (VARBEAMEN = 1) */ - { "VSSTOP", 0xdff1CA }, /* Vert line for VBLANK start */ - { "VBSTRT", 0xdff1CC }, /* Vert line for VBLANK start */ - { "VBSTOP", 0xdff1CE }, /* Vert line for VBLANK stop */ + { "BPL1PTH", 0xdff0E0, 2 }, /* Bit plane pointer 1 (high 5 bits) */ + { "BPL1PTL", 0xdff0E2, 2 }, /* Bit plane pointer 1 (low 15 bits) */ + { "BPL2PTH", 0xdff0E4, 2 }, /* Bit plane pointer 2 (high 5 bits) */ + { "BPL2PTL", 0xdff0E6, 2 }, /* Bit plane pointer 2 (low 15 bits) */ + { "BPL3PTH", 0xdff0E8, 2 }, /* Bit plane pointer 3 (high 5 bits) */ + { "BPL3PTL", 0xdff0EA, 2 }, /* Bit plane pointer 3 (low 15 bits) */ + { "BPL4PTH", 0xdff0EC, 2 }, /* Bit plane pointer 4 (high 5 bits) */ + { "BPL4PTL", 0xdff0EE, 2 }, /* Bit plane pointer 4 (low 15 bits) */ + { "BPL5PTH", 0xdff0F0, 2 }, /* Bit plane pointer 5 (high 5 bits) */ + { "BPL5PTL", 0xdff0F2, 2 }, /* Bit plane pointer 5 (low 15 bits) */ + { "BPL6PTH", 0xdff0F4, 2 }, /* Bit plane pointer 6 (high 5 bits) */ + { "BPL6PTL", 0xdff0F6, 2 }, /* Bit plane pointer 6 (low 15 bits) */ + { "BPL7PTH", 0xdff0F8, 2 }, /* Bit plane pointer 7 (high 5 bits) */ + { "BPL7PTL", 0xdff0FA, 2 }, /* Bit plane pointer 7 (low 15 bits) */ + { "BPL8PTH", 0xdff0FC, 2 }, /* Bit plane pointer 8 (high 5 bits) */ + { "BPL8PTL", 0xdff0FE, 2 }, /* Bit plane pointer 8 (low 15 bits) */ + { "BPLCON0", 0xdff100, 2 }, /* Bit plane control reg (misc control bits) */ + { "BPLCON1", 0xdff102, 2 }, /* Bit plane control reg (scroll val PF1,PF2) */ + { "BPLCON2", 0xdff104, 2 }, /* Bit plane control reg (priority control) */ + { "BPLCON3", 0xdff106, 2 }, /* Bit plane control reg (enhanced features) */ + { "BPL1MOD", 0xdff108, 2 }, /* Bit plane modulo (odd planes,or active- fetch lines if bitplane scan-doubling is enabled */ + { "BPL2MOD", 0xdff10A, 2 }, /* Bit plane modulo (even planes or inactive- fetch lines if bitplane scan-doubling is enabled */ + { "BPLCON4", 0xdff10C, 2 }, /* Bit plane control reg (bitplane and sprite masks) */ + { "CLXCON2", 0xdff10e, 2 }, /* Extended collision control reg */ + { "BPL1DAT", 0xdff110, 2 }, /* Bit plane 1 data (parallel to serial con- vert) */ + { "BPL2DAT", 0xdff112, 2 }, /* Bit plane 2 data (parallel to serial con- vert) */ + { "BPL3DAT", 0xdff114, 2 }, /* Bit plane 3 data (parallel to serial con- vert) */ + { "BPL4DAT", 0xdff116, 2 }, /* Bit plane 4 data (parallel to serial con- vert) */ + { "BPL5DAT", 0xdff118, 2 }, /* Bit plane 5 data (parallel to serial con- vert) */ + { "BPL6DAT", 0xdff11a, 2 }, /* Bit plane 6 data (parallel to serial con- vert) */ + { "BPL7DAT", 0xdff11c, 2 }, /* Bit plane 7 data (parallel to serial con- vert) */ + { "BPL8DAT", 0xdff11e, 2 }, /* Bit plane 8 data (parallel to serial con- vert) */ + { "SPR0PTH", 0xdff120, 2 }, /* Sprite 0 pointer (high 5 bits) */ + { "SPR0PTL", 0xdff122, 2 }, /* Sprite 0 pointer (low 15 bits) */ + { "SPR1PTH", 0xdff124, 2 }, /* Sprite 1 pointer (high 5 bits) */ + { "SPR1PTL", 0xdff126, 2 }, /* Sprite 1 pointer (low 15 bits) */ + { "SPR2PTH", 0xdff128, 2 }, /* Sprite 2 pointer (high 5 bits) */ + { "SPR2PTL", 0xdff12A, 2 }, /* Sprite 2 pointer (low 15 bits) */ + { "SPR3PTH", 0xdff12C, 2 }, /* Sprite 3 pointer (high 5 bits) */ + { "SPR3PTL", 0xdff12E, 2 }, /* Sprite 3 pointer (low 15 bits) */ + { "SPR4PTH", 0xdff130, 2 }, /* Sprite 4 pointer (high 5 bits) */ + { "SPR4PTL", 0xdff132, 2 }, /* Sprite 4 pointer (low 15 bits) */ + { "SPR5PTH", 0xdff134, 2 }, /* Sprite 5 pointer (high 5 bits) */ + { "SPR5PTL", 0xdff136, 2 }, /* Sprite 5 pointer (low 15 bits) */ + { "SPR6PTH", 0xdff138, 2 }, /* Sprite 6 pointer (high 5 bits) */ + { "SPR6PTL", 0xdff13A, 2 }, /* Sprite 6 pointer (low 15 bits) */ + { "SPR7PTH", 0xdff13C, 2 }, /* Sprite 7 pointer (high 5 bits) */ + { "SPR7PTL", 0xdff13E, 2 }, /* Sprite 7 pointer (low 15 bits) */ + { "SPR0POS", 0xdff140, 2 }, /* Sprite 0 vert-horiz start pos data */ + { "SPR0CTL", 0xdff142, 2 }, /* Sprite 0 position and control data */ + { "SPR0DATA", 0xdff144, 2 }, /* Sprite 0 image data register A */ + { "SPR0DATB", 0xdff146, 2 }, /* Sprite 0 image data register B */ + { "SPR1POS", 0xdff148, 2 }, /* Sprite 1 vert-horiz start pos data */ + { "SPR1CTL", 0xdff14A, 2 }, /* Sprite 1 position and control data */ + { "SPR1DATA", 0xdff14C, 2 }, /* Sprite 1 image data register A */ + { "SPR1DATB", 0xdff14E, 2 }, /* Sprite 1 image data register B */ + { "SPR2POS", 0xdff150, 2 }, /* Sprite 2 vert-horiz start pos data */ + { "SPR2CTL", 0xdff152, 2 }, /* Sprite 2 position and control data */ + { "SPR2DATA", 0xdff154, 2 }, /* Sprite 2 image data register A */ + { "SPR2DATB", 0xdff156, 2 }, /* Sprite 2 image data register B */ + { "SPR3POS", 0xdff158, 2 }, /* Sprite 3 vert-horiz start pos data */ + { "SPR3CTL", 0xdff15A, 2 }, /* Sprite 3 position and control data */ + { "SPR3DATA", 0xdff15C, 2 }, /* Sprite 3 image data register A */ + { "SPR3DATB", 0xdff15E, 2 }, /* Sprite 3 image data register B */ + { "SPR4POS", 0xdff160, 2 }, /* Sprite 4 vert-horiz start pos data */ + { "SPR4CTL", 0xdff162, 2 }, /* Sprite 4 position and control data */ + { "SPR4DATA", 0xdff164, 2 }, /* Sprite 4 image data register A */ + { "SPR4DATB", 0xdff166, 2 }, /* Sprite 4 image data register B */ + { "SPR5POS", 0xdff168, 2 }, /* Sprite 5 vert-horiz start pos data */ + { "SPR5CTL", 0xdff16A, 2 }, /* Sprite 5 position and control data */ + { "SPR5DATA", 0xdff16C, 2 }, /* Sprite 5 image data register A */ + { "SPR5DATB", 0xdff16E, 2 }, /* Sprite 5 image data register B */ + { "SPR6POS", 0xdff170, 2 }, /* Sprite 6 vert-horiz start pos data */ + { "SPR6CTL", 0xdff172, 2 }, /* Sprite 6 position and control data */ + { "SPR6DATA", 0xdff174, 2 }, /* Sprite 6 image data register A */ + { "SPR6DATB", 0xdff176, 2 }, /* Sprite 6 image data register B */ + { "SPR7POS", 0xdff178, 2 }, /* Sprite 7 vert-horiz start pos data */ + { "SPR7CTL", 0xdff17A, 2 }, /* Sprite 7 position and control data */ + { "SPR7DATA", 0xdff17C, 2 }, /* Sprite 7 image data register A */ + { "SPR7DATB", 0xdff17E, 2 }, /* Sprite 7 image data register B */ + { "COLOR00", 0xdff180, 2 }, /* Color table 00 */ + { "COLOR01", 0xdff182, 2 }, /* Color table 01 */ + { "COLOR02", 0xdff184, 2 }, /* Color table 02 */ + { "COLOR03", 0xdff186, 2 }, /* Color table 03 */ + { "COLOR04", 0xdff188, 2 }, /* Color table 04 */ + { "COLOR05", 0xdff18A, 2 }, /* Color table 05 */ + { "COLOR06", 0xdff18C, 2 }, /* Color table 06 */ + { "COLOR07", 0xdff18E, 2 }, /* Color table 07 */ + { "COLOR08", 0xdff190, 2 }, /* Color table 08 */ + { "COLOR09", 0xdff192, 2 }, /* Color table 09 */ + { "COLOR10", 0xdff194, 2 }, /* Color table 10 */ + { "COLOR11", 0xdff196, 2 }, /* Color table 11 */ + { "COLOR12", 0xdff198, 2 }, /* Color table 12 */ + { "COLOR13", 0xdff19A, 2 }, /* Color table 13 */ + { "COLOR14", 0xdff19C, 2 }, /* Color table 14 */ + { "COLOR15", 0xdff19E, 2 }, /* Color table 15 */ + { "COLOR16", 0xdff1A0, 2 }, /* Color table 16 */ + { "COLOR17", 0xdff1A2, 2 }, /* Color table 17 */ + { "COLOR18", 0xdff1A4, 2 }, /* Color table 18 */ + { "COLOR19", 0xdff1A6, 2 }, /* Color table 19 */ + { "COLOR20", 0xdff1A8, 2 }, /* Color table 20 */ + { "COLOR21", 0xdff1AA, 2 }, /* Color table 21 */ + { "COLOR22", 0xdff1AC, 2 }, /* Color table 22 */ + { "COLOR23", 0xdff1AE, 2 }, /* Color table 23 */ + { "COLOR24", 0xdff1B0, 2 }, /* Color table 24 */ + { "COLOR25", 0xdff1B2, 2 }, /* Color table 25 */ + { "COLOR26", 0xdff1B4, 2 }, /* Color table 26 */ + { "COLOR27", 0xdff1B6, 2 }, /* Color table 27 */ + { "COLOR28", 0xdff1B8, 2 }, /* Color table 28 */ + { "COLOR29", 0xdff1BA, 2 }, /* Color table 29 */ + { "COLOR30", 0xdff1BC, 2 }, /* Color table 30 */ + { "COLOR31", 0xdff1BE, 2 }, /* Color table 31 */ + { "HTOTAL", 0xdff1C0, 2 }, /* Highest number count in horiz line (VARBEAMEN = 1) */ + { "HSSTOP", 0xdff1C2, 2 }, /* Horiz line pos for HSYNC stop */ + { "HBSTRT", 0xdff1C4, 2 }, /* Horiz line pos for HBLANK start */ + { "HBSTOP", 0xdff1C6, 2 }, /* Horiz line pos for HBLANK stop */ + { "VTOTAL", 0xdff1C8, 2 }, /* Highest numbered vertical line (VARBEAMEN = 1) */ + { "VSSTOP", 0xdff1CA, 2 }, /* Vert line for VBLANK start */ + { "VBSTRT", 0xdff1CC, 2 }, /* Vert line for VBLANK start */ + { "VBSTOP", 0xdff1CE, 2 }, /* Vert line for VBLANK stop */ #if 0 { "SPRHSTRT", 0xdff1D0 }, /* UHRES sprite vertical start */ { "SPRHSTOP", 0xdff1D2 }, /* UHRES sprite vertical stop */ @@ -376,11 +376,11 @@ struct customData custd[] = { "HHPOSW", 0xdff1D8 }, /* DUAL mode hires H beam counter write */ { "HHPOSR", 0xdff1DA }, /* DUAL mode hires H beam counter read */ #endif - { "BEAMCON0", 0xdff1DC }, /* Beam counter control register (SHRES,UHRES,PAL) */ - { "HSSTRT", 0xdff1DE }, /* Horizontal sync start (VARHSY) */ - { "VSSTRT", 0xdff1E0 }, /* Vertical sync start (VARVSY) */ - { "HCENTER", 0xdff1E2 }, /* Horizontal pos for vsync on interlace */ - { "DIWHIGH", 0xdff1E4 }, /* Display window upper bits for start/stop */ + { "BEAMCON0", 0xdff1DC, 2 }, /* Beam counter control register (SHRES,UHRES,PAL) */ + { "HSSTRT", 0xdff1DE, 2 }, /* Horizontal sync start (VARHSY) */ + { "VSSTRT", 0xdff1E0, 2 }, /* Vertical sync start (VARVSY) */ + { "HCENTER", 0xdff1E2, 2 }, /* Horizontal pos for vsync on interlace */ + { "DIWHIGH", 0xdff1E4, 2 }, /* Display window upper bits for start/stop */ #if 0 { "BPLHMOD", 0xdff1E6 }, /* UHRES bit plane modulo */ { "SPRHPTH", 0xdff1E8 }, /* UHRES sprite pointer (high 5 bits) */ @@ -394,7 +394,7 @@ struct customData custd[] = { "RESERVED", 0xdff1F8 }, /* Reserved (forever i guess!) */ { "RESERVED", 0xdff1Fa }, /* Reserved (forever i guess!) */ #endif - { "FMODE", 0xdff1FC }, /* Fetch mode register */ + { "FMODE", 0xdff1FC, 2 }, /* Fetch mode register */ #if 0 { "NO-OP(NULL)", 0xdff1FE }, /* Can also indicate last 2 or 3 refresh cycles or the restart of the COPPER after lockup.*/ diff --git a/include/identify.h b/include/identify.h index 4da9bb84..01941c52 100755 --- a/include/identify.h +++ b/include/identify.h @@ -15,6 +15,7 @@ struct customData { const char *name; uae_u32 adr; + uae_u8 rw, dmaadr; }; diff --git a/memory.c b/memory.c index 889d5326..95480b8a 100755 --- a/memory.c +++ b/memory.c @@ -608,6 +608,7 @@ static void a1000_handle_kickstart (int mode) if (mode == 0) { a1000_kickstart_mode = 0; memcpy (kickmemory, kickmemory + 262144, 262144); + kickstart_version = (kickmemory[262144 + 12] << 8) | kickmemory[262144 + 13]; } else { a1000_kickstart_mode = 1; memset (kickmemory, 0, 262144); @@ -615,7 +616,6 @@ static void a1000_handle_kickstart (int mode) memcpy (kickmemory + 131072, a1000_bootrom, 65536); kickstart_version = 0; } - kickstart_version = (kickmemory[262144 + 12] << 8) | kickmemory[262144 + 13]; } void a1000_reset (void) @@ -1046,6 +1046,8 @@ static int read_kickstart (struct zfile *f, uae_u8 *mem, int size, int dochecksu a1000_bootrom = malloc (65536); memcpy (a1000_bootrom, kickmemory, 65536); a1000_handle_kickstart (1); + i = 524288; + dochecksum = 0; } if (dochecksum && i >= 262144) kickstart_checksum (mem, size); diff --git a/od-win32/avioutput.c b/od-win32/avioutput.c index 20bcfa22..529c20ab 100755 --- a/od-win32/avioutput.c +++ b/od-win32/avioutput.c @@ -651,10 +651,8 @@ void AVIOutput_Restart(void) void AVIOutput_End(void) { EnterCriticalSection(&AVIOutput_CriticalSection); - - avioutput_audio = avioutput_video = 0; + avioutput_enabled = 0; - if(has) { acmStreamUnprepareHeader(has, &ash, 0); @@ -720,7 +718,7 @@ void AVIOutput_Begin(void) } else { ext1 = ".avi"; ext2 = ".wav"; } - if (strlen (avioutput_filename) >= 4 && strcmpi (avioutput_filename + strlen (avioutput_filename) - 4, ext2)) + if (strlen (avioutput_filename) >= 4 && !strcmpi (avioutput_filename + strlen (avioutput_filename) - 4, ext2)) avioutput_filename[strlen (avioutput_filename) - 4] = 0; if (strlen (avioutput_filename) >= 4 && strcmpi (avioutput_filename + strlen (avioutput_filename) - 4, ext1)) strcat (avioutput_filename, ext1); diff --git a/od-win32/drivesound.c b/od-win32/drivesound.c deleted file mode 100755 index 4782c7bb..00000000 --- a/od-win32/drivesound.c +++ /dev/null @@ -1,191 +0,0 @@ -#include "sysconfig.h" -#include "sysdeps.h" - -#include "config.h" -#include "options.h" -#include "zfile.h" -#include "sounddep/sound.h" -#include "dxwrap.h" - -#include -#include -#include - -static LPDIRECTSOUND lpDS; -static LPDIRECTSOUNDBUFFER lpDSBprimary; - -#define DRIVESOUND_CLICK 0 -#define DRIVESOUND_STARTUP 1 -#define DRIVESOUND_SPIN 2 -#define DRIVESOUND_END 3 - -static LPDIRECTSOUNDBUFFER samples[4][DRIVESOUND_END]; -static int drivesound_enabled, drive_enabled[4]; -static int click_frequency[4]; -static int minfreq, maxfreq; - -extern GUID sound_device_guid[]; - -static void close_audio_ds (void) -{ - int i, j; - - drivesound_enabled = 0; - for (i = 0; i < DRIVESOUND_END; i++) { - for (j = 0; j < 4; j++) { - if (samples[j][i]) - IDirectSound_Release (samples[j][i]); - samples[j][i] = 0; - drive_enabled[j] = 0; - } - } - if (lpDSBprimary) - IDirectSound_Release (lpDSBprimary); - lpDSBprimary = 0; - if (lpDS) { - IDirectSound_Release (lpDS); - write_log ("DRIVESOUND: DirectSound driver freed\n"); - } - lpDS = 0; -} - -extern HWND hMainWnd; - -static int createsample (int drivenum, int samplenum, char *path) -{ - struct zfile *f; - uae_u8 *buf = 0; - int size, freq = 44100; - WAVEFORMATEX wavfmt; - DSBUFFERDESC sound_buffer; - HRESULT hr; - void *b1, *b2; - DWORD s1, s2; - - f = zfile_fopen (path, "rb"); - if (!f) { - write_log ("DRIVESOUND: can't open '%s'\n", path); - goto error; - } - zfile_fseek (f, 0, SEEK_END); - size = zfile_ftell (f); - buf = malloc (size); - zfile_fseek (f, 0, SEEK_SET); - zfile_fread (buf, size, 1, f); - zfile_fclose (f); - - if (samplenum == DRIVESOUND_CLICK) - click_frequency[drivenum] = freq; - wavfmt.wFormatTag = WAVE_FORMAT_PCM; - wavfmt.nChannels = 2; - wavfmt.nSamplesPerSec = freq; - wavfmt.wBitsPerSample = 16; - wavfmt.nBlockAlign = 16 / 8 * wavfmt.nChannels; - wavfmt.nAvgBytesPerSec = wavfmt.nBlockAlign * freq; - memset (&sound_buffer, 0, sizeof (sound_buffer)); - sound_buffer.dwSize = sizeof (sound_buffer); - sound_buffer.dwBufferBytes = size; - sound_buffer.lpwfxFormat = &wavfmt; - sound_buffer.dwFlags = DSBCAPS_LOCSOFTWARE | DSBCAPS_GLOBALFOCUS; - - hr = IDirectSound_CreateSoundBuffer( lpDS, &sound_buffer, &samples[drivenum][samplenum], NULL ); - if (hr != DS_OK) { - write_log ("DRIVESOUND: Secondary CreateSoundBuffer(%s) failure: %s\n", - path, DXError (hr)); - goto error; - } - hr = IDirectSoundBuffer_Lock (samples[drivenum][samplenum], 0, sndbufsize, &b1, &s1, &b2, &s2, DSBLOCK_ENTIREBUFFER); - if (hr != DS_OK) { - write_log ("DRIVESOUND: lock failed: %s\n", DXError (hr)); - goto error; - } - memcpy (b1, buf, size >= s1 ? s1 : size); - if (b2) - memcpy (b2, buf + s1, size - s1); - IDirectSoundBuffer_Unlock (samples[drivenum][samplenum], b1, s1, b2, s2); - write_log ("DRIVESOUND: drive %d, sample %d (%s) loaded\n", drivenum, samplenum, path); - - return 1; - error: - free (buf); - if (samples[drivenum][samplenum]) { - IDirectSound_Release (samples[drivenum][samplenum]); - samples[drivenum][samplenum] = 0; - } - return 0; -} - - -static int open_audio_ds (void) -{ - HRESULT hr; - int freq = currprefs.sound_freq; - - enumerate_sound_devices (0); - hr = DirectSoundCreate (&sound_device_guid[currprefs.win32_soundcard], &lpDS, NULL); - if (hr != DS_OK) { - write_log ("SOUND: DirectSoundCreate() failure: %s\n", DXError (hr)); - return 0; - } - hr = IDirectSound_SetCooperativeLevel (lpDS, hMainWnd, DSSCL_NORMAL); - if (hr != DS_OK) { - write_log ("SOUND: Can't set cooperativelevel: %s\n", DXError (hr)); - goto error; - } - - createsample(0, DRIVESOUND_CLICK, "drive_click.raw"); - createsample(0, DRIVESOUND_STARTUP, "drive_startup.raw"); - createsample(0, DRIVESOUND_SPIN, "drive_spin.raw"); - drive_enabled[0] = 1; - - drivesound_enabled = 1; - - return 1; - -error: - close_audio_ds (); - return 0; -} - -int drivesound_init (void) -{ - return open_audio_ds (); -} - -void drivesound_free (void) -{ - close_audio_ds (); -} - -void drivesound_click (int num, int delay) -{ - HRESULT hr; - LPDIRECTSOUNDBUFFER dsb; - - if (!drivesound_enabled || !drive_enabled[num]) - return; - dsb = samples[num][DRIVESOUND_CLICK]; - if (!dsb) - return; - hr = IDirectSoundBuffer_SetCurrentPosition (dsb, 0); - hr = IDirectSoundBuffer_Play (dsb, 0, 0, 0); -} - -void drivesound_motor (int num, int status) -{ - HRESULT hr; - - if (!drivesound_enabled || !drive_enabled[num]) - return; - if (!status) { - if (samples[num][DRIVESOUND_STARTUP]) - hr = IDirectSoundBuffer_Stop (samples[num][DRIVESOUND_STARTUP]); - if (samples[num][DRIVESOUND_SPIN]) - hr = IDirectSoundBuffer_Stop (samples[num][DRIVESOUND_SPIN]); - } else { - if (status == 2 && samples[num][DRIVESOUND_STARTUP]) - hr = IDirectSoundBuffer_Play (samples[num][DRIVESOUND_STARTUP], 0, 0, 0); - if (samples[num][DRIVESOUND_SPIN]) - hr = IDirectSoundBuffer_Play (samples[num][DRIVESOUND_SPIN], 0, 0, DSBPLAY_LOOPING); - } -} diff --git a/od-win32/resources/winuae.rc b/od-win32/resources/winuae.rc index a458c5e6..b33d2034 100755 --- a/od-win32/resources/winuae.rc +++ b/od-win32/resources/winuae.rc @@ -887,8 +887,8 @@ IDI_MEMORY ICON "chip.ico" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,8,26,0 - PRODUCTVERSION 0,8,26,0 + FILEVERSION 0,8,27,0 + PRODUCTVERSION 0,8,27,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -904,12 +904,12 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "WinUAE" - VALUE "FileVersion", "0.8.26" + VALUE "FileVersion", "0.8.27" VALUE "InternalName", "WinUAE" VALUE "LegalCopyright", "© 1996-2004 under the GNU Public License (GPL)" VALUE "OriginalFilename", "WinUAE.exe" VALUE "ProductName", "WinUAE" - VALUE "ProductVersion", "0.8.26" + VALUE "ProductVersion", "0.8.27" END END BLOCK "VarFileInfo" diff --git a/od-win32/sounddep/sound.c b/od-win32/sounddep/sound.c index 8865f05a..86bd5e6b 100755 --- a/od-win32/sounddep/sound.c +++ b/od-win32/sounddep/sound.c @@ -599,7 +599,7 @@ static void filtercheck (uae_s16 *sndbuffer, int len) void finish_sound_buffer (void) { - if (!have_sound || turbo_emulation) + if (turbo_emulation) return; filtercheck ((uae_s16*)sndbuffer, sndbufsize / 2); #ifdef DRIVESOUND @@ -608,9 +608,11 @@ void finish_sound_buffer (void) #ifdef AVIOUTPUT if (avioutput_audio) AVIOutput_WriteAudio ((uae_u8*)sndbuffer, sndbufsize); - if (!avioutput_framelimiter && (avioutput_video || avioutput_audio)) + if (avioutput_enabled && !avioutput_framelimiter) return; #endif + if (!have_sound) + return; finish_sound_buffer_ds (); } diff --git a/od-win32/win32.h b/od-win32/win32.h index 0e67f387..a35201b6 100755 --- a/od-win32/win32.h +++ b/od-win32/win32.h @@ -21,7 +21,7 @@ extern int manual_painting_needed; extern int manual_palette_refresh_needed; extern int mouseactive, focus; #define WINUAEBETA 1 -#define WINUAEBETASTR " Beta 3" +#define WINUAEBETASTR " Beta 4" extern void my_kbd_handler (int, int, int); extern void clearallkeys(void); diff --git a/od-win32/win32gui.c b/od-win32/win32gui.c index f902f78f..b79150c8 100755 --- a/od-win32/win32gui.c +++ b/od-win32/win32gui.c @@ -5541,9 +5541,9 @@ static void enable_for_avioutputdlg(HWND hDlg) { #if defined (PROWIZARD) EnableWindow( GetDlgItem( hDlg, IDC_PROWIZARD ), TRUE ); -#endif if (full_property_sheet) EnableWindow( GetDlgItem( hDlg, IDC_PROWIZARD ), FALSE ); +#endif EnableWindow(GetDlgItem(hDlg, IDC_SCREENSHOT), full_property_sheet ? FALSE : TRUE); @@ -5579,6 +5579,7 @@ static void enable_for_avioutputdlg(HWND hDlg) WIN32GUI_LoadUIString (IDS_AVIOUTPUT_NOCODEC, aviout_videoc, sizeof (aviout_videoc)); } SetWindowText(GetDlgItem(hDlg, IDC_AVIOUTPUT_VIDEO_STATIC), aviout_videoc); + EnableWindow(GetDlgItem(hDlg, IDC_AVIOUTPUT_ACTIVATED), (!avioutput_audio && !avioutput_video) ? FALSE : TRUE); } static BOOL CALLBACK AVIOutputDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) @@ -5689,6 +5690,10 @@ static BOOL CALLBACK AVIOutputDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM avioutput_video = 1; strcpy (aviout_videoc, string); SetWindowText(GetDlgItem(hDlg, IDC_AVIOUTPUT_VIDEO_STATIC), string); + if (avioutput_audio == AVIAUDIO_WAV) { + avioutput_audio = 0; + aviout_audioc[0] = 0; + } } else avioutput_video = 0; @@ -5725,7 +5730,9 @@ static BOOL CALLBACK AVIOutputDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM break; if (ofn.nFilterIndex == 2) { avioutput_audio = AVIAUDIO_WAV; - SetWindowText(GetDlgItem(hDlg, IDC_AVIOUTPUT_AUDIO_STATIC), "Wave (internal)"); + avioutput_video = 0; + aviout_videoc[0] = 0; + strcpy (aviout_audioc, "Wave (internal)"); if (strlen (avioutput_filename) > 4 && !stricmp (avioutput_filename + strlen (avioutput_filename) - 4, ".avi")) strcpy (avioutput_filename + strlen (avioutput_filename) - 4, ".wav"); } -- 2.47.3