dummy_lgeti, dummy_wgeti, ABFLAG_IO
};
+static const uae_u8 patchdata[]={0x0c,0x82,0x00,0x00,0x03,0xe8,0x64,0x00,0x00,0x46};
+static void patchrom (void)
+{
+ int i;
+ if (currprefs.cpu_model > 68020 || currprefs.cachesize || currprefs.m68k_speed != 0) {
+ uae_u8 *p = (uae_u8*)extendedkickmemory;
+ for (i = 0; i < 524288 - sizeof (patchdata); i++) {
+ if (!memcmp (p + i, patchdata, sizeof(patchdata))) {
+ protect_roms (false);
+ p[i + 6] = 0x4e;
+ p[i + 7] = 0x71;
+ p[i + 8] = 0x4e;
+ p[i + 9] = 0x71;
+ protect_roms (true);
+ write_log (_T("extended rom delay loop patched at 0x%p\n"), i + 6 + 0xe00000);
+ return;
+ }
+ }
+ write_log (_T("couldn't patch extended rom\n"));
+ }
+}
+
static void akiko_cdrom_free (void)
{
sys_cddev_close ();
akiko_inited = false;
}
-
void akiko_free (void)
{
akiko_reset ();
cdrom_playing = cdrom_paused = 0;
cdrom_data_offset = -1;
}
+ patchrom ();
if (!akiko_thread_running) {
akiko_thread_running = 1;
init_comm_pipe (&requests, 100, 1);
}
if (warned && waited) {
warned--;
- write_log (_T("waiting_blits detected\n"));
+ write_log (_T("waiting_blits detected PC=%08x\n"), M68K_GETPC);
}
if (bltstate == BLT_done)
return true;
#define HARD_DDF_LIMITS_DISABLED ((beamcon0 & 0x80) || (bplcon0 & 0x40))
/* The HRM says 0xD8, but that can't work... */
-#define HARD_DDF_STOP (HARD_DDF_LIMITS_DISABLED ? 0xff : 0xd4)
+#define HARD_DDF_STOP (HARD_DDF_LIMITS_DISABLED ? 0xff : 0xd6)
#define HARD_DDF_START_REAL 0x18
/* Programmed rates or superhires (!) disable normal DMA limits */
#define HARD_DDF_START (HARD_DDF_LIMITS_DISABLED ? 0x04 : 0x18)
+static void add_modulo (int nr)
+{
+ int mod;
+ if (fmode & 0x4000) {
+ if (((diwstrt >> 8) ^ vpos) & 1)
+ mod = bpl2mod;
+ else
+ mod = bpl1mod;
+ } else if (nr & 1)
+ mod = bpl2mod;
+ else
+ mod = bpl1mod;
+ bplpt[nr] += mod;
+ bplptx[nr] += mod;
+}
+
static void add_modulos (void)
{
int m1, m2;
shift = (nr & 1) ? toscr_delay2 : toscr_delay1;
if (shift < 8)
return;
- fetched[nr] >>= 7;
+ fetched[nr] >>= 6;
}
#endif
}
if (plf_state == plf_passed_stop2 && fetch_cycle >= (fetch_cycle & ~fetchunit_mask) + fetch_modulo_cycle) {
- int mod;
- if (fmode & 0x4000) {
- if (((diwstrt >> 8) ^ vpos) & 1)
- mod = bpl2mod;
- else
- mod = bpl1mod;
- } else if (nr & 1)
- mod = bpl2mod;
- else
- mod = bpl1mod;
- bplpt[nr] += mod;
- bplptx[nr] += mod;
+ add_modulo (nr);
if ((currprefs.cs_hacks & 2) || 0)
do_right_ddf_hack (nr, hpos);
#endif
-/* make sure fetch that goes beyond maxhpos is finished */
-static void finish_final_fetch (void)
-{
- if (plf_state != plf_end)
- return;
- plf_state = plf_finished;
- finish_playfield_line ();
-}
-
static void finish_last_fetch (int pos, int fm)
{
if (thisline_decision.plfleft < 0)
fetch_state = fetch_not_started;
}
}
+/* check special case where last fetch wraps to next line
+ * this makes totally corrupted and flickering display on
+ * real hardware due to refresh cycle conflicts
+ */
+static void maybe_finish_last_fetch (int pos, int fm)
+{
+ static int warned = 20;
+ bool done = false;
+
+ if (plf_state != plf_passed_stop2 || fetch_state != fetch_started || !dmaen (DMA_BITPLANE)) {
+ finish_last_fetch (pos, fm);
+ return;
+ }
+ do {
+ int cycle_start = fetch_cycle & fetchstart_mask;
+ switch (fm_maxplane) {
+ case 8:
+ switch (cycle_start) {
+ case 0: fetch (7, fm, pos); break;
+ case 1: fetch (3, fm, pos); break;
+ case 2: fetch (5, fm, pos); break;
+ case 3: fetch (1, fm, pos); break;
+ case 4: fetch (6, fm, pos); break;
+ case 5: fetch (2, fm, pos); break;
+ case 6: fetch (4, fm, pos); break;
+ case 7: fetch (0, fm, pos); break;
+ default:
+ goto end;
+ }
+ break;
+ case 4:
+ switch (cycle_start) {
+ case 0: fetch (3, fm, pos); break;
+ case 1: fetch (1, fm, pos); break;
+ case 2: fetch (2, fm, pos); break;
+ case 3: fetch (0, fm, pos); break;
+ default:
+ goto end;
+ }
+ break;
+ case 2:
+ switch (cycle_start) {
+ case 0: fetch (1, fm, pos); break;
+ case 1: fetch (0, fm, pos); break;
+ default:
+ goto end;
+ }
+ break;
+ }
+ fetch_cycle++;
+ toscr_nbits += 2 << toscr_res;
+
+ if (toscr_nbits > 16)
+ toscr_nbits = 0;
+ if (toscr_nbits == 16)
+ flush_display (fm);
+ done = true;
+ } while ((fetch_cycle & fetchunit_mask) != 0);
+
+ if (done && warned > 0) {
+ warned--;
+ write_log (_T("WARNING: bitplane DMA crossing scanlines!\n"));
+ }
+
+end:
+ finish_last_fetch (pos, fm);
+}
+
+
+/* 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;
+ finish_playfield_line ();
+}
STATIC_INLINE int one_fetch_cycle_0 (int pos, int ddfstop_to_test, int dma, int fm)
{
}
if (until >= maxhpos) {
- finish_last_fetch (pos, fm);
+ maybe_finish_last_fetch (pos, fm);
return;
}
for (; ; pos++) {
if (pos == until) {
if (until >= maxhpos) {
- finish_last_fetch (pos, fm);
+ maybe_finish_last_fetch (pos, fm);
return;
}
flush_display (fm);
return;
}
if (until >= maxhpos) {
- finish_last_fetch (pos, fm);
+ maybe_finish_last_fetch (pos, fm);
return;
}
flush_display (fm);
}
return v;
}
+uae_u32 get_iword_debug (uaecptr addr)
+{
+ if (debug_mmu_mode) {
+ return get_word_debug (addr);
+ } else {
+ if (valid_address (addr, 2))
+ return get_word (addr);
+ return 0xffff;
+ }
+}
+uae_u32 get_ilong_debug (uaecptr addr)
+{
+ if (debug_mmu_mode) {
+ return get_long_debug (addr);
+ } else {
+ if (valid_address (addr, 4))
+ return get_long (addr);
+ return 0xffffffff;
+ }
+}
int safe_addr (uaecptr addr, int size)
{
linetoscr_diw_start = dp_for_drawing->diwfirstword;
linetoscr_diw_end = dp_for_drawing->diwlastword;
- res_shift = lores_shift - bplres;
-
/* Perverse cases happen. */
if (linetoscr_diw_end < linetoscr_diw_start)
linetoscr_diw_end = linetoscr_diw_start;
+ res_shift = lores_shift - bplres;
+
playfield_start = linetoscr_diw_start;
playfield_end = linetoscr_diw_end;
if (playfield_end > visible_right_border)
playfield_end = visible_right_border;
-#if 0
- real_playfield_end = playfield_end;
- real_playfield_start = playfield_start;
-#endif
-
// Sprite hpos don't include DIW_DDF_OFFSET and can appear 1 lores pixel
// before first bitplane pixel appears.
// This means "bordersprite" condition is possible under OCS/ECS too. Argh!
playfield_end = linetoscr_diw_end;
}
int end = coord_hw_to_window_x (dp_for_drawing->plfleft * 2);
+ if (end < visible_left_border)
+ end = visible_left_border;
if (end < playfield_start && end > linetoscr_diw_start) {
playfield_start = end;
- ;//can_have_bordersprite = true;
- } else {
- ;//can_have_bordersprite = false;
}
- } else {
- ;//can_have_bordersprite = dp_for_drawing->bordersprite_seen;
}
#ifdef AGA
uae_u32 get_byte_debug (uaecptr addr);
uae_u32 get_word_debug (uaecptr addr);
uae_u32 get_long_debug (uaecptr addr);
+uae_u32 get_ilong_debug (uaecptr addr);
+uae_u32 get_iword_debug (uaecptr addr);
enum debugtest_item { DEBUGTEST_BLITTER, DEBUGTEST_KEYBOARD, DEBUGTEST_FLOPPY, DEBUGTEST_MAX };
static struct uae_input_device *keyboards;
static struct uae_input_device *internalevents;
static struct uae_input_device_kbr_default *keyboard_default, **keyboard_default_table;
+static int default_keyboard_layout[MAX_JPORTS];
#define KBR_DEFAULT_MAP_FIRST 0
#define KBR_DEFAULT_MAP_LAST 5
p->jports[portnum].id = start;
if (mode >= 0)
p->jports[portnum].mode = mode;
+ if (start < JSEM_JOYS)
+ default_keyboard_layout[portnum] = start;
+ config_changed = 1;
+ return 1;
+ }
+ // joystick not found, select default
+ if (start == JSEM_JOYS && p->jports[portnum].id < JSEM_JOYS) {
+ p->jports[portnum].id = default_keyboard_layout[portnum];
config_changed = 1;
return 1;
}
case Ad16:
{
TCHAR offtxt[80];
- disp16 = get_word_debug (pc); pc += 2;
+ disp16 = get_iword_debug (pc); pc += 2;
if (disp16 < 0)
_stprintf (offtxt, _T("-$%04x"), -disp16);
else
}
break;
case Ad8r:
- dp = get_word_debug (pc); pc += 2;
+ dp = get_iword_debug (pc); pc += 2;
disp8 = dp & 0xFF;
r = (dp & 0x7000) >> 12;
dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
_stprintf (name, _T("A%d, "), reg);
if (dp & 0x80) { base = 0; name[0] = 0; }
if (dp & 0x40) dispreg = 0;
- if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_word_debug (pc); pc += 2; }
- if ((dp & 0x30) == 0x30) { disp = get_long_debug (pc); pc += 4; }
+ if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
+ if ((dp & 0x30) == 0x30) { disp = get_ilong_debug (pc); pc += 4; }
base += disp;
- if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_word_debug (pc); pc += 2; }
- if ((dp & 0x3) == 0x3) { outer = get_long_debug (pc); pc += 4; }
+ if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
+ if ((dp & 0x3) == 0x3) { outer = get_ilong_debug (pc); pc += 4; }
if (!(dp & 4)) base += dispreg;
- if ((dp & 3) && !safemode) base = get_long_debug (base);
+ if ((dp & 3) && !safemode) base = get_ilong_debug (base);
if (dp & 4) base += dispreg;
addr = base + outer;
}
break;
case PC16:
- disp16 = get_word_debug (pc); pc += 2;
+ disp16 = get_iword_debug (pc); pc += 2;
addr += (uae_s16)disp16;
_stprintf (buffer, _T("(PC,$%04x) == $%08lx"), disp16 & 0xffff, (unsigned long)addr);
break;
case PC8r:
- dp = get_word_debug (pc); pc += 2;
+ dp = get_iword_debug (pc); pc += 2;
disp8 = dp & 0xFF;
r = (dp & 0x7000) >> 12;
dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
_stprintf (name, _T("PC, "));
if (dp & 0x80) { base = 0; name[0] = 0; }
if (dp & 0x40) dispreg = 0;
- if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_word_debug (pc); pc += 2; }
- if ((dp & 0x30) == 0x30) { disp = get_long_debug (pc); pc += 4; }
+ if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
+ if ((dp & 0x30) == 0x30) { disp = get_ilong_debug (pc); pc += 4; }
base += disp;
- if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_word_debug (pc); pc += 2; }
- if ((dp & 0x3) == 0x3) { outer = get_long_debug (pc); pc += 4; }
+ if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
+ if ((dp & 0x3) == 0x3) { outer = get_ilong_debug (pc); pc += 4; }
if (!(dp & 4)) base += dispreg;
- if ((dp & 3) && !safemode) base = get_long_debug (base);
+ if ((dp & 3) && !safemode) base = get_ilong_debug (base);
if (dp & 4) base += dispreg;
addr = base + outer;
}
break;
case absw:
- addr = (uae_s32)(uae_s16)get_word_debug (pc);
+ addr = (uae_s32)(uae_s16)get_iword_debug (pc);
_stprintf (buffer, _T("$%08lx"), (unsigned long)addr);
pc += 2;
break;
case absl:
- addr = get_long_debug (pc);
+ addr = get_ilong_debug (pc);
_stprintf (buffer, _T("$%08lx"), (unsigned long)addr);
pc += 4;
break;
case imm:
switch (size){
case sz_byte:
- _stprintf (buffer, _T("#$%02x"), (unsigned int)(get_word_debug (pc) & 0xff));
+ _stprintf (buffer, _T("#$%02x"), (unsigned int)(get_iword_debug (pc) & 0xff));
pc += 2;
break;
case sz_word:
- _stprintf (buffer, _T("#$%04x"), (unsigned int)(get_word_debug (pc) & 0xffff));
+ _stprintf (buffer, _T("#$%04x"), (unsigned int)(get_iword_debug (pc) & 0xffff));
pc += 2;
break;
case sz_long:
- _stprintf (buffer, _T("#$%08lx"), (unsigned long)(get_long_debug (pc)));
+ _stprintf (buffer, _T("#$%08lx"), (unsigned long)(get_ilong_debug (pc)));
pc += 4;
break;
default:
}
break;
case imm0:
- offset = (uae_s32)(uae_s8)get_word_debug (pc);
+ offset = (uae_s32)(uae_s8)get_iword_debug (pc);
_stprintf (buffer, _T("#$%02x"), (unsigned int)(offset & 0xff));
addr = pc + 2 + offset;
pc += 2;
break;
case imm1:
- offset = (uae_s32)(uae_s16)get_word_debug (pc);
+ offset = (uae_s32)(uae_s16)get_iword_debug (pc);
buffer[0] = 0;
_stprintf (buffer, _T("#$%04x"), (unsigned int)(offset & 0xffff));
addr = pc + offset;
pc += 2;
break;
case imm2:
- offset = (uae_s32)get_long_debug (pc);
+ offset = (uae_s32)get_ilong_debug (pc);
_stprintf (buffer, _T("#$%08lx"), (unsigned long)offset);
addr = pc + offset;
pc += 4;
struct instr *dp;
uaecptr pc, oldpc;
- oldpc = pc = m68k_getpc ();
+ pc = oldpc = addr;
opcode = get_word_debug (pc);
if (cpufunctbl[opcode] == op_illg_1) {
opcode = 0x4AFC;
}
if (dp->suse) {
- pc += ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0);
+ pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0);
}
if (dp->suse && dp->duse)
_tcscat (instrname, _T(","));
if (dp->duse) {
- pc += ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0);
+ pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0);
}
-
if (instrcode)
{
int i;
for (i = 0; i < (pc - oldpc) / 2; i++)
{
- _stprintf (instrcode, _T("%04x "), get_iword_1 (oldpc + i * 2));
+ _stprintf (instrcode, _T("%04x "), get_iword_debug (oldpc + i * 2));
instrcode += _tcslen (instrcode);
}
}
-
if (nextpc)
*nextpc = pc;
}
if (!hfd->handle->firstwrite && (hfd->flags & HFD_FLAGS_REALDRIVE)) {
hfd->handle->firstwrite = true;
if (ismounted (hfd->device_name, hfd->handle->h)) {
- gui_message (_T("\"%s\"\n\nBlock zero write attempt but drive has one or more mounted PC partitions. Erase the drive or unmount all PC partitions first."), name);
+ gui_message (_T("\"%s\"\n\nBlock zero write attempt but drive has one or more mounted PC partitions or WinUAE does not have Administrator privileges. Erase the drive or unmount all PC partitions first."), name);
hfd->ci.readonly = true;
return 0;
}
hdf_seek (hfd, offset);
ReadFile (hfd->handle->h, tmp, tmplen, &outlen2, NULL);
if (memcmp (hfd->cache, tmp, tmplen) != 0 || outlen != len)
- gui_message (_T("\"%s\"\n\nblock zero write failed!"), name);
+ gui_message (_T("\"%s\"\n\nblock zero write failed! Make sure WinUAE has Windows Administrator privileges."), name);
VirtualFree (tmp, 0, MEM_RELEASE);
}
}
return 0;
}
+STATIC_INLINE bool validatecoords2 (struct RenderInfo *ri, uae_u32 X, uae_u32 Y, uae_u32 Width, uae_u32 Height)
+{
+ if (Width >= 32768)
+ return false;
+ if (Height >= 32768)
+ return false;
+ if (X >= 32768)
+ return false;
+ if (Y >= 32768)
+ return false;
+ if (!Width || !Height)
+ return true;
+ if (ri) {
+ int bpp = GetBytesPerPixel (ri->RGBFormat);
+ if (Width * bpp > ri->BytesPerRow)
+ return false;
+ if (!valid_address (ri->AMemory, (Height - 1) * ri->BytesPerRow + (Width - 1) * bpp))
+ return false;
+ }
+ return true;
+}
+static bool validatecoords (struct RenderInfo *ri, uae_u32 X, uae_u32 Y, uae_u32 Width, uae_u32 Height)
+{
+ if (validatecoords2 (ri, X, Y, Width, Height))
+ return true;
+ write_log (_T("RTG invalid region: %08X:%d:%d (%dx%d)-(%dx%d)\n"), ri->AMemory, ri->BytesPerRow, ri->RGBFormat, X, Y, Width, Height);
+ return false;
+}
+
/*
* Amiga <-> native structure conversion functions
*/
static int CopyRenderInfoStructureA2U (uaecptr amigamemptr, struct RenderInfo *ri)
{
- uaecptr memp = get_long (amigamemptr + PSSO_RenderInfo_Memory);
-
- if (valid_address (memp, PSSO_RenderInfo_sizeof)) {
+ if (valid_address (amigamemptr, PSSO_RenderInfo_sizeof)) {
+ uaecptr memp = get_long (amigamemptr + PSSO_RenderInfo_Memory);
+ ri->AMemory = memp;
ri->Memory = get_real_address (memp);
ri->BytesPerRow = get_word (amigamemptr + PSSO_RenderInfo_BytesPerRow);
ri->RGBFormat = (RGBFTYPE)get_long (amigamemptr + PSSO_RenderInfo_RGBFormat);
- return 1;
+ // Can't really validate this better at this point, no height.
+ if (valid_address (memp, ri->BytesPerRow))
+ return 1;
}
write_log (_T("ERROR - Invalid RenderInfo memory area...\n"));
return 0;
static int CopyPatternStructureA2U (uaecptr amigamemptr, struct Pattern *pattern)
{
- uaecptr memp = get_long (amigamemptr + PSSO_Pattern_Memory);
- if (valid_address (memp, PSSO_Pattern_sizeof)) {
+ if (valid_address (amigamemptr, PSSO_Pattern_sizeof)) {
+ uaecptr memp = get_long (amigamemptr + PSSO_Pattern_Memory);
pattern->Memory = get_real_address (memp);
pattern->XOffset = get_word (amigamemptr + PSSO_Pattern_XOffset);
pattern->YOffset = get_word (amigamemptr + PSSO_Pattern_YOffset);
pattern->BgPen = get_long (amigamemptr + PSSO_Pattern_BgPen);
pattern->Size = get_byte (amigamemptr + PSSO_Pattern_Size);
pattern->DrawMode = get_byte (amigamemptr + PSSO_Pattern_DrawMode);
- return 1;
+ if (valid_address (memp, 2))
+ return 1;
}
write_log (_T("ERROR - Invalid Pattern memory area...\n"));
return 0;
if (NOBLITTER)
return 0;
+
if (CopyRenderInfoStructureA2U (renderinfo, &ri)) {
P96TRACE((_T("InvertRect %dbpp 0x%lx\n"), Bpp, (long)mask));
+ if (!validatecoords (&ri, X, Y, Width, Height))
+ return 1;
+
if (mask != 0xFF && Bpp > 1)
mask = 0xFF;
if (NOBLITTER)
return 0;
- if (CopyRenderInfoStructureA2U (renderinfo, &ri) && Y != 0xFFFF) {
+ if (CopyRenderInfoStructureA2U (renderinfo, &ri)) {
+ if (!validatecoords (&ri, X, Y, Width, Height))
+ return 1;
+
Bpp = GetBytesPerPixel (RGBFormat);
P96TRACE((_T("FillRect(%d, %d, %d, %d) Pen 0x%x BPP %d BPR %d Mask 0x%x\n"),
uae_u8 mask = blitrectdata.mask;
BLIT_OPCODE opcode = blitrectdata.opcode;
+ if (!validatecoords (ri, srcx, srcy, width, height))
+ return 1;
+ if (!validatecoords (dstri, dstx, dsty, width, height))
+ return 1;
+
uae_u8 Bpp = GetBytesPerPixel (ri->RGBFormat);
if (opcode == BLIT_DST) {
if (NOBLITTER_BLIT)
return 0;
-
P96TRACE((_T("BlitRectNoMaskComplete() op 0x%02x, %08x:(%4d,%4d) --> %08x:(%4d,%4d), wh(%4d,%4d)\n"),
OpCode, get_long (srcri + PSSO_RenderInfo_Memory), srcx, srcy, get_long (dstri + PSSO_RenderInfo_Memory), dstx, dsty, width, height));
result = BlitRect (srcri, dstri, srcx, srcy, dstx, dsty, width, height, 0xFF, OpCode);
if (NOBLITTER)
return 0;
-
if(CopyRenderInfoStructureA2U (rinf, &ri) && CopyPatternStructureA2U (pinf, &pattern)) {
+ if (!validatecoords (&ri, X, Y, W, H))
+ return 1;
+
Bpp = GetBytesPerPixel(ri.RGBFormat);
uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp; /* offset with address */
if (NOBLITTER)
return 0;
-
if (CopyRenderInfoStructureA2U (rinf, &ri) && CopyTemplateStructureA2U (tmpl, &tmp)) {
+ if (!validatecoords (&ri, X, Y, W, H))
+ return 1;
+
Bpp = GetBytesPerPixel (ri.RGBFormat);
uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp; /* offset into address */
if (NOBLITTER)
return 0;
+
if (minterm != 0x0C) {
write_log (_T("WARNING - BlitPlanar2Direct() has unhandled op-code 0x%x. Using fall-back routine.\n"), minterm);
return 0;
#define LANG_DLL 1
#if WINUAEPUBLICBETA
-#define WINUAEBETA _T("17")
+#define WINUAEBETA _T("18")
#else
#define WINUAEBETA _T("")
#endif
-#define WINUAEDATE MAKEBD(2013, 4, 19)
+#define WINUAEDATE MAKEBD(2013, 4, 25)
#define WINUAEEXTRA _T("")
//#define WINUAEEXTRA _T("AmiKit Preview")
#define WINUAEREV _T("")
- restore only single input target to default.
+Beta 18:
+
+- If config (for example default.uae) has keyboard layout A/B/C selected, it will be remembered as default
+ keyboard layout for selected port, then if new config is loaded and it has non-existing device
+ (for example unplugged gamepad), port is configured for remembered default keyboard layout instead of always
+ defaulting to layout A.
+- Patch stupid CD32 ROM CD drive detection CPU delay loop if configured for non-approximate CPU speed modes.
+- Validate RTG blit parameters more carefully to prevent invalid memory accesses if program(s) do bad things.
+- winuaeenforcer disassembly crashed due to recent debugger changes.
+- B15 sprite emulation update caused graphics corruption if display window was "too wide". (Himalaya / Avalanche)
+- Mention also Administrator privileges in real harddrive/memory card "block zero write failed" messages.
+- Modified emulation of ddfstrt/ddfstop value pairs that cause display corruption on real hardware due
+ to bitplane dma being active too long and conflicting with refresh/strobe slots, prints log message.
+
Beta 17:
- One more IDE emulation fix, bogus extra write interrupt removed (I think this was accidentally introduced in some recent