From a263c17c1cdcbaa1dfc31ae54a5922a3d7b38ef1 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Mon, 12 Mar 2012 19:01:39 +0200 Subject: [PATCH] 2400b22 --- calc.cpp | 453 ++++++++++++++++++ cfgfile.cpp | 137 ++++-- custom.cpp | 42 +- drawing.cpp | 20 +- include/calc.h | 3 + include/custom.h | 1 + include/options.h | 1 + newcpu.cpp | 7 +- od-win32/win32.cpp | 2 + od-win32/win32.h | 6 +- od-win32/win32gui.cpp | 2 - od-win32/winuae_msvc10/winuae_msvc.vcxproj | 1 + .../winuae_msvc10/winuae_msvc.vcxproj.filters | 3 + od-win32/winuaechangelog.txt | 6 + zfile.cpp | 4 +- 15 files changed, 616 insertions(+), 72 deletions(-) create mode 100644 calc.cpp create mode 100644 include/calc.h diff --git a/calc.cpp b/calc.cpp new file mode 100644 index 00000000..4d7e62db --- /dev/null +++ b/calc.cpp @@ -0,0 +1,453 @@ +/* +* UAE - The Un*x Amiga Emulator +* +* Infix->RPN conversion and calculation +* +* Copyright 1995-2002 Bernd Schmidt +* Copyright 1995 Alessandro Bissacco +* Copyright 2000-2010 Toni Wilen +*/ + + +/* + + Original code from http://en.wikipedia.org/wiki/Shunting_yard_algorithm + +*/ + +#define CALC_DEBUG 0 + +#if CALC_DEBUG +#define calc_log(x) do { write_log x; } while(0) +#else +#define calc_log(x) +#endif + +#include "sysconfig.h" +#include "sysdeps.h" + +#include "calc.h" + +#include +#include + +#define STACK_SIZE 32 +#define MAX_VALUES 32 +#define IOBUFFERS 256 + +static double parsedvalues[MAX_VALUES]; + +// operators +// precedence operators associativity +// 1 ! right to left +// 2 * / % left to right +// 3 + - left to right +// 4 = right to left +static int op_preced(const TCHAR c) +{ + switch(c) { + case '!': + return 4; + case '*': case '/': case '\\': case '%': + return 3; + case '+': case '-': + return 2; + case '=': + return 1; + } + return 0; +} + +static bool op_left_assoc(const TCHAR c) +{ + switch(c) { + // left to right + case '*': case '/': case '%': case '+': case '-': + return true; + // right to left + case '=': case '!': + return false; + } + return false; +} + +static unsigned int op_arg_count(const TCHAR c) +{ + switch(c) { + case '*': case '/': case '%': case '+': case '-': case '=': + return 2; + case '!': + return 1; + default: + return c - 'A'; + } + return 0; +} + +#define is_operator(c) (c == '+' || c == '-' || c == '/' || c == '*' || c == '!' || c == '%' || c == '=') +#define is_function(c) (c >= 'A' && c <= 'Z') +#define is_ident(c) ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z')) + +static bool shunting_yard(const TCHAR *input, TCHAR *output) +{ + const TCHAR *strpos = input, *strend = input + _tcslen(input); + TCHAR c, *outpos = output; + + TCHAR stack[STACK_SIZE]; // operator stack + unsigned int sl = 0; // stack length + TCHAR sc; // used for record stack element + + while(strpos < strend) { + if (sl >= STACK_SIZE) + return false; + + // read one token from the input stream + c = *strpos; + if(c != ' ') { + // If the token is a number (identifier), then add it to the output queue. + if(is_ident(c)) { + *outpos = c; ++outpos; + } + // If the token is a function token, then push it onto the stack. + else if(is_function(c)) { + stack[sl] = c; + ++sl; + } + // If the token is a function argument separator (e.g., a comma): + else if(c == ',') { + bool pe = false; + while(sl > 0) { + sc = stack[sl - 1]; + if(sc == '(') { + pe = true; + break; + } + else { + // Until the token at the top of the stack is a left parenthesis, + // pop operators off the stack onto the output queue. + *outpos = sc; + ++outpos; + sl--; + } + } + // If no left parentheses are encountered, either the separator was misplaced + // or parentheses were mismatched. + if(!pe) { + calc_log ((L"Error: separator or parentheses mismatched\n")); + return false; + } + } + // If the token is an operator, op1, then: + else if(is_operator(c)) { + while(sl > 0) { + sc = stack[sl - 1]; + // While there is an operator token, o2, at the top of the stack + // op1 is left-associative and its precedence is less than or equal to that of op2, + // or op1 is right-associative and its precedence is less than that of op2, + if(is_operator(sc) && + ((op_left_assoc(c) && (op_preced(c) <= op_preced(sc))) || + (!op_left_assoc(c) && (op_preced(c) < op_preced(sc))))) { + // Pop o2 off the stack, onto the output queue; + *outpos = sc; + ++outpos; + sl--; + } + else { + break; + } + } + // push op1 onto the stack. + stack[sl] = c; + ++sl; + } + // If the token is a left parenthesis, then push it onto the stack. + else if(c == '(') { + stack[sl] = c; + ++sl; + } + // If the token is a right parenthesis: + else if(c == ')') { + bool pe = false; + // Until the token at the top of the stack is a left parenthesis, + // pop operators off the stack onto the output queue + while(sl > 0) { + sc = stack[sl - 1]; + if(sc == '(') { + pe = true; + break; + } + else { + *outpos = sc; + ++outpos; + sl--; + } + } + // If the stack runs out without finding a left parenthesis, then there are mismatched parentheses. + if(!pe) { + calc_log ((L"Error: parentheses mismatched\n")); + return false; + } + // Pop the left parenthesis from the stack, but not onto the output queue. + sl--; + // If the token at the top of the stack is a function token, pop it onto the output queue. + if(sl > 0) { + sc = stack[sl - 1]; + if(is_function(sc)) { + *outpos = sc; + ++outpos; + sl--; + } + } + } + else { + calc_log ((L"Unknown token %c\n", c)); + return false; // Unknown token + } + } + ++strpos; + } + // When there are no more tokens to read: + // While there are still operator tokens in the stack: + while(sl > 0) { + sc = stack[sl - 1]; + if(sc == '(' || sc == ')') { + printf("Error: parentheses mismatched\n"); + return false; + } + *outpos = sc; + ++outpos; + --sl; + } + *outpos = 0; // Null terminator + return true; +} + + +struct calcstack +{ + TCHAR *s; + double val; +}; + +static double docalcx (TCHAR op, double v1, double v2) +{ + switch (op) + { + case '-': + return v1 - v2; + case '+': + return v1 + v2; + case '*': + return v1 * v2; + case '/': + return v1 / v2; + case '\\': + return (int)v1 % (int)v2; + + } + return 0; +} + +static double stacktoval(struct calcstack *st) +{ + if (st->s) { + if (_tcslen(st->s) == 1 && st->s[0] >= 'a' && st->s[0] <= 'z') + return parsedvalues[st->s[0] - 'a']; + return _tstof (st->s); + } else { + return st->val; + } +} + +static double docalc2 (TCHAR op, struct calcstack *sv1, struct calcstack *sv2) +{ + double v1, v2; + + v1 = stacktoval(sv1); + v2 = stacktoval(sv2); + return docalcx (op, v1, v2); +} +static double docalc1 (TCHAR op, struct calcstack *sv1, double v2) +{ + double v1; + + v1 = stacktoval(sv1); + return docalcx (op, v1, v2); +} + +static TCHAR *stacktostr (struct calcstack *st) +{ + static TCHAR out[256]; + if (st->s) + return st->s; + _stprintf(out, L"%f", st->val); + return out; +} + +static TCHAR *chartostack (TCHAR c) +{ + TCHAR *s = xmalloc (TCHAR, 2); + s[0] = c; + s[1] = 0; + return s; +} + +static bool execution_order(const TCHAR *input, double *outval) +{ + const TCHAR *strpos = input, *strend = input + _tcslen(input); + TCHAR c, res[4]; + unsigned int sl = 0, rn = 0; + struct calcstack stack[STACK_SIZE] = { 0 }, *sc, *sc2; + double val = 0; + int i; + bool ok = false; + + // While there are input tokens left + while(strpos < strend) { + + if (sl >= STACK_SIZE) + return false; + + // Read the next token from input. + c = *strpos; + // If the token is a value or identifier + if(is_ident(c)) { + // Push it onto the stack. + stack[sl].s = chartostack (c); + ++sl; + } + // Otherwise, the token is an operator (operator here includes both operators, and functions). + else if(is_operator(c) || is_function(c)) { + _stprintf(res, L"_%02d", rn); + calc_log ((L"%s = ", res)); + ++rn; + // It is known a priori that the operator takes n arguments. + unsigned int nargs = op_arg_count(c); + // If there are fewer than n values on the stack + if(sl < nargs) { + // (Error) The user has not input sufficient values in the expression. + return false; + } + // Else, Pop the top n values from the stack. + // Evaluate the operator, with the values as arguments. + if(is_function(c)) { + calc_log ((L"%c(", c)); + while(nargs > 0){ + sc = &stack[sl - nargs]; // to remove reverse order of arguments + if(nargs > 1) { + calc_log ((L"%s, ", sc)); + } + else { + calc_log ((L"%s)\n", sc)); + } + --nargs; + } + sl-=op_arg_count(c); + } + else { + if(nargs == 1) { + sc = &stack[sl - 1]; + sl--; + val = docalc1 (c, sc, val); + calc_log ((L"%c %s = %f;\n", c, stacktostr(sc), val)); + } + else { + sc = &stack[sl - 2]; + calc_log ((L"%s %c ", stacktostr(sc), c)); + sc2 = &stack[sl - 1]; + val = docalc2 (c, sc, sc2); + sl--;sl--; + calc_log ((L"%s = %f;\n", stacktostr(sc2), val)); + } + } + // Push the returned results, if any, back onto the stack. + stack[sl].val = val; + stack[sl].s = NULL; + ++sl; + } + ++strpos; + } + // If there is only one value in the stack + // That value is the result of the calculation. + if(sl == 1) { + sc = &stack[sl - 1]; + sl--; + calc_log ((L"result = %f\n", val)); + if (outval) + *outval = val; + ok = true; + } + for (i = 0; i < STACK_SIZE; i++) + xfree (stack[i].s); + + // If there are more values in the stack + // (Error) The user input has too many values. + + return ok; +} + +static bool parse_values(const TCHAR *ins, TCHAR *out) +{ + int ident = 0; + TCHAR tmp; + TCHAR inbuf[IOBUFFERS]; + int op; + + _tcscpy (inbuf, ins); + TCHAR *in = inbuf; + TCHAR *p = out; + op = 0; + while (*in) { + TCHAR *instart = in; + if (_istdigit (*in)) { + if (ident >= MAX_VALUES) + return false; + if (op > 1 && (in[-1] == '-' || in[-1] == '+')) { + instart--; + p--; + } + *p++ = ident + 'a'; + while (_istdigit (*in) || *in == '.') + in++; + tmp = *in; + *in = 0; + parsedvalues[ident++] = _tstof (instart); + *in = tmp; + op = 0; + } else { + if (is_operator(*in)) + op++; + *p++ = *in++; + } + } + *p = 0; + return true; +} + +bool calc(const TCHAR *input, double *outval) +{ + TCHAR output[IOBUFFERS], output2[IOBUFFERS]; + calc_log ((L"IN: '%s'\n", input)); + if (parse_values(input, output2)) { + if(shunting_yard(output2, output)) { + calc_log ((L"RPN OUT: %s\n", output)); + if(!execution_order(output, outval)) { + calc_log ((L"PARSE ERROR!\n")); + } else { + return true; + } + } + } + return false; +} + +bool iscalcformula (const TCHAR *formula) +{ + for (int i = 0; i < _tcslen (formula); i++) { + TCHAR c = formula[i]; + if (is_operator (c)) + return true; + } + return false; +} + diff --git a/cfgfile.cpp b/cfgfile.cpp index 114735dd..58216ad2 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -32,10 +32,11 @@ #include "blkdev.h" #include "statusline.h" #include "debug.h" +#include "calc.h" static int config_newfilesystem; static struct strlist *temp_lines; -static struct zfile *default_file; +static struct zfile *default_file, *configstore; static int uaeconfig; static int unicode_config = 0; @@ -202,6 +203,7 @@ static const TCHAR *obsolete[] = { #define UNEXPANDED L"$(FILE_PATH)" + static void trimwsa (char *s) { /* Delete trailing whitespace. */ @@ -2659,8 +2661,69 @@ invalid_fs: return 0; } + +static bool createconfigstore (struct uae_prefs*); +static int getconfigstoreline (const TCHAR *option, TCHAR *value); + +static void calcformula (struct uae_prefs *prefs, TCHAR *in) +{ + TCHAR out[MAX_DPATH], configvalue[CONFIG_BLEN]; + TCHAR *p = out; + double val; + int cnt1, cnt2; + static bool updatestore; + + if (_tcslen (in) < 2 || in[0] != '[' || in[_tcslen (in) - 1] != ']') + return; + if (!configstore || updatestore) + createconfigstore (prefs); + updatestore = false; + if (!configstore) + return; + cnt1 = cnt2 = 0; + for (int i = 1; i < _tcslen (in) - 1; i++) { + TCHAR c = _totupper (in[i]); + if (c >= 'A' && c <='Z') { + TCHAR *start = &in[i]; + while (_istalnum (c) || c == '_' || c == '.') { + i++; + c = in[i]; + } + TCHAR store = in[i]; + in[i] = 0; + //write_log (L"'%s'\n", start); + if (!getconfigstoreline (start, configvalue)) + return; + _tcscpy (p, configvalue); + p += _tcslen (p); + in[i] = store; + i--; + cnt1++; + } else { + cnt2++; + *p ++= c; + } + } + *p = 0; + if (cnt1 == 0 && cnt2 == 0) + return; + /* single config entry only? */ + if (cnt1 == 1 && cnt2 == 0) { + _tcscpy (in, out); + updatestore = true; + return; + } + if (calc (out, &val)) { + _stprintf (in, L"%d", (int)val); + updatestore = true; + return; + } +} + int cfgfile_parse_option (struct uae_prefs *p, TCHAR *option, TCHAR *value, int type) { + calcformula (p, value); + if (!_tcscmp (option, L"debug")) { write_log (L"CONFIG DEBUG: '%s'\n", value); return 1; @@ -2701,6 +2764,9 @@ static int cfgfile_separate_linea (const TCHAR *filename, char *line, TCHAR *lin int i; line1 = line; + line1 += strspn (line1, "\t \r\n"); + if (*line1 == ';') + return 0; line2 = strchr (line, '='); if (! line2) { TCHAR *s = au (line1); @@ -2741,6 +2807,9 @@ static int cfgfile_separate_line (TCHAR *line, TCHAR *line1b, TCHAR *line2b) int i; line1 = line; + line1 += _tcsspn (line1, L"\t \r\n"); + if (*line1 == ';') + return 0; line2 = _tcschr (line, '='); if (! line2) { write_log (L"CFGFILE: line was incomplete with only %s\n", line1); @@ -2861,6 +2930,40 @@ static void subst (TCHAR *p, TCHAR *f, int n) free (str); } +static int getconfigstoreline (const TCHAR *option, TCHAR *value) +{ + TCHAR tmp[CONFIG_BLEN * 2], tmp2[CONFIG_BLEN * 2]; + int idx = 0; + + if (!configstore) + return 0; + zfile_fseek (configstore, 0, SEEK_SET); + for (;;) { + if (!zfile_fgets (tmp, sizeof tmp / sizeof (TCHAR), configstore)) + return 0; + if (!cfgfile_separate_line (tmp, tmp2, value)) + continue; + if (!_tcsicmp (option, tmp2)) + return 1; + } +} + +static bool createconfigstore (struct uae_prefs *p) +{ + uae_u8 zero = 0; + zfile_fclose (configstore); + configstore = zfile_fopen_empty (NULL, L"configstore", 50000); + if (!configstore) + return false; + zfile_fseek (configstore, 0, SEEK_SET); + uaeconfig++; + cfgfile_save_options (configstore, p, 0); + uaeconfig--; + cfg_write (&zero, configstore); + zfile_fseek (configstore, 0, SEEK_SET); + return true; +} + static char *cfg_fgets (char *line, int max, struct zfile *fh) { #ifdef SINGLEFILE @@ -3449,23 +3552,6 @@ void cfgfile_addcfgparam (TCHAR *line) temp_lines = u; } -static int getconfigstoreline (struct zfile *z, TCHAR *option, TCHAR *value) -{ - TCHAR tmp[CONFIG_BLEN * 2]; - int idx = 0; - - for (;;) { - TCHAR b = 0; - if (zfile_fread (&b, 1, sizeof (TCHAR), z) != 1) - return 0; - tmp[idx++] = b; - tmp[idx] = 0; - if (b == '\n' || b == 0) - break; - } - return cfgfile_separate_line (tmp, option, value); -} - #if 0 static int cfgfile_handle_custom_event (TCHAR *custom, int mode) { @@ -3591,7 +3677,6 @@ uae_u32 cfgfile_modify (uae_u32 index, TCHAR *parms, uae_u32 size, TCHAR *out, u int argv, i; uae_u32 err; TCHAR zero = 0; - static struct zfile *configstore; static TCHAR *configsearch; static int configsearchfound; @@ -3688,22 +3773,15 @@ uae_u32 cfgfile_modify (uae_u32 index, TCHAR *parms, uae_u32 size, TCHAR *out, u argv = cmdlineparser (parms, argc, UAELIB_MAX_PARSE); if (argv <= 1 && index == 0xffffffff) { - zfile_fclose (configstore); + createconfigstore (&currprefs); xfree (configsearch); - configstore = zfile_fopen_empty (NULL, L"configstore", 50000); configsearch = NULL; - if (argv > 0 && _tcslen (argc[0]) > 0) - configsearch = my_strdup (argc[0]); if (!configstore) { err = 20; goto end; } - zfile_fseek (configstore, 0, SEEK_SET); - uaeconfig++; - cfgfile_save_options (configstore, &currprefs, 0); - uaeconfig--; - cfg_write (&zero, configstore); - zfile_fseek (configstore, 0, SEEK_SET); + if (argv > 0 && _tcslen (argc[0]) > 0) + configsearch = my_strdup (argc[0]); err = 0xffffffff; configsearchfound = 0; goto end; @@ -4062,6 +4140,7 @@ void default_prefs (struct uae_prefs *p, int type) p->fpu_model = 0; p->cpu_model = 68000; + p->m68k_speed_throttle = 0; p->cpu_clock_multiplier = 0; p->cpu_frequency = 0; p->mmu_model = 0; diff --git a/custom.cpp b/custom.cpp index bc323b8f..8b18e116 100644 --- a/custom.cpp +++ b/custom.cpp @@ -132,7 +132,7 @@ struct ev2 eventtab2[ev2_max]; int vpos; static int vpos_count, vpos_count_prev; -static int lof_store; // real bit in custom registers +int lof_store; // real bit in custom registers static int lof_current; // what display device thinks static int lol; static int next_lineno, prev_lineno; @@ -189,6 +189,7 @@ double vblank_hz = VBLANK_HZ_PAL, fake_vblank_hz, vblank_hz_stored; static int vblank_hz_mult, vblank_hz_state; static struct chipset_refresh *stored_chipset_refresh; int doublescan; +bool programmedmode; frame_time_t syncbase; static int fmode; uae_u16 beamcon0, new_beamcon0; @@ -2964,6 +2965,7 @@ void init_hz (bool fullinit) vpos_count = vpos_count_prev = 0; doublescan = 0; + programmedmode = false; if ((beamcon0 & 0xA0) != (new_beamcon0 & 0xA0)) hzc = 1; if (beamcon0 != new_beamcon0) { @@ -3017,6 +3019,7 @@ void init_hz (bool fullinit) maxvpos_nom = maxvpos; equ_vblank_endline = -1; doublescan = htotal <= 164 ? 1 : 0; + programmedmode = true; dumpsync (); hzc = 1; } @@ -5143,6 +5146,7 @@ static void framewait (void) if (vs > 0) { curr_time = read_processor_time (); + vsyncmaxtime = curr_time + vsynctimebase; render_screen (); show_screen (); frame_shown = true; @@ -5163,7 +5167,7 @@ static void framewait (void) vsync_busywait_do (NULL, (bplcon0 & 4) != 0 && !lof_changed && !lof_changing, lof_store != 0); vsync_busywait_start (); vsyncmintime = curr_time; - vsyncmaxtime = curr_time + vsynctimebase; + vsyncmaxtime = curr_time + vsynctimebase * (100 - currprefs.m68k_speed_throttle) / 100; } else { @@ -5185,9 +5189,9 @@ static void framewait (void) if (currprefs.m68k_speed < 0) { curr_time = read_processor_time (); if (curr_time - vsyncmaxtime >= 0 && curr_time - vsyncmaxtime < vsynctimebase) { - vsyncmaxtime = curr_time + vsynctimebase - (curr_time - vsyncmaxtime); + vsyncmaxtime = curr_time + vsynctimebase * (100 - currprefs.m68k_speed_throttle) / 100 - (curr_time - vsyncmaxtime); } else { - vsyncmaxtime = curr_time + vsynctimebase; + vsyncmaxtime = curr_time + vsynctimebase * (100 - currprefs.m68k_speed_throttle) / 100; } vsyncmintime = curr_time; return; @@ -5793,10 +5797,13 @@ static void hsync_handler_post (bool onvsync) if (vpos + 1 == maxvpos + lof_store) { /* really last line, just run the cpu emulation until whole vsync time has been used */ is_syncline = 1; - vsyncmintime = vsyncmaxtime; + if (currprefs.m68k_speed_throttle) + vsyncmintime = read_processor_time (); /* end of CPU emulation time */ + else + vsyncmintime = vsyncmaxtime; /* emulate if still time left */ } else { /* end of scanline, run cpu emulation as long as we still have time */ - vsyncmintime += vsynctimebase / maxvpos_nom; + vsyncmintime += (vsynctimebase * (100 - currprefs.m68k_speed_throttle)) / (maxvpos_nom * 100); if (!vblank_found_chipset && (int)vsyncmaxtime - (int)vsyncmintime > 0) { is_syncline = -1; frame_time_t rpt = read_processor_time (); @@ -5807,29 +5814,6 @@ static void hsync_handler_post (bool onvsync) } } -#if 0 -#ifdef JIT - if (currprefs.cachesize) { - if (currprefs.m68k_speed < 0) { - jitcount++; - if (isvsync () >= 0 && trigger_frh (jitcount)) { - frh_handler (); - } - is_syncline = (trigger_frh (jitcount + 1) && ! rpt_did_reset) ? -1 : 0; - //write_log (L"%d %d\n", jitcount & (N_LINES - 1), is_syncline); - } else { - is_syncline = 0; - } - if (vpos + 1 == maxvpos + lof_store) - is_syncline = 1; - } else { -#endif - is_syncline = (vpos + 1 == maxvpos + lof_store && currprefs.m68k_speed < 0) ? 1 : 0; -#ifdef JIT - } -#endif -#endif - if (!nocustom ()) { int lineno = vpos; if (lineno >= MAXVPOS) diff --git a/drawing.cpp b/drawing.cpp index d3160fc4..590d5138 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -327,6 +327,7 @@ extern int first_planes_vpos, last_planes_vpos; extern int diwfirstword_total, diwlastword_total; extern int ddffirstword_total, ddflastword_total; extern int firstword_bplcon1; +extern int lof_store; #define MIN_DISPLAY_W 256 #define MIN_DISPLAY_H 192 @@ -377,12 +378,18 @@ int get_custom_limits (int *pw, int *ph, int *pdx, int *pdy) if (gclow > 0 && gcloh > 0) ret = -1; - last_planes_vpos = (last_planes_vpos) & ~1; - plflastline_total = (plflastline_total) & ~1; + if (interlace_seen) { + // interlace = only use long frames + if (!lof_store) + return 1; + last_planes_vpos++; + plflastline_total++; + } + if (!plflastline_total) plflastline_total = last_planes_vpos; - if (doublescan <= 0) { + if (doublescan <= 0 && !programmedmode) { int min = coord_diw_to_window_x (92); int max = coord_diw_to_window_x (460); if (diwfirstword_total < min) @@ -443,7 +450,7 @@ int get_custom_limits (int *pw, int *ph, int *pdx, int *pdy) if (w == 0 || h == 0) return 0; - if (doublescan <= 0) { + if (doublescan <= 0 && !programmedmode) { if ((w >> currprefs.gfx_resolution) < MIN_DISPLAY_W) { dx += (w - (MIN_DISPLAY_W << currprefs.gfx_resolution)) / 2; w = MIN_DISPLAY_W << currprefs.gfx_resolution; @@ -467,7 +474,7 @@ int get_custom_limits (int *pw, int *ph, int *pdx, int *pdy) if (w <= 0 || h <= 0 || dx <= 0 || dy <= 0) return ret; - if (doublescan <= 0) { + if (doublescan <= 0 && !programmedmode) { if (dx > gfxvidinfo.outbuffer->inwidth / 3) return ret; if (dy > gfxvidinfo.outbuffer->inheight / 3) @@ -482,11 +489,12 @@ int get_custom_limits (int *pw, int *ph, int *pdx, int *pdy) *ph = h; *pdx = dx; *pdy = dy; - +#if 1 write_log (L"Display Size: %dx%d Offset: %dx%d\n", w, h, dx, dy); write_log (L"First: %d Last: %d MinV: %d MaxV: %d Min: %d\n", plffirstline_total, plflastline_total, first_planes_vpos, last_planes_vpos, minfirstline); +#endif return 1; } diff --git a/include/calc.h b/include/calc.h new file mode 100644 index 00000000..be732348 --- /dev/null +++ b/include/calc.h @@ -0,0 +1,3 @@ + +extern bool calc(const TCHAR *input, double *outval); +extern bool iscalcformula (const TCHAR *formula); diff --git a/include/custom.h b/include/custom.h index 00c8e1af..2ec96b44 100644 --- a/include/custom.h +++ b/include/custom.h @@ -114,6 +114,7 @@ extern int hsyncstartpos; extern int minfirstline, vblank_endline, numscrlines; extern double vblank_hz, fake_vblank_hz; extern int vblank_skip, doublescan; +extern bool programmedmode; extern frame_time_t syncbase; #define DMA_AUD0 0x0001 diff --git a/include/options.h b/include/options.h index c6647a37..8aed9888 100644 --- a/include/options.h +++ b/include/options.h @@ -380,6 +380,7 @@ struct uae_prefs { struct multipath path_cd; int m68k_speed; + int m68k_speed_throttle; int cpu_model; int mmu_model; int cpu060_revision; diff --git a/newcpu.cpp b/newcpu.cpp index e8a62582..3fa7b501 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -3384,8 +3384,11 @@ STATIC_INLINE int do_specialties (int cycles) } if (!uae_int_requested && currprefs.cpu_idle && currprefs.m68k_speed != 0 && ((regs.spcflags & SPCFLAG_STOP)) == SPCFLAG_STOP) { - /* sleep 1ms if STOP-instruction is executed */ - if (1) { + /* sleep 1ms if STOP-instruction is executed + * but only if we have free frametime left to prevent slowdown + */ + frame_time_t rpt = read_processor_time (); + if ((int)rpt - (int)vsyncmaxtime < 0) { static int sleepcnt, lvpos, zerocnt; if (vpos != lvpos) { sleepcnt--; diff --git a/od-win32/win32.cpp b/od-win32/win32.cpp index 97cbd33a..d5949b7f 100644 --- a/od-win32/win32.cpp +++ b/od-win32/win32.cpp @@ -5750,6 +5750,7 @@ void fpux_restore (int *v) typedef BOOL (CALLBACK* SETPROCESSDPIAWARE)(void); typedef BOOL (CALLBACK* CHANGEWINDOWMESSAGEFILTER)(UINT, DWORD); + int PASCAL wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) { SETPROCESSDPIAWARE pSetProcessDPIAware; @@ -5797,6 +5798,7 @@ int PASCAL wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdL pSetProcessDPIAware (); log_open (NULL, 0, 0); + __try { WinMain2 (hInstance, hPrevInstance, lpCmdLine, nCmdShow); } __except(WIN32_ExceptionFilter (GetExceptionInformation (), GetExceptionCode ())) { diff --git a/od-win32/win32.h b/od-win32/win32.h index 5272ba6b..cf827f9a 100644 --- a/od-win32/win32.h +++ b/od-win32/win32.h @@ -19,9 +19,9 @@ #define LANG_DLL 1 //#define WINUAEBETA L"" -#define WINUAEBETA L"Beta 21" -#define WINUAEDATE MAKEBD(2012, 3, 10) -#define WINUAEEXTRA L"" +#define WINUAEBETA L"Beta 22" +#define WINUAEDATE MAKEBD(2012, 3, 12) +#define WINUAEEXTRA L"RC1" //#define WINUAEEXTRA L"AmiKit Preview" #define WINUAEREV L"" diff --git a/od-win32/win32gui.cpp b/od-win32/win32gui.cpp index 2614dcab..1ddb66f0 100644 --- a/od-win32/win32gui.cpp +++ b/od-win32/win32gui.cpp @@ -12170,8 +12170,6 @@ static void input_toggleautofire (void) return; evt = inputdevice_get_mapping (input_selected_device, input_selected_widget, &flags, NULL, name, custom, input_selected_sub_num); - if (evt <= 0) - return; if ((flags & (IDEV_MAPPED_INVERTTOGGLE | IDEV_MAPPED_AUTOFIRE_SET)) == (IDEV_MAPPED_INVERTTOGGLE | IDEV_MAPPED_AUTOFIRE_SET)) flags &= ~(IDEV_MAPPED_INVERTTOGGLE | IDEV_MAPPED_AUTOFIRE_SET); else if (flags & IDEV_MAPPED_AUTOFIRE_SET) { diff --git a/od-win32/winuae_msvc10/winuae_msvc.vcxproj b/od-win32/winuae_msvc10/winuae_msvc.vcxproj index 08ad3d6b..07dd5971 100644 --- a/od-win32/winuae_msvc10/winuae_msvc.vcxproj +++ b/od-win32/winuae_msvc10/winuae_msvc.vcxproj @@ -555,6 +555,7 @@ + diff --git a/od-win32/winuae_msvc10/winuae_msvc.vcxproj.filters b/od-win32/winuae_msvc10/winuae_msvc.vcxproj.filters index 17c918d2..7e053946 100644 --- a/od-win32/winuae_msvc10/winuae_msvc.vcxproj.filters +++ b/od-win32/winuae_msvc10/winuae_msvc.vcxproj.filters @@ -502,6 +502,9 @@ common + + common + diff --git a/od-win32/winuaechangelog.txt b/od-win32/winuaechangelog.txt index af70eabc..4d6516cb 100644 --- a/od-win32/winuaechangelog.txt +++ b/od-win32/winuaechangelog.txt @@ -1,4 +1,10 @@ +Beta 22: (RC1) + +- CPU Idle limit added, do not sleep if there are no frame time left, no more slowdowns if CPU Idle is set too high. +- Only use long frames to recalculate interlace autoscale positiong. (Autoscale jitter in some interlace setups) +- Autoscale didn't always ignore standard mode display limits when displaying programmed display modes. + Beta 21: (Fastest possible vsync should be fixed finally, only some testing left to do) - Direct3D masks and scanlines fixed, forgotten testing code.. (b20) diff --git a/zfile.cpp b/zfile.cpp index 6c61017a..fb098586 100644 --- a/zfile.cpp +++ b/zfile.cpp @@ -2256,7 +2256,9 @@ TCHAR *zfile_fgets (TCHAR *s, int size, struct zfile *z) break; } *p = z->data[z->seek++]; - if (*p == '\n') { + if (*p == 0 && i == 0) + return NULL; + if (*p == '\n' || *p == 0) { p++; break; } -- 2.47.3