static unsigned long ciaatod, ciabtod, ciaatol, ciabtol, ciaaalarm, ciabalarm;
static int ciaatlatch, ciabtlatch;
-static bool oldled, oldovl, oldcd32mute;
+static bool oldovl, oldcd32mute;
static bool led;
static int led_old_brightness;
static unsigned long led_cycles_on, led_cycles_off, led_cycle;
event2_newevent_xx (-1, cycles + TOD_INC_DELAY, 0, CIAA_tod_handler);
}
-static void bfe001_change (void)
+static void check_led (void)
{
uae_u8 v = ciaapra;
bool led2;
led = led2;
led_old_brightness = -1;
}
+}
+
+static void bfe001_change (void)
+{
+ uae_u8 v = ciaapra;
+ check_led ();
if (currprefs.cs_ciaoverlay && (v & 1) != oldovl) {
oldovl = v & 1;
if (!oldovl) {
case 12:
return ciabsdr;
case 13:
+#if CIAB_DEBUG_IRQ
+ if (ciabicr & (0x80 | 0x40))
+ write_log (_T("CIAB IRQ cleared\n"));
+#endif
tmp = ciabicr & ~0x40;
ciabicr = 0;
return tmp;
kblostsynccnt = 0;
serbits = 0;
oldcd32mute = 1;
- oldled = true;
resetwarning_phase = resetwarning_timer = 0;
heartbeat_cnt = 0;
ciab_tod_event_state = 0;
DISK_select_set (ciabprb);
}
map_overlay (0);
+ check_led ();
#ifdef SERIAL_PORT
if (currprefs.use_serial && !savestate_state)
serial_dtr_off (); /* Drop DTR at reset */
#define CUSTOM_DEBUG 0
#define SPRITE_DEBUG 0
-#define SPRITE_DEBUG_MINY 0x0
+#define SPRITE_DEBUG_MINY 246
#define SPRITE_DEBUG_MAXY 0x300
#define SPR0_HPOS 0x15
#define MAX_SPRITES 8
static struct decision thisline_decision;
static int fetch_cycle, fetch_modulo_cycle;
-static int bitplane_dma_turned_on;
enum plfstate
{
plf_wait_stop,
plf_passed_stop,
plf_passed_stop2,
- plf_end,
- plf_finished
+ plf_end
} plf_state;
+enum plfrenderstate
+{
+ plfr_idle,
+ plfr_active,
+ plfr_end,
+ plfr_finished
+} plfr_state;
+
enum fetchstate {
fetch_not_started,
fetch_started_first,
if (warned > 0) {
write_log (_T("buggy copper cycle conflict with blitter ch %c %08x <- %08x PC=%08x\n"), 'A' + (chnum - 1), *ptr, srcptr, m68k_getpc ());
warned--;
+ //activate_debugger ();
}
if ((currprefs.cs_hacks & 1) && currprefs.cpu_model == 68000)
*ptr = srcptr;
/* Expansions from bplcon0/bplcon1. */
static int toscr_res, toscr_res2p;
-static int toscr_nr_planes, toscr_nr_planes2, toscr_nr_planes_agnus, fetchwidth;
+static int toscr_nr_planes, toscr_nr_planes2, toscr_nr_planes_agnus, toscr_nr_planes_shifter;
+static int fetchwidth;
static int toscr_delay[2], toscr_delay_adjusted[2];
-static int delay_cycles, delay_lastcycle;
+static int delay_cycles, delay_lastcycle[2];
static bool bplcon1_written;
/* The number of bits left from the last fetched words.
return curr_diagram[(hpos - cycle_diagram_shift) & fetchstart_mask];
}
+static int islinetoggle (void)
+{
+ int linetoggle = 0;
+ if (!(beamcon0 & 0x0800) && !(beamcon0 & 0x0020) && (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) {
+ linetoggle = 1; // NTSC and !LOLDIS -> LOL toggles every line
+ } else if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS) && currprefs.ntscmode) {
+ linetoggle = 1; // hardwired NTSC Agnus
+ }
+ return linetoggle;
+}
+
/* Expand bplcon0/bplcon1 into the toscr_xxx variables. */
static void compute_toscr_delay (int bplcon1)
{
#endif
}
+static void set_delay_lastcycle (void)
+{
+ delay_lastcycle[0] = ((maxhpos + 1) * 2 + 0) << bplcon0_res;
+ delay_lastcycle[1] = delay_lastcycle[0];
+ if (islinetoggle ())
+ delay_lastcycle[1]++;
+}
+
static int bpldmasetuphpos, bpldmasetuphpos_diff;
static int bpldmasetupphase;
static void update_toscr_planes (int fm);
fetchmode_size = 16 << fetchmode;
fetchmode_bytes = 2 << fetchmode;
fetchmode_mask = fetchmode_size - 1;
- delay_lastcycle = (maxhpos * 2) << bplcon0_res;
+ set_delay_lastcycle ();
compute_toscr_delay (bplcon1);
if (thisline_decision.plfleft < 0) {
if (todisplay_fetched[oddeven] && dp == delay) {
- for (int i = oddeven; i < MAX_PLANES; i += 2) {
+ for (int i = oddeven; i < toscr_nr_planes_shifter; i += 2) {
todisplay2[i] = todisplay[i];
}
todisplay_fetched[oddeven] = false;
do_tosrc (oddeven, 2, diff, 0);
nbits2 -= diff;
if (todisplay_fetched[oddeven]) {
- for (int i = oddeven; i < MAX_PLANES; i += 2)
+ for (int i = oddeven; i < toscr_nr_planes_shifter; i += 2)
todisplay2[i] = todisplay[i];
todisplay_fetched[oddeven] = false;
}
do_tosrc (0, 1, diff, 0);
nbits2 -= diff;
if (todisplay_fetched[0]) {
- memcpy (todisplay2, todisplay, sizeof todisplay);
+ for (int i = 0; i < toscr_nr_planes_shifter; i++)
+ todisplay2[i] = todisplay[i];
todisplay_fetched[0] = false;
todisplay_fetched[1] = false;
}
do_tosrc (oddeven, 2, diff, fm);
nbits2 -= diff;
if (todisplay_fetched[oddeven]) {
- for (int i = oddeven; i < MAX_PLANES; i += 2)
+ for (int i = oddeven; i < toscr_nr_planes_shifter; i += 2)
todisplay2_aga[i] = todisplay_aga[i];
todisplay_fetched[oddeven] = false;
}
do_tosrc (0, 1, diff, fm);
nbits2 -= diff;
if (todisplay_fetched[0]) {
- memcpy (todisplay2_aga, todisplay_aga, sizeof todisplay_aga);
+ for (int i = 0; i < toscr_nr_planes_shifter; i++)
+ todisplay2_aga[i] = todisplay_aga[i];
todisplay_fetched[0] = false;
todisplay_fetched[1] = false;
}
}
}
+static void toscr_right_edge (int nbits, int fm)
+{
+ // Emulate hpos counter (delay_cycles) reseting at the end of scanline.
+ // (Result is ugly shift in graphics in far right overscan)
+ int diff = delay_lastcycle[lol] - delay_cycles;
+ int nbits2 = nbits;
+ if (nbits2 >= diff) {
+ do_delays (diff, fm);
+ nbits2 -= diff;
+ delay_cycles = 0;
+ toscr_delay[0] -= 2;
+ toscr_delay[0] &= fetchmode_mask;
+ toscr_delay[1] -= 2;
+ toscr_delay[1] &= fetchmode_mask;
+ }
+ if (nbits2) {
+ do_delays (nbits2, fm);
+ delay_cycles += nbits2;
+ }
+}
+
STATIC_INLINE void toscr_1 (int nbits, int fm)
{
- if (delay_cycles + nbits >= delay_lastcycle) {
- // Emulate hpos counter (delay_cycles) reseting at the end of scanline.
- // It can cause glitch in far right overscan.
- int diff = delay_lastcycle - delay_cycles;
- int nbits2 = nbits;
- if (nbits2 >= diff) {
- do_delays (diff, fm);
- nbits2 -= diff;
- delay_cycles = 0;
- }
- if (nbits2)
- do_delays (nbits2, fm);
+ if (delay_cycles + nbits >= delay_lastcycle[lol]) {
+ toscr_right_edge (nbits, fm);
} else if (toscr_delay[0] == toscr_delay[1]) {
// Most common case.
do_delays_fast (nbits, fm);
+ delay_cycles += nbits;
} else {
do_delays (nbits, fm);
+ delay_cycles += nbits;
}
out_nbits += nbits;
- delay_cycles += nbits;
if (out_nbits == 32) {
int i;
uae_u8 *dataptr = line_data[next_lineno] + out_offs * 4;
i += 32 - out_nbits;
toscr_1 (32 - out_nbits, fm);
}
- i += 32;
-
- memset (todisplay, 0, sizeof todisplay);
- if (fm)
- memset (todisplay_aga, 0, sizeof todisplay_aga);
+ i += 32;
toscr_1 (16, fm);
toscr_1 (16, fm);
if (fm == 2) {
- /* flush AGA full 64-bit shift register */
+ /* flush AGA full 64-bit shift register + possible data in todisplay */
+ i += 32;
+ toscr_1 (16, fm);
+ toscr_1 (16, fm);
i += 32;
toscr_1 (16, fm);
toscr_1 (16, fm);
}
- memset (todisplay2, 0, sizeof todisplay2);
- if (fm)
- memset (todisplay2_aga, 0, sizeof todisplay2_aga);
-
return i >> (1 + toscr_res);
}
toscr_nbits = 0;
}
+static void update_denise_shifter_planes (int hpos)
+{
+ int np = GET_PLANES (bplcon0d);
+ // if DMA has ended but there is still data waiting in todisplay,
+ // it must be flushed out before number of planes change
+ if (np < toscr_nr_planes_shifter && hpos > thisline_decision.plfright && thisline_decision.plfright && (todisplay_fetched[0] || todisplay_fetched[1])) {
+ int diff = (hpos - thisline_decision.plfright) << (1 + toscr_res);
+ while (diff >= 16) {
+ toscr_1 (16, fetchmode);
+ diff -= 16;
+ }
+ if (diff)
+ toscr_1 (diff, fetchmode);
+ thisline_decision.plfright += hpos - thisline_decision.plfright;
+ }
+ toscr_nr_planes_shifter = np;
+ if (isocs7planes ()) {
+ if (toscr_nr_planes_shifter < 6)
+ toscr_nr_planes_shifter = 6;
+ }
+}
+
STATIC_INLINE void update_denise (int hpos)
{
int res = GET_RES_DENISE (bplcon0d);
} else {
toscr_nr_planes2 = toscr_nr_planes;
}
+ toscr_nr_planes_shifter = toscr_nr_planes2;
}
STATIC_INLINE void fetch_start (int hpos)
#endif
-static void finish_last_fetch (int pos, int fm)
+static void finish_last_fetch (int pos, int fm, bool reallylast)
{
if (thisline_decision.plfleft < 0)
return;
- if (plf_state >= plf_end)
+// if (reallylast)
+// plf_state = plf_end;
+ if (plfr_state >= plfr_end)
return;
- plf_state = plf_end;
+ plfr_state = plfr_end;
flush_display (fm);
- // This may not be the last fetch, store current endpos for future use.
- // There is at least one demo that has two DDFSTRT-DDFSTOP horizontal sections.
- thisline_decision.plfright = pos;
-
- if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) {
- ddfstate = DIW_waiting_start;
- fetch_state = fetch_not_started;
+ if (!reallylast) {
+ // This may not be the last fetch, store current endpos for future use.
+ // There is at least one demo that has two DDFSTRT-DDFSTOP horizontal sections.
+ thisline_decision.plfright = pos;
+#if 1
+ if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) {
+ ddfstate = DIW_waiting_start;
+ fetch_state = fetch_not_started;
+ }
}
+#endif
}
/* check special case where last fetch wraps to next line
* this makes totally corrupted and flickering display on
bool done = false;
if (plf_state != plf_passed_stop2 || (fetch_state != fetch_started && fetch_state != fetch_started_first) || !dmaen (DMA_BITPLANE)) {
- finish_last_fetch (pos, fm);
+ finish_last_fetch (pos, fm, true);
return;
}
do {
default:
goto end;
}
- break;
+ break;
}
fetch_cycle++;
toscr_nbits += toscr_res2p;
}
end:
- finish_last_fetch (pos, fm);
+ finish_last_fetch (pos, fm, true);
}
/* make sure fetch that goes beyond maxhpos is finished */
static void finish_final_fetch (void)
{
- if (plf_state < plf_end) {
- finish_last_fetch (maxhpos, fetchmode);
- if (plf_state != plf_end)
- return;
- }
- plf_state = plf_finished;
+ if (plfr_state < plf_end)
+ finish_last_fetch (maxhpos, fetchmode, true);
+ plfr_state = plfr_finished;
// This is really the end of scanline, we can finally flush all remaining data.
thisline_decision.plfright += flush_plane_data (fetchmode);
thisline_decision.plflinelen = out_offs;
STATIC_INLINE int one_fetch_cycle_0 (int pos, int ddfstop_to_test, int dma, int fm)
{
- if (plf_state < plf_passed_stop && pos == ddfstop_to_test)
- plf_state = plf_passed_stop;
+ if (dma || (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) {
+ if (plf_state < plf_passed_stop && pos == ddfstop_to_test)
+ plf_state = plf_passed_stop;
- if ((fetch_cycle & fetchunit_mask) == 0) {
- if (plf_state == plf_passed_stop2) {
- finish_last_fetch (pos, fm);
- return 1;
- }
- if (plf_state == plf_passed_stop) {
- plf_state = plf_passed_stop2;
- } else if (plf_state == plf_passed_stop2) {
- plf_state = plf_end;
+ if ((fetch_cycle & fetchunit_mask) == 0) {
+ if (plf_state == plf_passed_stop2) {
+ finish_last_fetch (pos, fm, false);
+ return 1;
+ }
+ if (plf_state == plf_passed_stop) {
+ plf_state = plf_passed_stop2;
+ } else if (plf_state == plf_passed_stop2) {
+ plf_state = plf_end;
+ }
}
}
flush_display (fm);
}
+STATIC_INLINE int get_ddfstop_to_test (int hpos)
+{
+ /* 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. */
+ int ddfstop_to_test = HARD_DDF_STOP;
+ if (ddfstop >= hpos && plfstop < ddfstop_to_test)
+ ddfstop_to_test = plfstop;
+ return ddfstop_to_test;
+
+}
STATIC_INLINE void update_fetch (int until, int fm)
{
int pos;
if (nodraw () || plf_state >= plf_end)
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;
-
+ ddfstop_to_test = get_ddfstop_to_test (last_fetch_hpos);
pos = last_fetch_hpos;
cycle_diagram_shift = last_fetch_hpos - fetch_cycle;
}
// vdiw getting cleared mid-scan = fetches also stop
- if (diwstate == DIW_waiting_start && plf_state < plf_wait_stop) {
+ if ((diwstate == DIW_waiting_start || !dma) && plf_state < plf_wait_stop) {
// ecs = continue at passed_stop
// ocs = line is done
if (currprefs.chipset_mask & CSMASK_ECS_AGNUS)
#else
fetch_state = fetch_started;
#endif
+ plfr_state = plfr_active;
ddfstate = DIW_waiting_stop;
+ if (hstart >= get_ddfstop_to_test (hpos))
+ plf_state = plf_passed_stop;
if (!bpldmawasactive) {
- plfstrt_sprite = plfstrt;
+ plfstrt_sprite = hstart;
+ // OCS Agnus needs at least 1 empty cycle between
+ // sprite fetch and bitplane cycle sequence start.
+ if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
+ plfstrt_sprite--;
fetch_cycle = 0;
update_denise (last_fetch_hpos);
if (bpl1dat_written_at_least_once && hstart > last_fetch_hpos) {
update_fetch_x (hstart, fetchmode);
}
+ estimate_last_fetch_cycle (hstart);
+
last_fetch_hpos = hstart;
#endif
}
+#if 0
/* this may turn on datafetch if program turns dma on during the ddf */
static void maybe_start_bpl_dma (int hpos)
{
return;
if (hpos <= plfstrt)
return;
- if (hpos > plfstop - fetchunit)
+ if (hpos >= plfstop)
return;
if (ddfstate != DIW_waiting_start)
plf_state = plf_passed_stop;
start_bpl_dma (hpos, hpos);
}
+#endif
STATIC_INLINE bool cant_this_last_line (void)
{
return;
if (fetch_state == fetch_not_started) {
- int start = (currprefs.chipset_mask & CSMASK_ECS_AGNUS) ? plfstrt - 4 : HARD_DDF_START_REAL - 2;
- if (last_decide_line_hpos < start && hpos >= start) {
- if (plf_state == plf_idle || plf_state == plf_end)
- plf_state = plf_start;
+ bool dma = dmaen (DMA_BITPLANE) != 0;
+ bool dmaecs = dma || (currprefs.chipset_mask & CSMASK_ECS_AGNUS);
+ int bplstart = hpos;
+
+ // dma needs to be on when matching ddfstrt if OCS Agnus
+ if (dmaecs) {
+ int start = (currprefs.chipset_mask & CSMASK_ECS_AGNUS) ? plfstrt - 4 : HARD_DDF_START_REAL - 2;
+ if (last_decide_line_hpos < start && hpos >= start) {
+ if (plf_state >= plf_passed_stop2 || plf_state == plf_idle) {
+ plf_state = plf_start;
+ }
+ }
}
- if ((diwstate == DIW_waiting_stop || (currprefs.chipset_mask & CSMASK_ECS_AGNUS))) {
- int ok = 0;
-
- if (last_decide_line_hpos < plfstrt && hpos >= plfstrt) {
- if (plf_state == plf_start)
- plf_state = plf_active;
- if (plf_state == plf_active)
- 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 (hpos - 2 == ddfstrt_old_hpos)
- ok = 0;
+
+ if (diwstate == DIW_waiting_stop) {
+
+ if (dmaecs) {
+ if (last_decide_line_hpos < plfstrt && hpos >= plfstrt) {
+ /* 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 (plf_state == plf_start && hpos - 2 != ddfstrt_old_hpos)
+ plf_state = plf_active;
+ bplstart = plfstrt;
+ }
}
- if (ok && diwstate == DIW_waiting_stop) {
- if (dmaen (DMA_BITPLANE) && bitplane_dma_turned_on + 4 < hpos) {
- start_bpl_dma (hpos, plfstrt);
- estimate_last_fetch_cycle (plfstrt);
+
+ if (dmaecs) {
+ // did we just match ddfstop but missed ddfstrt? DMA starts from passed plfstop state.
+ if (last_decide_line_hpos > plfstrt && (plf_state == plf_active || plf_state == plf_wait_stop) && diwstate == DIW_waiting_stop) {
+ int stop = get_ddfstop_to_test (last_decide_line_hpos);
+ if (last_decide_line_hpos < stop && hpos >= stop) {
+ if (dma) {
+ // we did, fetches start!
+ bplstart = plfstop;
+ plf_state = plf_active;
+ } else {
+ // line done
+ plf_state = plf_end;
+ }
+ }
}
- last_decide_line_hpos = hpos;
+ }
+
+ if (dma) {
+ if (plf_state == plf_active && (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS) || hpos >= 0x18)) {
+ start_bpl_dma (hpos, bplstart);
+ last_decide_line_hpos = hpos;
#ifndef CUSTOM_SIMPLE
- do_sprites (hpos);
+ do_sprites (hpos);
#endif
- return;
+ return;
+ }
}
}
}
reset_moddelays ();
reset_bplldelays ();
reset_dbplh_all (256);
- bitplane_dma_turned_on = 0;
+ delay_cycles = 0;
+ compute_toscr_delay (bplcon1);
- if (plf_state > plf_active)
- plf_state = plf_idle;
- if (plf_state == plf_active && !(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
+ if (plf_state >= plf_passed_stop2)
plf_state = plf_idle;
+ plfr_state = plfr_idle;
/* ECS/AGA and ddfstop > maxhpos == always-on display */
if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) {
}
memset (outword, 0, sizeof outword);
+ memset (fetched, 0, sizeof fetched);
todisplay_fetched[0] = todisplay_fetched[1] = false;
+ memset (todisplay, 0, sizeof todisplay);
+ memset (todisplay2, 0, sizeof todisplay2);
+#ifdef AGA
+ if (currprefs.chipset_mask & CSMASK_AGA) {
+ memset (todisplay_aga, 0, sizeof todisplay_aga);
+ memset (todisplay2_aga, 0, sizeof todisplay2_aga);
+ }
+#endif
if (bitplane_line_crossing) {
// BPL1DAT would have been written after end of last scanline.
#endif
}
-static int islinetoggle (void)
-{
- int linetoggle = 0;
- if (!(beamcon0 & 0x0800) && !(beamcon0 & 0x0020) && (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) {
- linetoggle = 1; // NTSC and !LOLDIS -> LOL toggles every line
- } else if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS) && currprefs.ntscmode) {
- linetoggle = 1; // hardwired NTSC Agnus
- }
- return linetoggle;
-}
-
int vsynctimebase_orig;
void compute_vsynctime (void)
vblank_hz_lace = 227.0 * 312.5 * 50.0 / (maxvpos * maxhpos);;
minfirstline = vsstop > vbstop ? vsstop : vbstop;
if (minfirstline > maxvpos / 2)
- minfirstline = vsstop > vsstop ? vbstop : vsstop;
+ minfirstline = vsstop > vbstop ? vbstop : vsstop;
if (minfirstline < 2)
minfirstline = 2;
if (minfirstline >= maxvpos)
if (vblank_hz > 300)
vblank_hz = 300;
maxhpos_short = maxhpos;
- delay_lastcycle = (maxhpos * 2) << bplcon0_res;
+ set_delay_lastcycle ();
if (beamcon0 & 0x80) {
if (hbstrt > maxhpos)
hsyncstartpos = hbstrt + 1;
/*
* register functions
*/
-STATIC_INLINE uae_u16 DENISEID (int *missing)
+static uae_u16 DENISEID (int *missing)
{
*missing = 0;
if (currprefs.cs_deniserev >= 0)
return vp;
}
+static void vposback (int oldvpos)
+{
+ if (cop_state.state == COP_wait && oldvpos == cop_state.vcmp) {
+ copper_enabled_thisline = 0;
+ unset_special (SPCFLAG_COPPER);
+ }
+}
+
static void VPOSW (uae_u16 v)
{
int oldvpos = vpos;
vpos = oldvpos;
}
+
static void VHPOSW (uae_u16 v)
{
int oldvpos = vpos;
#if 0
if (M68K_GETPC < 0xf00000 || 1)
write_log (_T("VHPOSW %04X PC=%08x\n"), v, M68K_GETPC);
+#endif
+#if 0
+ int hp = v & 0xff;
+ int oldhp = current_hpos ();
+ if (hp != oldhp) {
+ if (hp >= maxhpos)
+ hp = maxhpos - 1;
+ eventtab[ev_hsync].oldcycles = get_cycles () - hp * CYCLE_UNIT;
+ eventtab[ev_hsync].evtime = eventtab[ev_hsync].oldcycles + HSYNCTIME;
+ events_schedule ();
+ }
#endif
v >>= 8; // lets ignore hpos for now
vpos &= 0xff00;
} else if (vpos < minfirstline && oldvpos < minfirstline) {
vpos = oldvpos;
}
+#if 0
+ if (vpos < oldvpos)
+ vposback (oldvpos);
+#endif
}
static uae_u16 VHPOSR (void)
if (changed & (DMA_MASTER | DMA_BITPLANE)) {
ddf_change = vpos;
- if (dmaen (DMA_BITPLANE))
- maybe_start_bpl_dma (hpos);
+#if 0
+ if (dmaen (DMA_BITPLANE)) {
+ if (vpos == 0xba)
+ write_log (_T("*"));
+// maybe_start_bpl_dma (hpos);
+ } else {
+ write_log (_T("!"));
+ }
+#endif
}
-
events_schedule();
}
return 0;
}
+static void rethink_intreq (void)
+{
+ serial_check_irq ();
+ rethink_cias ();
+#ifdef A2065
+ rethink_a2065 ();
+#endif
+#ifdef A2091
+ rethink_a2091 ();
+#endif
+#ifdef CDTV
+ rethink_cdtv ();
+#endif
+#ifdef CD32
+ rethink_akiko ();
+#endif
+ rethink_gayle ();
+}
+
static void send_interrupt_do (uae_u32 v)
{
INTREQ_0 (0x8000 | (1 << v));
}
}
+static int int_recursive; // yes, bad idea.
+
static void send_intena_do (uae_u32 v)
{
- intena_internal = v;
+ setclr (&intena_internal, v);
doint ();
+ int_recursive++;
+ rethink_intreq ();
+ int_recursive--;
}
+
static void send_intreq_do (uae_u32 v)
{
- intreq_internal = v;
+ setclr (&intreq_internal, v);
doint ();
+ int_recursive++;
+ rethink_intreq ();
+ int_recursive--;
}
static void INTENA (uae_u16 v)
if (!(v & 0x8000) && old == intena)
return;
if (use_eventmode (v)) {
- event2_newevent_xx (-1, INT_PROCESSING_DELAY, intena, send_intena_do);
+ event2_newevent_xx (-1, INT_PROCESSING_DELAY, v, send_intena_do);
} else {
intena_internal = intena;
if (v & 0x8000)
{
if (use_eventmode (v)) {
setclr (&intreq, v);
- send_intreq_do (intreq);
+ send_intreq_do (v);
} else {
setclr (&intreq, v);
setclr (&intreq_internal, v);
}
}
-void INTREQ_0 (uae_u16 v)
+bool INTREQ_0 (uae_u16 v)
{
#if 0
if (!(v & 0x8000) && (v & (0x80 | 0x100 | 0x200 | 0x400) != 0x0780))
write_log (_T("audirq clear %04x %04x\n"), v, intreq);
#endif
-
uae_u16 old = intreq;
setclr (&intreq, v);
- if (use_eventmode (v)) {
+ if (int_recursive) {
+ // don't add new event if this call came from send_intreq_do/rethink
+ // and intreq didn't change.
+ // it wouldn't make any difference except to slow down everything
+ if (old == intreq)
+ return false;
+ }
+
+ if ((use_eventmode (v) || event2_count)) {
// don't bother to waste time for interrupt queuing if nothing changes
- // but only if we are sure there is no queued changes
+ // but only if we are sure there is no other queued changes
if (old == intreq && intreq_internal == intreq)
- return;
- event2_newevent_xx (-1, INT_PROCESSING_DELAY, intreq, send_intreq_do);
+ return false;
+ event2_newevent_xx (-1, INT_PROCESSING_DELAY, v, send_intreq_do);
+ return false;
} else {
+ uae_u16 old2 = intreq_internal;
intreq_internal = intreq;
- if (intreq == old)
- return;
- if (v & 0x8000)
+ if (old == intreq && old2 == intreq_internal)
+ return false;
+ if ((v & 0x8000) || currprefs.cpu_cycle_exact)
doint ();
+ return true;
}
}
void INTREQ (uae_u16 data)
{
- INTREQ_0 (data);
- serial_check_irq ();
- rethink_cias ();
-#ifdef A2065
- rethink_a2065 ();
-#endif
-#ifdef A2091
- rethink_a2091 ();
-#endif
-#ifdef CDTV
- rethink_cdtv ();
-#endif
-#ifdef CD32
- rethink_akiko ();
-#endif
- rethink_gayle ();
+ if (INTREQ_0 (data))
+ rethink_intreq ();
}
static void ADKCON (int hpos, uae_u16 v)
#endif
if (thisline_decision.plfleft < 0)
update_denise (hpos);
+ else
+ update_denise_shifter_planes (hpos);
}
static void BPLCON0 (int hpos, uae_u16 v)
bpl1dat_written = true;
bpl1dat_written_at_least_once = true;
if (thisline_decision.plfleft < 0) {
- thisline_decision.plfleft = hpos;
+ thisline_decision.plfleft = (hpos + 3) & ~1;
reset_bpl_vars ();
update_denise (hpos);
}
reset_decisions ();
plf_state = plf_idle;
+ plfr_state = plfr_idle;
// copy color changes
dip1 = curr_drawinfo + next_lineno - 1;
return wrprot1;
}
+static bool isrecognizedext (const TCHAR *name)
+{
+ const TCHAR *ext = _tcsrchr (name, '.');
+ if (ext) {
+ if (!_tcsicmp (ext + 1, _T("adf")) || !_tcsicmp (ext + 1, _T("adz")) || !_tcsicmp (ext + 1, _T("st")) || !_tcsicmp (ext + 1, _T("ima")) || !_tcsicmp (ext + 1, _T("img")))
+ return true;
+ }
+ return false;
+}
+
static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR *fname, bool fake, bool forcedwriteprotect)
{
uae_u8 buffer[2 + 2 + 4 + 4];
trackid *tid;
int num_tracks, size;
int canauto;
- const TCHAR *ext;
drive_image_free (drv);
DISK_validate_filename (p, fname, 1, &drv->wrprot, &drv->crc32, &drv->diskfile);
gui_disk_image_change (dnum, fname, drv->wrprot);
- canauto = 0;
- ext = _tcsrchr (fname, '.');
- if (ext) {
- if (!_tcsicmp (ext + 1, _T("adf")) || !_tcsicmp (ext + 1, _T("adz")) || !_tcsicmp (ext + 1, _T("st")) || !_tcsicmp (ext + 1, _T("ima")) || !_tcsicmp (ext + 1, _T("img")))
- canauto = 1;
- }
-
if (!drv->motoroff) {
drv->dskready_up_time = DSKREADY_UP_TIME;
drv->dskready_down_time = 0;
zfile_fseek (drv->diskfile, 0, SEEK_SET);
}
+ canauto = 0;
+ if (isrecognizedext (fname))
+ canauto = 1;
+ if (!canauto && drv->diskfile && isrecognizedext (zfile_getname (drv->diskfile)))
+ canauto = 1;
+
if (drv->catweasel) {
drv->wrprot = true;
static int real_playfield_start, real_playfield_end;
static int linetoscr_diw_start, linetoscr_diw_end;
static int native_ddf_left, native_ddf_right;
-#if 0
-static bool can_have_bordersprite;
-#endif
static int pixels_offset;
static int src_pixel, ham_src_pixel;
}
-// left or right border sprite
-static void pfield_do_linetoscr_border (int start, int stop, bool blank)
+// left or right AGA border sprite
+static void pfield_do_linetoscr_bordersprite_aga (int start, int stop, bool blank)
{
- bool old = issprites;
- issprites = colors_for_drawing.bordersprite != 0;
- pfield_do_linetoscr (start, stop, blank);
- issprites = old;
+ if (res_shift == 0) {
+ switch (gfxvidinfo.drawbuffer.pixbytes) {
+ case 2: src_pixel = linetoscr_16_aga_spronly (LTPARMS); break;
+ case 4: src_pixel = linetoscr_32_aga_spronly (LTPARMS); break;
+ }
+ } else if (res_shift == 2) {
+ switch (gfxvidinfo.drawbuffer.pixbytes) {
+ case 2: src_pixel = linetoscr_16_stretch2_aga_spronly (LTPARMS); break;
+ case 4: src_pixel = linetoscr_32_stretch2_aga_spronly (LTPARMS); break;
+ }
+ } else if (res_shift == 1) {
+ switch (gfxvidinfo.drawbuffer.pixbytes) {
+ case 2: src_pixel = linetoscr_16_stretch1_aga_spronly (LTPARMS); break;
+ case 4: src_pixel = linetoscr_32_stretch1_aga_spronly (LTPARMS); break;
+ }
+ } else if (res_shift == -1) {
+ if (currprefs.gfx_lores_mode) {
+ switch (gfxvidinfo.drawbuffer.pixbytes) {
+ case 2: src_pixel = linetoscr_16_shrink1f_aga_spronly (LTPARMS); break;
+ case 4: src_pixel = linetoscr_32_shrink1f_aga_spronly (LTPARMS); break;
+ }
+ } else {
+ switch (gfxvidinfo.drawbuffer.pixbytes) {
+ case 2: src_pixel = linetoscr_16_shrink1_aga_spronly (LTPARMS); break;
+ case 4: src_pixel = linetoscr_32_shrink1_aga_spronly (LTPARMS); break;
+ }
+ }
+ } else if (res_shift == -2) {
+ if (currprefs.gfx_lores_mode) {
+ switch (gfxvidinfo.drawbuffer.pixbytes) {
+ case 2: src_pixel = linetoscr_16_shrink2f_aga_spronly (LTPARMS); break;
+ case 4: src_pixel = linetoscr_32_shrink2f_aga_spronly (LTPARMS); break;
+ }
+ } else {
+ switch (gfxvidinfo.drawbuffer.pixbytes) {
+ case 2: src_pixel = linetoscr_16_shrink2_aga_spronly (LTPARMS); break;
+ case 4: src_pixel = linetoscr_32_shrink2_aga_spronly (LTPARMS); break;
+ }
+ }
+ }
}
static void dummy_worker (int start, int stop, bool blank)
}
}
- do_color_changes (pfield_do_fill_line, pfield_do_linetoscr, lineno);
+#ifdef AGA
+ if (dip_for_drawing->nr_sprites && colors_for_drawing.bordersprite)
+ do_color_changes (pfield_do_linetoscr_bordersprite_aga, pfield_do_linetoscr, lineno);
+ else
+#endif
+ do_color_changes (pfield_do_fill_line, pfield_do_linetoscr, lineno);
if (dh == dh_emerg)
memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.drawbuffer.pixbytes * gfxvidinfo.drawbuffer.inwidth);
#ifdef AGA
if (dosprites) {
- int i;
-
- for (i = 0; i < dip_for_drawing->nr_sprites; i++)
+ for (int i = 0; i < dip_for_drawing->nr_sprites; i++)
draw_sprites_aga (curr_sprite_entries + dip_for_drawing->first_sprite_entry + i, 1);
- uae_u16 oxor = bplxor;
- if (dp_for_drawing->ham_seen) {
- int todraw_amiga = res_shift_from_window (visible_right_border - visible_left_border);
- init_ham_decoding ();
- memset (ham_linebuf + ham_decode_pixel, 0, todraw_amiga * sizeof (uae_u32));
- }
- if (dip_for_drawing->nr_color_changes) {
- bplxor = 0;
- do_color_changes (pfield_do_fill_line, pfield_do_linetoscr_border, lineno);
- bplxor = oxor;
- }
+ do_color_changes (pfield_do_linetoscr_bordersprite_aga, pfield_do_linetoscr_bordersprite_aga, lineno);
#else
if (0) {
#endif
nextevent = currcycle + mintime;
}
-static int iwas1 = 123, iwas2 = 123, ihandled = 123;
-
void do_cycles_slow (unsigned long cycles_to_add)
{
if ((pissoff -= cycles_to_add) >= 0)
currcycle = nextevent;
for (i = 0; i < ev_max; i++) {
- iwas1 = i;
if (eventtab[i].active && eventtab[i].evtime == currcycle) {
- iwas2 = i;
- ihandled = -1;
- (*eventtab[i].handler)();
- ihandled = 1;
+ if (eventtab[i].handler == NULL) {
+ gui_message(_T("eventtab[%d].handler is null!\n"), i);
+ eventtab[i].active = 0;
+ } else {
+ (*eventtab[i].handler)();
+ }
}
}
events_schedule ();
static void expamem_init_a4091 (void)
{
#ifdef NCR
- ncr_init ();
+ ncr_autoconfig_init ();
#endif
}
static void expamem_init_gfxboard_memory (void)
FSIN_explibok:
move.l d0,a4
+ ; create fake configdev
+ exg a4,a6
+ jsr -$030(a6) ;expansion/AllocConfigDev
+ tst.l d0
+ beq.s .nocd
+ move.l d0,a0
+ lea start(pc),a1
+ move.l a1,d0
+ clr.w d0
+ move.l d0,32(a0)
+ move.l #65536,36(a0)
+ move.w #$0104,16(a0) ;type + product
+ move.w #2011,16+4(a0) ;manufacturer
+ moveq #1,d0
+ move.l d0,22(a0) ;serial
+ jsr -$01e(a6) ;expansion/AddConfigDev
+.nocd
+ exg a4,a6
+
tst.l $10c(a5)
beq.w FSIN_none
#include "gayle.h"
#include "savestate.h"
#include "a2091.h"
+#include "ncr_scsi.h"
#include "cdtv.h"
#include "sana2.h"
#include "bsdsocket.h"
#include "blkdev.h"
#include "isofs_api.h"
#include "scsi.h"
+#include "uaenative.h"
#ifdef RETROPLATFORM
#include "rp.h"
#endif
gayle_add_ide_unit (uci->controller - HD_CONTROLLER_IDE0, uci);
allocuci (&currprefs, nr, -1);
} else if (uci->controller <= HD_CONTROLLER_SCSI6) {
- if (currprefs.cs_mbdmac > 0) {
+ if (currprefs.cs_mbdmac == 1) {
#ifdef A2091
a3000_add_scsi_unit (uci->controller - HD_CONTROLLER_SCSI0, uci);
allocuci (&currprefs, nr, -1);
+#endif
+ } else if (currprefs.cs_mbdmac == 2) {
+#ifdef NCR
+ a4000t_add_scsi_unit (uci->controller - HD_CONTROLLER_SCSI0, uci);
+ allocuci (&currprefs, nr, -1);
#endif
} else if (currprefs.cs_a2091) {
#ifdef A2091
a2091_add_scsi_unit (uci->controller - HD_CONTROLLER_SCSI0, uci);
allocuci (&currprefs, nr, -1);
+#endif
+ } else if (currprefs.cs_a4091) {
+#ifdef NCR
+ a4091_add_scsi_unit (uci->controller - HD_CONTROLLER_SCSI0, uci);
+ allocuci (&currprefs, nr, -1);
#endif
} else if (currprefs.cs_cdtvscsi) {
#ifdef CDTV
#ifdef BSDSOCKET
resaddr = bsdlib_startup (resaddr);
#endif
+#ifdef WITH_UAENATIVE
+ resaddr = uaenative_startup (resaddr);
+#endif
#ifdef SCSIEMU
resaddr = scsidev_startup (resaddr);
#endif
db(0x00); db(0x00); db(0x00); db(0x10); db(0x00); db(0x00); db(0x00); db(0x00);
- db(0x60); db(0x02); db(0x00); db(0x09); db(0x60); db(0x00); db(0x0a); db(0xe8);
- db(0x00); db(0x00); db(0x08); db(0x84); db(0x00); db(0x00); db(0x00); db(0xe0);
- db(0x00); db(0x00); db(0x02); db(0x44); db(0x00); db(0x00); db(0x00); db(0x24);
- db(0x00); db(0x00); db(0x03); db(0x52); db(0x00); db(0x00); db(0x00); db(0x00);
- db(0x00); db(0x00); db(0x13); db(0x76); db(0x43); db(0xfa); db(0x18); db(0x81);
+ db(0x60); db(0x02); db(0x00); db(0x09); db(0x60); db(0x00); db(0x0b); db(0x20);
+ db(0x00); db(0x00); db(0x08); db(0xbc); db(0x00); db(0x00); db(0x00); db(0xe0);
+ db(0x00); db(0x00); db(0x02); db(0x7c); db(0x00); db(0x00); db(0x00); db(0x24);
+ db(0x00); db(0x00); db(0x03); db(0x8a); db(0x00); db(0x00); db(0x00); db(0x00);
+ db(0x00); db(0x00); db(0x13); db(0xae); db(0x43); db(0xfa); db(0x18); db(0xb9);
db(0x4e); db(0xae); db(0xff); db(0xa0); db(0x20); db(0x40); db(0x20); db(0x28);
db(0x00); db(0x16); db(0x20); db(0x40); db(0x4e); db(0x90); db(0x4e); db(0x75);
db(0x48); db(0xe7); db(0xe0); db(0xe2); db(0x30); db(0x3c); db(0xff); db(0x38);
- db(0x72); db(0x11); db(0x61); db(0x00); db(0x17); db(0x6a); db(0x4e); db(0x90);
+ db(0x72); db(0x11); db(0x61); db(0x00); db(0x17); db(0xa2); db(0x4e); db(0x90);
db(0x4a); db(0x80); db(0x67); db(0x4c); db(0x2c); db(0x78); db(0x00); db(0x04);
db(0x0c); db(0x6e); db(0x00); db(0x25); db(0x00); db(0x14); db(0x65); db(0x40);
db(0x70); db(0x14); db(0x24); db(0x00); db(0x72); db(0x01); db(0x4e); db(0xae);
db(0x20); db(0x68); db(0x00); db(0x02); db(0x2f); db(0x08); db(0x4e); db(0x90);
db(0x20); db(0x5f); db(0x58); db(0x8f); db(0x48); db(0xe7); db(0xff); db(0x7e);
db(0x22); db(0x4e); db(0x20); db(0x08); db(0x30); db(0x7c); db(0xff); db(0xb8);
- db(0x4e); db(0xae); db(0xfe); db(0x5c); db(0x61); db(0x00); db(0x12); db(0xb8);
- db(0x61); db(0x00); db(0x16); db(0x80); db(0x4c); db(0xdf); db(0x7e); db(0xff);
+ db(0x4e); db(0xae); db(0xfe); db(0x5c); db(0x61); db(0x00); db(0x12); db(0xf0);
+ db(0x61); db(0x00); db(0x16); db(0xb8); db(0x4c); db(0xdf); db(0x7e); db(0xff);
db(0x4e); db(0x75); db(0x00); db(0x00); db(0x08); db(0x00); db(0x00); db(0x02);
db(0x67); db(0x06); db(0x4e); db(0xb9); db(0x00); db(0xf0); db(0x00); db(0x00);
db(0x4e); db(0xf9); db(0x00); db(0xf0); db(0x00); db(0x00); db(0x00); db(0x00);
db(0x48); db(0xe7); db(0xff); db(0xfe); db(0x2c); db(0x78); db(0x00); db(0x04);
- db(0x30); db(0x3c); db(0xff); db(0xec); db(0x61); db(0x00); db(0x16); db(0xc0);
- db(0x2a); db(0x50); db(0x43); db(0xfa); db(0x17); db(0xe2); db(0x70); db(0x24);
+ db(0x30); db(0x3c); db(0xff); db(0xec); db(0x61); db(0x00); db(0x16); db(0xf8);
+ db(0x2a); db(0x50); db(0x43); db(0xfa); db(0x18); db(0x1a); db(0x70); db(0x24);
db(0x7a); db(0x01); db(0x4e); db(0xae); db(0xfd); db(0xd8); db(0x4a); db(0x80);
- db(0x66); db(0x0c); db(0x43); db(0xfa); db(0x17); db(0xd2); db(0x70); db(0x00);
+ db(0x66); db(0x0c); db(0x43); db(0xfa); db(0x18); db(0x0a); db(0x70); db(0x00);
db(0x7a); db(0x00); db(0x4e); db(0xae); db(0xfd); db(0xd8); db(0x28); db(0x40);
+ db(0xc9); db(0x4e); db(0x4e); db(0xae); db(0xff); db(0xd0); db(0x4a); db(0x80);
+ db(0x67); db(0x2c); db(0x20); db(0x40); db(0x43); db(0xfa); db(0xfe); db(0xe2);
+ db(0x20); db(0x09); db(0x42); db(0x40); db(0x21); db(0x40); db(0x00); db(0x20);
+ db(0x21); db(0x7c); db(0x00); db(0x01); db(0x00); db(0x00); db(0x00); db(0x24);
+ db(0x31); db(0x7c); db(0x01); db(0x04); db(0x00); db(0x10); db(0x31); db(0x7c);
+ db(0x07); db(0xdb); db(0x00); db(0x14); db(0x70); db(0x01); db(0x21); db(0x40);
+ db(0x00); db(0x16); db(0x4e); db(0xae); db(0xff); db(0xe2); db(0xc9); db(0x4e);
db(0x4a); db(0xad); db(0x01); db(0x0c); db(0x67); db(0x00); db(0x00); db(0x5c);
db(0x20); db(0x3c); db(0x00); db(0x00); db(0x02); db(0x34); db(0x22); db(0x3c);
db(0x00); db(0x01); db(0x00); db(0x01); db(0x4e); db(0xae); db(0xff); db(0x3a);
db(0x70); db(0x05); db(0x4e); db(0xae); db(0xff); db(0x58); db(0x4c); db(0xdf);
db(0x07); db(0x03); db(0x4e); db(0x75); db(0x52); db(0x91); db(0x70); db(0x00);
db(0x4e); db(0x75); db(0x48); db(0xe7); db(0xc0); db(0xc0); db(0x61); db(0x00);
- db(0xfc); db(0xe0); db(0x70); db(0x1a); db(0x22); db(0x3c); db(0x00); db(0x01);
+ db(0xfc); db(0xa8); db(0x70); db(0x1a); db(0x22); db(0x3c); db(0x00); db(0x01);
db(0x00); db(0x01); db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x22); db(0x40);
db(0x41); db(0xfa); db(0x15); db(0x02); db(0x23); db(0x48); db(0x00); db(0x0a);
db(0x41); db(0xfa); db(0xfe); db(0xd2); db(0x23); db(0x48); db(0x00); db(0x0e);
db(0x30); db(0x3c); db(0xff); db(0x18); db(0x61); db(0x00); db(0x0e); db(0x58);
db(0x4e); db(0x90); db(0x20); db(0x03); db(0x16); db(0x29); db(0x00); db(0x4f);
db(0x4a); db(0x80); db(0x66); db(0x1a); db(0x27); db(0x7c); db(0x00); db(0x00);
- db(0x17); db(0x70); db(0x00); db(0x14); db(0x41); db(0xfa); db(0xf6); db(0x8e);
+ db(0x17); db(0x70); db(0x00); db(0x14); db(0x41); db(0xfa); db(0xf6); db(0x56);
db(0x20); db(0x08); db(0xe4); db(0x88); db(0x27); db(0x40); db(0x00); db(0x20);
db(0x70); db(0xff); db(0x27); db(0x40); db(0x00); db(0x24); db(0x08); db(0x07);
db(0x00); db(0x00); db(0x67); db(0x40); db(0x0c); db(0x03); db(0x00); db(0x80);
db(0x48); db(0xe7); db(0xc0); db(0x80); db(0x30); db(0x3c); db(0xff); db(0x38);
db(0x72); db(0x66); db(0x61); db(0x00); db(0x00); db(0x0a); db(0x4e); db(0x90);
db(0x4c); db(0xdf); db(0x01); db(0x03); db(0x4e); db(0x75); db(0x41); db(0xfa);
- db(0xe8); db(0x44); db(0x02); db(0x80); db(0x00); db(0x00); db(0xff); db(0xff);
+ db(0xe8); db(0x0c); db(0x02); db(0x80); db(0x00); db(0x00); db(0xff); db(0xff);
db(0xd1); db(0xc0); db(0x4e); db(0x75); db(0x69); db(0x6e); db(0x70); db(0x75);
db(0x74); db(0x2e); db(0x64); db(0x65); db(0x76); db(0x69); db(0x63); db(0x65);
db(0x00); db(0x74); db(0x69); db(0x6d); db(0x65); db(0x72); db(0x2e); db(0x64);
return buffer;
}
+static void makefromsr (void)
+{
+ printf ("\tMakeFromSR();\n");
+ if (using_ce || using_ce020)
+ printf ("\tregs.ipl_pin = intlev ();\n");
+}
+
static void check_ipl (void)
{
if (using_ce || using_ce020)
fill_prefetch_next ();
}
printf ("\tregs.sr %c= src;\n", curi->mnemo == i_EORSR ? '^' : '|');
- printf ("\tMakeFromSR ();\n");
+ makefromsr ();
break;
case i_ANDSR:
printf ("\tMakeSR ();\n");
fill_prefetch_next ();
}
printf ("\tregs.sr &= src;\n");
- printf ("\tMakeFromSR ();\n");
+ makefromsr ();
break;
case i_SUB:
{
addcycles000 (6);
printf ("\tregs.sr = src;\n");
}
- printf ("\tMakeFromSR ();\n");
+ makefromsr ();
if (cpu_level <= 1) {
// 68000 does 2xprefetch
sync_m68k_pc ();
genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
printf ("\tregs.sr = src;\n");
}
- printf ("\tMakeFromSR ();\n");
+ makefromsr ();
printf ("\tm68k_setstopped ();\n");
sync_m68k_pc ();
// STOP does not prefetch anything
printf ("\tsr = %s (4);\n", srcwi);
printf ("\tif (!(sr & 0x8000)) { Exception (8); goto %s; }\n", endlabelstr);
printf ("\tregs.sr = sr;\n");
- printf ("\tMakeFromSR ();\n");
+ makefromsr ();
printf ("\tm68k_setstopped();\n");
m68k_pc_offset += 4;
sync_m68k_pc ();
genamode (NULL, Aipi, "7", sz_long, "pc", 1, 0, GF_NOREFILL);
printf ("\tregs.sr = sr;\n");
setpc ("pc");
- printf ("\tMakeFromSR ();\n");
+ makefromsr ();
} else if (cpu_level == 1 && using_prefetch) {
int old_brace_level = n_braces;
printf ("\tuae_u16 newsr; uae_u32 newpc;\n");
printf ("\t\telse { m68k_areg (regs, 7) += offset; Exception (14); goto %s; }\n", endlabelstr);
printf ("\t\tregs.sr = newsr; MakeFromSR ();\n}\n");
pop_braces (old_brace_level);
- printf ("\tregs.sr = newsr; MakeFromSR ();\n");
+ printf ("\tregs.sr = newsr;\n");
+ makefromsr ();
printf ("\tif (newpc & 1) {\n");
printf ("\t\texception3i (0x%04X, newpc);\n", opcode);
printf ("\t\tgoto %s;\n", endlabelstr);
printf ("\t\telse if (frame == 0xb) { m68k_areg (regs, 7) += offset + 84; break; }\n");
}
printf ("\t\telse { m68k_areg (regs, 7) += offset; Exception (14); goto %s; }\n", endlabelstr);
- printf ("\t\tregs.sr = newsr; MakeFromSR ();\n}\n");
+ printf ("\t\tregs.sr = newsr;\n");
+ makefromsr ();
+ printf ("}\n");
pop_braces (old_brace_level);
- printf ("\tregs.sr = newsr; MakeFromSR ();\n");
+ printf ("\tregs.sr = newsr;\n");
+ makefromsr ();
printf ("\tif (newpc & 1) {\n");
printf ("\t\texception3i (0x%04X, newpc);\n", opcode);
printf ("\t\tgoto %s;\n", endlabelstr);
printf ("\tregs.sr &= 0xFF00; sr &= 0xFF;\n");
printf ("\tregs.sr |= sr;\n");
setpc ("pc");
- printf ("\tMakeFromSR ();\n");
+ makefromsr ();
printf ("\tif (m68k_getpc () & 1) {\n");
printf ("\t\tuaecptr faultpc = m68k_getpc ();\n");
setpc ("oldpc");
curi->dmode, "dstreg", curi->size, "dst", 2, GF_AA);
//genamode (curi, curi->smode, "srcreg", curi->size, "src", 0, 0, GF_AA);
//genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 2, 0, GF_AA);
- fill_prefetch_next ();
if (curi->smode == Ad8r || curi->smode == PC8r)
addcycles000 (2);
+ fill_prefetch_next ();
genastore ("srca", curi->dmode, "dstreg", curi->size, "dst");
break;
case i_PEA:
printf ("else");
start_brace ();
printf ("\n");
+ get_prefetch_020 ();
if (cpu_level >= 4) {
// apparently 68040/060 needs to always write at the end of RMW cycle
printf ("\t");
{
outlnf ("static int NOINLINE linetoscr_%s%s%s%s (int spix, int dpix, int dpix_end)",
get_depth_str (bpp),
- get_hmode_str (hmode), aga ? "_aga" : "", spr ? "_spr" : "");
+ get_hmode_str (hmode), aga ? "_aga" : "", spr > 0 ? "_spr" : (spr < 0 ? "_spronly" : ""));
}
static void out_linetoscr_do_srcpix (DEPTH_T bpp, HMODE_T hmode, int aga, CMODE_T cmode, int spr)
{
- if (aga && cmode != CMODE_DUALPF) {
- if (spr)
- outln ( " sprpix_val = pixdata.apixels[spix];");
- outln ( " spix_val = pixdata.apixels[spix] ^ xor_val;");
- } else if (cmode != CMODE_HAM) {
- outln ( " spix_val = pixdata.apixels[spix];");
- if (spr)
- outln ( " sprpix_val = spix_val;");
+ if (spr < 0) {
+ outln ( " sprpix_val = 0;");
+ } else {
+ if (aga && cmode != CMODE_DUALPF) {
+ if (spr)
+ outln ( " sprpix_val = pixdata.apixels[spix];");
+ outln ( " spix_val = pixdata.apixels[spix] ^ xor_val;");
+ } else if (cmode != CMODE_HAM) {
+ outln ( " spix_val = pixdata.apixels[spix];");
+ if (spr)
+ outln ( " sprpix_val = spix_val;");
+ }
}
}
static void out_linetoscr_do_dstpix (DEPTH_T bpp, HMODE_T hmode, int aga, CMODE_T cmode, int spr)
{
+ if (spr < 0)
+ return;
if (aga && cmode == CMODE_HAM) {
outln ( " spix_val = ham_linebuf[spix];");
outln ( " dpix_val = CONVERT_RGB (spix_val);");
static void out_linetoscr_do_incspix (DEPTH_T bpp, HMODE_T hmode, int aga, CMODE_T cmode, int spr)
{
+ if (spr < 0)
+ return;
if (hmode == HMODE_HALVE1F) {
outln ( " {");
outln ( " uae_u32 tmp_val;");
outlnf (" buf[dpix++] = %s;", var);
}
-static void out_sprite (DEPTH_T bpp, HMODE_T hmode, CMODE_T cmode, int aga, int cnt)
+static void out_sprite (DEPTH_T bpp, HMODE_T hmode, CMODE_T cmode, int aga, int cnt, int spr)
{
if (aga) {
if (cnt == 1) {
outln ( "while (dpix < dpix_end) {");
if (spr)
outln ( " uae_u32 sprpix_val;");
- outln ( " uae_u32 spix_val;");
- outln ( " uae_u32 dpix_val;");
+ if (spr >= 0) {
+ outln ( " uae_u32 spix_val;");
+ outln ( " uae_u32 dpix_val;");
+ }
outln ( " uae_u32 out_val;");
outln ( "");
out_linetoscr_do_dstpix (bpp, hmode, aga, cmode, spr);
out_linetoscr_do_incspix (bpp, hmode, aga, cmode, spr);
- outln ( " out_val = dpix_val;");
+ if (spr >= 0)
+ outln ( " out_val = dpix_val;");
+ else
+ outln ( " out_val = colors_for_drawing.acolors[0];");
if (hmode != HMODE_DOUBLE && hmode != HMODE_DOUBLE2X && bpp == DEPTH_16BPP && spr == 0) {
out_linetoscr_do_srcpix (bpp, hmode, aga, cmode, spr);
outln ( " dpix += 2;");
} else if (bpp == DEPTH_16BPP) {
if (spr) {
- out_sprite (bpp, hmode, cmode, aga, 2);
+ out_sprite (bpp, hmode, cmode, aga, 2, spr);
} else {
outln ( " *((uae_u32 *)&buf[dpix]) = out_val;");
outln ( " dpix += 2;");
}
} else {
if (spr) {
- out_sprite (bpp, hmode, cmode, aga, 2);
+ out_sprite (bpp, hmode, cmode, aga, 2, spr);
} else {
put_dpix ("out_val");
put_dpix ("out_val");
outln ( " dpix += 4;");
} else if (bpp == DEPTH_16BPP) {
if (spr) {
- out_sprite (bpp, hmode, cmode, aga, 4);
+ out_sprite (bpp, hmode, cmode, aga, 4, spr);
} else {
outln ( " *((uae_u32 *)&buf[dpix]) = out_val;");
outln ( " dpix += 2;");
}
} else {
if (spr) {
- out_sprite (bpp, hmode, cmode, aga, 4);
+ out_sprite (bpp, hmode, cmode, aga, 4, spr);
} else {
put_dpix ("out_val");
put_dpix ("out_val");
} else {
if (bpp == DEPTH_16BPP) {
if (spr) {
- out_sprite (bpp, hmode, cmode, aga, 1);
+ out_sprite (bpp, hmode, cmode, aga, 1, spr);
} else {
outln ( " *((uae_u32 *)&buf[dpix]) = out_val;");
outln ( " dpix += 2;");
}
} else {
if (spr) {
- out_sprite (bpp, hmode, cmode, aga, 1);
+ out_sprite (bpp, hmode, cmode, aga, 1, spr);
} else {
put_dpix ("out_val");
}
outlnf ( " %s *buf = (%s *) xlinebuffer;", get_depth_type_str (bpp), get_depth_type_str (bpp));
if (spr)
outln ( " uae_u8 sprcol;");
- if (aga)
+ if (aga && spr >= 0)
outln ( " uae_u8 xor_val = bplxor;");
outln ( "");
- outln ( " if (bplham) {");
- out_linetoscr_mode (bpp, hmode, aga, spr, CMODE_HAM);
- outln ( " } else if (bpldualpf) {");
- out_linetoscr_mode (bpp, hmode, aga, spr, CMODE_DUALPF);
- outln ( " } else if (bplehb) {");
- out_linetoscr_mode (bpp, hmode, aga, spr, CMODE_EXTRAHB);
- outln ( " } else {");
- out_linetoscr_mode (bpp, hmode, aga, spr, CMODE_NORMAL);
+ if (spr >= 0) {
+ outln ( " if (bplham) {");
+ out_linetoscr_mode (bpp, hmode, aga, spr, CMODE_HAM);
+ outln ( " } else if (bpldualpf) {");
+ out_linetoscr_mode (bpp, hmode, aga, spr, CMODE_DUALPF);
+ outln ( " } else if (bplehb) {");
+ out_linetoscr_mode (bpp, hmode, aga, spr, CMODE_EXTRAHB);
+ outln ( " } else {");
+ out_linetoscr_mode (bpp, hmode, aga, spr, CMODE_NORMAL);
+ } else {
+ outln ( " if (1) {");
+ out_linetoscr_mode (bpp, hmode, aga, spr, CMODE_NORMAL);
+ }
outln ( " }\n");
outln ( " return spix;");
set_outfile (stdout);
outln ("/*");
- outln (" * E-UAE - The portable Amiga emulator.");
+ outln (" * UAE - The portable Amiga emulator.");
outln (" *");
outln (" * This file was generated by genlinetoscr. Don't edit.");
outln (" */");
for (aga = 0; aga <= 1 ; aga++) {
if (aga && bpp == DEPTH_8BPP)
continue;
- for (spr = 0; spr <= 1; spr++) {
+ for (spr = -1; spr <= 1; spr++) {
+ if (!aga && spr < 0)
+ continue;
for (hmode = HMODE_NORMAL; hmode <= HMODE_MAX; hmode++)
out_linetoscr (bpp, hmode, aga, spr);
}
#define MEMLOGR 0
#define MEMLOGW 0
#define MEMLOGINDIRECT 0
-#define MEMDEBUG 0
+#define MEMDEBUG 1
#define MEMDEBUGMASK 0x7fffff
-#define MEMDEBUGTEST 0x280000
+#define MEMDEBUGTEST 0x1ff000
#define PICASSOIV_DEBUG_IO 0
static bool memlogr = false;
#define ISP4() (currprefs.rtgmem_type == PICASSOIV_Z2 || currprefs.rtgmem_type == PICASSOIV_Z3)
+// Picasso II: 8* 4x256 (1M) or 16* 4x256 (2M)
+// Piccolo: 8* 4x256 + 2* 16x256 (2M)
+
static struct gfxboard boards[] =
{
{
+
+#ifndef A2091_H
+#define A2091_H
+
#ifdef A2091
extern addrbank dmaca2091_bank;
extern int add_scsi_tape (int ch, const TCHAR *tape_directory, bool readonly);
#endif
+
+#endif /* A2091H */
+#ifndef BLKDEV_H
+#define BLKDEV_H
+
#define DEVICE_SCSI_BUFSIZE (65536 - 1024)
#define SCSI_UNIT_DISABLED -1
extern void blkdev_exitgui (void);
bool filesys_do_disk_change (int, bool);
+
+#endif /* BLKDEV_H */
* (c) 1995 Bernd Schmidt
*/
+#ifndef CUSTOM_H
+#define CUSTOM_H
+
#include "machdep/rpt.h"
/* These are the masks that are ORed together in the chipset_mask option.
extern int joy0button, joy1button;
extern void INTREQ (uae_u16);
-extern void INTREQ_0 (uae_u16);
+extern bool INTREQ_0 (uae_u16);
extern void INTREQ_f (uae_u16);
extern void send_interrupt (int num, int delay);
extern uae_u16 INTREQR (void);
extern int current_maxvpos (void);
extern struct chipset_refresh *get_chipset_refresh (void);
extern void compute_framesync (void);
+
+#endif /* CUSTOM_H */
#endif
}
+STATIC_INLINE int current_hpos_safe (void)
+{
+ int hp = (get_cycles () - eventtab[ev_hsync].oldcycles) / CYCLE_UNIT;
+ return hp;
+}
+
STATIC_INLINE int current_hpos (void)
{
- return (get_cycles () - eventtab[ev_hsync].oldcycles) / CYCLE_UNIT;
+ int hp = current_hpos_safe ();
+ if (hp < 0 || hp >= 256) {
+ gui_message(_T("hpos = %d!?\n"), hp);
+ hp = 0;
+ }
+ return hp;
}
STATIC_INLINE bool cycles_in_range (unsigned long endcycles)
* Copyright 1997 Bernd Schmidt
*/
+#ifndef FILESYS_H
+#define FILESYS_H
+
struct hardfilehandle;
#define MAX_HDF_CACHE_BLOCKS 128
extern void getchsgeometry_hdf (struct hardfiledata *hfd, uae_u64 size, int *pcyl, int *phead, int *psectorspertrack);
extern void getchspgeometry (uae_u64 total, int *pcyl, int *phead, int *psectorspertrack, bool idegeometry);
+#endif /* MEMORY_H */
* Copyright 1995 Bernd Schmidt
*/
+#ifndef MEMORY_H
+#define MEMORY_H
+
extern void memory_reset (void);
extern void a1000_reset (void);
extern uae_s32 getz2size (struct uae_prefs *p);
extern ULONG getz2endaddr (void);
+
+#endif /* MEMORY_H */
* Copyright 1995-2001 Bernd Schmidt
*/
+#ifndef OPTIONS_H
+#define OPTIONS_H
+
#define UAEMAJOR 2
#define UAEMINOR 7
#define UAESUBREV 1
#define MAX_TOTAL_SCSI_DEVICES 8
/* maximum number native input devices supported (single type) */
-#define MAX_INPUT_DEVICES 16
+#define MAX_INPUT_DEVICES 20
/* maximum number of native input device's buttons and axles supported */
#define MAX_INPUT_DEVICE_EVENTS 256
/* 4 different customization settings */
extern int machdep_init (void);
extern void machdep_free (void);
+
+#endif /* OPTIONS_H */
#define SCSI_STATUS_RESERVATION_CONFLICT 0x18
#define SCSI_STATUS_COMMAND_TERMINATED 0x22
#define SCSI_STATUS_QUEUE_FULL 0x28
-#define SCSI_STATUS_ACA_ACTIVE 0x30
\ No newline at end of file
+#define SCSI_STATUS_ACA_ACTIVE 0x30
--- /dev/null
+/*
+* UAE - The Un*x Amiga Emulator
+*
+* UAE Native Interface (UNI)
+*
+* Copyright 2013-2014 Frode Solheim
+*/
+
+#ifndef _UAE_UAENATIVE_H_
+#define _UAE_UAENATIVE_H_
+
+#ifdef WITH_UAENATIVE
+
+#if defined(_WIN32) || defined(WINDOWS)
+
+ #define UNIAPI __declspec(dllimport)
+ #define UNICALL __cdecl
+
+#else // _WIN32 not defined
+
+ #define UNIAPI
+ #define UNICALL
+
+#endif
+
+#include "uni_common.h"
+
+#define UNI_FLAG_ASYNCHRONOUS 1
+#define UNI_FLAG_COMPAT 2
+#define UNI_FLAG_NAMED_FUNCTION 4
+
+uae_u32 uaenative_open_library(TrapContext *context, int flags);
+uae_u32 uaenative_get_function(TrapContext *context, int flags);
+uae_u32 uaenative_call_function(TrapContext *context, int flags);
+uae_u32 uaenative_close_library(TrapContext *context, int flags);
+
+void *uaenative_get_uaevar(void);
+
+void uaenative_install ();
+uaecptr uaenative_startup (uaecptr resaddr);
+
+/* This function must return a list of directories to look for native
+ * libraries in. The returned list must be NULL-terminated, and must not
+ * be de-allocated. */
+const TCHAR **uaenative_get_library_dirs(void);
+
+#endif // WITH_UAENATIVE
+
+#endif // _UAE_UAENATIVE_H_
--- /dev/null
+/*
+* UAE - The Un*x Amiga Emulator
+*
+* UAE Native Interface (UNI)
+*
+* Copyright 2013-2014 Frode Solheim
+*/
+
+#ifndef _UAE_UNI_COMMON_H_
+#define _UAE_UNI_COMMON_H_
+
+#define UNI_VERSION 1
+
+#ifndef UNI_MIN_VERSION
+// MIN_UNI_VERSION decides which callback functions are declared available.
+// The default, unless overriden is to required the current UNI version.
+#define UNI_MIN_VERSION UNI_VERSION
+#endif
+
+#define UNI_ERROR_NOT_ENABLED 0x70000001
+#define UNI_ERROR_INVALID_LIBRARY 0x70000002
+#define UNI_ERROR_INVALID_FUNCTION 0x70000002
+#define UNI_ERROR_FUNCTION_NOT_FOUND 0x70000003
+#define UNI_ERROR_LIBRARY_NOT_FOUND 0x70000004
+#define UNI_ERROR_INVALID_FLAGS 0x70000005
+#define UNI_ERROR_COULD_NOT_OPEN_LIBRARY 0x70000006
+#define UNI_ERROR_ILLEGAL_LIBRARY_NAME 0x70000007
+#define UNI_ERROR_LIBRARY_TOO_OLD 0x70000008
+#define UNI_ERROR_INIT_FAILED 0x70000009
+#define UNI_ERROR_INTERFACE_TOO_OLD 0x7000000a
+
+// these errors are only return from the Amiga-side uni wrappers
+#define UNI_ERROR_AMIGALIB_NOT_OPEN 0x71000000
+
+// On all current platforms, char, short and int short be 1, 2 and 4 bytes
+// respectively, so we just use these simple types.
+
+typedef char uni_char;
+typedef unsigned char uni_uchar;
+typedef short uni_short;
+typedef unsigned short uni_ushort;
+typedef int uni_long;
+typedef unsigned int uni_ulong;
+
+typedef int (UNICALL *uni_version_function)();
+typedef void * (UNICALL *uni_resolve_function)(uni_ulong ptr);
+typedef const uni_char * (UNICALL *uni_uae_version_function)(void);
+
+struct uni {
+ uni_long d1;
+ uni_long d2;
+ uni_long d3;
+ uni_long d4;
+ uni_long d5;
+ uni_long d6;
+ uni_long d7;
+ uni_long a1;
+ uni_long a2;
+ uni_long a3;
+ uni_long a4;
+ uni_long a5;
+ uni_long a7;
+
+#if UNI_VERSION >= 2
+ // add new struct entries for version 2 here
+#endif
+
+#ifdef CPUEMU_0 // UAE
+ uni_long result;
+ uni_long error;
+ uni_ulong function;
+ uni_ulong library;
+ void *native_function;
+ void *uaevar_compat;
+ int flags;
+ uaecptr task;
+#endif
+};
+
+#endif // _UAE_UNI_COMMON_H_
#include "gayle.h"
#include "gfxboard.h"
#include "luascript.h"
+#include "uaenative.h"
#ifdef RETROPLATFORM
#include "rp.h"
#endif
#if defined (BSDSOCKET)
bsdlib_install ();
#endif
+#ifdef WITH_UAENATIVE
+ uaenative_install ();
+#endif
}
static int real_main2 (int argc, TCHAR **argv)
// "scsi.device", "carddisk.device", "card.resource" };
uaecptr base = size == ROM_SIZE_512 ? 0xf80000 : 0xfc0000;
- if (currprefs.cs_mbdmac == 2)
- residents[0] = NULL;
- for (i = 0; i < size - 100; i++) {
- if (kickmemory[i] == 0x4a && kickmemory[i + 1] == 0xfc) {
- uaecptr addr;
- addr = (kickmemory[i + 2] << 24) | (kickmemory[i + 3] << 16) | (kickmemory[i + 4] << 8) | (kickmemory[i + 5] << 0);
- if (addr != i + base)
- continue;
- addr = (kickmemory[i + 14] << 24) | (kickmemory[i + 15] << 16) | (kickmemory[i + 16] << 8) | (kickmemory[i + 17] << 0);
- if (addr >= base && addr < base + size) {
- j = 0;
- while (residents[j]) {
- if (!memcmp (residents[j], kickmemory + addr - base, strlen (residents[j]) + 1)) {
- TCHAR *s = au (residents[j]);
- write_log (_T("KSPatcher: '%s' at %08X disabled\n"), s, i + base);
- xfree (s);
- kickmemory[i] = 0x4b; /* destroy RTC_MATCHWORD */
- patched++;
- break;
+ if (currprefs.cs_mbdmac != 2) {
+ for (i = 0; i < size - 100; i++) {
+ if (kickmemory[i] == 0x4a && kickmemory[i + 1] == 0xfc) {
+ uaecptr addr;
+ addr = (kickmemory[i + 2] << 24) | (kickmemory[i + 3] << 16) | (kickmemory[i + 4] << 8) | (kickmemory[i + 5] << 0);
+ if (addr != i + base)
+ continue;
+ addr = (kickmemory[i + 14] << 24) | (kickmemory[i + 15] << 16) | (kickmemory[i + 16] << 8) | (kickmemory[i + 17] << 0);
+ if (addr >= base && addr < base + size) {
+ j = 0;
+ while (residents[j]) {
+ if (!memcmp (residents[j], kickmemory + addr - base, strlen (residents[j]) + 1)) {
+ TCHAR *s = au (residents[j]);
+ write_log (_T("KSPatcher: '%s' at %08X disabled\n"), s, i + base);
+ xfree (s);
+ kickmemory[i] = 0x4b; /* destroy RTC_MATCHWORD */
+ patched++;
+ break;
+ }
+ j++;
}
- j++;
}
}
}
#define RDP_DEVICE1 _T("\\??\\Root#")
#define RDP_DEVICE2 _T("\\\\?\\Root#")
-static int rdpdevice(TCHAR *buf)
+static int rdpdevice(const TCHAR *buf)
{
if (!_tcsncmp (RDP_DEVICE1, buf, _tcslen (RDP_DEVICE1)))
return 1;
}
}
-static void dumphidcaps (struct didata *did)
+static void dumphidcaps (struct didata *did, int cnt)
{
HIDP_CAPS caps = did->hidcaps;
- write_log (_T("\n******** USB HID: '%s'\n"), did->name);
+ write_log (_T("\n******** %d USB HID: '%s'\n"), cnt, did->name);
write_log (_T("Usage: %04x\n"), caps.Usage);
write_log (_T("UsagePage: %04x\n"), caps.UsagePage);
write_log (_T("InputReportByteLength: %u\n"), caps.InputReportByteLength);
if (MAX_RAW_KEYBOARD > 0 && rnum_kb > MAX_RAW_KEYBOARD)
rnum_kb = MAX_RAW_KEYBOARD;
-
+ write_log (_T("HID device check:\n"));
for (int rawcnt = 0; rawcnt < gotnum; rawcnt++) {
HANDLE h = ridl[rawcnt].hDevice;
int type = ridl[rawcnt].dwType;
} else
continue;
- if (GetRawInputDeviceInfo (h, RIDI_DEVICENAME, NULL, &vtmp) == -1)
+ if (GetRawInputDeviceInfo (h, RIDI_DEVICENAME, NULL, &vtmp) == -1) {
+ write_log (_T("%p RIDI_DEVICENAME failed\n"), h);
continue;
- if (vtmp >= bufsize)
+ }
+ if (vtmp >= bufsize) {
+ write_log (_T("%p RIDI_DEVICENAME too big %d\n"), h, vtmp);
continue;
- if (GetRawInputDeviceInfo (h, RIDI_DEVICENAME, buf1, &vtmp) == -1)
+ }
+ if (GetRawInputDeviceInfo (h, RIDI_DEVICENAME, buf1, &vtmp) == -1) {
+ write_log (_T("%p RIDI_DEVICENAME %d failed\n"), h, vtmp);
continue;
+ }
rdi = (PRID_DEVICE_INFO)buf2;
memset (rdi, 0, sizeof (RID_DEVICE_INFO));
rdi->cbSize = sizeof (RID_DEVICE_INFO);
- if (GetRawInputDeviceInfo (h, RIDI_DEVICEINFO, NULL, &vtmp) == -1)
+ if (GetRawInputDeviceInfo (h, RIDI_DEVICEINFO, NULL, &vtmp) == -1) {
+ write_log (_T("%p RIDI_DEVICEINFO failed\n"), h);
continue;
- if (vtmp >= bufsize)
+ }
+ if (vtmp >= bufsize) {
+ write_log (_T("%p RIDI_DEVICEINFO too big %d\n"), h, vtmp);
continue;
- if (GetRawInputDeviceInfo (h, RIDI_DEVICEINFO, buf2, &vtmp) == -1)
+ }
+ if (GetRawInputDeviceInfo (h, RIDI_DEVICEINFO, buf2, &vtmp) == -1) {
+ write_log (_T("%p RIDI_DEVICEINFO %d failed\n"), h, vtmp);
continue;
+ }
+
+ write_log (_T("%p %04x/%04x (%d/%d)\n"), h, rdi->hid.dwVendorId, rdi->hid.dwProductId, rdi->hid.usUsage, rdi->hid.usUsagePage);
if (type == RIM_TYPEMOUSE) {
if (rdpdevice (buf1))
continue;
- if (num_mouse >= MAX_INPUT_DEVICES - 1) /* leave space for Windows mouse */
+ if (num_mouse >= MAX_INPUT_DEVICES - 1) {/* leave space for Windows mouse */
+ write_log (_T("Too many mice\n"));
continue;
+ }
did += num_mouse;
num_mouse++;
rmouse++;
} else if (type == RIM_TYPEKEYBOARD) {
if (rdpdevice (buf1))
continue;
- if (num_keyboard >= MAX_INPUT_DEVICES)
+ if (num_keyboard >= MAX_INPUT_DEVICES) {
+ write_log (_T("Too many keyboards\n"));
continue;
+ }
did += num_keyboard;
num_keyboard++;
rkb++;
} else if (type == RIM_TYPEHID) {
if (rdpdevice (buf1))
continue;
- if (rdi->hid.usUsage != 4 && rdi->hid.usUsage != 5)
+ if (rdi->hid.usUsage != 4 && rdi->hid.usUsage != 5) {
+ write_log (_T("RAWHID: Usage not 4 or 5 (%d)\n"), rdi->hid.usUsage);
continue;
- if (rdi->hid.usUsagePage >= 0xff00) // vendor specific
+ }
+ if (rdi->hid.usUsagePage >= 0xff00) { // vendor specific
+ write_log (_T("RAWHID: Ignored vendor specific %04x\n"), rdi->hid.usUsagePage);
continue;
+ }
for (i = 0; hidnorawinput[i].vid; i++) {
if (rdi->hid.dwProductId == hidnorawinput[i].pid && rdi->hid.dwVendorId == hidnorawinput[i].vid)
break;
}
- if (hidnorawinput[i].vid || num_joystick >= MAX_INPUT_DEVICES)
+ if (hidnorawinput[i].vid) {
+ write_log (_T("RAWHID: blacklisted\n"));
continue;
+ }
+ if (num_joystick >= MAX_INPUT_DEVICES) {
+ write_log (_T("RAWHID: too many devices\n"));
+ continue;
+ }
did += num_joystick;
num_joystick++;
rhid++;
if (HidP_GetCaps (did->hidpreparseddata, &did->hidcaps) == HIDP_STATUS_SUCCESS) {
PHIDP_BUTTON_CAPS bcaps;
USHORT size = did->hidcaps.NumberInputButtonCaps;
- dumphidcaps (did);
+ dumphidcaps (did, rawcnt);
bcaps = xmalloc (HIDP_BUTTON_CAPS, size);
if (HidP_GetButtonCaps (HidP_Input, bcaps, &size, did->hidpreparseddata) == HIDP_STATUS_SUCCESS) {
dumphidbuttoncaps (bcaps, size);
rawprevkey = -1;
}
+static void flushmsgpump (void)
+{
+ MSG msg;
+ while (PeekMessage (&msg, 0, 0, 0, PM_REMOVE)) {
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+}
static int acquire_kb (int num, int flags)
{
if (num < 0) {
doregister_rawinput ();
if (currprefs.keyboard_leds_in_use) {
+ //write_log (_T("***********************acquire_kb_led\n"));
if (!currprefs.win32_kbledmode) {
if (DefineDosDevice (DDD_RAW_TARGET_PATH, _T("Kbd"), _T("\\Device\\KeyboardClass0"))) {
kbhandle = CreateFile (_T("\\\\.\\Kbd"), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
originalleds = oldleds;
//write_log (_T("stored %08x -> %08x\n"), originalleds, newleds);
}
- update_leds ();
+ set_leds (newleds);
+ flushmsgpump ();
}
return 1;
}
if (num < 0) {
doregister_rawinput ();
if (currprefs.keyboard_leds_in_use) {
+ //write_log (_T("*********************** unacquire_kb_led\n"));
if (originalleds != -1) {
//write_log (_T("restored %08x -> %08x\n"), oldleds, originalleds);
set_leds (originalleds);
originalleds = -1;
+ flushmsgpump ();
}
if (kbhandle != INVALID_HANDLE_VALUE) {
CloseHandle (kbhandle);
* - block 0 is zeroed
*/
-int harddrive_dangerous, do_rdbdump;
+int harddrive_dangerous = 0x1234dead;
+int do_rdbdump;
static struct uae_driveinfo uae_drives[MAX_FILESYSTEM_UNITS];
+#if 0
+static void fixdrive (struct hardfiledata *hfd)
+{
+ uae_u8 data[512];
+ struct zfile *zf = zfile_fopen (_T("d:\\amiga\\hdf\\a500supradrive.hdf"), _T("rb"));
+ for (int i = 0; i < 0x30000 / 512; i++) {
+ zfile_fread (data, 1, 512, zf);
+ hdf_write (hfd, data, i * 512, 512);
+ }
+ zfile_fclose (zf);
+
+}
+#endif
+
static int isnomediaerr (DWORD err)
{
if (err == ERROR_NOT_READY ||
goto end;
if (!DeviceIoControl (h, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &r, NULL))
write_log (_T("WARNING: '%s' FSCTL_ALLOW_EXTENDED_DASD_IO returned %d\n"), name, GetLastError ());
+
//queryidentifydevice (hfd);
_tcsncpy (hfd->vendor_id, udi->vendor_id, 8);
_tcsncpy (hfd->product_id, udi->product_id, 16);
}
hfd->handle_valid = HDF_HANDLE_WIN32;
hfd->emptyname = my_strdup (name);
+ //fixdrive (hfd);
} else {
hfd->flags = HFD_FLAGS_REALDRIVE;
hfd->drive_empty = -1;
#define __i386__
#define WINDOWS
#define ZLIB_WINAPI
+#define PACKAGE_STRING "WinUAE"
#ifndef UAE_MINI
#define RETROPLATFORM /* Cloanto RetroPlayer support */
#define WITH_CHD
#define WITH_LUA /* lua scripting */
+#define WITH_UAENATIVE
#else
#endif
}
+struct winuae //this struct is put in a6 if you call
+ //execute native function
+{
+ HWND amigawnd; //adress of amiga Window Windows Handle
+ unsigned int changenum; //number to detect screen close/open
+ unsigned int z3offset; //the offset to add to acsess Z3 mem from Dll side
+};
+
+void *uaenative_get_uaevar (void)
+{
+ static struct winuae uaevar;
+#ifdef _WIN32
+ uaevar.amigawnd = hAmigaWnd;
+#endif
+ uaevar.z3offset = (uae_u32)get_real_address (0x10000000) - 0x10000000;
+ return &uaevar;
+}
+
+const TCHAR **uaenative_get_library_dirs (void)
+{
+ static const TCHAR **nats;
+ static TCHAR *path;
+
+ if (nats == NULL)
+ nats = xcalloc (const TCHAR*, 3);
+ if (path == NULL) {
+ path = xcalloc (TCHAR, MAX_DPATH);
+ _tcscpy (path, start_path_data);
+ _tcscat (path, _T("plugins"));
+ }
+ nats[0] = start_path_data;
+ nats[1] = path;
+ return nats;
+}
typedef BOOL (CALLBACK* CHANGEWINDOWMESSAGEFILTER)(UINT, DWORD);
#define LANG_DLL 1
#if WINUAEPUBLICBETA
-#define WINUAEBETA _T("4")
+#define WINUAEBETA _T("5")
#else
#define WINUAEBETA _T("")
#endif
-#define WINUAEDATE MAKEBD(2014, 1, 18)
+#define WINUAEDATE MAKEBD(2014, 2, 2)
#define WINUAEEXTRA _T("")
//#define WINUAEEXTRA _T("AmiKit Preview")
//#define WINUAEEXTRA _T("Amiga Forever Edition")
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
-VisualStudioVersion = 12.0.21005.1
+VisualStudioVersion = 12.0.30110.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winuae", "winuae_msvc.vcxproj", "{4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}"
EndProject
{BE211CE1-3955-4674-A664-5038FC791980}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{BE211CE1-3955-4674-A664-5038FC791980}.Debug|Mixed Platforms.Build.0 = Debug|x86
{BE211CE1-3955-4674-A664-5038FC791980}.Debug|Win32.ActiveCfg = Debug|x86
- {BE211CE1-3955-4674-A664-5038FC791980}.Debug|Win32.Build.0 = Debug|x86
{BE211CE1-3955-4674-A664-5038FC791980}.Debug|x64.ActiveCfg = Debug|x86
{BE211CE1-3955-4674-A664-5038FC791980}.Debug|x86.ActiveCfg = Debug|x86
{BE211CE1-3955-4674-A664-5038FC791980}.Debug|x86.Build.0 = Debug|x86
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
- <CallingConvention>StdCall</CallingConvention>
+ <CallingConvention>FastCall</CallingConvention>
<CompileAs>Default</CompileAs>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<EnablePREfast>false</EnablePREfast>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<IgnoreSpecificDefaultLibraries>LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
- <DelayLoadDLLs>wpcap.dll;packet.dll;d3dx9_43.dll;openal32.dll;wintab32.dll;portaudio_x86.dll;ws2_32.dll;msacm32.dll;wtsapi32.dll;dsound.dll;ddraw.dll;Iphlpapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <DelayLoadDLLs>wpcap.dll;packet.dll;d3dx9_43.dll;openal32.dll;wintab32.dll;portaudio_x86.dll;ws2_32.dll;msacm32.dll;wtsapi32.dll;dsound.dll;wininet.dll;avrt.dll;ddraw.dll;Iphlpapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>.\Debug/winuae.pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<ClCompile Include="..\..\isofs.cpp" />
<ClCompile Include="..\..\luascript.cpp" />
<ClCompile Include="..\..\qemuvga\cirrus_vga.cpp" />
+ <ClCompile Include="..\..\qemuvga\lsi53c895a.cpp" />
<ClCompile Include="..\..\qemuvga\qemuuaeglue.cpp" />
<ClCompile Include="..\..\qemuvga\vga.cpp" />
<ClCompile Include="..\..\scsitape.cpp" />
<ClCompile Include="..\..\slirp\udp.cpp" />
<ClCompile Include="..\..\specialmonitors.cpp" />
<ClCompile Include="..\..\statusline.cpp" />
+ <ClCompile Include="..\..\uaenative.cpp" />
<ClCompile Include="..\ahidsound_dsonly.cpp" />
<ClCompile Include="..\ahidsound_new.cpp" />
<ClCompile Include="..\avioutput.cpp" />
<ClCompile Include="..\..\cpuemu_13.cpp">
<Filter>common</Filter>
</ClCompile>
+ <ClCompile Include="..\..\uaenative.cpp">
+ <Filter>common</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\qemuvga\lsi53c895a.cpp">
+ <Filter>qemu</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\resources\35floppy.ico">
+1 -> 0: 0,1FE,1FE,1FE,..
+1 -> 1: 0,1FE,0,1FE,0,..
+1 -> 2: 0,1FE,70,1FE,70,.. (C-)
+1 -> 9: 0,1FE,0,74,0,74,.. (DA)
+1 -> B: 0,1FE,70,0,74,70,0,74,70,0,74,.. (ACD)
+1 -> C: 0,1FE,72,74,70,72,74,70,72,.. (CBA)
+1 -> D: 0,1FE,72,74,70,72,74,70,72,.. (CBA)
+1 -> E: 0,1FE,70,70,70,70,.. (C)
+1 -> F: 0,1FE,70,70,74,70,70,70,74,70,70,70,74,.. (CCCA)
+
- restore only single input target to default.
+- More than one horizontal DDFSTRT-DDFSTOP window is now accurately emulated without requiring any hacks.
+ Random garbage between display windows is also gone. (Subtle Shades / Nuance)
+- Removed some more obsolete variables from display emulation.
+- Saigon Megademo fix got accidentally broken in b2.
+- 260b17 "strange right edge overscan display shift" optional hack removed, new delay/shift register
+ behavior creates identical output automatically simply by reseting delay counter (hpos counter) at the
+ end of scanline. NOTE: Some programs with large overscan can now have small graphics corruption in right
+ border (gap in graphics), it is not a bug, it is accurate emulation. (For example Back in Bizness / 2000AD)
+- Some OCS only programs may now have graphics corruption in ECS mode (if bitplane DMA crosses scanlines),
+ this is also not a bug, real hardware would show even worse corruption. Someday this will be more accurately emulated.
+- Agnus vpos counter increase delayed by 1 cycle. Fixes Hit the Road / Flash Production "Floffy2" part.
+- Keyboard leds as power/floppy/etc indicators are now properly restored back to original state when
+ keyboard input is not active, changing led config on the fly also works now.
+- Exiting GUI with close button or ALT-F4 didn't save GUI position.
+
+Beta 3:
+
+- Sprites near left border had strange corruption (b1)
+- "toscr_nbits > 16" error in some situations (b1)
+- "Modified interrupt delays" b1 change was bad, sometimes interrupt request was kept active
+ causing spurious interrupts (which caused crashes).
+- New autoresolution selection was not loaded correctly from config file.
+- Blitter final D write don't increase "nasty" count. (Which makes sense, blit is already
+ finished, blitbusy bit was cleared 2 cycles ago)
+- Removed most BPLxDAT related hacks, they become obsolete after b2 BPLCON1 update (it also changed
+ how data gets moved to shift registers). May introduce new glitches and if it does, it needs
+ correct emulation updates, not hacks.
+
+Beta 2:
+
+- BPLCON1 mid scan line modifications now should match real hardware 100%.
+ This was very big change, old emulation was functionally close enough but very far from real
+ hardware behavior. Old code couldn't emulate some side-effects correctly.
+
+- Partial/full scanline based mode ("SPEEDUP") is again used more regularly, "is it safe to use" check
+ got partially broken during 2.7.0 betas. It is also more optimal in AGA 32/64-bit fetch modes.
+- AGA border sprite in right border and 2x or 4x horizontal sprite pixels (vs bitplane pixels): sprite's
+ rightmost pixel(s) were missing.
+- Superhires and top or bottom border sprite: graphics garbage was seen in border area, memory
+ corruption was also possible in some situations.
+- Magic mouse + mousehack mode now always stops keyboard input when mouse is outside of emulation
+ window, even if window still has focus.
+- 68020/030 CAAR register preserves also all reserved bits.
+- Disable JIT if config has 68000/010 CPU and non-zero JIT cache size.
+- 68020 CE broke interrupt state fetch, interrupt didn't clear if write to INTREQ was immediately
+ followed by RTE. (b1)
+- Does not anymore require SSE2 capable CPU (b1 did)
+
+Beta 1:
+
Lots of small blitter, copper and CPU timing adjustments. (Thanks to amilo3438 for collecting huge amounts
of demo test cases). Lots of logic analyzer tests done during last few weeks.
_stprintf (p, _T("%03d"), tb.millitm);
p += _tcslen (p);
if (vsync_counter != 0xffffffff)
- _stprintf (p, _T(" [%d %03d%s%03d]"), vsync_counter, current_hpos (), lof_store ? _T("-") : _T("="), vpos);
+ _stprintf (p, _T(" [%d %03d%s%03d]"), vsync_counter, current_hpos_safe (), lof_store ? _T("-") : _T("="), vpos);
_tcscat (p, _T(": "));
return out;
}
premsg ();
+ if (!_tcsicmp (format, _T("*")))
+ count = 0;
+
EnterCriticalSection (&cs);
va_start (parms, format);
bufp = buffer;
*
*/
-#ifndef MEMORY_H
-#define MEMORY_H
+#ifndef QMEMORY_H
+#define QMEMORY_H
#ifndef CONFIG_USER_ONLY
#endif
-#endif
+#endif /* QMEMORY */
+
--- /dev/null
+/*
+* UAE - The Un*x Amiga Emulator
+*
+* UAE Native Interface (UNI) - uaenative.library
+*
+* Copyright 2013-2014 Frode Solheim. Amiga-side library sample code
+* provided by Toni Wilen.
+*
+* TODO: Handling UAE reset and shutdown better. When resetting the Amiga,
+* all opened native libraries should be closed, and all async call threads
+* should be stopped.
+*/
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+
+#ifdef WITH_UAENATIVE
+
+#include <stdlib.h>
+#include "options.h"
+#include "memory.h"
+#include "custom.h"
+#include "newcpu.h"
+#include "traps.h"
+#include "autoconf.h"
+#include "execlib.h"
+#include "threaddep/thread.h"
+#include "native2amiga.h"
+#include "events.h"
+#include "uaenative.h"
+#include "fsdb.h"
+
+#if defined(FSUAE) && defined(WINDOWS)
+#define _WIN32
+#endif
+
+#ifndef _WIN32
+#include <dlfcn.h>
+#endif
+
+static double syncdivisor;
+
+#define SIGBIT 8 // SIGB_DOS
+
+// the function prototype for the callable native functions
+typedef uae_s32 (UNICALL *uae_uni_native_function)(struct uni *uni);
+
+// the function prototype for the callable native functions (old style)
+typedef uae_u32 (UNICALL *uae_uni_native_compat_function)(uae_u32, uae_u32,
+ uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32,
+ uae_u32, uae_u32, uae_u32, void *, uae_u32, void *);
+
+// the function prototype for the native library's uni_init function
+typedef int (UNICALL *uni_init_function)(void);
+
+struct library_data {
+ void *dl_handle;
+ uae_thread_id thread_id;
+ uae_sem_t empty_count;
+ uae_sem_t full_count;
+ int thread_stop_flag;
+ struct uni *uni;
+};
+
+struct uni_handle {
+ struct library_data *library;
+ void *function;
+};
+
+static uni_handle *g_handles = NULL;
+static int g_allocated_handles = 0;
+static int g_max_handle = -1;
+
+#if defined (_WIN32)
+ #define OS_EXTENSION _T("-windows")
+ #define FILE_EXTENSION _T(".dll")
+#elif defined (LINUX)
+ #define OS_EXTENSION _T("-linux")
+ #define FILE_EXTENSION _T(".so")
+#elif defined (MACOSX)
+ #define OS_EXTENSION _T("-macosx")
+ #define FILE_EXTENSION _T(".dylib")
+#elif defined (FREEBSD)
+ #define OS_EXTENSION _T("-freebsd")
+ #define FILE_EXTENSION _T(".so")
+#elif defined (OPENBSD)
+ #define OS_EXTENSION _T("-openbsd")
+ #define FILE_EXTENSION _T(".so")
+#else
+ #define OS_EXTENSION _T("-unknown")
+ #define FILE_EXTENSION _T(".unknown")
+#endif
+
+#if defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
+ #define ARCH_EXTENSION _T("-x86-64")
+#elif defined(__i386__) || defined (_M_IX86)
+ #define ARCH_EXTENSION _T("-x86")
+#elif defined(__ppc__)
+ #define ARCH_EXTENSION _T("-ppc")
+#else
+ #define ARCH_EXTENSION _T("-unknown")
+#endif
+
+static int UNICALL uni_version(void)
+{
+ return UNI_VERSION;
+}
+
+static void * UNICALL uni_resolve(uae_u32 ptr)
+{
+ void *result = get_real_address (ptr);
+ //printf ("UNI: resolve address 0x%08x -> %p\n", ptr, result);
+ return result;
+}
+
+static const char * UNICALL uni_uae_version(void)
+{
+ // A standard GNU macro with a string containing program name and
+ // version, e.g. "WinUAE 2.7.0" or "FS-UAE 2.3.16dev".
+ return PACKAGE_STRING;
+}
+
+static void free_library_data(struct library_data *library_data) {
+ if (library_data->empty_count) {
+ uae_sem_destroy(&library_data->empty_count);
+ }
+ if (library_data->full_count) {
+ uae_sem_destroy(&library_data->full_count);
+ }
+ free(library_data);
+}
+
+static uae_u32 register_handle(library_data *library_data, void *function)
+{
+ int index = -1;
+ if (g_max_handle >= g_allocated_handles - 1) {
+ // Entries above g_max_handle are assumed to be uninitialized,
+ // but unused/"freed" entries below g_max_handle must be zeroed.
+ // Try to find a reusable entry before allocating more space.
+ for (int i = 0; i < g_max_handle; i++) {
+ if (g_handles[i].library == NULL && g_handles[i].function == NULL) {
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) {
+ int new_count = g_allocated_handles * 2;
+ if (new_count == 0) {
+ new_count = 128;
+ }
+ write_log("uni: allocating memory for %d handles\n", new_count);
+ g_handles = (uni_handle *) realloc(g_handles,
+ new_count * sizeof(struct uni_handle));
+ g_allocated_handles = new_count;
+ }
+ }
+
+ if (index == -1) {
+ index = g_max_handle + 1;
+ g_max_handle = index;
+ }
+
+ g_handles[index].library = library_data;
+ g_handles[index].function = function;
+
+ // valid handles start from 0x80000000, anything below is error code
+ return (uae_u32) 0x80000000 + (uae_u32) index;
+}
+
+static TCHAR *get_native_library_path (const TCHAR *library_name)
+{
+ write_log (_T("uni: find_native_library %s\n"), library_name);
+ TCHAR path[PATH_MAX];
+ const TCHAR **library_dirs = uaenative_get_library_dirs ();
+
+ for (const TCHAR **dir = library_dirs; *dir != NULL; dir++) {
+ // name must already have been checked to not contain anything
+ // to allow access to parent directories.
+ _sntprintf (path, PATH_MAX, _T("%s%s%s"), *dir, library_name,
+ OS_EXTENSION ARCH_EXTENSION FILE_EXTENSION);
+ write_log (_T("uni: checking %s\n"), path);
+ if (my_existsfile (path)) {
+ return my_strdup (path);
+ }
+#ifdef _WIN32
+ // for compatibility with existing WinUAE native interface
+ _sntprintf (path, PATH_MAX, _T("%s%s.dll"), *dir, library_name);
+ write_log (_T("uni: checking %s\n"), path);
+ if (my_existsfile (path)) {
+ return my_strdup (path);
+ }
+#endif
+ }
+ return NULL;
+}
+
+static void *dl_symbol(void *dl, const char *name)
+{
+ if (dl == NULL) {
+ return NULL;
+ }
+#ifdef _WIN32
+ return (void *) GetProcAddress ((HINSTANCE) dl, name);
+#else
+ return dlsym (dl, name);
+#endif
+}
+
+static void dl_close(void *dl)
+{
+#ifdef _WIN32
+ FreeLibrary ((HMODULE) dl);
+#else
+ dlclose (dl);
+#endif
+}
+
+static void set_library_globals(void *dl)
+{
+ void *address;
+
+ address = dl_symbol(dl, "uni_version");
+ if (address) *((uni_version_function *) address) = &uni_version;
+
+ address = dl_symbol(dl, "uni_resolve");
+ if (address) *((uni_resolve_function *) address) = &uni_resolve;
+
+ address = dl_symbol(dl, "uni_uae_version");
+ if (address) *((uni_uae_version_function *) address) = &uni_uae_version;
+}
+
+static uae_u32 open_library (const char *name, uae_u32 min_version)
+{
+ syncdivisor = (3580000.0 * CYCLE_UNIT) / (double) syncbase;
+
+ for (const char *c = name; *c; c++) {
+ if (*c == '/' || *c == '\\' || *c == ':') {
+ return UNI_ERROR_ILLEGAL_LIBRARY_NAME;
+ }
+ }
+
+ TCHAR *tname = au (name);
+ write_log (_T("uni: open native library '%s'\n"), tname);
+ TCHAR *path = get_native_library_path (tname);
+ free (tname);
+ if (path == NULL) {
+ write_log(_T("uni: library not found\n"));
+ return UNI_ERROR_LIBRARY_NOT_FOUND;
+ }
+
+ write_log (_T("uni: found library at %s - opening\n"), path);
+#ifdef _WIN32
+ void *dl = LoadLibrary (path);
+#else
+ void *dl = dlopen (path, RTLD_NOW);
+#endif
+ free(path);
+ if (dl == NULL) {
+ write_log (_T("uni: error opening library errno %d\n"), errno);
+ return UNI_ERROR_COULD_NOT_OPEN_LIBRARY;
+ }
+
+ // FIXME: check min version
+
+ set_library_globals(dl);
+
+ void *function_address = dl_symbol(dl, "uni_init");
+ if (function_address) {
+ int error = ((uni_init_function) function_address)();
+ if (error) {
+ dl_close(dl);
+ return error;
+ }
+ }
+
+ struct library_data *library_data = (struct library_data *) malloc(
+ sizeof(struct library_data));
+ memset(library_data, 0, sizeof(struct library_data));
+ library_data->dl_handle = dl;
+
+ uae_u32 handle = register_handle (library_data, NULL);
+ write_log(_T("uni: opened library %08x (%p)\n"), handle, dl);
+ return handle;
+}
+
+uae_u32 uaenative_open_library (TrapContext *context, int flags)
+{
+ if (!currprefs.native_code) {
+ write_log(_T("uni: tried to open native library, but native code ")
+ _T("is not enabled\n"));
+ return UNI_ERROR_NOT_ENABLED;
+ }
+
+ uaecptr name;
+ uae_u32 min_version;
+ if (flags & UNI_FLAG_COMPAT) {
+ name = m68k_areg (regs, 0);
+ min_version = 0;
+ }
+ else {
+ name = m68k_areg (regs, 1);
+ min_version = m68k_dreg (regs, 0);
+ }
+
+ uae_u32 result = open_library (
+ (const char *) get_real_address (name), min_version);
+
+ if ((flags & UNI_FLAG_COMPAT) && !(result & 0x80000000)) {
+ // error opening library, return 0 for error in compatibility mode
+ return 0;
+ }
+ return result;
+}
+
+static struct library_data *get_library_data_from_handle (uae_u32 handle)
+{
+ int index = handle - (uae_u32) 0x80000000;
+ //printf("check library index %u\n", index);
+ if (index < 0 || index > g_max_handle) {
+ //printf("index < 0 || index > g_max_handle\n");
+ return NULL;
+ }
+ if (g_handles[index].function) {
+ //printf("- g_handles[index].function\n");
+ return NULL;
+ }
+ return g_handles[index].library;
+}
+
+static uae_u32 get_function_handle (uae_u32 handle, const char *name)
+{
+ struct library_data *library_data = get_library_data_from_handle (handle);
+ if (library_data == NULL) {
+ write_log(_T("uni: get_function - invalid library (%d)\n"), handle);
+ return UNI_ERROR_INVALID_LIBRARY;
+ }
+
+ void *function_address = dl_symbol (library_data->dl_handle, name);
+ if (!function_address) {
+ write_log(_T("uni: get_function - function (%s) not found ")
+ _T("in library %d (%p)\n"), name, handle,
+ library_data->dl_handle);
+ return UNI_ERROR_FUNCTION_NOT_FOUND;
+ }
+ return register_handle (library_data, function_address);
+}
+
+uae_u32 uaenative_get_function (TrapContext *context, int flags)
+{
+ if (!currprefs.native_code) {
+ return UNI_ERROR_NOT_ENABLED;
+ }
+
+ //m68k_dreg (regs, 1), m68k_areg (regs, 0),
+ //m68k_dreg (regs, 0), m68k_areg (regs, 1),
+
+ uaecptr name;
+ uae_u32 library;
+ if (flags & UNI_FLAG_COMPAT) {
+ name = m68k_areg (regs, 0);
+ library = m68k_dreg (regs, 1);
+ }
+ else {
+ library = m68k_areg (regs, 0);
+ name = m68k_areg (regs, 1);
+ }
+
+ uae_u32 result = get_function_handle (
+ library, (const char *) get_real_address (name));
+
+ if ((flags & UNI_FLAG_COMPAT) && !(result & 0x80000000)) {
+ // error getting function, return 0 for error in compatibility mode
+ return 0;
+ }
+ return result;
+}
+
+#if defined(X86_MSVC_ASSEMBLY)
+
+static uae_u32 do_call_function_compat_asm (struct uni *uni)
+{
+ unsigned int espstore;
+ void *native_func = uni->native_function;
+ uae_u32 d1 = uni->d1;
+ uae_u32 d2 = uni->d2;
+ uae_u32 d3 = uni->d3;
+ uae_u32 d4 = uni->d4;
+ uae_u32 d5 = uni->d5;
+ uae_u32 d6 = uni->d6;
+ uae_u32 d7 = uni->d7;
+ uae_u32 a1 = uni->a1;
+ uae_u32 a2 = uni->a2;
+ uae_u32 a3 = uni->a3;
+ uae_u32 a4 = uni->a4;
+ uae_u32 a5 = uni->a5;
+ uae_u32 a7 = uni->a7;
+ uae_u32 regs_ = (uae_u32)®s;
+ void *a6 = uni->uaevar_compat;
+
+ __asm
+ { mov espstore,esp
+ push regs_
+ push a7
+ push a6
+ push a5
+ push a4
+ push a3
+ push a2
+ push a1
+ push d7
+ push d6
+ push d5
+ push d4
+ push d3
+ push d2
+ push d1
+ call native_func
+ mov esp,espstore
+ }
+}
+
+#endif
+
+static void do_call_function (struct uni *uni) {
+ printf("uni: calling native function %p\n", uni->native_function);
+
+ unsigned long start_time;
+ const int flags = uni->flags;
+ if ((flags & UNI_FLAG_ASYNCHRONOUS) == 0) {
+ start_time = read_processor_time ();
+ }
+
+ if (uni->flags & UNI_FLAG_COMPAT) {
+#if defined(X86_MSVC_ASSEMBLY)
+ uni->result = (uae_s32) do_call_function_compat_asm(uni);
+#else
+ uni->result = ((uae_uni_native_compat_function) uni->native_function) (
+ uni->d1, uni->d2, uni->d3, uni->d4, uni->d5, uni->d6,
+ uni->d7, uni->a1, uni->a2, uni->a3, uni->a4, uni->a5,
+ uni->uaevar_compat, uni->a7, ®s);
+#endif
+ }
+ else {
+ uni->result = ((uae_uni_native_function) uni->native_function) (uni);
+ }
+
+ if ((flags & UNI_FLAG_ASYNCHRONOUS) == 0) {
+ unsigned long time_diff = read_processor_time () - start_time;
+ double v = syncdivisor * time_diff;
+ if (v > 0) {
+ if (v > 1000000 * CYCLE_UNIT) {
+ v = 1000000 * CYCLE_UNIT;
+ }
+ // compensate for the time spent in the native function
+ do_extra_cycles ((unsigned long) (syncdivisor * time_diff));
+ }
+ }
+}
+
+static void *uaenative_thread(void *arg)
+{
+ struct library_data *library_data = (struct library_data *) arg;
+
+ while (1) {
+ uae_sem_wait(&library_data->full_count);
+ if (library_data->thread_stop_flag) {
+ break;
+ }
+ if (library_data->uni) {
+ do_call_function (library_data->uni);
+ uae_Signal (library_data->uni->task, 1 << SIGBIT);
+ }
+ library_data->uni = NULL;
+ uae_sem_post(&library_data->empty_count);
+ }
+
+ write_log (_T("uni: uaenative_thread exiting\n"));
+ free_library_data(library_data);
+ return NULL;
+}
+
+uae_u32 uaenative_call_function (TrapContext *context, int flags)
+{
+ if (!currprefs.native_code) {
+ return UNI_ERROR_NOT_ENABLED;
+ }
+
+ struct uni uni;
+ uni.function = m68k_areg (regs, 0);
+ if (flags & UNI_FLAG_COMPAT) {
+ uni.library = 0;
+ uni.uaevar_compat = uaenative_get_uaevar();
+ }
+ else if (flags & UNI_FLAG_NAMED_FUNCTION) {
+ uni.library = m68k_dreg (regs, 0);
+ }
+ else {
+ uni.library = 0;
+ }
+
+ struct library_data *library_data;
+
+ if (uni.library) {
+ // library handle given, function is pointer to function name
+ const char *function = (const char *) get_real_address (uni.function);
+
+ library_data = get_library_data_from_handle (uni.library);
+ if (library_data == NULL) {
+ write_log (_T("uni: get_function - invalid library (%d)\n"),
+ uni.library);
+ return UNI_ERROR_INVALID_LIBRARY;
+ }
+
+ uni.native_function = dl_symbol (library_data->dl_handle, function);
+ if (uni.native_function == NULL) {
+ write_log (_T("uni: get_function - function (%s) not found ")
+ _T("in library %d (%p)\n"), function, uni.library,
+ library_data->dl_handle);
+ return UNI_ERROR_FUNCTION_NOT_FOUND;
+ }
+ }
+ else {
+ // library handle not given, function argument is function handle
+ int index = uni.function - (uae_u32) 0x80000000;
+ if (index >= 0 && index <= g_max_handle) {
+ uni.native_function = g_handles[index].function;
+ library_data = g_handles[index].library;
+ }
+ else {
+ uni.native_function = NULL;
+ }
+ if (uni.native_function == NULL) {
+ // printf ("UNI_ERROR_INVALID_FUNCTION\n");
+ return UNI_ERROR_INVALID_FUNCTION;
+ }
+ }
+
+ if (context == NULL) {
+ // we have no context and cannot call into m68k space
+ flags &= ~UNI_FLAG_ASYNCHRONOUS;
+ }
+
+ uni.d1 = m68k_dreg (regs, 1);
+ uni.d2 = m68k_dreg (regs, 2);
+ uni.d3 = m68k_dreg (regs, 3);
+ uni.d4 = m68k_dreg (regs, 4);
+ uni.d5 = m68k_dreg (regs, 5);
+ uni.d6 = m68k_dreg (regs, 6);
+ uni.d7 = m68k_dreg (regs, 7);
+ uni.a1 = m68k_areg (regs, 1);
+ uni.a2 = m68k_areg (regs, 2);
+ uni.a3 = m68k_areg (regs, 3);
+ uni.a4 = m68k_areg (regs, 4);
+ uni.a5 = m68k_areg (regs, 5);
+ uni.a7 = m68k_areg (regs, 7);
+
+ uni.flags = flags;
+ uni.error = 0;
+
+ if (flags & UNI_FLAG_ASYNCHRONOUS) {
+ uaecptr sysbase = get_long (4);
+ uni.task = get_long (sysbase + 276); // ThisTask
+
+ // make sure signal bit is cleared
+ m68k_dreg (regs, 0) = 0;
+ m68k_dreg (regs, 1) = 1 << SIGBIT;
+ CallLib (context, sysbase, -0x132); // SetSignal
+
+ // start thread if necessary
+ if (!library_data->thread_id) {
+ uae_sem_init (&library_data->full_count, 0, 0);
+ // we don't have a queue as such, the thread only processes
+ // one item at a time with a "queue size" of 1
+ uae_sem_init (&library_data->empty_count, 0, 1);
+ uae_start_thread (_T("uaenative"), uaenative_thread,
+ library_data, &library_data->thread_id);
+ }
+
+ // signal async thread to process new function call
+ uae_sem_wait(&library_data->empty_count);
+ library_data->uni = &uni;
+ uae_sem_post(&library_data->full_count);
+
+ // wait for signal
+ m68k_dreg (regs, 0) = 1 << SIGBIT;
+ CallLib (context, sysbase, -0x13e); // Wait
+ write_log (_T("uni: -- Got async result --\n"));
+ }
+ else {
+ // synchronous mode, just call the function here and now
+ do_call_function(&uni);
+ }
+ return uni.result;
+}
+
+uae_u32 uaenative_close_library(TrapContext *context, int flags)
+{
+ if (!currprefs.native_code) {
+ return UNI_ERROR_NOT_ENABLED;
+ }
+
+ uae_u32 handle;
+ if (flags & UNI_FLAG_COMPAT) {
+ handle = m68k_dreg (regs, 1);
+ }
+ else {
+ handle = m68k_areg (regs, 1);
+ }
+
+ struct library_data *library_data = get_library_data_from_handle (handle);
+ if (library_data == NULL) {
+ return UNI_ERROR_INVALID_LIBRARY;
+ }
+
+ dl_close (library_data->dl_handle);
+
+ // We now "free" the library and function entries for this library. This
+ // makes the entries available for re-use. The bad thing about this is
+ // that it could be possible for a buggy Amiga program to call a
+ // mismatching function if a function handle is kept after the library
+ // is closed.
+ for (int i = 0; i <= g_max_handle; i++) {
+ if (g_handles[i].library == library_data) {
+ g_handles[i].library = NULL;
+ g_handles[i].function = NULL;
+ }
+ }
+
+ if (library_data->thread_id) {
+ write_log (_T("uni: signalling uaenative_thread to stop\n"));
+ library_data->thread_stop_flag = 1;
+ // wake up thread so it can shut down
+ uae_sem_post(&library_data->full_count);
+ }
+ else {
+ free_library_data(library_data);
+ }
+
+ return 0;
+}
+
+// ----------------------------------------------------------------------------
+
+typedef uae_u32 (REGPARAM2 *uae_library_trap) (TrapContext *context);
+
+struct uae_library_trap_def {
+ uae_library_trap function; // native function pointer for trap
+ int flags; // trap flags, e.g. TRAPFLAG_EXTRA_STACK
+ uaecptr aptr; // address of trap (Amiga-side)
+};
+
+struct uae_library {
+ // these members must be specified
+ const TCHAR *name;
+ const TCHAR *id;
+ int version;
+ int revision;
+ uae_library_trap_def *traps;
+
+ // these members can default to 0
+ int data_size;
+
+ // these members will be initialized by library functions
+ uaecptr aptr_name;
+ uaecptr aptr_id;
+ uaecptr aptr_init;
+ uaecptr aptr_func_table;
+ uaecptr aptr_data_table;
+};
+
+void uae_library_install (struct uae_library *library)
+{
+ library->aptr_name = ds (library->name);
+ library->aptr_id = ds (library->id);
+
+ for (uae_library_trap_def *t = library->traps; t->function; t++) {
+ t->aptr = here ();
+ calltrap (deftrap2 (t->function, t->flags, _T("")));
+ dw (RTS);
+ }
+
+ library->aptr_func_table = here ();
+ for (uae_library_trap_def *t = library->traps + 1; t->function; t++) {
+ dl (t->aptr);
+ }
+ dl (0xFFFFFFFF); // end of table
+
+ library->aptr_data_table = here ();
+ dw (0xE000); // INITBYTE
+ dw (0x0008); // LN_TYPE
+ dw (0x0900); // NT_LIBRARY
+ dw (0xE000); // INITBYTE
+ dw (0x0009); // LN_PRI
+ dw (0xCE00); // -50
+ dw (0xC000); // INITLONG
+ dw (0x000A); // LN_NAME
+ dl (library->aptr_name);
+ dw (0xE000); // INITBYTE
+ dw (0x000E); // LIB_FLAGS
+ dw (0x0600); // LIBF_SUMUSED | LIBF_CHANGED
+ dw (0xD000); // INITWORD
+ dw (0x0014); // LIB_VERSION
+ dw (library->version);
+ dw (0xD000);
+ dw (0x0016); // LIB_REVISION
+ dw (library->revision);
+ dw (0xC000);
+ dw (0x0018); // LIB_IDSTRING
+ dl (library->aptr_id);
+ dl (0x00000000); // end of table
+
+ library->aptr_init = here ();
+ dl (SIZEOF_LIBRARY + library->data_size);
+ dl (library->aptr_func_table);
+ dl (library->aptr_data_table);
+ dl (library->traps[0].aptr);
+
+ write_log (_T("%s installed\n"), library->name);
+}
+
+uaecptr uae_library_startup (uaecptr res_addr, struct uae_library *library)
+{
+ if (library->aptr_name == 0 || !currprefs.native_code) {
+ return res_addr;
+ }
+
+ put_word (res_addr + 0x00, 0x4AFC);
+ put_long (res_addr + 0x02, res_addr);
+ put_long (res_addr + 0x06, res_addr + 0x1A); // Continue scan here
+ put_word (res_addr + 0x0A, 0x8004); // RTF_AUTOINIT, RT_VERSION
+ put_word (res_addr + 0x0C, 0x0970); // NT_LIBRARY, RT_PRI
+ put_long (res_addr + 0x0E, library->aptr_name);
+ put_long (res_addr + 0x12, library->aptr_id);
+ put_long (res_addr + 0x16, library->aptr_init);
+
+ return res_addr + 0x1A;
+}
+
+// ----------------------------------------------------------------------------
+
+static uae_u32 REGPARAM2 lib_init (TrapContext *context)
+{
+ uaecptr aptr_base = m68k_dreg (regs, 0);
+#if 0
+ uaecptr aptr_data = aptr_base + SIZEOF_LIBRARY; // sizeof(Library)
+ // our library data area, LIB_DATA_SIZE must be at least as big
+ put_long (aptr_data + 0, somedata);
+#endif
+ return aptr_base;
+}
+
+static uae_u32 REGPARAM2 lib_open (TrapContext *context)
+{
+ // we could do some security checks here if only some specific Amiga
+ // tasks can call us or something like that
+ put_word (m68k_areg (regs, 6) + 32,
+ get_word (m68k_areg (regs, 6) + 32) + 1);
+ return m68k_areg (regs, 6);
+}
+
+static uae_u32 REGPARAM2 lib_close (TrapContext *context)
+{
+ put_word (m68k_areg (regs, 6) + 32,
+ get_word (m68k_areg (regs, 6) + 32) - 1);
+ return 0;
+}
+
+static uae_u32 REGPARAM2 lib_expunge (TrapContext *context)
+{
+ return 0;
+}
+
+static uae_u32 REGPARAM2 lib_null (TrapContext *context)
+{
+ return 0;
+}
+
+static uae_u32 REGPARAM2 lib_open_library (TrapContext *context)
+{
+ return uaenative_open_library (context, 0);
+}
+
+static uae_u32 REGPARAM2 lib_close_library (TrapContext *context)
+{
+ return uaenative_close_library (context, 0);
+}
+
+static uae_u32 REGPARAM2 lib_get_function (TrapContext *context)
+{
+ return uaenative_get_function (context, 0);
+}
+
+static uae_u32 REGPARAM2 lib_call_function (TrapContext *context)
+{
+ int flags = 0;
+ return uaenative_call_function (context, flags);
+}
+
+static uae_u32 REGPARAM2 lib_call_function_async (TrapContext *context)
+{
+ int flags = UNI_FLAG_ASYNCHRONOUS;
+ return uaenative_call_function (context, flags);
+}
+
+static uae_u32 REGPARAM2 lib_call_function_by_name (TrapContext *context)
+{
+ int flags = UNI_FLAG_NAMED_FUNCTION;
+ return uaenative_call_function (context, flags);
+}
+
+static uae_u32 REGPARAM2 lib_call_function_by_name_async (TrapContext *context)
+{
+ int flags = UNI_FLAG_ASYNCHRONOUS | UNI_FLAG_NAMED_FUNCTION;
+ return uaenative_call_function (context, flags);
+}
+
+static uae_library_trap_def uaenative_functions[] = {
+ { lib_init },
+ { lib_open },
+ { lib_close },
+ { lib_expunge },
+ { lib_null },
+ { lib_open_library },
+ { lib_close_library },
+ { lib_get_function },
+ { lib_call_function },
+ { lib_call_function_async, TRAPFLAG_EXTRA_STACK },
+ { lib_call_function_by_name },
+ { lib_call_function_by_name_async, TRAPFLAG_EXTRA_STACK },
+ { NULL },
+};
+
+static struct uae_library uaenative_library = {
+ _T("uaenative.library"),
+ _T("UAE Native Interface 1.0"),
+ 1, // version
+ 0, // revision
+ uaenative_functions,
+};
+
+void uaenative_install (void)
+{
+ uae_library_install (&uaenative_library);
+}
+
+uaecptr uaenative_startup (uaecptr res_addr)
+{
+ return uae_library_startup (res_addr, &uaenative_library);
+}
+
+#endif // WITH_UAENATIVE
if (!memcmp (buf, "PKD\x13", 4) || !memcmp (buf, "PKD\x11", 4)) {
TCHAR *fn;
int sectors = buf[18];
- int heads = buf[15];
+ int reserved = buf[15];
int blocks = (buf[6] << 8) | buf[7];
int blocksize = (buf[10] << 8) | buf[11];
struct zfile *zo;
uae_u8 *nullsector;
nullsector = xcalloc (uae_u8, blocksize);
- sectors /= heads;
+ sectors /= 2;
if (buf[3] == 0x13) {
off = 52;
if (buf[off - 1] == 1) {
off = 32;
}
- if (size < 1760 * 512)
+ // some Amiga disk images are smaller than full adf for some reason
+ if (sectors == 11 && size < 1760 * 512)
size = 1760 * 512;
if (zfile_getfilename (zi) && _tcslen (zfile_getfilename (zi))) {