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;
{
if (++blinea_shift == 16) {
blinea_shift = 0;
- bltcnxlpt += 2;
+ bltcpt += 2;
}
}
{
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;
}
STATIC_INLINE void blitter_nxline(void)
{
- bltdpt = bltcpt = bltcnxlpt;
blineb = (blineb << 1) | (blineb >> 15);
if (--blt_info.vblitsize == 0) {
bltstate = BLT_done;
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));
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;
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);
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);
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;
cop_state.state = COP_skip_in2;
break;
case COP_strobe_delay:
- cop_state.state = COP_read1;
+ cop_state.state = COP_read1_in2;
break;
default:
+++ /dev/null
- /*
- * 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 <ctype.h>
-#include <assert.h>
-
-#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
#include "disk.h"
#include "savestate.h"
#include "autoconf.h"
+#include "akiko.h"
static int debugger_active;
static uaecptr skipaddr_start, skipaddr_end, skipaddr_doskip;
" W <address> <value> Write into Amiga memory\n"
" w <num> <address> <length> <R/W/RW> [<value>]\n"
" Add/remove memory watchpoints\n"
+ " wd Enable illegal access logger\n"
" S <file> <addr> <n> Save a block of Amiga memory\n"
" s <string>/<values> [<addr>] [<length>]\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"
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;
{
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;
free (debug_mem_banks);
debug_mem_banks = 0;
memwatch_enabled = 0;
+ free (illgdebug);
+ illgdebug = 0;
}
static int initialize_memwatch (void)
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;
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;
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) {
/* 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
+++ /dev/null
-/*
-
- FDI to raw bit stream converter
- Copyright (c) 2001 by Toni Wilen <twilen@arabuusimiehet.com>
- FDI 2.0 support
- Copyright (c) 2003-2004 by Toni Wilen <twilen@arabuusimiehet.com>
- 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* 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 <assert.h>
-
-#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;
-}
-
+++ /dev/null
-/*
-
- FDI to raw bit stream converter
- Copyright (c) 2001 by Toni Wilen <twilen@arabuusimiehet.com>
- FDI 2.0 support
- Copyright (c) 2003-2004 by Toni Wilen <twilen@arabuusimiehet.com>
- 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* IF UAE */
-#include "sysconfig.h"
-#include "sysdeps.h"
-#include "zfile.h"
-/* ELSE */
-//#include "types.h"
-
-#include "fdi2raw.h"
-
-#undef DEBUG
-#define VERBOSE
-
-#include <assert.h>
-
-#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;
-}
-
#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 */
{ "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) */
{ "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.*/
{
const char *name;
uae_u32 adr;
+ uae_u8 rw, dmaadr;
};
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);
memcpy (kickmemory + 131072, a1000_bootrom, 65536);
kickstart_version = 0;
}
- kickstart_version = (kickmemory[262144 + 12] << 8) | kickmemory[262144 + 13];
}
void a1000_reset (void)
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);
void AVIOutput_End(void)
{
EnterCriticalSection(&AVIOutput_CriticalSection);
-
- avioutput_audio = avioutput_video = 0;
+
avioutput_enabled = 0;
-
if(has)
{
acmStreamUnprepareHeader(has, &ash, 0);
} 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);
+++ /dev/null
-#include "sysconfig.h"
-#include "sysdeps.h"
-
-#include "config.h"
-#include "options.h"
-#include "zfile.h"
-#include "sounddep/sound.h"
-#include "dxwrap.h"
-
-#include <windows.h>
-#include <mmsystem.h>
-#include <dsound.h>
-
-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);
- }
-}
//
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
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"
void finish_sound_buffer (void)
{
- if (!have_sound || turbo_emulation)
+ if (turbo_emulation)
return;
filtercheck ((uae_s16*)sndbuffer, sndbufsize / 2);
#ifdef DRIVESOUND
#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 ();
}
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);
{
#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);
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)
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;
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");
}