From 5824a72326ba92798d5f4c9e335aaaf3693aa0c4 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 2 Feb 2014 17:57:49 +0200 Subject: [PATCH] 2710b5 --- cia.cpp | 16 +- custom.cpp | 456 +++++++--- disk.cpp | 24 +- drawing.cpp | 74 +- events.cpp | 13 +- expansion.cpp | 2 +- filesys.asm | 19 + filesys.cpp | 17 +- filesys_bootrom.cpp | 35 +- gencpu.cpp | 34 +- genlinetoscr.cpp | 80 +- gfxboard.cpp | 7 +- include/a2091.h | 6 + include/blkdev.h | 5 + include/custom.h | 7 +- include/events.h | 13 +- include/filesys.h | 4 + include/memory.h | 5 + include/options.h | 7 +- include/scsi.h | 2 +- include/uaenative.h | 49 + include/uni_common.h | 80 ++ main.cpp | 4 + memory.cpp | 40 +- od-win32/dinput.cpp | 74 +- od-win32/hardfile_win32.cpp | 19 +- od-win32/sysconfig.h | 2 + od-win32/win32.cpp | 34 + od-win32/win32.h | 4 +- od-win32/winuae_msvc11/winuae_msvc.sln | 3 +- od-win32/winuae_msvc11/winuae_msvc.vcxproj | 6 +- .../winuae_msvc11/winuae_msvc.vcxproj.filters | 6 + od-win32/winuaechangelog.txt | 60 ++ od-win32/writelog.cpp | 5 +- qemuvga/qemumemory.h | 7 +- uaenative.cpp | 851 ++++++++++++++++++ zfile.cpp | 7 +- 37 files changed, 1772 insertions(+), 305 deletions(-) create mode 100644 include/uaenative.h create mode 100644 include/uni_common.h create mode 100644 uaenative.cpp diff --git a/cia.cpp b/cia.cpp index 3be2da65..948b55bf 100644 --- a/cia.cpp +++ b/cia.cpp @@ -76,7 +76,7 @@ static unsigned long ciaata_passed, ciaatb_passed, ciabta_passed, ciabtb_passed; 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; @@ -853,7 +853,7 @@ void CIAA_tod_inc (int cycles) 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; @@ -865,6 +865,12 @@ static void bfe001_change (void) 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) { @@ -1119,6 +1125,10 @@ static uae_u8 ReadCIAB (unsigned int addr) 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; @@ -1482,7 +1492,6 @@ void CIA_reset (void) kblostsynccnt = 0; serbits = 0; oldcd32mute = 1; - oldled = true; resetwarning_phase = resetwarning_timer = 0; heartbeat_cnt = 0; ciab_tod_event_state = 0; @@ -1506,6 +1515,7 @@ void CIA_reset (void) 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 */ diff --git a/custom.cpp b/custom.cpp index ffe097f0..b964025c 100644 --- a/custom.cpp +++ b/custom.cpp @@ -64,7 +64,7 @@ #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 @@ -389,7 +389,6 @@ static uae_u32 thisline_changed; static struct decision thisline_decision; static int fetch_cycle, fetch_modulo_cycle; -static int bitplane_dma_turned_on; enum plfstate { @@ -399,10 +398,17 @@ 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, @@ -492,6 +498,7 @@ void alloc_cycle_blitter (int hpos, uaecptr *ptr, int chnum) 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; @@ -918,9 +925,10 @@ static uae_u64 fetched_aga[MAX_PLANES]; /* 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. @@ -1009,6 +1017,17 @@ STATIC_INLINE int is_bitplane_dma_inline (int hpos) 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) { @@ -1035,6 +1054,14 @@ 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); @@ -1069,7 +1096,7 @@ static void setup_fmodes (int hpos) 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) { @@ -1343,7 +1370,7 @@ STATIC_INLINE void do_delays_3_ecs (int nbits) 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; @@ -1359,7 +1386,7 @@ STATIC_INLINE void do_delays_3_ecs (int nbits) 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; } @@ -1382,7 +1409,8 @@ STATIC_INLINE void do_delays_fast_3_ecs (int nbits) 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; } @@ -1404,7 +1432,7 @@ STATIC_INLINE void do_delays_3_aga (int nbits, int fm) 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; } @@ -1426,7 +1454,8 @@ STATIC_INLINE void do_delays_fast_3_aga (int nbits, int fm) 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; } @@ -1483,29 +1512,41 @@ STATIC_INLINE void do_delays_fast (int nbits, int fm) } } +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; @@ -1571,26 +1612,21 @@ static int flush_plane_data (int fm) 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); } @@ -1601,6 +1637,28 @@ STATIC_INLINE void flush_display (int fm) 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); @@ -1620,6 +1678,7 @@ STATIC_INLINE void update_denise (int hpos) } else { toscr_nr_planes2 = toscr_nr_planes; } + toscr_nr_planes_shifter = toscr_nr_planes2; } STATIC_INLINE void fetch_start (int hpos) @@ -1953,23 +2012,28 @@ static void do_long_fetch (int hpos, int nwords, int dma, int fm) #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 @@ -1981,7 +2045,7 @@ static void maybe_finish_last_fetch (int pos, int fm) 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 { @@ -2018,7 +2082,7 @@ static void maybe_finish_last_fetch (int pos, int fm) default: goto end; } - break; + break; } fetch_cycle++; toscr_nbits += toscr_res2p; @@ -2037,19 +2101,16 @@ static void maybe_finish_last_fetch (int pos, int fm) } 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; @@ -2059,18 +2120,20 @@ static void finish_final_fetch (void) 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; + } } } @@ -2187,6 +2250,17 @@ static void update_fetch_x (int until, int fm) 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; @@ -2197,13 +2271,7 @@ STATIC_INLINE void update_fetch (int until, int fm) 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; @@ -2239,7 +2307,7 @@ STATIC_INLINE void update_fetch (int until, int fm) } // 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) @@ -2379,11 +2447,18 @@ static void start_bpl_dma (int hpos, int hstart) #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) { @@ -2415,6 +2490,8 @@ static void start_bpl_dma (int hpos, int hstart) update_fetch_x (hstart, fetchmode); } + estimate_last_fetch_cycle (hstart); + last_fetch_hpos = hstart; @@ -2432,6 +2509,7 @@ static void start_bpl_dma (int hpos, int 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) { @@ -2449,12 +2527,13 @@ 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) { @@ -2484,34 +2563,58 @@ STATIC_INLINE void decide_line (int hpos) 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; + } } } } @@ -3299,12 +3402,12 @@ static void reset_decisions (void) 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) { @@ -3315,7 +3418,16 @@ static void reset_decisions (void) } 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. @@ -3346,17 +3458,6 @@ static void reset_decisions (void) #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) @@ -3726,7 +3827,7 @@ void init_hz (bool fullinit) 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) @@ -3754,7 +3855,7 @@ void init_hz (bool fullinit) 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; @@ -3894,7 +3995,7 @@ static uae_u32 REGPARAM2 timehack_helper (TrapContext *context) /* * register functions */ -STATIC_INLINE uae_u16 DENISEID (int *missing) +static uae_u16 DENISEID (int *missing) { *missing = 0; if (currprefs.cs_deniserev >= 0) @@ -4013,6 +4114,14 @@ static uae_u16 VPOSR (void) 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; @@ -4040,12 +4149,24 @@ static void VPOSW (uae_u16 v) 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; @@ -4055,6 +4176,10 @@ static void VHPOSW (uae_u16 v) } else if (vpos < minfirstline && oldvpos < minfirstline) { vpos = oldvpos; } +#if 0 + if (vpos < oldvpos) + vposback (oldvpos); +#endif } static uae_u16 VHPOSR (void) @@ -4281,10 +4406,16 @@ static void DMACON (int hpos, uae_u16 v) 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(); } @@ -4335,6 +4466,25 @@ STATIC_INLINE int use_eventmode (uae_u16 v) 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)); @@ -4353,15 +4503,24 @@ void send_interrupt (int num, int delay) } } +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) @@ -4372,7 +4531,7 @@ 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) @@ -4395,56 +4554,52 @@ void INTREQ_f (uae_u16 v) { 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) @@ -4601,6 +4756,8 @@ static void BPLCON0_Denise (int hpos, uae_u16 v, bool immediate) #endif if (thisline_decision.plfleft < 0) update_denise (hpos); + else + update_denise_shifter_planes (hpos); } static void BPLCON0 (int hpos, uae_u16 v) @@ -4748,7 +4905,7 @@ static void BPLxDAT (int hpos, int num, 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); } @@ -6925,6 +7082,7 @@ static void hsync_scandoubler (void) reset_decisions (); plf_state = plf_idle; + plfr_state = plfr_idle; // copy color changes dip1 = curr_drawinfo + next_lineno - 1; diff --git a/disk.cpp b/disk.cpp index 33972653..f3ef0660 100644 --- a/disk.cpp +++ b/disk.cpp @@ -932,13 +932,22 @@ static bool diskfile_iswriteprotect (struct uae_prefs *p, const TCHAR *fname, in 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); @@ -954,13 +963,6 @@ static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR 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; @@ -993,6 +995,12 @@ static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR 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; diff --git a/drawing.cpp b/drawing.cpp index 56ba5c1d..efe3a663 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -743,9 +743,6 @@ static int playfield_start, playfield_end; 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; @@ -1567,13 +1564,49 @@ static void pfield_do_linetoscr (int start, int stop, bool blank) } -// 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) @@ -2411,7 +2444,12 @@ static void pfield_draw_line (struct vidbuffer *vb, int lineno, int gfx_ypos, in } } - 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); @@ -2462,21 +2500,9 @@ static void pfield_draw_line (struct vidbuffer *vb, int lineno, int gfx_ypos, in #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 diff --git a/events.cpp b/events.cpp index 23e9a2e1..4563424c 100644 --- a/events.cpp +++ b/events.cpp @@ -40,8 +40,6 @@ void events_schedule (void) 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) @@ -83,12 +81,13 @@ void do_cycles_slow (unsigned long cycles_to_add) 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 (); diff --git a/expansion.cpp b/expansion.cpp index 5df8c53a..a0634b75 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -1238,7 +1238,7 @@ static void expamem_init_a2091 (void) static void expamem_init_a4091 (void) { #ifdef NCR - ncr_init (); + ncr_autoconfig_init (); #endif } static void expamem_init_gfxboard_memory (void) diff --git a/filesys.asm b/filesys.asm index fc68435e..f16b63be 100644 --- a/filesys.asm +++ b/filesys.asm @@ -163,6 +163,25 @@ filesys_init: 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 diff --git a/filesys.cpp b/filesys.cpp index 9af52a1b..b1ba2be0 100644 --- a/filesys.cpp +++ b/filesys.cpp @@ -45,6 +45,7 @@ #include "gayle.h" #include "savestate.h" #include "a2091.h" +#include "ncr_scsi.h" #include "cdtv.h" #include "sana2.h" #include "bsdsocket.h" @@ -55,6 +56,7 @@ #include "blkdev.h" #include "isofs_api.h" #include "scsi.h" +#include "uaenative.h" #ifdef RETROPLATFORM #include "rp.h" #endif @@ -828,15 +830,25 @@ static void initialize_mountinfo (void) 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 @@ -6289,6 +6301,9 @@ static uae_u32 REGPARAM2 filesys_diagentry (TrapContext *context) #ifdef BSDSOCKET resaddr = bsdlib_startup (resaddr); #endif +#ifdef WITH_UAENATIVE + resaddr = uaenative_startup (resaddr); +#endif #ifdef SCSIEMU resaddr = scsidev_startup (resaddr); #endif diff --git a/filesys_bootrom.cpp b/filesys_bootrom.cpp index 0119d3fe..50948e85 100644 --- a/filesys_bootrom.cpp +++ b/filesys_bootrom.cpp @@ -1,13 +1,13 @@ 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); @@ -22,17 +22,24 @@ 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); @@ -106,7 +113,7 @@ 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); @@ -300,7 +307,7 @@ 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); @@ -757,7 +764,7 @@ 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); diff --git a/gencpu.cpp b/gencpu.cpp index e262a64c..342dcdb6 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -508,6 +508,13 @@ static const char *gen_nextibyte (int flags) 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) @@ -2794,7 +2801,7 @@ static void gen_opcode (unsigned long int opcode) fill_prefetch_next (); } printf ("\tregs.sr %c= src;\n", curi->mnemo == i_EORSR ? '^' : '|'); - printf ("\tMakeFromSR ();\n"); + makefromsr (); break; case i_ANDSR: printf ("\tMakeSR ();\n"); @@ -2810,7 +2817,7 @@ static void gen_opcode (unsigned long int opcode) fill_prefetch_next (); } printf ("\tregs.sr &= src;\n"); - printf ("\tMakeFromSR ();\n"); + makefromsr (); break; case i_SUB: { @@ -3315,7 +3322,7 @@ static void gen_opcode (unsigned long int opcode) addcycles000 (6); printf ("\tregs.sr = src;\n"); } - printf ("\tMakeFromSR ();\n"); + makefromsr (); if (cpu_level <= 1) { // 68000 does 2xprefetch sync_m68k_pc (); @@ -3415,7 +3422,7 @@ static void gen_opcode (unsigned long int opcode) 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 @@ -3428,7 +3435,7 @@ static void gen_opcode (unsigned long int opcode) 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 (); @@ -3441,7 +3448,7 @@ static void gen_opcode (unsigned long int opcode) 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"); @@ -3458,7 +3465,8 @@ static void gen_opcode (unsigned long int opcode) 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); @@ -3500,9 +3508,12 @@ static void gen_opcode (unsigned long int opcode) 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); @@ -3620,7 +3631,7 @@ static void gen_opcode (unsigned long int opcode) 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"); @@ -3795,9 +3806,9 @@ static void gen_opcode (unsigned long int opcode) 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: @@ -4532,6 +4543,7 @@ static void gen_opcode (unsigned long int opcode) 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"); diff --git a/genlinetoscr.cpp b/genlinetoscr.cpp index ff08dc24..cad58008 100644 --- a/genlinetoscr.cpp +++ b/genlinetoscr.cpp @@ -118,24 +118,30 @@ static void out_linetoscr_decl (DEPTH_T bpp, HMODE_T hmode, int aga, int spr) { 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);"); @@ -171,6 +177,8 @@ static void out_linetoscr_do_dstpix (DEPTH_T bpp, HMODE_T hmode, int aga, CMODE_ 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;"); @@ -216,7 +224,7 @@ static void put_dpix (const char *var) 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) { @@ -325,8 +333,10 @@ static void out_linetoscr_mode (DEPTH_T bpp, HMODE_T hmode, int aga, int spr, CM 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 ( ""); @@ -334,7 +344,10 @@ static void out_linetoscr_mode (DEPTH_T bpp, HMODE_T hmode, int aga, int spr, CM 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); @@ -353,14 +366,14 @@ static void out_linetoscr_mode (DEPTH_T bpp, HMODE_T hmode, int aga, int spr, CM 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"); @@ -372,7 +385,7 @@ static void out_linetoscr_mode (DEPTH_T bpp, HMODE_T hmode, int aga, int spr, CM 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;"); @@ -381,7 +394,7 @@ static void out_linetoscr_mode (DEPTH_T bpp, HMODE_T hmode, int aga, int spr, CM } } 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"); @@ -392,14 +405,14 @@ static void out_linetoscr_mode (DEPTH_T bpp, HMODE_T hmode, int aga, int spr, CM } 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"); } @@ -438,18 +451,23 @@ static void out_linetoscr (DEPTH_T bpp, HMODE_T hmode, int aga, int spr) 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;"); @@ -479,7 +497,7 @@ int main (int argc, char *argv[]) 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 (" */"); @@ -489,7 +507,9 @@ int main (int argc, char *argv[]) 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); } diff --git a/gfxboard.cpp b/gfxboard.cpp index 1c88e645..b0a65a71 100644 --- a/gfxboard.cpp +++ b/gfxboard.cpp @@ -11,9 +11,9 @@ #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; @@ -102,6 +102,9 @@ struct gfxboard #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[] = { { diff --git a/include/a2091.h b/include/a2091.h index bfc1b9d4..a060ff68 100644 --- a/include/a2091.h +++ b/include/a2091.h @@ -1,3 +1,7 @@ + +#ifndef A2091_H +#define A2091_H + #ifdef A2091 extern addrbank dmaca2091_bank; @@ -35,3 +39,5 @@ extern int add_scsi_cd (int ch, int unitnum); extern int add_scsi_tape (int ch, const TCHAR *tape_directory, bool readonly); #endif + +#endif /* A2091H */ diff --git a/include/blkdev.h b/include/blkdev.h index 9e4f6a17..dc902a29 100644 --- a/include/blkdev.h +++ b/include/blkdev.h @@ -1,4 +1,7 @@ +#ifndef BLKDEV_H +#define BLKDEV_H + #define DEVICE_SCSI_BUFSIZE (65536 - 1024) #define SCSI_UNIT_DISABLED -1 @@ -210,3 +213,5 @@ extern void blkdev_entergui (void); extern void blkdev_exitgui (void); bool filesys_do_disk_change (int, bool); + +#endif /* BLKDEV_H */ diff --git a/include/custom.h b/include/custom.h index 9dedd0a4..660fba93 100644 --- a/include/custom.h +++ b/include/custom.h @@ -6,6 +6,9 @@ * (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. @@ -85,7 +88,7 @@ extern unsigned int joy0dir, joy1dir; 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); @@ -231,3 +234,5 @@ extern bool ispal (void); extern int current_maxvpos (void); extern struct chipset_refresh *get_chipset_refresh (void); extern void compute_framesync (void); + +#endif /* CUSTOM_H */ diff --git a/include/events.h b/include/events.h index 733f2150..78d48393 100644 --- a/include/events.h +++ b/include/events.h @@ -110,9 +110,20 @@ STATIC_INLINE void set_cycles (unsigned long int x) #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) diff --git a/include/filesys.h b/include/filesys.h index e77c41f7..bdf625c9 100644 --- a/include/filesys.h +++ b/include/filesys.h @@ -6,6 +6,9 @@ * Copyright 1997 Bernd Schmidt */ +#ifndef FILESYS_H +#define FILESYS_H + struct hardfilehandle; #define MAX_HDF_CACHE_BLOCKS 128 @@ -146,3 +149,4 @@ extern void getchsgeometry (uae_u64 size, int *pcyl, int *phead, int *psectorspe 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 */ diff --git a/include/memory.h b/include/memory.h index 82e58b00..bc997fa9 100644 --- a/include/memory.h +++ b/include/memory.h @@ -6,6 +6,9 @@ * Copyright 1995 Bernd Schmidt */ +#ifndef MEMORY_H +#define MEMORY_H + extern void memory_reset (void); extern void a1000_reset (void); @@ -440,3 +443,5 @@ extern void memcpyah (uae_u8 *dst, uaecptr src, int size); extern uae_s32 getz2size (struct uae_prefs *p); extern ULONG getz2endaddr (void); + +#endif /* MEMORY_H */ diff --git a/include/options.h b/include/options.h index 7d03b364..df515546 100644 --- a/include/options.h +++ b/include/options.h @@ -7,6 +7,9 @@ * Copyright 1995-2001 Bernd Schmidt */ +#ifndef OPTIONS_H +#define OPTIONS_H + #define UAEMAJOR 2 #define UAEMINOR 7 #define UAESUBREV 1 @@ -30,7 +33,7 @@ struct strlist { #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 */ @@ -664,3 +667,5 @@ extern struct uae_prefs currprefs, changed_prefs; extern int machdep_init (void); extern void machdep_free (void); + +#endif /* OPTIONS_H */ diff --git a/include/scsi.h b/include/scsi.h index d359f09d..c3f0ebdd 100644 --- a/include/scsi.h +++ b/include/scsi.h @@ -108,4 +108,4 @@ extern void tape_media_change (int unitnum, struct uaedev_config_info*); #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 diff --git a/include/uaenative.h b/include/uaenative.h new file mode 100644 index 00000000..b06af08f --- /dev/null +++ b/include/uaenative.h @@ -0,0 +1,49 @@ +/* +* 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_ diff --git a/include/uni_common.h b/include/uni_common.h new file mode 100644 index 00000000..47487ad2 --- /dev/null +++ b/include/uni_common.h @@ -0,0 +1,80 @@ +/* +* 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_ diff --git a/main.cpp b/main.cpp index 7189e864..e73b5cc9 100644 --- a/main.cpp +++ b/main.cpp @@ -56,6 +56,7 @@ #include "gayle.h" #include "gfxboard.h" #include "luascript.h" +#include "uaenative.h" #ifdef RETROPLATFORM #include "rp.h" #endif @@ -1004,6 +1005,9 @@ void virtualdevice_init (void) #if defined (BSDSOCKET) bsdlib_install (); #endif +#ifdef WITH_UAENATIVE + uaenative_install (); +#endif } static int real_main2 (int argc, TCHAR **argv) diff --git a/memory.cpp b/memory.cpp index 4147f808..bae8ff25 100644 --- a/memory.cpp +++ b/memory.cpp @@ -1266,27 +1266,27 @@ static int patch_residents (uae_u8 *kickmemory, int size) // "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++; } } } diff --git a/od-win32/dinput.cpp b/od-win32/dinput.cpp index 874c0696..8a7dc5a3 100644 --- a/od-win32/dinput.cpp +++ b/od-win32/dinput.cpp @@ -986,7 +986,7 @@ static void sortobjects (struct didata *did) #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; @@ -1392,11 +1392,11 @@ static void dumphidbuttoncaps (PHIDP_BUTTON_CAPS pcaps, int size) } } -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); @@ -1500,7 +1500,7 @@ static bool initialize_rawinput (void) 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; @@ -1533,28 +1533,44 @@ static bool initialize_rawinput (void) } 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++; @@ -1562,8 +1578,10 @@ static bool initialize_rawinput (void) } 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++; @@ -1571,16 +1589,26 @@ static bool initialize_rawinput (void) } 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++; @@ -1675,7 +1703,7 @@ static bool initialize_rawinput (void) 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); @@ -3164,6 +3192,14 @@ static void release_keys (void) 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) { @@ -3172,6 +3208,7 @@ 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); @@ -3189,7 +3226,8 @@ static int acquire_kb (int num, int flags) originalleds = oldleds; //write_log (_T("stored %08x -> %08x\n"), originalleds, newleds); } - update_leds (); + set_leds (newleds); + flushmsgpump (); } return 1; } @@ -3219,10 +3257,12 @@ static void unacquire_kb (int num) 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); diff --git a/od-win32/hardfile_win32.cpp b/od-win32/hardfile_win32.cpp index abd531ad..961e2083 100644 --- a/od-win32/hardfile_win32.cpp +++ b/od-win32/hardfile_win32.cpp @@ -75,9 +75,24 @@ struct uae_driveinfo { * - 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 || @@ -624,6 +639,7 @@ int hdf_open_target (struct hardfiledata *hfd, const TCHAR *pname) 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); @@ -672,6 +688,7 @@ int hdf_open_target (struct hardfiledata *hfd, const TCHAR *pname) } hfd->handle_valid = HDF_HANDLE_WIN32; hfd->emptyname = my_strdup (name); + //fixdrive (hfd); } else { hfd->flags = HFD_FLAGS_REALDRIVE; hfd->drive_empty = -1; diff --git a/od-win32/sysconfig.h b/od-win32/sysconfig.h index 7a01da22..de038003 100644 --- a/od-win32/sysconfig.h +++ b/od-win32/sysconfig.h @@ -16,6 +16,7 @@ #define __i386__ #define WINDOWS #define ZLIB_WINAPI +#define PACKAGE_STRING "WinUAE" #ifndef UAE_MINI @@ -77,6 +78,7 @@ #define RETROPLATFORM /* Cloanto RetroPlayer support */ #define WITH_CHD #define WITH_LUA /* lua scripting */ +#define WITH_UAENATIVE #else diff --git a/od-win32/win32.cpp b/od-win32/win32.cpp index 45b91d92..c7ead3be 100644 --- a/od-win32/win32.cpp +++ b/od-win32/win32.cpp @@ -6210,6 +6210,40 @@ void fpux_restore (int *v) #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); diff --git a/od-win32/win32.h b/od-win32/win32.h index bcd8f033..4f4bbad6 100644 --- a/od-win32/win32.h +++ b/od-win32/win32.h @@ -19,11 +19,11 @@ #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") diff --git a/od-win32/winuae_msvc11/winuae_msvc.sln b/od-win32/winuae_msvc11/winuae_msvc.sln index d22f82c8..9e4cb803 100644 --- a/od-win32/winuae_msvc11/winuae_msvc.sln +++ b/od-win32/winuae_msvc11/winuae_msvc.sln @@ -1,6 +1,6 @@ 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 @@ -397,7 +397,6 @@ Global {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 diff --git a/od-win32/winuae_msvc11/winuae_msvc.vcxproj b/od-win32/winuae_msvc11/winuae_msvc.vcxproj index 4fe2386b..b0e677f9 100644 --- a/od-win32/winuae_msvc11/winuae_msvc.vcxproj +++ b/od-win32/winuae_msvc11/winuae_msvc.vcxproj @@ -204,7 +204,7 @@ Level3 true EditAndContinue - StdCall + FastCall Default 4996;%(DisableSpecificWarnings) false @@ -224,7 +224,7 @@ $(OutDir)$(TargetName)$(TargetExt) true LIBCMT;%(IgnoreSpecificDefaultLibraries) - 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) + 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) true .\Debug/winuae.pdb Windows @@ -799,6 +799,7 @@ + @@ -822,6 +823,7 @@ + diff --git a/od-win32/winuae_msvc11/winuae_msvc.vcxproj.filters b/od-win32/winuae_msvc11/winuae_msvc.vcxproj.filters index 1cf15a3b..c97d11ed 100644 --- a/od-win32/winuae_msvc11/winuae_msvc.vcxproj.filters +++ b/od-win32/winuae_msvc11/winuae_msvc.vcxproj.filters @@ -628,6 +628,12 @@ common + + common + + + qemu + diff --git a/od-win32/winuaechangelog.txt b/od-win32/winuaechangelog.txt index 1cc917a3..ac5217d7 100644 --- a/od-win32/winuaechangelog.txt +++ b/od-win32/winuaechangelog.txt @@ -1,6 +1,66 @@ +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. diff --git a/od-win32/writelog.cpp b/od-win32/writelog.cpp index 10991a55..a10e7bbc 100644 --- a/od-win32/writelog.cpp +++ b/od-win32/writelog.cpp @@ -417,7 +417,7 @@ static TCHAR *writets (void) _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; } @@ -498,6 +498,9 @@ void write_log (const TCHAR *format, ...) premsg (); + if (!_tcsicmp (format, _T("*"))) + count = 0; + EnterCriticalSection (&cs); va_start (parms, format); bufp = buffer; diff --git a/qemuvga/qemumemory.h b/qemuvga/qemumemory.h index 1ddfb673..0c30a8e2 100644 --- a/qemuvga/qemumemory.h +++ b/qemuvga/qemumemory.h @@ -11,8 +11,8 @@ * */ -#ifndef MEMORY_H -#define MEMORY_H +#ifndef QMEMORY_H +#define QMEMORY_H #ifndef CONFIG_USER_ONLY @@ -899,4 +899,5 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, #endif -#endif +#endif /* QMEMORY */ + diff --git a/uaenative.cpp b/uaenative.cpp new file mode 100644 index 00000000..efeda726 --- /dev/null +++ b/uaenative.cpp @@ -0,0 +1,851 @@ +/* +* 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 +#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 +#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 diff --git a/zfile.cpp b/zfile.cpp index 45c1ed94..52a50738 100644 --- a/zfile.cpp +++ b/zfile.cpp @@ -1023,7 +1023,7 @@ static struct zfile *dsq (struct zfile *z, int lzx, int *retcode) 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; @@ -1034,7 +1034,7 @@ static struct zfile *dsq (struct zfile *z, int lzx, int *retcode) uae_u8 *nullsector; nullsector = xcalloc (uae_u8, blocksize); - sectors /= heads; + sectors /= 2; if (buf[3] == 0x13) { off = 52; if (buf[off - 1] == 1) { @@ -1047,7 +1047,8 @@ static struct zfile *dsq (struct zfile *z, int lzx, int *retcode) 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))) { -- 2.47.3