// // fmtb_parse.c - read a wpic*.txt file (stdin) and parse into motion codes (stdout) // // Copyright (C) 2006 Nathan (Acorn) Pooley // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // version 2 as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License (gpl.txt) for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // You can contact the author, Nathan (Acorn) Pooley, by writing // to Nathan (Acorn) Pooley, 949 Buckeye Drive, Sunnyvale, CA 94086, USA // or through the form at http://www.rawbw.com/~acorn/wand/feedback.html // //#@DOC@ read a wpic*.txt spell file (stdin) and parse into motion tokens //########################################################################### //############################### INCLUDES ################################## //########################################################################### #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <ctype.h> #include "picsim.h" #include "ac_assert.h" #include "spells.h" Spell spells[] = { #include "spells.c" {0}, }; //########################################################################### //############################### DEFINES ################################### //########################################################################### #define USE_PIC_PARSE1 1 #define USE_PIC_FILLGAP 1 #define USE_PIC_FINDWEAK 1 #define USE_PIC_FINDPULSE 1 #define USE_PIC_MARKLAST 1 #define USE_PIC_TOKENIZE 1 #define DBG_PARSE1_MINIMAL 0 #define DBG_FILLGAP_MINIMAL 0 #define DBG_FINDWEAK 0 #define DBG_FINDPULSE 0 #define DBG_MARKLAST 0 #define DBG_TOKENIZE 0 #define DBG_LOADSPELL 0 #define DBG_SCORETOK 0 #define DBG_SCORESPELL 0 #define DBG_CHECKSPELLS 0 #define MAX_TOKENS 1000 #define MINIMAL 1 #define ASSERT(c) AC_ASSERT(c) #define DEBUG 0 #define CNT_MAX 1024 #define ABS(a) ((a)<0?-(a):(a)) #define MIN(a,b) ((a)<(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b)) #define TH_T_STILL 0.25 #define TH_A_JUMP 5 #define TH_A_NEWQUAD 7 #define TH_A_SNAPQUAD 6 #define TH_A_CONNECT 2 //########################################################################### //############################### TYPEDEFS ################################## //########################################################################### typedef struct PSpellRec { int flags; int maxscore; int holdoff; const char *name; char *baseName; const char *mwanemes; unsigned char tokens[MAX_TOKENS]; int len; int score; int spellinfo; int id; int sortId; unsigned char pic_mwanemes[MAX_TOKENS]; unsigned char pic_tokens[MAX_TOKENS]; } PSpell; typedef struct Motion2Rec { int shape; int imp; int maxmag; int angle; // 0xc0=end 0xa0=start // // strictly for debug // int dbg_atime; } Motion2; //NOTE: dir & MONO are required in PULSE shapes too typedef enum MotionFlagsEnum { MFLG_ZERO = 0x01, // only used in parse MFLG_MONO = 0x02, // NEEDED MFLG_CIRCLE = 0x04, // NEEDED MFLG_BEST_MAG = 0x08, // not really used MFLG_BEST_IMP = 0x10, // not really used MFLG_MISSING_CIRCLE = 0x20, // unused MFLG_PREV_PAUSE = 0x40, // ? MFLG_NEXT_PAUSE = 0x80, // ? MFLG_END = 0xff } MotionFlags; typedef struct MotionRec { int b_atime; // not needed int b_dtime; // not needed int b_imp; int b_minmag; // only used for deltamag int b_maxmag; int b_deltamag; // only used in parse1 int b_angle; int b_flags; struct MotionRec *c_next; struct MotionRec *c_prev; int c_shape; int c_dir; int c_imp; #if !MINIMAL int c_time; int c_oct; int c_best_angle; int c_best_mag; int c_cnt; int c_isum; int c_maxstep; int c_maxdmag; int c_asum; int c_flags; #endif int token; } Motion; typedef struct SpellCreateInfoRec { int lastAngle; int prevCircleCnt; } SpellCreateInfo; //########################################################################### //############################### PROTOTYPES ################################ //########################################################################### static int setSilent(int val); static void printMotion(char *str, Motion *mlist, Motion *m, int color); static void printMotion2(char *str, Motion2 *mlist, Motion2 *m, int color); static void breakpt(void); static char *colorStr(int bg); static char *spellTokenStr(int tok); static char *motionTokenStr(unsigned int tok); //########################################################################### //############################### GLOBALS ################################### //########################################################################### char *OPT_input_filename=0; int OPT_raw = 0; int OPT_result_motion_only = 0; int OPT_result_spell_only = 0; int OPT_export = 0; int OPT_showspell = 0; int OPT_filelist = 0; int OPT_vital = 0; int OPT_allspells = 0; int OPT_describe = 0; int OPT_quick = 0; int OPT_showtime = 0; int OPT_silent = 0; int OPT_silent2 = 0; int OPT_use_original = 0; int OPT_use_minimal = 0; int OPT_use_picsim = 0; int OPT_use_classic = 0; int OPT_use_experimental = 0; int OPT_use_all = 0; int OPT_show_tokens = 0; int OPT_nocolor = 0; int OPT_noaddr = 0; int OPT_nocrash = 0; int OPT_onespell = 0; int OPT_no_orig = 1; int OPT_crosscheck = 0; int OPT_check_comparetok = 1; int OPT_do_picsim = 1; char *OPT_result_filename = 0; char *OPT_mwaneme_filename = 0; char gCmdline[1000] = ""; PSpell *gCurrentSpell = 0; int gCurrentMwanemeIndex = 0; int gCompareCnt = 0; picChip *chip = 0; static PSpell *gBestSpell1_m = 0; static PSpell *gBestSpell2_m = 0; static PSpell *gChooseSpell_m = 0; static PSpell *gBestSpell1 = 0; static PSpell *gBestSpell2 = 0; static PSpell *gChooseSpell = 0; static int gMaxMaxscore = 0; static int gMaxHoldoff = 0; static char *quadStr[] = { "Down ", "Right", "Up ", "Left ", }; static char *octStr[] = { "d ", "dr", " r", "ur", "u ", "ul", " l", "dl", }; static char *octStr2[] = { "v", ".", ">", "'", "^", "`", "<", ",", }; static char *motionShapeStr[] = { MOTION_SHAPE_STRING() }; #if 0 static char *spellShapeStr[] = { MOTION_SHAPE_STRING() }; #endif // // score for a spell-shape that is skipped (not matched by any motion-shape) // static int ignoreSpells[8] = { 100, // SSHP_PAUSE 15, // SSHP_CIRCLE 0, // SSHP_OCIRCLE 1, // SSHP_OPULSE 100, // SSHP_PULSE 0, // SSHP_WILD 99999, 99999, }; // // score for a motion-shape that is skipped (not matched by any spell-shape) // static int ignoreMotions[8] = { 1, // MSHP_DIRTY_CIRCLE, 20, // MSHP_DIRTY_CIRCLE_PLUS, 1, // MSHP_CLEAN_CIRCLE, 100, // MSHP_CLEAN_CIRCLE_PLUS, 1, // MSHP_PULSE, 100, // MSHP_PULSE_PLUS, 0, // MSHP_CIRCLE_GAP, 0, // MSHP_PAUSE, }; // // NO LONGER USED - no spell pauses // static int scorePause[8] = { 0, // MSHP_PAUSE, 30, // MSHP_CLEAN_CIRCLE, 1000, // MSHP_CLEAN_CIRCLE_PLUS, 30, // MSHP_DIRTY_CIRCLE, 1000, // MSHP_DIRTY_CIRCLE_PLUS, 30, // MSHP_PULSE, 1000, // MSHP_PULSE_PLUS, 0, // MSHP_CIRCLE_GAP }; static int scorePulse[5] = { 0, // same dir * 0, // off by 2 * 0, // off by 4 (45 deg) * 6, // off by 6 * 1000, // off by 8 (90 deg) * }; static int scoreCircleMatch = 0; static int scoreCircleMiss = 1000; static int scorePulseMiss = 1000; //########################################################################### //############################### PIC DEFS ################################## //########################################################################### #define PIC_CSIM 1 int v_mo_oct; int v_mo_angle; int v_mo_impl; int v_mo_imph; int v_mo_maxmag; int v_mo_shape; int v_mo_minmag; int v_mo_flags; int v_tmp; int v_mo_save_fsr0l; int v_mo_save_fsr0h; int v_mo_save_fsr1l; int v_mo_save_fsr1h; int v_mo_save_fsr2l; int v_mo_save_fsr2h; //int v_last_global; int v_mo1_mo_angle; int v_mo1_mo_maxmag; int v_mo1_mo_minmag; int v_mo1_mo_impl; int v_mo1_mo_imph; int v_mo1_mo_flags; int v_mo2_next_mh; int v_mo2_next_ml; int v_mo2_next_mdh; int v_mo2_next_mdl; int v_mo2_bits; #include "fmtb_pic.c" //=========================================================================== // init_pic() //=========================================================================== static void init_pic(void) { picTest(); chip = picChipCreate("WandPic", "Pic18lf2525"); picChipSetCurrent(chip); // // globals (if any) go here // //picRegGlobal(v_last_global,0); // // These globals are defined in wand.asm // picRegGlobal(v_tmp,0); init_pic_globals(); picRegSet(chip, TBLPTRU, 0); picSetCycle(0); } //=========================================================================== // picSpellWrite() - //=========================================================================== static void picSpellWrite(int val) { if (!gCurrentSpell) return; ASSERT(val >=0 && val < 256); ASSERT(gCurrentMwanemeIndex < MAX_TOKENS); gCurrentSpell->pic_mwanemes[gCurrentMwanemeIndex++] = val; } //=========================================================================== // picSpellRead() - //=========================================================================== static int picSpellRead(void) { static PSpell dummy; int val; if (!gCurrentSpell) return -1; if (gCurrentSpell->name == 0) { switch(gCurrentMwanemeIndex) { case 0: gCurrentMwanemeIndex++; return (PIC_MWN_END_SPELLS&0xff); case 1: gCurrentSpell = 0; gCurrentMwanemeIndex = 0; return (PIC_MWN_END_SPELLS>>8); default: ASSERT(0); } } ASSERT(gCurrentSpell); ASSERT(gCurrentMwanemeIndex < MAX_TOKENS); val = gCurrentSpell->pic_mwanemes[gCurrentMwanemeIndex++]; if (DBG_LOADSPELL) { if (gCurrentMwanemeIndex-1<5) { static char *istr[8] = { "spellinfol", "spellinfoh", "maxscore", "holdoff", "initial octant", "???", "???", "???", }; printf("%sREAD mwaneme[%3d] = %02x %s%s\n", colorStr(2), gCurrentMwanemeIndex-1, val, istr[(gCurrentMwanemeIndex-1)&7], colorStr(-1)); } else { printf("%sREAD mwaneme[%3d] = %02x %s dir=%2d oct=%d cnt=%d%s\n", colorStr(2), gCurrentMwanemeIndex-1, val, PIC_MWN_PULSE(val)?"pulse ":"circle", PIC_MWN_DIR(val), PIC_MWN_OCT(val), PIC_MWN_CNT(val), colorStr(-1)); } } if (val == STOKEN_END && (gCurrentMwanemeIndex-1)>=6) { ASSERT(gCurrentMwanemeIndex-1 >= 6+2); // at least two spell tokens gCurrentSpell++; gCurrentMwanemeIndex = 0; if (OPT_onespell) { gCurrentSpell = &dummy; dummy.name = 0; } } return val; } //=========================================================================== // spell_read_byte() - //=========================================================================== static void spell_read_byte(void) { int val = picSpellRead(); ASSERT(val >= 0); picRegSet(0,TABLAT,val); } //########################################################################### //############################### CODE ###################################### //########################################################################### //=========================================================================== // fmtbAssertFailed() //=========================================================================== static void fmtbAssertFailed( const char *cond, const char *func, const char *file, int line) { fprintf(stderr," FAILED for Cmdline: %s\n",gCmdline); } //=========================================================================== // colorStr() //=========================================================================== static char *colorStr(int bg) { if (OPT_nocolor) return ""; #define ESC "\033" switch(bg) { case 0: return ESC "[40;37m"; case 1: return ESC "[0m" ESC "[41m"; case 2: return ESC "[0m" ESC "[42;30m"; case 3: return ESC "[0m" ESC "[43;30m"; case 4: return ESC "[0m" ESC "[44m"; case 5: return ESC "[0m" ESC "[45m"; case 6: return ESC "[0m" ESC "[46;30m"; case 7: return ESC "[0m" ESC "[47;30m"; default: return ESC "[0m"; } } //=========================================================================== // breakpt() //=========================================================================== static void breakpt(void) { } //=========================================================================== // fatalError() //=========================================================================== void fatalError(const char *fmt, ...) { va_list ap; printf("\n\nERROR\n"); fprintf(stderr,"\n\nERROR:\n"); va_start(ap,fmt); vfprintf(stderr,fmt,ap); va_end(ap); fprintf(stderr,"\n\n"); ASSERT(!"Fatal Error"); } //=========================================================================== // setSilent() - set silent & return old value //=========================================================================== static int setSilent(int val) { int old = OPT_silent; OPT_silent = val; return old; } //=========================================================================== // eraseLocalVars() - erase all local variables //=========================================================================== static void eraseLocalVars(void) { // // erase all local vars // #if 0 picRegEraseRange(chip, v_last_global, 0x17f); #else picRegEraseRange(chip, 0, 0x17f); #endif // // erase special functions regs that are not considered global // picRegErase(chip, FSR0L); picRegErase(chip, FSR0H); picRegErase(chip, FSR1L); picRegErase(chip, FSR1H); picRegErase(chip, FSR2L); picRegErase(chip, FSR2H); picRegErase(chip, WREG); picRegErase(chip, PRODH); picRegErase(chip, PRODL); picRegErase(chip, TABLAT); picRegErase(chip, TBLPTRH); picRegErase(chip, TBLPTRL); } //=========================================================================== // marker() //=========================================================================== static void marker(int n) { int i; if (OPT_silent) return; for (i=0; i<20; i++) { printf("MARK %3d %4x %4x %4x %4x %4x %4x\n",n,i,i,i,i,i,i); } } //=========================================================================== // writeM1List() //=========================================================================== static void writeM1List(Motion *mlist, int addr) { Motion *m = mlist; // // Stored as follows: // // Pause: // 0 - time (h) // 1 - time (l) // 2 - unused (set to 0xff) // 3 - angle (0xff indicates pause) // // Angle: // 0 - time (h) // 1 - time (l) // 2 - max mag // 3 - angle (0-31) // 4 - imp (h) // 5 - imp (l) // 6 - min mag // 7 - flags // // End of buffer // 0 - time (h) // 1 - time (l) // 2 - unused (set to 0xff) // 3 - angle (0xfe indicates end of buffer) // while(1) { if (m->b_angle > 31) { ASSERT(m->b_angle == 0xff); if (m[1].b_angle == 0xfe) { break; } picRegSet(chip, addr++, (m->b_dtime>>8) & 0xff); picRegSet(chip, addr++, m->b_dtime & 0xff); picRegSet(chip, addr++, 0xff); picRegSet(chip, addr++, 0xff); } else { int flags = m->b_flags; flags = (flags & 1) | 0x80; picRegSet(chip, addr++, (m->b_dtime>>8) & 0xff); picRegSet(chip, addr++, m->b_dtime & 0xff); picRegSet(chip, addr++, m->b_maxmag); picRegSet(chip, addr++, m->b_angle); picRegSet(chip, addr++, (m->b_imp>>8) & 0xff); picRegSet(chip, addr++, m->b_imp & 0xff); picRegSet(chip, addr++, m->b_minmag); picRegSet(chip, addr++, flags); } m++; } picRegSet(chip, addr++, 0); picRegSet(chip, addr++, 0); picRegSet(chip, addr++, 0xff); picRegSet(chip, addr++, 0xfe); ASSERT(addr <= RAMBUF_ACC + RAMBUF_ACC_LEN); } //=========================================================================== // writeM2List() //=========================================================================== static void writeM2List(Motion2 *m2list, int addr) { Motion2 *m = m2list; int shape; int maxmag; int imp; int angle; int start = addr; ASSERT(m2list->angle == ANGLE_START); // // Stored as follows: // 0 - angle // 1 - impulsel // 2 - impulseh // 3 - maxmag // 4 - shape // while(1) { // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; picRegSet(chip, addr++, angle); picRegSet32(chip, addr, addr+1, -1, -1, imp); addr += 2; picRegSet(chip, addr++, maxmag); picRegSet(chip, addr++, shape); if (angle & AFLG_END) break; } ASSERT(addr - start <= RAMBUF_M2LIST_LEN); ASSERT(addr - start <= RAMBUF_M3LIST_LEN); } //=========================================================================== // readM2List() //=========================================================================== static void readM2List(Motion2 *m2list, int addr) { Motion2 *md = m2list; int shape; int maxmag; int imp; int angle; int start = addr; //ASSERT(m2list->angle == ANGLE_START); while(1) { angle = picRV(addr++); imp = picRegValU32(chip, addr, addr+1, -1,-1); addr += 2; maxmag = picRV(addr++); shape = picRV(addr++); // w_shp_write md->shape = shape; md->maxmag = maxmag; md->angle = angle; md->imp = imp; md++; if (angle & AFLG_END) break; } ASSERT(m2list->angle == ANGLE_START); ASSERT(addr - start <= RAMBUF_M2LIST_LEN); ASSERT(addr - start <= RAMBUF_M3LIST_LEN); } //=========================================================================== // readTokens() //=========================================================================== static void readTokens(int *tokens, int addr) { int start = addr; while(1) { int tok = picRV(addr++); *(tokens++) = tok; if (tok == MTOKEN_END) break; } ASSERT(addr - start <= RAMBUF_MTOKENS_LEN); } //=========================================================================== // adiff() - returned signed difference of 2 angles //=========================================================================== static int adiff(int a1, int a0) { int a = a1 - a0; a &= 0x1f; if (a & 0x10) a -= 0x20; return a; } //=========================================================================== // odiff() - returned signed difference of 2 octants //=========================================================================== static int odiff(int o1, int o0) { int o = o1 - o0; o &= 0x7; if (o & 0x4) o -= 0x8; return o; } //=========================================================================== // a2quad() - convert angle to quadrant //=========================================================================== static int a2quad(int a) { return ((a+4) >> 3) & 3; } //=========================================================================== // quad2a() - convert quadrant to angle //=========================================================================== static int quad2a(int q) { return (q<<3) & 0x1f; } //=========================================================================== // a2oct() - convert angle to octant //=========================================================================== static int a2oct(int a) { return ((a+2) >> 2) & 7; } //=========================================================================== // oct2a() - convert octant to angle //=========================================================================== static int oct2a(int o) { return (o<<2) & 0x1f; } //=========================================================================== // flagStr() //=========================================================================== static const char *flagStr(int f) { static char s[10]; s[0] = f & MFLG_ZERO ? 'Z' : ' '; s[1] = f & MFLG_MONO ? 'M' : ' '; s[2] = f & MFLG_CIRCLE ? 'C' : ' '; s[3] = f & MFLG_BEST_MAG ? 'G' : ' '; s[4] = f & MFLG_BEST_IMP ? 'I' : ' '; s[5] = 0; return s; } //=========================================================================== // spellTokenStr() //=========================================================================== static char *spellTokenStr(int tok) { static char buf[10]; int oct = a2oct(TOKEN_ANGLE(tok)); int dir = TOKEN_DIR(tok); if (tok==STOKEN_END) { return " END"; } switch(TOKEN_SHAPE(tok)) { case SSHP_PAUSE: sprintf(buf,"Pause"); break; case SSHP_CIRCLE: sprintf(buf," %3s%s",dir<0?" CW":"CCW",octStr2[oct]); break; case SSHP_OCIRCLE: sprintf(buf," %3s%s",dir<0?" cw":"ccw",octStr2[oct]); break; case SSHP_OPULSE: sprintf(buf," op%s",octStr2[oct]); break; case SSHP_PULSE: sprintf(buf," P%s",octStr2[oct]); break; case SSHP_WILD: sprintf(buf,"Wild "); break; default: sprintf(buf,"?????"); break; } return buf; } //=========================================================================== // mwanemeDescStr() //=========================================================================== static char *mwanemeDescStr(const char *mwanemes) { static char buf[MAX_TOKENS*4]; char *s = buf; const char *m = mwanemes; while(*m) { switch(*m) { case 'e': s += sprintf(s,"ccw2 "); break; case 'i': s += sprintf(s,"ccw3 "); break; case 'a': s += sprintf(s,"cw1 "); break; case 'o': s += sprintf(s,"cw2 "); break; case 'u': s += sprintf(s,"cw3 "); break; case 'y': s += sprintf(s,"ccw1 "); break; case 'd': s += sprintf(s,"^ "); break; case 'k': s += sprintf(s,"> "); break; case 'g': s += sprintf(s,"v "); break; case 'f': s += sprintf(s,"< "); break; case 'h': s += sprintf(s,"ur "); break; case 's': s += sprintf(s,"dr "); break; case 'm': s += sprintf(s,"dl "); break; case 'l': s += sprintf(s,"ul "); break; default: fatalError("ERROR: BAD PHONEME CHARACTER: %c\n in '%s'\n", *m,mwanemes); } ASSERT(s-buf < MAX_TOKENS*4 - 10); m++; } *s = 0; return buf; } //=========================================================================== // describeSpells() //=========================================================================== static void describeSpells(PSpell *slist) { static char *u = "------------------------------------------------------"; PSpell *s; printf("Description of spells\n"); printf("---------------------\n"); printf(" %20s %20s %8s %4s %4s %4s %s\n", "name", "mwanemes", "flags", "mxsc", "hold", "id", "mwaneme description"); printf(" %.20s %.20s %.8s %.4s %.4s %.4s %.19s\n", u,u,u,u,u,u,u); for (s=slist; s->name; s++) { printf(" %20s %20s %08x %4d %4d %4d %s\n", s->name, s->mwanemes, s->flags, s->maxscore, s->holdoff, s->id, mwanemeDescStr(s->mwanemes)); if (OPT_onespell) break; } } //=========================================================================== // motionTokenStr() //=========================================================================== static char *motionTokenStr(unsigned int tok) { static char buf[10]; int oct = a2oct(TOKEN_ANGLE(tok)); int dir = TOKEN_DIR(tok); if (tok==MTOKEN_END) { return " END"; } switch(TOKEN_SHAPE(tok)) { case MSHP_PAUSE: sprintf(buf,"PAUSE"); break; case MSHP_CLEAN_CIRCLE: sprintf(buf," %3s%s",dir<0?" CW":"CCW",octStr2[oct]); break; case MSHP_CLEAN_CIRCLE_PLUS: sprintf(buf,"+%3s%s",dir<0?" CW":"CCW",octStr2[oct]); break; case MSHP_DIRTY_CIRCLE: sprintf(buf," %3s%s",dir<0?" cw":"ccw",octStr2[oct]); break; case MSHP_DIRTY_CIRCLE_PLUS: sprintf(buf,"+%3s%s",dir<0?" cw":"ccw",octStr2[oct]); break; case MSHP_PULSE: sprintf(buf," p%s",octStr2[oct]); break; case MSHP_PULSE_PLUS: sprintf(buf," +P%s",octStr2[oct]); break; case MSHP_CIRCLE_GAP: sprintf(buf,"G%3s%s",dir<0?" cw":"ccw",octStr2[oct]); break; default: sprintf(buf,"?????"); break; } return buf; } //=========================================================================== // lookPrint() //=========================================================================== static void lookPrint(Motion *mlist, int mcnt) { Motion *m, *mp; if (OPT_silent) return; mp = 0; #if 0 && !MINIMAL for (m=mlist; m; mp=m, m = m->c_next) { if (m->b_angle == 0xff) { printf("AA 0x%08x: %04x Pause\n", m->b_atime, m->c_time ); } else { printf("AA 0x%08x: %04x shape=%d %s a=%02x %c %d%s %s d=%2d imp=%04x %04x MaxDMag=%02x maxStep=%02x " "ad=%3d flg=%02x %s %02x %s\n", m->b_atime, m->c_time, m->c_shape, motionShapeStr[m->c_shape], m->b_angle, quadStr[a2quad(m->b_angle)][0], m->c_oct, octStr[m->c_oct], octStr2[m->c_oct], m->c_dir, m->c_imp, m->c_isum, m->c_maxdmag, m->c_maxstep, (m==mlist || m->b_angle == 0xff || mp->b_angle == 0xff) ? 0:adiff(m->b_angle,mp->b_angle), m->b_flags, flagStr(m->b_flags), m->token, motionTokenStr(m->token)); } } printf("\n\n"); #else for (m=mlist; m; mp=m, m = m->c_next) { if (m->b_angle == 0xff) { printf("AA2 0x%08x: %04x Pause\n", m->b_atime, m->b_dtime); } else { printf("AA2 0x%08x: %04x shape=%d %s a=%02x %c %d%s %s d=%2d imp=%04x %04x MaxDMag=%02x maxStep=%02x " "ad=%3d flg=%02x %s %02x %s\n", m->b_atime, m->b_dtime, 0, //m->c_shape, motionShapeStr[m->c_shape], m->b_angle, quadStr[a2quad(m->b_angle)][0], a2oct(m->b_angle), octStr[a2oct(m->b_angle)], octStr2[a2oct(m->b_angle)], m->c_dir, m->c_imp, 0, //m->c_isum, m->b_deltamag, //m->c_maxdmag, 0, //m->c_maxstep, (m==mlist || m->b_angle == 0xff || mp->b_angle == 0xff) ? 0:adiff(m->b_angle,mp->b_angle), m->b_flags, flagStr(m->b_flags), 0, //m->token, motionTokenStr(m->token)); } } printf("\n\n"); #endif } //=========================================================================== // stringMotion() //=========================================================================== static char *stringMotion(char *str, Motion *mlist, Motion *m) { static char strBuf[1000]; char *s = strBuf; if (mlist && ((unsigned int)(m-mlist)<CNT_MAX)) { s+=sprintf(s,"%smlist[%3d] = %08x = ",str,m-mlist, OPT_noaddr?0:(int)m); } else { s+=sprintf(s,"%smlist[??] = %08x = ",str, OPT_noaddr?0:(int)m); } if (m->b_angle == 0xff) { s+=sprintf(s,"0x%08x: %04x Pause a=%02x sh=%02x", m->b_atime, m->b_dtime, m->b_angle, m->c_shape & MSHF_SHP_MASK); } else { s+=sprintf(s,"0x%08x: %3s%s a=%02x %d %c imp=%04x mag=%02x sh=%02x: %s %s%s%s%s%s%s%s dmag=%02x %02x (%5.3f)" " flg=%02x %s", m->b_atime, (m->c_dir<0)?" cw":"ccw", m->b_flags & MFLG_MONO ? " ":"?", m->b_angle, a2oct(m->b_angle), octStr2[a2oct(m->b_angle)][0], m->c_imp ? m->c_imp : m->b_imp, m->b_maxmag, m->c_shape & MSHF_SHP_MASK, //m->c_shape, motionShapeStr[m->c_shape & MSHF_SHP_MASK], m->b_flags & MFLG_CIRCLE ? "C" : " ", (m->c_prev && m->c_prev->c_shape==MSHP_PAUSE)? "P" : " ", m->b_flags & MFLG_MONO ? "M" : " ", (m->c_dir<0) ? "D" : " ", m->b_flags & MFLG_ZERO ? "Z" : " ", m->b_flags & MFLG_BEST_MAG ? "G" : " ", m->b_flags & MFLG_BEST_IMP ? "I" : " ", m->b_maxmag-m->b_minmag, m->b_deltamag, (double)m->b_deltamag/(double)m->b_maxmag, m->b_flags, flagStr(m->b_flags)); } return strBuf; } //=========================================================================== // stringMotion2() //=========================================================================== static char *stringMotion2(char *str, Motion2 *mlist, Motion2 *m) { static char strBufList[4][1000]; static char *strBuf = 0; char *s; if (strBuf == strBufList[3]) { strBuf = strBufList[0]; } else if (strBuf == strBufList[0]) { strBuf = strBufList[1]; } else if (strBuf == strBufList[1]) { strBuf = strBufList[2]; } else { strBuf = strBufList[3]; } s = strBuf; if (mlist) { s+=sprintf(s,"%smlist[%3d] = %08x = ",str,m-mlist, OPT_noaddr?0:(int)m); } else { s+=sprintf(s,"%smlist[??] = %08x = ",str, OPT_noaddr?0:(int)m); } if (m->angle & AFLG_START) { s+=sprintf(s,"START"); return strBuf; } if (m->angle & AFLG_END) { s+=sprintf(s,"END"); return strBuf; } s+=sprintf(s," %3s%s a=%02x %d %s imp=%04x mag=%02x sh=%02x: %s %s%s%s%s%s", (m->shape & MSHF_DIR)?" cw":"ccw", m->shape & MSHF_MONO ? " ":"?", m->angle, a2oct(m->angle), octStr2[a2oct(m->angle)], m->imp, m->maxmag, m->shape & MSHF_SHP_MASK, motionShapeStr[m->shape & MSHF_SHP_MASK], m->shape & MSHF_CIRCLE ? "C" : " ", m->shape & MSHF_PREV_PAUSE ? "P" : " ", m->shape & MSHF_MONO ? "M" : " ", m->shape & MSHF_DIR ? "D" : " ", ""); return strBuf; } //=========================================================================== // printMotion() //=========================================================================== static void printMotion(char *str, Motion *mlist, Motion *m, int color) { if (OPT_silent) return; if (color >= 0 && color <= 7) { printf("%s",colorStr(color)); } printf("%s",stringMotion(str,mlist,m)); printf("%s\n",colorStr(-1)); } //=========================================================================== // printMotion2() //=========================================================================== static void printMotion2(char *str, Motion2 *mlist, Motion2 *m, int color) { if (OPT_silent) return; if (color >= 0 && color <= 7) { printf("%s",colorStr(color)); } printf("%s",stringMotion2(str,mlist,m)); printf("%s\n",colorStr(-1)); } //=========================================================================== // all3Print() //=========================================================================== static void all3Print(Motion *mlist, Motion2 *m2list_min, Motion2 *m2list_pic) { int show_orig = 1; int show_min = 1; int show_pic = 1; char *str1, *str2, *str3; char *s1, *s2, *s3; Motion *m = mlist; Motion2 *mm = m2list_min; Motion2 *mp = m2list_pic; Motion2 *ma; int waspausec = 0; int waspausep = 0; int skipcnt; if (OPT_silent) return; printMotion2("Mini ",m2list_min,mm,2); mm++; printMotion2("Pic ",m2list_min,mp,4); mp++; while(1) { int err=0; if (mm && (mm->angle & AFLG_END)) mm = 0; if (mp && (mp->angle & AFLG_END)) mp = 0; if (!m && !mm && !mp) break; printf("\n"); str1 = m ? stringMotion("Orig ",mlist,m) : "Orig END:"; str2 = mm ? stringMotion2("Mini ",m2list_min, mm) : "Mini END"; str3 = mp ? stringMotion2("Pic ",m2list_pic,mp) : "Pic END"; ma = mm ? mm : mp; if (!ma) { m = m ? m->c_next : 0; } else if (!m) { mm = mm ? mm+1 : mm; mp = mp ? mp+1 : mp; } else if ((ma->shape & MSHF_SHP_MASK) == MSHP_CIRCLE_GAP && m->c_shape != MSHP_CIRCLE_GAP) { str1 = "Orig --:"; mm = mm ? mm+1 : mm; mp = mp ? mp+1 : mp; if (show_orig) { err=1; } } else if ((ma->shape & MSHF_SHP_MASK) != MSHP_CIRCLE_GAP && m->c_shape == MSHP_CIRCLE_GAP) { str2 = "Mini --:"; str3 = "Pic --:"; m = m->c_next; if (show_min && show_pic) { err=1; } } else if (mm && (mm->shape & MSHF_PREV_PAUSE) && !waspausec && mp && (mp->shape & MSHF_PREV_PAUSE) && !waspausep) { waspausec = 1; waspausep = 1; str2 = "Mini PAUSE"; str3 = "Pic PAUSE"; m = m->c_next; } else if (mm && (mm->shape & MSHF_PREV_PAUSE) && !waspausec) { waspausec = 1; waspausep = 0; str2 = "Mini PAUSE"; mp = mp ? mp+1 : mp; m = m->c_next; } else if (mp && (mp->shape & MSHF_PREV_PAUSE) && !waspausep) { waspausep = 1; waspausec = 0; str3 = "Pic PAUSE"; mm = mm ? mm+1 : mm; m = m->c_next; } else { waspausec = 0; waspausep = 0; mm = mm ? mm+1 : mm; mp = mp ? mp+1 : mp; m = m->c_next; } do { int c1=0, c2=0, c3=0; int cnt = 0; skipcnt = 0; if (err) break; s1 = str1; s2 = str2; s3 = str3; while(1) { cnt++; if (*s1 == ':') c1++; if (*s2 == '=') c2++; if (*s3 == '=') c3++; if (c1) { skipcnt = cnt; break; } if (c2 == 2) { skipcnt = cnt; c2++; } if (c3 == 2) { skipcnt = cnt; c3++; } s1 = *s1 ? s1+1 : s1; s2 = *s2 ? s2+1 : s2; s3 = *s3 ? s3+1 : s3; } } while(0); if (show_orig) { int cnt = 0; s1 = str1; s2 = str2; s3 = str3; printf("%s",colorStr(5)); while(cnt<skipcnt) { cnt++; printf("%c",*s1); s1 = *s1 ? s1+1 : s1; s2 = *s2 ? s2+1 : s2; s3 = *s3 ? s3+1 : s3; } printf("%c",*s1); s1 = *s1 ? s1+1 : s1; s2 = *s2 ? s2+1 : s2; s3 = *s3 ? s3+1 : s3; while(1) { if (*s1 == 0) break; if ((*s1 == *s2 || *s2==0) && !err) { printf("%s",colorStr(5)); } else { printf("%s",colorStr(1)); } printf("%c",*s1); s1 = *s1 ? s1+1 : s1; s2 = *s2 ? s2+1 : s2; s3 = *s3 ? s3+1 : s3; } printf("%s\n",colorStr(-1)); } if (show_min) { int cnt = 0; s1 = str1; s2 = str2; s3 = str3; printf("%s",colorStr(2)); while(cnt<skipcnt) { cnt++; printf("%c",*s2?*s2:' '); s1 = *s1 ? s1+1 : s1; s2 = *s2 ? s2+1 : s2; s3 = *s3 ? s3+1 : s3; } printf("%c",*s2?*s2:' '); s1 = *s1 ? s1+1 : s1; s2 = *s2 ? s2+1 : s2; s3 = *s3 ? s3+1 : s3; while(1) { int e = err; if (*s2 == 0) break; if (show_orig) { if (*s1 != *s2 && *s1) e=1; } if (show_pic) { if (*s3 != *s2 && *s3) e=1; } if (!e) { printf("%s",colorStr(2)); } else { printf("%s",colorStr(1)); } printf("%c",*s2); s1 = *s1 ? s1+1 : s1; s2 = *s2 ? s2+1 : s2; s3 = *s3 ? s3+1 : s3; } printf("%s\n",colorStr(-1)); } if (show_pic) { int cnt = 0; s1 = str1; s2 = str2; s3 = str3; printf("%s",colorStr(4)); while(cnt<skipcnt) { cnt++; printf("%c",*s3?*s3:' '); s1 = *s1 ? s1+1 : s1; s2 = *s2 ? s2+1 : s2; s3 = *s3 ? s3+1 : s3; } printf("%c",*s3?*s3:' '); s1 = *s1 ? s1+1 : s1; s2 = *s2 ? s2+1 : s2; s3 = *s3 ? s3+1 : s3; while(1) { if (*s3 == 0) break; if ((*s2 == *s3 || *s2==0) && !err) { printf("%s",colorStr(4)); } else { printf("%s",colorStr(1)); } printf("%c",*s3); s1 = *s1 ? s1+1 : s1; s2 = *s2 ? s2+1 : s2; s3 = *s3 ? s3+1 : s3; } printf("%s\n",colorStr(-1)); } } printf("\n\n"); } #if 0 //=========================================================================== // bothPrint() //=========================================================================== static void bothPrint(Motion *mlist, Motion2 *m2list) { char *str1, *str2; char *s1, *s2; Motion *m = mlist; Motion2 *m2 = m2list; int waspause = 0; if (OPT_silent) return; printMotion2("Mini ",m2list,m2,-1); m2++; while(1) { int err=0; if (!m && !m2) break; if (m2->angle & AFLG_END) m2 = 0; str1 = m ? stringMotion("Orig ",mlist,m) : "Orig END:"; str2 = m2 ? stringMotion2("Mini ",m2list,m2) : "Mini END"; if (!m2) { m = m->c_next; } else if (!m) { m2++; } else if ((m2->shape & MSHF_SHP_MASK) == MSHP_CIRCLE_GAP && m->c_shape != MSHP_CIRCLE_GAP) { str1 = "Orig --:"; m2++; err=1; } else if ((m2->shape & MSHF_SHP_MASK) != MSHP_CIRCLE_GAP && m->c_shape == MSHP_CIRCLE_GAP) { str2 = "Mini --:"; m = m->c_next; err=1; } else if ((m2->shape & MSHF_PREV_PAUSE) && !waspause) { waspause = 1; str2 = "Mini PAUSE"; m = m->c_next; } else { waspause = 0; m2++; m = m->c_next; } s1 = str1; s2 = str2; printf("%s",colorStr(5)); while(1) { if (*s1 == ':') break; printf("%c",*s1); s1 = *s1 ? s1+1 : s1; s2 = *s2 ? s2+1 : s2; } printf("%c",*s1); s1 = *s1 ? s1+1 : s1; s2 = *s2 ? s2+1 : s2; while(1) { if (*s1 == 0) break; if ((*s1 == *s2 || *s2==0) && !err) { printf("%s",colorStr(5)); } else { printf("%s",colorStr(3)); } printf("%c",*s1); s1 = *s1 ? s1+1 : s1; s2 = *s2 ? s2+1 : s2; } printf("%s\n",colorStr(-1)); s1 = str1; s2 = str2; while(1) { if (*s1 == ':') break; printf("%c",*s2?*s2:' '); s1 = *s1 ? s1+1 : s1; s2 = *s2 ? s2+1 : s2; } printf("%c",*s2?*s2:' '); s1 = *s1 ? s1+1 : s1; s2 = *s2 ? s2+1 : s2; while(1) { if (*s2 == 0) break; if ((*s1 == *s2 || *s1==0) && !err) { printf("%s",colorStr(-1)); } else { printf("%s",colorStr(3)); } printf("%c",*s2); s1 = *s1 ? s1+1 : s1; s2 = *s2 ? s2+1 : s2; } printf("%s\n",colorStr(-1)); } printf("\n\n"); } #endif //=========================================================================== // initialPrint() - print initial motion data //=========================================================================== static void initialPrint(Motion *mlist) { Motion *m; if (OPT_silent) return; for (m=mlist; m->b_angle != 0xfe; m++) { if (m->b_angle == 0xff) { printf("AA1 0x%08x: %04x Pause\n", m->b_atime, m->b_dtime); } else { printf("AA1 0x%08x: %04x a=%02x %c %c imp=%04x mag=%02x %02x %02x dmag=%02x %02x (%5.3f)" " flg=%02x %s\n", m->b_atime, m->b_dtime, m->b_angle, quadStr[a2quad(m->b_angle)][0], octStr2[a2oct(m->b_angle)][0], m->b_imp, m->b_minmag, 0, //m->b_avgmag, m->b_maxmag, m->b_maxmag-m->b_minmag, m->b_deltamag, (double)m->b_deltamag/(double)m->b_maxmag, m->b_flags, flagStr(m->b_flags)); } } printf("\n\n"); } //=========================================================================== // parse1_minimal() //=========================================================================== static void parse1_minimal(Motion *mlist, Motion2 *m2list) { Motion *m; Motion2 *md; int maxstep = 0; int maxdmag = 0; int asum = 0; int shape; int maxmag; int imp; int angle; int shape_flags; int mo_imp; int mo_minmag; int mo_maxmag; int mo_angle; int mo_flags; int mo_dir; int mo_oct; int prev_mo_oct; int prev_mo_angle; int step; int was_just_pause; int restart; int got_angle; int got_dir; int dbg_got_mo_dir = 0; int dbg_atime = 0; int dbg_atimes = 0; int dbg = DBG_PARSE1_MINIMAL; m = mlist; md = m2list; if (!OPT_silent) { printf("\nstart parse1_minimal\n"); } angle = ANGLE_START; // w_shp_write md->shape = shape; md->maxmag = maxmag; md->angle = angle; md->imp = imp; md->dbg_atime = 0; printMotion2("WRITE ",m2list,md,4); md++; was_just_pause = 1; got_angle = 0; got_dir = 0; mo_dir = 0; while(1) { prev_mo_angle = mo_angle; prev_mo_oct = mo_oct; step = 0; // w_mo_read mo_imp = m->b_imp; mo_minmag = m->b_minmag; // only used for deltamag mo_maxmag = m->b_maxmag; mo_angle = m->b_angle; mo_flags = m->b_flags; dbg_atime = m->b_atime; printMotion("READ ",mlist,m,2); m++; mo_oct = a2oct(mo_angle); if (mo_angle & 0x80) { if (was_just_pause) { if (mo_angle == 0xfe) break; continue; } restart = 1; } else if (was_just_pause) { restart = 1; got_angle = 0; } else { if (mo_oct != prev_mo_oct) restart = 1; step = adiff(mo_angle, prev_mo_angle); mo_dir = 0; if (step < 0) { step = -step; mo_dir = MSHF_DIR; } dbg_got_mo_dir = 1; } if (dbg) { printf(" restart=%d mo_dir=%02x shape_flags=%02x wjpause=%d\n", restart,mo_dir,shape_flags,was_just_pause); } if (restart) { if (got_angle) { asum += step; if (step > maxstep) { maxstep = step; } shape = MSHP_PULSE; if (!got_dir) { shape_flags &= ~MSHF_MONO; } if ((mo_dir ^ shape_flags) & MSHF_DIR) { shape_flags &= ~MSHF_MONO; } if ((shape_flags & MSHF_MONO) == 0) { // pulse } else if (shape_flags & MSHF_PREV_PAUSE) { // pulse } else if (mo_angle & 0x80) { // pulse } else if (asum < 4) { // pulse } else if (maxstep>5) { // pulse } else { shape = MSHP_DIRTY_CIRCLE; if (maxstep>3) { // dirty circle } else if (maxdmag >=8) { // dirty circle } else if (shape_flags & MSHF_ZERO) { // dirty circle } else { shape = MSHP_CLEAN_CIRCLE; } } if (dbg) { printf(" shape=%02x shape_flags=%02x mo_dir=%02x\n", shape,shape_flags,mo_dir); } shape |= (shape_flags & MSHF_FLG_MASK); if ((shape & MSHF_MONO) == 0) { shape &= ~MSHF_DIR; } // w_shp_write md->shape = shape; md->maxmag = maxmag; md->angle = angle; md->imp = imp; md->dbg_atime = dbg_atimes; printMotion2("WRITE ",m2list,md,4); md++; } if (mo_angle == 0xfe) break; if (dbg) { printf(" RESTART\n"); } asum = 0; imp = 0; maxstep = 0; maxdmag = 0; maxmag = 0; got_angle = 0; #if 0 got_dir=0; #endif shape_flags &= MSHF_DIR; shape_flags |= MSHF_MONO; restart = 0; dbg_atimes = dbg_atime; } if (mo_angle & 0x80) { was_just_pause = 1; } else { int dmag; if (dbg) { printf(" DIR: wjp=%d got_dir=%d got_angle=%d mo_dir=%02x " "shape_flags=%02x mo_flags=%02x\n", was_just_pause,got_dir,got_angle, mo_dir,shape_flags,mo_flags); } if (was_just_pause) { was_just_pause = 0; got_dir = 0; dbg_got_mo_dir = 0; shape_flags |= MSHF_PREV_PAUSE; if (OPT_use_classic) { shape_flags &= ~MSHF_MONO; } } else { ASSERT(dbg_got_mo_dir); if (!got_dir) { shape_flags &= ~MSHF_DIR; shape_flags |= mo_dir & MSHF_DIR; } if (dbg) { printf(" DIR2: mo_dir=%02x shape_flags=%02x ^=%02x " "MSHF_DIR=%02x RES=%02x\n", mo_dir,shape_flags,mo_dir ^ shape_flags,MSHF_DIR, ((mo_dir ^ shape_flags) & MSHF_DIR)); } if ((mo_dir ^ shape_flags) & MSHF_DIR) { shape_flags &= ~(MSHF_MONO | MSHF_DIR); shape_flags |= mo_dir & MSHF_DIR; } if (dbg) { printf(" DIR2: shape_flags=%02x\n",shape_flags); } got_dir = 1; } got_angle = 1; imp += mo_imp; if (mo_maxmag > maxmag) { maxmag = mo_maxmag; angle = mo_angle; dbg_atimes = dbg_atime; } ASSERT(MSHF_ZERO == MFLG_ZERO); shape_flags |= (mo_flags & MSHF_ZERO); dmag = mo_maxmag - mo_minmag; if (mo_flags & MSHF_ZERO) { dmag = mo_maxmag; } if (dmag > maxdmag) { maxdmag = dmag; } asum += step; if (maxstep < step) { maxstep = step; } } } angle = ANGLE_END; // w_shp_write md->shape = shape; md->maxmag = maxmag; md->angle = angle; md->imp = imp; md->dbg_atime = dbg_atimes; printMotion2("WRITE ",m2list,md,4); md++; printf("%s",colorStr(-1)); if (!OPT_silent) { printf("end parse1_minimal\n\n"); } } //=========================================================================== // parse1_pic() //=========================================================================== static void parse1_pic(Motion *mlist, Motion2 *m2list) { #if USE_PIC_PARSE1 eraseLocalVars(); writeM1List(mlist, RAMBUF_ACC); w_mo1_parse1(); if (!OPT_silent || !USE_PIC_FILLGAP) { readM2List(m2list, RAMBUF_M2LIST); } #else parse1_minimal(mlist,m2list); #endif } //=========================================================================== // parse1() //=========================================================================== static void parse1(Motion *mlist, int mcnt) { Motion *m; Motion *ms = 0; int maxstep = 0; int maxdmag = 0; int asum = 0; #if 0 if (MINIMAL) { parse1_minimal(mlist,cnt); return; } #endif for (m=mlist; ; m++) { int o = a2oct(m->b_angle); int restart = 0; int ad = 0; int step = 0; int dir = 0; if (m->b_angle == 0xfe) { if (!OPT_use_classic) { if (m->c_prev) { m->c_prev->c_next = 0; } } m = 0; } if (!m || !ms) { restart = 1; } else if (m->b_angle == 0xff) { restart = ms->b_angle != 0xff; } else if (ms->b_angle == 0xff) { restart = 1; } else { restart = o != a2oct(ms->b_angle); ad = adiff(m->b_angle, (m-1)->b_angle); step = ABS(ad); dir = ad < 0 ? -1 : 1; } if (step > maxstep) { maxstep = step; } if (restart) { if (ms) { #if !MINIMAL ms->c_maxdmag = maxdmag; #endif asum += step; if (dir != ms->c_dir) { ms->b_flags &= ~MFLG_MONO; } if ((ms->b_flags & MFLG_MONO) == 0) { asum = 0; ms->c_dir = 0; } // // default token is pause // ms->token = TOKEN_CREATE_MO(MSHP_PAUSE,0,0); if (ms->b_angle & 0x80) { ms->c_shape = MSHP_PAUSE; } else if (ms == mlist || !m || (ms-1)->b_angle == 0xff || m->b_angle==0xff) { ms->c_shape = MSHP_PULSE; } else if ((ms->b_flags&MFLG_MONO) && maxstep<=5 && asum >= 4) { ms->c_shape = MSHP_DIRTY_CIRCLE; if (maxstep<=3 && maxdmag<8 && (ms->b_flags & MFLG_ZERO)==0) { ms->c_shape = MSHP_CLEAN_CIRCLE; } } else { ms->c_shape = MSHP_PULSE; } #if !MINIMAL ms->c_asum = asum; #endif ms->c_next = m; if (m) m->c_prev = ms; } if (!m) break; ms = m; ms->c_dir = dir; #if !MINIMAL ms->c_cnt = 1; #endif ms->c_imp = ms->b_imp; #if !MINIMAL ms->c_time = ms->b_dtime; ms->c_oct = o; ASSERT(ms->c_oct == a2oct(ms->b_angle)); ms->c_maxstep = maxstep; #endif #if !MINIMAL ms->c_best_angle = ms->b_angle; ms->c_best_mag = ms->b_maxmag; #endif ms->b_flags |= MFLG_MONO; maxdmag = ms->b_deltamag; asum = step; maxstep = step; ms->c_next = 0; } else { #if !MINIMAL ms->c_cnt++; ms->c_time += m->b_dtime; #endif if (m->b_angle == 0xff) { // double pause - ignore } else { if (dir != ms->c_dir) { ms->b_flags &= ~MFLG_MONO; } ms->c_imp += m->b_imp; #if MINIMAL if (m->b_maxmag > ms->b_maxmag) { ms->b_angle = m->b_angle; ms->b_maxmag = m->b_maxmag; } #else if (m->b_maxmag > ms->c_best_mag) { ms->b_angle = m->b_angle; ms->b_maxmag = m->b_maxmag; ms->c_best_angle = m->b_angle; ms->c_best_mag = m->b_maxmag; } #endif ms->b_flags |= m->b_flags; maxdmag = MAX(maxdmag,m->b_deltamag); asum += step; } } } } //=========================================================================== // insertNode() //=========================================================================== static Motion *insertNode(Motion *mlist, Motion *prev) { // NOTE: MEMORY LEAK! these are never freed Motion *m = malloc(sizeof(Motion)); memcpy(m,prev,sizeof(*m)); m->c_prev = prev; m->c_next = prev->c_next; prev->c_next = m; if (prev->c_next) prev->c_next->c_prev = m; ASSERT(m->c_next && m->c_prev); #if 0 m->b_atime = m->c_next->b_atime; m->b_dtime = 0; #else m->b_atime = (m->c_prev->b_atime + m->c_next->b_atime)/2; m->b_dtime = m->c_next->b_atime - m->b_atime; m->c_prev->b_dtime = m->b_atime - m->c_prev->b_atime; #endif m->b_imp = 0; m->b_minmag = 0; m->b_maxmag = 0; m->b_deltamag = 0; //m->b_angle; //m->b_flags; //m->c_shape; #if !MINIMAL m->c_time = 0; m->c_maxstep = 0; m->c_cnt = 0; m->c_isum = 0; #endif m->c_imp = 0; //m->c_dir; //m->c_best_angle; //m->c_best_mag; //m->c_maxdmag; //m->c_asum; //m->token; return m; } //=========================================================================== // fillCircleGaps_minimal() //=========================================================================== static void fillCircleGaps_minimal(Motion2 *mlist) { Motion2 m3list[1000]; Motion2 *m, *mg, *md, *mgd, *ms, *msd; int cnt0, cnt1; int cnt1b; int oct, prev_oct, delta_oct; int gap_oct; int shape; int maxmag; int imp; int angle; int shape0; int added; int added_cnt; int dbg = DBG_FILLGAP_MINIMAL; int dbg_atime; int dbg_gap_atime; do { if (!OPT_silent) { printf("start fillCircleGaps_minimal\n"); } m = mlist; md = m3list; while(1) { // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; dbg_atime = m->dbg_atime; printMotion2("READ ",mlist,m,2); m++; // w_shp_write md->shape = shape; md->maxmag = maxmag; md->angle = angle; md->imp = imp; md->dbg_atime = dbg_atime; printMotion2("WRITE ",m3list,md,4); md++; if (angle & AFLG_END) break; } added = 0; added_cnt = 0; // // check for gaps in circles // ms = &m3list[1]; msd = mlist+1; while(1) { m = ms; md = msd; //breakpt(); // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; dbg_atime = m->dbg_atime; printMotion2("READ ",m3list,m,2); m++; if (angle & AFLG_END) break; ms = m; msd = md+1; shape0 = shape; cnt0 = cnt1 = 1-2; cnt1b = 0; oct = a2oct(angle); if (dbg) { printf("START: shape0=%02x oct=%d\n",shape0,oct); } while(1) { dbg_gap_atime = dbg_atime; // w_shp_write md->shape = shape; md->maxmag = maxmag; md->angle = angle; md->imp = imp; md->dbg_atime = dbg_atime; printMotion2("WRIT1 ",mlist,md,4); md++; prev_oct = oct; // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; dbg_atime = m->dbg_atime; printMotion2("READ ",m3list,m,2); m++; if (angle & AFLG_END) break; if (shape & MSHF_PREV_PAUSE) break; #if 1 oct = a2oct(angle); delta_oct = oct - prev_oct; delta_oct &= 7; if ((shape0 & MSHF_MONO) == 0) { shape0 = MSHF_MONO; if (delta_oct & 4) { shape0 |= MSHF_DIR; } } if (shape0 & MSHF_DIR) delta_oct = -delta_oct; delta_oct &= 7; if (shape & MSHF_MONO) { if ((shape^shape0) & MSHF_DIR) break; } #else if ((shape0 & MSHF_MONO) == 0) { shape0 = shape; } if (shape & MSHF_MONO) { if ((shape^shape0) & MSHF_DIR) break; } oct = a2oct(angle); delta_oct = oct - prev_oct; if (shape0 & MSHF_DIR) delta_oct = -delta_oct; delta_oct &= 7; #endif if (delta_oct != 1) break; if (dbg) { printf("OK: shape=%02x oct=%d delta_oct=%d\n", shape,oct,delta_oct); } cnt0++; } if (dbg) { printf("NOT OK: shape=%02x oct=%d delta_oct=%d\n", shape,oct,delta_oct); } if (angle & AFLG_END) break; m--; if (shape & MSHF_PREV_PAUSE) continue; if (shape & MSHF_MONO) { if ((shape^shape0) & MSHF_DIR) continue; } ASSERT(shape0 & MSHF_MONO); if (delta_oct != 2) continue; gap_oct = prev_oct+1; if (shape0 & MSHF_DIR) gap_oct -= 2; gap_oct &= 7; mg = m; mgd = md; m++; if (!OPT_silent || dbg) { printf("gap? cnt0=%d cnt1=%d oct=%d\n",cnt0+2,cnt1+2,oct); } dbg_gap_atime = (dbg_gap_atime + dbg_atime)/2; while(1) { // w_shp_write md->shape = shape; md->maxmag = maxmag; md->angle = angle; md->imp = imp; md->dbg_atime = dbg_atime; printMotion2("WRIT2 ",mlist,md,4); md++; prev_oct = oct; // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; dbg_atime = m->dbg_atime; printMotion2("READ ",m3list,m,2); m++; if (angle & AFLG_END) break; if (shape & MSHF_PREV_PAUSE) break; if (shape & MSHF_MONO) { if ((shape^shape0) & MSHF_DIR) break; } oct = a2oct(angle); delta_oct = oct - prev_oct; if (shape0 & MSHF_DIR) delta_oct = -delta_oct; delta_oct &= 7; if (delta_oct == 2) { cnt1b++; if (cnt1b > 1) break; } else if (delta_oct != 1) { break; } if (dbg) { printf("OK: shape=%02x oct=%d delta_oct=%d\n", shape,oct,delta_oct); } cnt1++; } m--; //breakpt(); if (dbg) { printf("check: cnt0=%d cnt1=%d\n",cnt0+2,cnt1+2); } if (cnt0>=2-2 && cnt1>=2-2 && (cnt0+cnt1 >= 6-2-2)) { shape = MSHP_CIRCLE_GAP|MSHF_MONO; shape |= shape0 & MSHF_DIR; maxmag = 0; imp = 0; angle = oct2a(gap_oct); ms = mg; md = mgd; // w_shp_write md->shape = shape; md->maxmag = maxmag; md->angle = angle; md->imp = imp; md->dbg_atime = dbg_gap_atime; printMotion2("WRIT3 ",mlist,md,5); md++; msd = md; added=1; added_cnt++; } } angle = ANGLE_END; // w_shp_write md->shape = shape; md->maxmag = maxmag; md->angle = angle; md->imp = imp; md->dbg_atime = dbg_atime; printMotion2("WRIT4 ",mlist,md,4); md++; if (!OPT_silent) { printf("end fillCircleGaps_minimal (added %d)\n",added_cnt); } } while(added); (void)dbg; } //=========================================================================== // fillCircleGaps_pic() //=========================================================================== static void fillCircleGaps_pic(Motion2 *mlist) { #if USE_PIC_FILLGAP eraseLocalVars(); #if !USE_PIC_PARSE1 writeM2List(mlist, RAMBUF_M2LIST); #endif w_mo2_fill_circle_gaps(); if (!OPT_silent || !USE_PIC_FINDWEAK) { readM2List(mlist, RAMBUF_M2LIST); } #else fillCircleGaps_minimal(mlist); #endif } //=========================================================================== // fillCircleGaps() //=========================================================================== static int fillCircleGaps(Motion *mlist, int mcnt) { Motion *ms, *m, *mg; int cnt0, cnt1; int oct0, oct; int added = 0; if (!OPT_silent) { printf("start fillCircleGaps\n"); } // // check counter-clockwise circles (dir == 1) // for (ms=mlist; ms; ) { printMotion("READ1 ",mlist,ms,2); if (ms->c_dir < 0) { ms = ms->c_next; continue; } cnt0 = 1; #if !MINIMAL ASSERT(ms->c_oct == a2oct(ms->c_best_angle)); #endif #if MINIMAL oct0 = a2oct(ms->b_angle); #else oct0 = ms->c_oct; #endif for (m=ms->c_next; m; m=m->c_next) { printMotion("READ2 ",mlist,m,2); if (m->c_dir < 0) { break; } #if MINIMAL oct = a2oct(m->b_angle); #else oct = m->c_oct; #endif if (((oct - oct0)&7) != 1) break; cnt0++; oct0 = oct; } if (!m) break; if (m->c_dir < 0 || ((oct - oct0)&7) != 2) { ms = m; continue; } mg = m; cnt1 = 1; oct0 = oct; for (m=m->c_next; m; m=m->c_next) { printMotion("READ3 ",mlist,m,2); oct = a2oct(m->b_angle); if (((oct - oct0)&7) != 1) break; cnt1++; oct0 = oct; } if (cnt0>=2 && cnt1>=2 && (cnt0+cnt1 > 5)) { m = insertNode(mlist,mg->c_prev); m->c_dir = 1; #if !MINIMAL m->c_maxstep = 0; #endif #if MINIMAL { int o = a2oct(mg->b_angle); o = (o-1) & 7; m->b_angle = oct2a(o); } #else m->c_oct = (mg->c_oct - 1) & 7; m->c_best_angle = oct2a(m->c_oct); m->b_angle = m->c_best_angle; #endif m->b_flags = MFLG_MONO | MFLG_MISSING_CIRCLE; m->c_shape = MSHP_CIRCLE_GAP; printMotion("INS4 ",mlist,m,5); added++; } ms = ms->c_next; } // // check clockwise circles (dir == -1) // for (ms=mlist; ms; ) { printMotion("READ5 ",mlist,ms,2); if (ms->c_dir > 0) { ms = ms->c_next; continue; } cnt0 = 1; oct0 = a2oct(ms->b_angle); for (m=ms->c_next; m; m=m->c_next) { printMotion("READ6 ",mlist,m,2); if (m->c_dir > 0) { break; } oct = a2oct(m->b_angle); if (((oct - oct0)&7) != 7) break; cnt0++; oct0 = oct; } if (!m) break; if (m->c_dir > 0 || ((oct - oct0)&7) != 6) { ms = m; continue; } mg = m; cnt1 = 1; oct0 = oct; for (m=m->c_next; m; m=m->c_next) { printMotion("READ7 ",mlist,m,2); oct = a2oct(m->b_angle); if (((oct - oct0)&7) != 7) break; cnt1++; oct0 = oct; } if (cnt0>=2 && cnt1>=2 && (cnt0+cnt1 > 5)) { m = insertNode(mlist,mg->c_prev); m->c_dir = -1; #if !MINIMAL m->c_maxstep = 0; #endif #if MINIMAL { int o = a2oct(mg->b_angle); o = (o+1) & 7; m->b_angle = oct2a(o); } #else m->c_oct = (mg->c_oct + 1) & 7; m->c_best_angle = oct2a(m->c_oct); m->b_angle = m->c_best_angle; #endif m->b_flags = MFLG_MONO | MFLG_MISSING_CIRCLE; m->c_shape = MSHP_CIRCLE_GAP; printMotion("INS8 ",mlist,m,5); added++; } ms = ms->c_next; } if (!OPT_silent) { printf("end fillCircleGaps (added %d)\n",added); } return added; } //=========================================================================== // findWeakCircles_minimal() //=========================================================================== static void findWeakCircles_minimal(Motion2 *mlist) { Motion2 *ms, *m, *m2; int dcnt, ccnt; int shape; int maxmag; int imp; int angle; int shp; if (!OPT_silent) { printf("start findWeakCircles_minimal\n"); } m=mlist+1; while(1) { ms = m; ccnt = dcnt = 0; while(1) { // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; if (angle & AFLG_END) break; if (shape & MSHF_PREV_PAUSE) break; shp = shape & MSHF_SHP_MASK; if (shp == MSHP_DIRTY_CIRCLE) { dcnt++; } else if (shp == MSHP_CLEAN_CIRCLE) { ccnt++; #if ALLOW_GAPS_IN_STRONG_CIRCLES } else if (shp == MSHP_CIRCLE_GAP) { #endif } else { break; } } m2 = m-1; m = ms; if (ccnt > 4 || (ccnt>0 && ccnt+dcnt>5)) { while(1) { m->shape |= MSHF_CIRCLE; m++; if (m == m2) break; } } else if (ccnt > 0) { while(1) { if ((m->shape & MSHF_SHP_MASK) == MSHP_CLEAN_CIRCLE) { m->shape = (m->shape & MSHF_FLG_MASK) | MSHP_DIRTY_CIRCLE; } m++; if (m == m2) break; } } else { if (angle & AFLG_END) break; m++; } } if (!OPT_silent) { printf("end findWeakCircles_minimal\n"); } } //=========================================================================== // findWeakCircles_pic() //=========================================================================== static void findWeakCircles_pic(Motion2 *mlist) { #if USE_PIC_FINDWEAK eraseLocalVars(); #if !USE_PIC_FILLGAP writeM2List(mlist, RAMBUF_M2LIST); #endif w_mo3_find_weak_circles(); if (!OPT_silent || !USE_PIC_FINDPULSE) { readM2List(mlist, RAMBUF_M2LIST); } #else findWeakCircles_minimal(mlist); #endif } //=========================================================================== // findWeakCircles() //=========================================================================== static void findWeakCircles(Motion *mlist, int mcnt) { Motion *ms, *m, *m2; int dcnt, ccnt; if (!OPT_silent) { printf("start findWeakCircles\n"); } for (ms=mlist; ms; ) { ccnt = dcnt = 0; for (m=ms; m; m=m->c_next) { if (m->c_shape == MSHP_DIRTY_CIRCLE) { dcnt++; } else if (m->c_shape == MSHP_CLEAN_CIRCLE) { ccnt++; } else if (OPT_use_classic) { break; #if ALLOW_GAPS_IN_STRONG_CIRCLES } else if (m->c_shape == MSHP_CIRCLE_GAP) { #endif } else { break; } } if (ccnt > 4 || (ccnt>0 && ccnt+dcnt>5)) { for (m2=ms; m2!=m; m2=m2->c_next) { m2->b_flags |= MFLG_CIRCLE; } m2 = ms->c_prev; if (m2->c_shape == MSHP_PULSE && (m2->b_flags & MFLG_MONO) && m2->c_dir == ms->c_dir) { int m2o = a2oct(m2->b_angle); int mso = a2oct(ms->b_angle); int d = odiff(m2o, mso); if (ABS(d) < 2) { m2->b_flags |= MFLG_CIRCLE; } } m2 = m->c_prev; if (m->c_shape == MSHP_PULSE && (m->b_flags & MFLG_MONO) && m->c_dir == ms->c_dir) { int m2o = a2oct(m2->b_angle); int mo = a2oct(m->b_angle); int d = odiff(mo, m2o); if (ABS(d) < 2) { m->b_flags |= MFLG_CIRCLE; } } } else if (ccnt>0) { for (m2=ms; m2!=m; m2=m2->c_next) { if (OPT_use_classic) { m2->c_shape = MSHP_DIRTY_CIRCLE; } else { ASSERT(m2->c_shape != MSHP_CLEAN_CIRCLE_PLUS); if (m2->c_shape == MSHP_CLEAN_CIRCLE) { m2->c_shape = MSHP_DIRTY_CIRCLE; } } } } ms = m==ms ? m->c_next : m; } if (!OPT_silent) { printf("end findWeakCircles\n"); } } #if 0 // // this version looks for short periods of time surrounded by gaps and // adds PLUS bit to the best one // //=========================================================================== // findBestPulses_minimal() //=========================================================================== static void findBestPulses_minimal(Motion2 *mlist) { Motion2 *m, *ms, *save_m; Motion2 *best_imp_m=0, *best_mag_m=0; int best_imp; int best_mag; int d; int isum = 0; int mo, mpo; int prev_angle; int shape; int maxmag; int imp; int angle; int shp; int cur_angle; int min_angle; int max_angle; if (!OPT_silent) { printf("start findBestPulses_minimal\n"); } m=mlist+1; while(1) { ms = m; best_imp_m = m; best_mag_m = m; // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; if (angle&AFLG_END) break; shp = shape & MSHF_SHP_MASK; if (shp == MSHP_CIRCLE_GAP) continue; best_imp = imp; isum = imp; best_mag = maxmag; cur_angle = min_angle = max_angle = 127; while(1) { prev_angle = angle; // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; if (angle&AFLG_END) break; if (shape & MSHF_PREV_PAUSE) break; shp = shape & MSHF_SHP_MASK; if (shp == MSHP_CIRCLE_GAP) break; d = adiff(angle,prev_angle); if (shp != MSHP_CLEAN_CIRCLE && (shape&MSHF_CIRCLE)==0) { if (ABS(d) > 5) break; } cur_angle += d; min_angle = MIN(min_angle,cur_angle); max_angle = MAX(max_angle,cur_angle); mo = a2oct(angle); mpo = a2oct(prev_angle); d = odiff(mo, mpo); if (ABS(d) > 1) break; if (maxmag > best_mag) { best_mag = maxmag; best_mag_m = m-1; } isum += imp; if (imp > best_imp) { best_imp = imp; best_imp_m = m-1; } } save_m = m-1; if (!OPT_silent) { printf("consider PLUS isum=%04x " "mag=m2list[%2d] (a%02x %02x %04x) " "imp=m2list[%2d] (a%02x %02x %04x) %d...%d " "a=%d-%d=%d\n", isum, best_mag_m-mlist, best_mag_m->angle&0x1f, best_mag_m->maxmag, best_mag_m->imp, best_imp_m-mlist, best_imp_m->angle&0x1f, best_imp_m->maxmag, best_imp_m->imp, ms-mlist, save_m-mlist-1, max_angle, min_angle, max_angle - min_angle); } if (isum >= 0x500 && max_angle - min_angle < 20) { if (best_imp_m != best_mag_m) { if (best_imp_m->angle == best_mag_m->angle) { best_imp_m = best_mag_m; if (!OPT_silent) { printf(" angle matches - use best_mag_m [%d]\n", best_mag_m-mlist); } } else { if (!OPT_silent) { printf(" reject: mag angle != imp angle\n"); } } } if (best_imp_m == best_mag_m) { m = best_imp_m; // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; m--; m->shape |= MSHF_PLUS; if (!OPT_silent) { printf(" set plus [%d]\n", best_mag_m-mlist); } } } m = save_m; } if (!OPT_silent) { printf("end findBestPulses_minimal\n"); } } #else #if 0 // // This version has a bunch of stuff - not that great // #define BEST_PULSES_ALG_2 1 #define BEST_PULSES_ALLOW_CIRCLES 1 #define BEST_PULSES_ALG_3 1 #define BEST_PULSES_ALG_4 1 #define BEST_PULSES_ALG_5 1 #define BEST_PULSES_BEST_MI 1 #define BEST_PULSES_BETTER_ISUM 1 #if BEST_PULSES_ALLOW_CIRCLES && !BEST_PULSES_ALG_2 #error "Bad combo ALLOW_CIRCLES requires ALG_2" #endif #if BEST_PULSES_ALG_3 && !BEST_PULSES_ALG_2 #error "Bad combo ALG_3 requires ALG_2" #endif #if BEST_PULSES_ALG_4 && !BEST_PULSES_ALG_3 #error "Bad combo ALG_4 requires ALG_3" #endif #if BEST_PULSES_ALG_5 && !BEST_PULSES_ALG_3 #error "Bad combo ALG_5 requires ALG_3" #endif //=========================================================================== // findBestPulses_minimal() //=========================================================================== static void findBestPulses_minimal(Motion2 *mlist) { Motion2 *m, *ms; Motion2 *best_imp_m=0, *best_mag_m=0; int best_imp; int best_mag; int d; int isum = 0; int mo, mpo; int was_clean_circle=0; int prev_angle; int shape; int maxmag; int imp; int angle; int shp; #if BEST_PULSES_ALG_3 int save_angle; #endif if (!OPT_silent) { printf("start findBestPulses_minimal\n"); } m=mlist+1; while(1) { ms = m; best_imp_m = m; best_mag_m = m; // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; if (angle&AFLG_END) break; shp = shape & MSHF_SHP_MASK; #if BEST_PULSES_ALG_2 if (shape & MSHF_PLUS) continue; if (shape & MSHF_NEAR_PLUS) continue; if (shp == MSHP_CIRCLE_GAP) continue; #else if (shp == MSHP_DIRTY_CIRCLE) { // keep going #if 1 if (shape & MSHF_CIRCLE) { continue; } #else if (was_clean_circle) { was_clean_circle = 0; continue; } #endif } else if (shp == MSHP_PULSE) { // keep going } else if (shp == MSHP_CLEAN_CIRCLE) { was_clean_circle = 1; continue; } else { was_clean_circle = 0; continue; } #endif was_clean_circle = 0; best_imp = imp; isum = imp; best_mag = maxmag; while(1) { prev_angle = angle; // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; if (angle&AFLG_END) break; if (shape & MSHF_PREV_PAUSE) break; shp = shape & MSHF_SHP_MASK; #if BEST_PULSES_ALG_2 if (shape & MSHF_PLUS) break; if (shape & MSHF_NEAR_PLUS) break; if (shp == MSHP_CIRCLE_GAP) break; #else if (shp == MSHP_DIRTY_CIRCLE) { if (m->shape & MSHF_CIRCLE) { break; } } else if (shp == MSHP_PULSE) { // keep going } else { break; } #endif d = adiff(angle,prev_angle); if (ABS(d) > 5) break; mo = a2oct(angle); mpo = a2oct(prev_angle); d = odiff(mo, mpo); if (ABS(d) > 1) break; if (maxmag > best_mag) { best_mag = maxmag; best_mag_m = m-1; } isum += imp; if (imp > best_imp) { best_imp = imp; best_imp_m = m-1; } } if (isum >= 0x500) { #if BEST_PULSES_BETTER_ISUM Motion2 *save_m = m; #if BEST_PULSES_BEST_MI best_imp_m = best_mag_m; #endif if (best_imp_m != best_mag_m) { if (!OPT_silent) { printf("ignore PLUS isum=%04x " "mag=m2list[%2d] (a%02x %02x %04x) " "imp=m2list[%2d] (a%02x %02x %04x) %d...%d\n", isum, best_mag_m-mlist, best_mag_m->angle&0x1f, best_mag_m->maxmag, best_mag_m->imp, best_imp_m-mlist, best_imp_m->angle&0x1f, best_imp_m->maxmag, best_imp_m->imp, ms-mlist, save_m-mlist-1); } } if (best_imp_m == best_mag_m) { m = best_mag_m; // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; #if BEST_PULSES_BEST_MI best_mag = maxmag; #endif save_angle = angle; isum = imp; m--; if (!OPT_silent) { printf("consider PLUS isum=%04x " "mag=m2list[%2d] (a%02x %02x %04x) " "imp=m2list[%2d] (a%02x %02x %04x) %d...%d\n", isum, best_mag_m-mlist, best_mag_m->angle&0x1f, best_mag_m->maxmag, best_mag_m->imp, best_imp_m-mlist, best_imp_m->angle&0x1f, best_imp_m->maxmag, best_imp_m->imp, ms-mlist, save_m-mlist-1); } // // add impulse from preceding motions // m--; while(1) { // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; if (angle & AFLG_START) break; if (shape & MSHF_PLUS) break; if (shape & MSHF_NEAR_PLUS) break; d = adiff(angle,save_angle); if (ABS(d) > 5) break; #if BEST_PULSES_BEST_MI if (maxmag > best_mag) { best_mag = maxmag; best_mag_m = m-1; } #endif m -= 1; isum += imp; if (!OPT_silent) { printf(" add isum=%04x " " m=m2list[%2d] (a%02x %02x %04x)\n", isum, m-mlist, angle&0x1f, maxmag, imp); } m -= 1; } // // set MSHF_NEAR_PLUS on following motions // m = best_mag_m; // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; while(1) { // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; if (angle & AFLG_END) break; if (shape & MSHF_PLUS) break; if (shape & MSHF_NEAR_PLUS) break; d = adiff(angle,save_angle); if (ABS(d) > 5) break; #if BEST_PULSES_BEST_MI if (maxmag > best_mag) { best_mag = maxmag; best_mag_m = m-1; } #endif m -= 1; isum += imp; if (!OPT_silent) { printf(" add isum=%04x " " m=m2list[%2d] (a%02x %02x %04x)\n", isum, m-mlist, angle&0x1f, maxmag, imp); } m += 1; } m = save_m; #if BEST_PULSES_BEST_MI if (best_mag_m != best_imp_m) { if (best_mag_m->angle != best_imp_m->angle) { isum = 0; if (!OPT_silent) { printf(" rej 1 PLUS isum=%04x " "mag=m2list[%2d] (a%02x %02x %04x) " "imp=m2list[%2d] (a%02x %02x %04x) %d...%d\n", isum, best_mag_m-mlist, best_mag_m->angle&0x1f, best_mag_m->maxmag, best_mag_m->imp, best_imp_m-mlist, best_imp_m->angle&0x1f, best_imp_m->maxmag, best_imp_m->imp, ms-mlist, save_m-mlist-1); } } } #endif if (isum >= 0x500) { if (!OPT_silent) { printf(" accept PLUS isum=%04x " "mag=m2list[%2d] (a%02x %02x %04x) " "imp=m2list[%2d] (a%02x %02x %04x) %d...%d\n", isum, best_mag_m-mlist, best_mag_m->angle&0x1f, best_mag_m->maxmag, best_mag_m->imp, best_imp_m-mlist, best_imp_m->angle&0x1f, best_imp_m->maxmag, best_imp_m->imp, ms-mlist, save_m-mlist-1); } best_imp_m = best_mag_m; } else { if (!OPT_silent) { printf(" reject PLUS isum=%04x " "mag=m2list[%2d] (a%02x %02x %04x) " "imp=m2list[%2d] (a%02x %02x %04x) %d...%d\n", isum, best_mag_m-mlist, best_mag_m->angle&0x1f, best_mag_m->maxmag, best_mag_m->imp, best_imp_m-mlist, best_imp_m->angle&0x1f, best_imp_m->maxmag, best_imp_m->imp, ms-mlist, save_m-mlist-1); } // // if this assert is triggered then consider using // BEST_PULSES_BETTER_ISUM code. Otherwise there is no // need. // ASSERT(!"BEST_PULSES_BETTER_ISUM is having an effect!!"); best_mag_m = 0; } } #endif if (best_imp_m == best_mag_m) { m = best_imp_m; // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; m--; #if BEST_PULSES_ALG_2 shp = shape & MSHF_SHP_MASK; if (shp == MSHP_CLEAN_CIRCLE && !BEST_PULSES_ALLOW_CIRCLES && (shape & MSHF_CIRCLE) != 0) { m->shape |= MSHF_NEAR_PLUS; if (!OPT_silent) { printf(" set NEAR_PLUS in m2list[%2d] (1)\n", m-mlist); } } else { m->shape |= MSHF_PLUS; if (!OPT_silent) { printf(" set PLUS in m2list[%2d]\n", m-mlist); } #if BEST_PULSES_ALG_3 save_angle = angle; #endif // // set MSHF_NEAR_PLUS on preceding motions // m--; while(1) { prev_angle = angle; // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; if (angle & AFLG_START) break; if (shape & MSHF_PLUS) break; if (shape & MSHF_NEAR_PLUS) break; #if !BEST_PULSES_ALG_5 #if !BEST_PULSES_ALG_4 d = adiff(angle,prev_angle); if (ABS(d) > 5) break; #endif mo = a2oct(angle); mpo = a2oct(prev_angle); d = odiff(mo, mpo); if (ABS(d) > 1) break; #endif #if BEST_PULSES_ALG_3 d = adiff(angle,save_angle); if (ABS(d) >= 8) break; #endif m -= 1; m->shape |= MSHF_NEAR_PLUS; if (!OPT_silent) { printf(" set NEAR_PLUS in m2list[%2d] (2)\n", m-mlist); } m -= 1; } // // set MSHF_NEAR_PLUS on following motions // m = best_imp_m; // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; while(1) { prev_angle = angle; // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; if (angle & AFLG_END) break; if (shape & MSHF_PLUS) break; if (shape & MSHF_NEAR_PLUS) break; #if !BEST_PULSES_ALG_5 #if !BEST_PULSES_ALG_4 d = adiff(angle,prev_angle); if (ABS(d) > 5) break; #endif mo = a2oct(angle); mpo = a2oct(prev_angle); d = odiff(mo, mpo); if (ABS(d) > 1) break; #endif #if BEST_PULSES_ALG_3 d = adiff(angle,save_angle); if (ABS(d) >= 8) break; #endif m -= 1; m->shape |= MSHF_NEAR_PLUS; if (!OPT_silent) { printf(" set NEAR_PLUS in m2list[%2d] (3)\n", m-mlist); } m += 1; } } #if 1 m = ms; #else m = ms+1; #endif #else m->shape |= MSHF_PLUS; #endif } } m--; } if (!OPT_silent) { printf("end findBestPulses_minimal\n"); } } #else // // This version should be identical to original // //=========================================================================== // findBestPulses_minimal() //=========================================================================== static void findBestPulses_minimal(Motion2 *mlist) { Motion2 *m, *ms; Motion2 *best_imp_m, *best_mag_m; int best_imp, best_mag; int d; int isum = 0; int mo, mpo; int shp; int prev_shp; int shape; int maxmag; int imp; int angle; int prev_angle; if (!OPT_silent) { printf("start findBestPulses\n"); } shp = -1; m = mlist + 1; while(1) { ms = m; // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; if (angle & AFLG_END) break; prev_shp = shp; shp = shape & MSHF_SHP_MASK; if (shp == MSHP_DIRTY_CIRCLE) { if (prev_shp == MSHP_CLEAN_CIRCLE) continue; } else if (shp != MSHP_PULSE) { continue; } best_imp_m = ms; best_mag_m = ms; best_mag = maxmag; best_imp = imp; isum = imp; while(1) { prev_angle = angle; ms = m; // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; if (angle & AFLG_END) break; if (shape & MSHF_PREV_PAUSE) { break; } shp = shape & MSHF_SHP_MASK; if (shp == MSHP_DIRTY_CIRCLE) { if (shape & MSHF_CIRCLE) break; } else if (shp != MSHP_PULSE) { break; } d = adiff(angle,prev_angle); if (ABS(d) > 5) break; mo = a2oct(angle); mpo = a2oct(prev_angle); d = odiff(mo, mpo); if (ABS(d) > 1) break; if (maxmag > best_mag) { best_mag = maxmag; best_mag_m = ms; } if (imp > best_imp) { best_imp = imp; best_imp_m = ms; } isum += imp; } if (isum >= 0x500) { if (best_imp_m == best_mag_m) { ASSERT((best_imp_m->shape & MSHF_SHP_MASK) == MSHP_PULSE || (best_imp_m->shape & MSHF_SHP_MASK) == MSHP_DIRTY_CIRCLE); m = best_imp_m; m->shape |= MSHF_PLUS; } } m = ms; } if (!OPT_silent) { printf("end findBestPulses\n"); } } #endif #endif //=========================================================================== // findBestPulses_pic() //=========================================================================== static void findBestPulses_pic(Motion2 *mlist) { #if USE_PIC_FINDPULSE eraseLocalVars(); #if !USE_PIC_FINDWEAK writeM2List(mlist, RAMBUF_M2LIST); #endif w_mo4_find_best_pulses(); if (!OPT_silent || !USE_PIC_MARKLAST) { readM2List(mlist, RAMBUF_M2LIST); } #else findBestPulses_minimal(mlist); #endif } //=========================================================================== // findBestPulses() //=========================================================================== static void findBestPulses(Motion *mlist, int mcnt) { Motion *m, *ms; Motion *best_imp=0, *best_mag=0; int d; int isum = 0; int mo, mpo; if (!OPT_silent) { printf("start findBestPulses\n"); } for (ms=mlist; ms; ms = ms->c_next) { if (ms->c_shape == MSHP_DIRTY_CIRCLE && ms->c_prev->c_shape == MSHP_CLEAN_CIRCLE) continue; if (ms->c_shape != MSHP_PULSE && ms->c_shape != MSHP_DIRTY_CIRCLE) continue; best_imp = ms; best_mag = ms; isum = ms->c_imp; for (m=ms->c_next; m; ms=m, m=m->c_next) { if (m->c_shape != MSHP_PULSE && m->c_shape != MSHP_DIRTY_CIRCLE) break; if (m->c_shape == MSHP_DIRTY_CIRCLE && (m->b_flags & MFLG_CIRCLE)) break; d = adiff(m->b_angle,m->c_prev->b_angle); if (ABS(d) > 5) break; mo = a2oct(m->b_angle); mpo = a2oct(m->c_prev->b_angle); d = odiff(mo, mpo); if (ABS(d) > 1) break; if (m->b_maxmag > best_mag->b_maxmag) { best_mag = m; } if (m->c_imp > best_imp->c_imp) { best_imp = m; } isum += m->c_imp; } if (isum >= 0x500) { best_imp->b_flags |= MFLG_BEST_IMP; best_mag->b_flags |= MFLG_BEST_MAG; if (best_imp == best_mag) { switch(best_imp->c_shape) { case MSHP_PULSE: best_imp->c_shape = MSHP_PULSE_PLUS; break; case MSHP_DIRTY_CIRCLE: best_imp->c_shape = MSHP_DIRTY_CIRCLE_PLUS; break; case MSHP_CLEAN_CIRCLE: best_imp->c_shape = MSHP_CLEAN_CIRCLE_PLUS; break; } } } } if (!OPT_silent) { printf("end findBestPulses\n"); } } //=========================================================================== // markLast_minimal() - mark last few(3) pulses as unimportant //=========================================================================== static void markLast_minimal(Motion2 *mlist) { Motion2 *m; int cnt = 3; int shape; int maxmag; int imp; int angle; m=mlist+1; while(1) { // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; if (angle & AFLG_END) break; } m--; m--; shape = 0; do { #if 0 if (shape & MSHF_PREV_PAUSE) { cnt--; if (cnt == 0) break; } #endif // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; m++; if (angle & AFLG_START) break; m--; m->shape &= ~MSHF_PLUS; printMotion2("marklast ",mlist,m,5); m--; } while(--cnt); } //=========================================================================== // markLast_pic() - mark last few(3) pulses as unimportant //=========================================================================== static void markLast_pic(Motion2 *mlist) { #if USE_PIC_MARKLAST eraseLocalVars(); #if !USE_PIC_FINDPULSE writeM2List(mlist, RAMBUF_M2LIST); #endif w_mo5_marklast(); // // have to do this to get mtimes for pic // if (1 || !OPT_silent || !USE_PIC_TOKENIZE) { readM2List(mlist, RAMBUF_M2LIST); } #else markLast_minimal(mlist); #endif } //=========================================================================== // markLast() - mark last few(3) pulses as unimportant //=========================================================================== static void markLast(Motion *mlist, int mcnt) { Motion *m; int cnt = 0; if (!mlist) return; for (m=mlist; m->c_next; m=m->c_next); while(m && cnt<3) { switch(m->c_shape) { case MSHP_PAUSE: break; case MSHP_CLEAN_CIRCLE: case MSHP_DIRTY_CIRCLE: case MSHP_PULSE: case MSHP_CIRCLE_GAP: cnt++; break; case MSHP_CLEAN_CIRCLE_PLUS: m->c_shape = MSHP_CLEAN_CIRCLE; cnt++; break; case MSHP_DIRTY_CIRCLE_PLUS: m->c_shape = MSHP_DIRTY_CIRCLE; cnt++; break; case MSHP_PULSE_PLUS: m->c_shape = MSHP_PULSE; cnt++; break; } m = m->c_prev; } } //=========================================================================== // tokenize_minimal() //=========================================================================== static void tokenize_minimal(Motion2 *mlist, int *tokens, int *atimes) { Motion2 *m; int shape; int maxmag; int imp; int angle; int dir; int atime; int cnt = 0; m=mlist+1; while(1) { // w_shp_read shape = m->shape; maxmag = m->maxmag; imp = m->imp; angle = m->angle; atime = m->dbg_atime; m++; if (angle & AFLG_END) break; dir = shape&MSHF_DIR?-1:1; if (((shape & MSHF_SHP_MASK) & ~MSHF_PLUS) == MSHP_PULSE) dir = 1; *(tokens++) = TOKEN_CREATE_MO(shape, dir, angle); *(atimes++) = atime; cnt++; ASSERT(cnt < 256); } *tokens = MTOKEN_END; } //=========================================================================== // tokenize_pic() //=========================================================================== static void tokenize_pic(Motion2 *mlist, int *tokens, int *atimes) { #if USE_PIC_TOKENIZE int dummy[CNT_MAX]; if (mlist && atimes) { // // just to get atimes // tokenize_minimal(mlist,dummy, atimes); } eraseLocalVars(); #if !USE_PIC_MARKLAST writeM2List(mlist, RAMBUF_M2LIST); #endif w_mo6_tokenize(); if (mlist) { readM2List(mlist, RAMBUF_M2LIST); } readTokens(tokens, RAMBUF_MTOKENS); #else tokenize_minimal(mlist,tokens,atimes); #endif } //=========================================================================== // tokenize() //=========================================================================== static void tokenize(Motion *mlist, int mcnt) { Motion *m; for (m=mlist; m; m=m->c_next) { #if !MINIMAL ASSERT(odiff(m->c_oct, a2oct(m->b_angle)) == 0); #endif m->token = TOKEN_CREATE_MO(m->c_shape, m->c_dir, m->b_angle); ASSERT(m->token != MTOKEN_END); } } //=========================================================================== // look() //=========================================================================== static void look(Motion *mlist, int mcnt) { if (!OPT_silent) { printf("\n\n"); } marker(1); parse1(mlist,mcnt); marker(2); if (!OPT_silent) { printf("\nPOST parse1\n\n"); lookPrint(mlist,mcnt); } marker(3); while(fillCircleGaps(mlist,mcnt)); marker(4); if (!OPT_silent) { printf("\nPOST fillCircleGaps\n\n"); lookPrint(mlist,mcnt); } marker(5); findWeakCircles(mlist,mcnt); marker(6); if (!OPT_silent) { printf("\nPOST findWeakCircles\n\n"); lookPrint(mlist,mcnt); } marker(7); findBestPulses(mlist,mcnt); marker(8); if (!OPT_silent) { printf("\nPOST findBestPulses\n\n"); lookPrint(mlist,mcnt); } marker(9); markLast(mlist,mcnt); marker(10); if (!OPT_silent) { printf("\nPOST markLast\n\n"); lookPrint(mlist,mcnt); } marker(11); tokenize(mlist,mcnt); marker(12); if (!OPT_silent) { printf("\nPOST tokenize\n\n"); lookPrint(mlist,mcnt); } } //=========================================================================== // look_minimal() //=========================================================================== static void look_minimal(Motion *mlist, int *tokens, int *atimes) { Motion2 m2list[1000]; marker(1); parse1_minimal(mlist,m2list); marker(2); if (!OPT_silent) { printf("\nPOST parse1\n\n"); lookPrint(mlist,0); } marker(3); fillCircleGaps_minimal(m2list); marker(4); marker(5); findWeakCircles_minimal(m2list); marker(6); marker(7); findBestPulses_minimal(m2list); marker(8); marker(9); markLast_minimal(m2list); marker(10); marker(11); tokenize_minimal(m2list,tokens, atimes); marker(12); } //=========================================================================== // look_pic() //=========================================================================== static void look_pic(Motion *mlist, int *tokens, int *atimes, PSpell *slist) { gCurrentSpell = slist; gCurrentMwanemeIndex = 0; eraseLocalVars(); writeM1List(mlist, RAMBUF_ACC); if (OPT_use_picsim) { w_check_motion_spell(); } else { w_mo1_parse1(); w_mo2_fill_circle_gaps(); w_mo3_find_weak_circles(); w_mo4_find_best_pulses(); w_mo5_marklast(); w_mo6_tokenize(); } readTokens(tokens, RAMBUF_MTOKENS); } //=========================================================================== // look_all3() //=========================================================================== static void look_all3( Motion *mlist, int mcnt, int *tokens_min, int *tokens_pic, int *atimes_min, int *atimes_pic) { int i; Motion mlist_save[CNT_MAX]; Motion2 m2list_min[1000]; Motion2 m2list_pic[1000]; memcpy(mlist_save,mlist,sizeof(mlist_save)); if (!OPT_silent) { printf("\n\n"); } parse1_pic(mlist,m2list_pic); for (i=0;i<CNT_MAX;i++) { if (memcmp(&mlist[i],&mlist_save[i],sizeof(Motion))) { printf("parse1_pic changed mlist[%d] = %08x\n", i,(int)&mlist[i]); ASSERT(!"parse1_pic changed mlist!!"); } } marker(1); parse1_minimal(mlist,m2list_min); for (i=0;i<CNT_MAX;i++) { if (memcmp(&mlist[i],&mlist_save[i],sizeof(Motion))) { printf("parse1_minimal changed mlist[%d] = %08x\n", i,(int)&mlist[i]); ASSERT(!"parse1_minimal changed mlist!!"); } } if (!OPT_silent) { printf("\n\n"); } parse1(mlist,mcnt); marker(2); if (!OPT_silent) { lookPrint(mlist,mcnt); printf("\nPOST parse1\n\n"); all3Print(mlist, m2list_min, m2list_pic); } //breakpt(); marker(3); while(fillCircleGaps(mlist,mcnt)); fillCircleGaps_minimal(m2list_min); fillCircleGaps_pic(m2list_pic); marker(4); if (!OPT_silent) { lookPrint(mlist,mcnt); printf("\nPOST fillCircleGaps\n\n"); all3Print(mlist, m2list_min, m2list_pic); } //breakpt(); marker(5); findWeakCircles(mlist,mcnt); findWeakCircles_minimal(m2list_min); findWeakCircles_pic(m2list_pic); marker(6); if (!OPT_silent) { lookPrint(mlist,mcnt); printf("\nPOST findWeakCircles\n\n"); all3Print(mlist, m2list_min, m2list_pic); } //breakpt(); marker(7); findBestPulses(mlist,mcnt); findBestPulses_minimal(m2list_min); findBestPulses_pic(m2list_pic); marker(8); if (!OPT_silent) { lookPrint(mlist,mcnt); printf("\nPOST findBestPulse\n\n"); all3Print(mlist, m2list_min, m2list_pic); } //breakpt(); marker(9); markLast(mlist,mcnt); markLast_minimal(m2list_min); markLast_pic(m2list_pic); marker(10); if (!OPT_silent) { lookPrint(mlist,mcnt); printf("\nPOST markLast\n\n"); all3Print(mlist, m2list_min, m2list_pic); } //breakpt(); marker(11); tokenize(mlist,mcnt); tokenize_minimal(m2list_min,tokens_min, atimes_min); tokenize_pic(m2list_pic,tokens_pic, atimes_pic); marker(12); if (!OPT_silent) { lookPrint(mlist,mcnt); printf("\nPOST tokenize\n\n"); all3Print(mlist, m2list_min, m2list_pic); } //breakpt(); } #if 0 //=========================================================================== // look_both() //=========================================================================== static void look_both(Motion *mlist, int mcnt, int *tokens) { Motion2 m2list[1000]; parse1_minimal(mlist,m2list); if (!OPT_silent) { printf("\n\n"); } parse1(mlist,mcnt); if (!OPT_silent) { lookPrint(mlist,mcnt); printf("\nPOST parse1\n\n"); bothPrint(mlist, m2list); } //breakpt(); while(fillCircleGaps(mlist,mcnt)); fillCircleGaps_minimal(m2list); if (!OPT_silent) { lookPrint(mlist,mcnt); printf("\nPOST fillCircleGaps\n\n"); bothPrint(mlist, m2list); } //breakpt(); findWeakCircles(mlist,mcnt); findWeakCircles_minimal(m2list); if (!OPT_silent) { lookPrint(mlist,mcnt); printf("\nPOST findWeakCircles\n\n"); bothPrint(mlist, m2list); } //breakpt(); findBestPulses(mlist,mcnt); findBestPulses_minimal(m2list); if (!OPT_silent) { lookPrint(mlist,mcnt); printf("\nPOST findBestPulse\n\n"); bothPrint(mlist, m2list); } //breakpt(); markLast(mlist,mcnt); markLast_minimal(m2list); if (!OPT_silent) { lookPrint(mlist,mcnt); printf("\nPOST markLast\n\n"); bothPrint(mlist, m2list); } //breakpt(); tokenize(mlist,mcnt); tokenize_minimal(m2list,tokens); if (!OPT_silent) { lookPrint(mlist,mcnt); printf("\nPOST tokenize\n\n"); bothPrint(mlist, m2list); } //breakpt(); } #endif //=========================================================================== // getline2() //=========================================================================== static int getline2(FILE *fp, char *line, char *end) { int c = getc(fp); if (c==EOF) return 0; end--; while(c!='\n' && c!=EOF && line != end) { *(line++) = c; c = getc(fp); } *line = 0; return 1; } //=========================================================================== // getline() //=========================================================================== static int getline(FILE *fp, Motion *m) { float list[6]; int idx = 0; char line[1000]; char *s, *e; while(1) { if (!getline2(fp,line,line+sizeof(line))) { return 0; } s = line; while(1) { while(isspace(*s)) s++; if (*s == '#' || *s == 0) { break; } list[idx] = strtod(s,&e); if (!e || e==s) { printf("ERROR parsing line:\n %s\n",line); fprintf(stderr,"Error parsing line:\n %s\n",line); break; } s = e; idx++; if (idx >= sizeof(list)/sizeof(list[0])) break; } if (idx) { while (idx < sizeof(list)/sizeof(list[0])) { list[idx++] = 0.0; } m->b_dtime = 0; m->b_atime = list[0]; m->b_angle = list[1]; m->b_imp = list[2]; m->b_minmag = list[3]; m->b_maxmag = list[4]; m->b_flags = list[5]; m->b_deltamag = m->b_maxmag - m->b_minmag; if (m->b_flags & MFLG_ZERO) { m->b_deltamag = m->b_maxmag; } if (m->b_angle == 0xff) { m->b_imp = 0; m->b_minmag = 0; m->b_maxmag = 0; m->b_flags = 0; m->b_deltamag = 0; } return 1; } } } //=========================================================================== // get() - read the file //=========================================================================== static int get(FILE *in, Motion *m, Motion *end) { #if 0 int atime = 0; #endif int cnt = 0; // // start with a pause // m->b_atime = 0; m->b_angle = 0xff; m++; cnt++; while(m != end-1 && getline(in,m)) { (m-1)->b_dtime = m->b_atime - (m-1)->b_atime; #if 0 m->b_atime = atime; atime += m->b_dtime; #endif m++; cnt++; } // // end with a pause // m->b_atime = 0; m->b_dtime = 0; m->b_angle = 0xff; m++; cnt++; m->b_angle = 0xfe; return cnt; } //=========================================================================== // compareToken() //=========================================================================== static void compareToken( int *ignoreMotion, int *ignoreSpell, int *val, int stok, int mtok) { int mshape = TOKEN_SHAPE(mtok); int mdir = TOKEN_DIR(mtok); int mangle = TOKEN_ANGLE(mtok); int sshape = TOKEN_SHAPE(stok); int sdir = TOKEN_DIR(stok); int sangle = TOKEN_ANGLE(stok); int d; int add = 0; *ignoreMotion = ignoreMotions[mshape]; *ignoreSpell = ignoreSpells[sshape]; *val = 10000; switch(sshape) { case SSHP_PAUSE: ASSERT(!"Pause in spell - not allowed"); *val = scorePause[mshape]; break; case SSHP_CIRCLE: case SSHP_OCIRCLE: *val = scoreCircleMiss; switch(mshape) { case MSHP_CLEAN_CIRCLE_PLUS: case MSHP_DIRTY_CIRCLE_PLUS: case MSHP_CLEAN_CIRCLE: case MSHP_DIRTY_CIRCLE: case MSHP_CIRCLE_GAP: if (mdir != sdir) break; #if FIX_CIRCLE_OCT_COMPARE //printf("TODO:CONFIRM FIX_CIRCLE_OCT_COMPARE IS A GOOD IDEA!!!!\n"); d = adiff(mangle,sangle); d = ABS(d); if (d>2) break; #else d = a2oct(mangle) - a2oct(sangle); if (d) break; #endif *val = scoreCircleMatch; break; case MSHP_PULSE: case MSHP_PULSE_PLUS: #if FIX_CIRCLE_OCT_COMPARE //printf("TODO:CONFIRM FIX_CIRCLE_OCT_COMPARE IS A GOOD IDEA!!!!\n"); d = adiff(mangle,sangle); d = ABS(d); if (d>2) break; #else d = a2oct(mangle) - a2oct(sangle); if (d) break; #endif *val = scoreCircleMatch; break; case MSHP_PAUSE: break; } break; case SSHP_PULSE: case SSHP_OPULSE: *val = scorePulseMiss; switch(mshape) { case MSHP_CLEAN_CIRCLE: //add += 4; case MSHP_DIRTY_CIRCLE: //add += 2; case MSHP_PULSE: //add += 2; case MSHP_CLEAN_CIRCLE_PLUS: case MSHP_DIRTY_CIRCLE_PLUS: case MSHP_PULSE_PLUS: d = adiff(mangle, sangle); d = ABS(d); if (d < 10) { *val = scorePulse[d/2] + add; } break; case MSHP_PAUSE: case MSHP_CIRCLE_GAP: break; } break; case SSHP_WILD: *val = 1; break; default: fatalError("Bad token in compareToken\n"); } gCompareCnt++; // // check results of pic w_moa_score_tok: function // if (OPT_check_comparetok && OPT_do_picsim) { int pic_mignore; int pic_signore; int pic_match; picRegSet(0,picRegId(v_moa_stok),stok); picRegSet(0,picRegId(v_moa_mtok),mtok); w_moa_score_tok(); pic_mignore = picRV(picRegId(v_moa_mignore)); pic_signore = picRV(picRegId(v_moa_signore)); pic_match = picRV(picRegId(v_moa_match)); if (*ignoreMotion > 254) { ASSERT(pic_mignore == 255); } else { ASSERT(*ignoreMotion == pic_mignore); } if (*ignoreSpell > 254) { ASSERT(pic_signore == 255); } else { ASSERT(*ignoreSpell == pic_signore); } #if 0 if (*val > 254) { ASSERT(pic_match == 255); } else { ASSERT(*val == pic_match); } #else if (*val >= 0x7f) { ASSERT(pic_match >= 0x7f); } else { ASSERT(*val == pic_match); } #endif } } //=========================================================================== // printColor() //=========================================================================== static void printColor(int diff) { if (diff<0) diff = -diff; printf("%s",colorStr( (diff)>=10 ? 1 : (diff)>=4 ? 3 : (diff)>=1 ? 4 : 2)); } //=========================================================================== // writeResult() //=========================================================================== static void writeResult(FILE *out, int t, int s, int m, int delta) { fprintf(out,"%d.0 %d.0 %d.0 %d.0\n",t,s,m,delta); } //=========================================================================== // scoreSpell_pic() //=========================================================================== static void scoreSpell_pic(PSpell *s) { int score; gCurrentSpell = s; gCurrentMwanemeIndex = 0; w_mo7_load_spell(); w_mo9_score_spell(); score = picRV(picRegId(v_mo9_score)); ASSERT(score == s->score || (score==255 && s->score>=255) ); } //=========================================================================== // scoreSpell() //=========================================================================== static int scoreSpell(PSpell *spell, Motion *mlist, char *path, int doprint) { Motion *m; unsigned char *spellTokens; unsigned char *s; static int mtx[1000]; int scnt,mcnt,slen; int ignoreMotion, ignoreSpell, match, val, corner, lastval = 0; FILE *out = 0; int prev_atime = 0; // // get rid of leading pause // for (s=spell->tokens; *s && TOKEN_SHAPE(*s) == SSHP_PAUSE; s++); spellTokens = s; if (doprint==2) { printf(" "); for (scnt=1, s=spellTokens; *s; scnt++, s++) { printf("%5s ",spellTokenStr(*s)); } printf("\n "); for (scnt=1, s=spellTokens; *s; scnt++, s++) { printf(" 0x%02x ",*s); } printf("\n %-4d ",0); } else if (doprint==3) { printf(" %5s\n",spell->name); printf(" %5s %5s\n","spell","motion"); if (OPT_result_filename && OPT_result_filename[0]) { out = fopen(OPT_result_filename, "w"); } } mtx[0] = 0; for (scnt=1, s=spellTokens; *s; scnt++, s++) { compareToken( &ignoreMotion, &ignoreSpell, &match, *s, TOKEN_CREATE_MO(MSHP_PULSE, 0, 0)); mtx[scnt] = val = mtx[scnt-1] + ignoreSpell; if (doprint==2) { if (path[scnt]) { printColor(val-lastval); lastval = val; } printf("<%-4d",mtx[scnt]); printf("%s ",colorStr(-1)); } else if (doprint==3 && path[scnt]) { printf(" %5s %d %5s ", spellTokenStr(*s), a2oct(a2oct(TOKEN_ANGLE(*s))), "skip"); printColor(ignoreSpell); printf("%4d %4d%s\n",ignoreSpell,val,colorStr(-1)); } else if (doprint == -1) { path[scnt] = '<'; } } slen = scnt; for (mcnt=1, m = mlist; m; mcnt++, m=m->c_next) { corner = mtx[0]; compareToken( &ignoreMotion, &ignoreSpell, &match, TOKEN_CREATE_SP(SSHP_PULSE, 0, 0), m->token); mtx[0] = val = corner + ignoreMotion; if (doprint==2) { printf("\n%5s %02x ",motionTokenStr(m->token),0/*m->token*/); if (path[slen*mcnt]) { printColor(match-lastval); lastval = val; } printf("^%-4d",mtx[0]); printf("%s ",colorStr(-1)); } else if (doprint==3 && path[slen*mcnt]) { printf(" %5s %d %5s ", "skip", a2oct(a2oct(TOKEN_ANGLE(m->token))), motionTokenStr(m->token)); printColor(ignoreMotion); printf("%4d %4d%s\n",ignoreMotion,val,colorStr(-1)); } else if (doprint == -1) { path[slen*mcnt] = '^'; } for (scnt=1, s=spellTokens; *s; scnt++, s++) { char *src = "\\"; compareToken(&ignoreMotion, &ignoreSpell, &match, *s, m->token); val = match + corner; if (val > ignoreMotion + mtx[scnt]) { val = ignoreMotion + mtx[scnt]; src="^"; } if (val > ignoreSpell + mtx[scnt-1]) { val = ignoreSpell + mtx[scnt-1]; src="<"; } if (doprint==2) { if (path[slen*mcnt+scnt]) { printColor(val-lastval); lastval = val; } printf("%s%-4d", src,val); printf("%s ",colorStr(-1)); } else if (doprint==3 && path[slen*mcnt+scnt]) { int delta = 1000; switch(src[0]) { case '^': printf(" %5s %d %5s ", "skip", a2oct(a2oct(TOKEN_ANGLE(m->token))), motionTokenStr(m->token)); delta = ignoreMotion; if (out && !OPT_result_spell_only) { writeResult(out, m->b_atime, -1, m->token, OPT_result_motion_only?0:delta); prev_atime = m->b_atime; } break; case '<': printf(" %5s %d %5s ", spellTokenStr(*s), a2oct(a2oct(TOKEN_ANGLE(*s))), "skip"); delta = ignoreSpell; if (out && !OPT_result_motion_only) { writeResult(out, prev_atime, *s, -1, OPT_result_spell_only?0:delta); } break; case '\\': printf(" %5s %d %d %5s ", spellTokenStr(*s), a2oct(a2oct(TOKEN_ANGLE(*s))), a2oct(a2oct(TOKEN_ANGLE(m->token))), motionTokenStr(m->token)); delta = match; if (out) { if (OPT_result_motion_only) { writeResult(out, m->b_atime, -1, m->token, 0); } else if (OPT_result_spell_only) { writeResult(out, m->b_atime, *s, -1, 0); } else { writeResult(out, m->b_atime, *s, m->token, delta); } prev_atime = m->b_atime; } break; default: printf(" %5s %5s ", "????", "????"); break; } printColor(delta); printf("%4d %4d%s\n",delta,val,colorStr(-1)); } else if (doprint==-1) { path[slen*mcnt+scnt] = src[0]; } corner = mtx[scnt]; mtx[scnt] = val; } } if (doprint==2) { printf("\n"); } else if (doprint == -1) { int i; int mlen = mcnt; // // find path // path[0] = '*'; scnt--; mcnt--; while(scnt>=0 && mcnt>=0) { int c = path[slen*mcnt+scnt]; path[slen*mcnt+scnt] = '*'; switch(c) { case '<': scnt--; break; case '^': mcnt--; break; case '\\': case '*': mcnt--; scnt--; break; } } for (i=0; i<mlen*slen; i++) { if (path[i] != '*') path[i] = 0; } } if (out) { printf("Wrote %s\n",OPT_result_filename); fclose(out); } if (doprint>0 && doprint<3) { printf("Score vs %-25s = %8d\n",spell->name,val); } spell->score = val; return val; } //=========================================================================== // spellInit() //=========================================================================== static void spellInit(SpellCreateInfo *si) { memset(si,0,sizeof(*si)); si->lastAngle = -1; } //=========================================================================== // spellCircleSub() //=========================================================================== static unsigned char *spellCircleSub(unsigned char *t, int dir, int *oct, int optional) { int dbg = DBG_LOADSPELL; static int table_cw[8] = { 6,7,0,1,2,3,4,5 }; static int table_ccw[8] = { 2,3,4,5,6,7,0,1 }; int *table = dir<0 ? table_cw : table_ccw; if (optional) { *(t++) = TOKEN_CREATE_SP(SSHP_OCIRCLE, dir, oct2a(table[*oct])); if (dbg) { printf(" %s %02x\n",spellTokenStr(*(t-1)),*(t-1)); } } else { *(t++) = TOKEN_CREATE_SP(SSHP_CIRCLE, dir, oct2a(table[*oct])); if (dbg) { printf(" %s %02x\n",spellTokenStr(*(t-1)),*(t-1)); } } *oct = (*oct + dir) & 7; return t; } //=========================================================================== // spellCircle() //=========================================================================== static unsigned char *spellCircle(unsigned char *t, SpellCreateInfo *si, int cnt) { int dbg = DBG_LOADSPELL; int oct = a2oct(si->lastAngle); int dir = 1; int prevdir; int cnt0 = 0, cnt1 = 0, cnt2 = 0; if (cnt < 0) { dir = -1; cnt = -cnt; } if (dbg) { printf("spellCircle dir=%s1 cnt=%d\n", (dir<0)?"-":"+", cnt); } // // write the pic version of the mwaneme // picSpellWrite(PIC_MWN_CREATE_CIRC(dir,cnt)); // // Circles always end with // - lastAngle pointing the way it is supposed to and // - 2nd to last optional circle pulse perpendicular to end direction // // For example, if end angle is oct==2 (right) // tokens = ... CW4 CW3 CW2 oCW1 oCW0 oCW7 // si->lastAngle = oct2a(oct); switch(TOKEN_SHAPE(t[-1])) { case SSHP_PAUSE: *(t++) = TOKEN_CREATE_SP(SSHP_OPULSE, 0, oct2a(oct)); if (dbg) { printf(" %s %02x\n",spellTokenStr(*(t-1)),*(t-1)); } oct = (oct - dir) & 7; cnt0 = 1; cnt1 = 2+8-1-2 + (8*(cnt-1)); cnt2 = 3; // NOTE: same lastAngle break; case SSHP_CIRCLE: case SSHP_OCIRCLE: prevdir = TOKEN_DIR(t[-1]); if (prevdir == dir) { t -= 3; oct = (oct - prevdir) & 7; cnt0 = 0; cnt1 = 2 + 8 - 2 + (8*(cnt-1)); cnt2 = 3; // NOTE: same lastAngle } else { oct = (oct + 4) & 7; *(t++) = TOKEN_CREATE_SP(SSHP_OPULSE, 0, oct2a(oct)); if (dbg) { printf(" %s %02x\n",spellTokenStr(*(t-1)),*(t-1)); } *(t++) = TOKEN_CREATE_SP(SSHP_OPULSE, 0, oct2a((oct+prevdir)&7)); if (dbg) { printf(" %s %02x\n",spellTokenStr(*(t-1)),*(t-1)); } *(t++) = TOKEN_CREATE_SP(SSHP_OPULSE, 0, oct2a(oct)); if (dbg) { printf(" %s %02x\n",spellTokenStr(*(t-1)),*(t-1)); } oct = (oct - dir) & 7; cnt0 = 2; cnt1 = 2+8-2-2 + (8*(cnt-1)); cnt2 = 3; // circlSlop=5 si->lastAngle = oct2a(oct); } break; case SSHP_OPULSE: case SSHP_PULSE: oct = (oct - dir) & 7; cnt0 = 3; cnt1 = 2+8-3-2 + (8*(cnt-1)); cnt2 = 3; // NOTE: same lastAngle break; default: fatalError("Bad token in spellCircle() \n"); } while(cnt0--) { t = spellCircleSub(t, dir, &oct, 1); } while(cnt1--) { t = spellCircleSub(t, dir, &oct, 0); } while(cnt2--) { t = spellCircleSub(t, dir, &oct, 1); } si->prevCircleCnt = cnt; return t; } //=========================================================================== // spellPulse() //=========================================================================== static unsigned char *spellPulse(unsigned char *t, SpellCreateInfo *si, int oct) { int dbg = DBG_LOADSPELL; int revoct = (oct + 4) & 7; int optional = 0; int dir, octc, octprev = a2oct(si->lastAngle); int cnt; if (dbg) { printf("spellPulse oct=%d\n", oct); } // // write the pic version of the mwaneme // picSpellWrite(PIC_MWN_CREATE_PULSE(oct)); switch(TOKEN_SHAPE(t[-1])) { case SSHP_PAUSE: *(t++) = TOKEN_CREATE_SP(SSHP_OPULSE,0,oct2a(oct)); if (dbg) { printf(" %s %02x\n",spellTokenStr(*(t-1)),*(t-1)); } break; case SSHP_OPULSE: case SSHP_PULSE: // // same direction as last pulse? // if (revoct == octprev) { optional = 1; *(t++) = TOKEN_CREATE_SP(SSHP_OPULSE,0,oct2a(oct)); if (dbg) { printf(" %s %02x\n",spellTokenStr(*(t-1)),*(t-1)); } // // opposite direction of previous // } else if (oct == octprev) { break; // // some other angle (less) // } else if (odiff(oct,octprev) > 0) { while(octprev != oct) { t = spellCircleSub(t, 1, &octprev, 1); } } else { while(octprev != oct) { t = spellCircleSub(t, -1, &octprev, 1); } } break; case SSHP_CIRCLE: case SSHP_OCIRCLE: dir = TOKEN_DIR(t[-1]); octc = a2oct(si->lastAngle); //printf("octc=%d\n",octc); // t now points to the CW2 in example above t -= 4; //printf("t[]=%02x\n",*t); // oct now points up (4) in example above octc = (octc - dir * 2) & 7; cnt = -1; //printf("octc=%d cnt=%d\n",octc,cnt); if (si->prevCircleCnt > 1) { t -= 1; octc = (octc - dir) & 7; cnt -= 1; } //printf("t[]=%02x\n",*t); //printf("octc=%d cnt=%d\n",octc,cnt); //printf("S octc(%d) +dir(%d) !=? oct=%d\n",octc,dir,oct); while(((octc+dir)&7) != oct) { //printf("+ octc(%d) +dir(%d) !=? oct=%d\n",octc,dir,oct); t = spellCircleSub(t, dir, &octc, 0); cnt++; } //printf("E octc(%d) +dir(%d) !=? oct=%d\n",octc,dir,oct); // // if less than full circle add an extra optional circle // if (cnt < 0) { //printf("EXTRA\n"); for (cnt=0; cnt<8; cnt++) { t = spellCircleSub(t, dir, &octc, 1); } } //printf("2 octc=%d\n",octc); t = spellCircleSub(t, dir, &octc, 1); //printf("1 octc=%d\n",octc); t = spellCircleSub(t, dir, &octc, 1); //printf("0 octc=%d revoct=%d\n",octc,revoct); break; default: fatalError("Bad token in spellCircle() \n"); } if (optional) { *(t++) = TOKEN_CREATE_SP(SSHP_OPULSE,0,oct2a(revoct)); if (dbg) { printf(" %s %02x\n",spellTokenStr(*(t-1)),*(t-1)); } } else { *(t++) = TOKEN_CREATE_SP(SSHP_PULSE,0,oct2a(revoct)); if (dbg) { printf(" %s %02x\n",spellTokenStr(*(t-1)),*(t-1)); } } #if 0 *(t++) = TOKEN_CREATE_SP(SSHP_OPULSE,0,oct2a(oct)); if (dbg) { printf(" %s %02x\n",spellTokenStr(*(t-1)),*(t-1)); } #endif si->lastAngle = oct2a(revoct); si->prevCircleCnt = 0; return t; } //=========================================================================== // spellPause() //=========================================================================== static unsigned char *spellPause(unsigned char *t, SpellCreateInfo *si) { int dbg = DBG_LOADSPELL; ASSERT(!"Inserting pause into spell (no longer supported)"); *(t++) = TOKEN_CREATE_SP( SSHP_PAUSE, 0, 0); if (dbg) { printf(" %s %02x\n",spellTokenStr(*(t-1)),*(t-1)); } si->prevCircleCnt = 0; return t; } //=========================================================================== // createSpell() //=========================================================================== static void createSpell(PSpell *s) { int dbg = DBG_LOADSPELL; SpellCreateInfo si[1]; unsigned char *t = s->tokens; const char *p; int oct; int startAngle = -1; spellInit(si); startAngle = -1; for (p=s->mwanemes; *p; p++) { switch(*p) { case 'e': case 'i': case 'a': case 'o': case 'u': case 'y': case ' ': break; case 'd': startAngle = oct2a(4); break; case 'k': startAngle = oct2a(2); break; case 'g': startAngle = oct2a(0); break; case 'f': startAngle = oct2a(6); break; case 'h': startAngle = oct2a(3); break; case 's': startAngle = oct2a(1); break; case 'm': startAngle = oct2a(7); break; case 'l': startAngle = oct2a(5); break; default: fatalError("ERROR: BAD PHONEME CHARACTER: %c\n in '%s'\n", *p,s->mwanemes); } if (startAngle >= 0) { si->lastAngle = startAngle; break; } } ASSERT(startAngle >= 0 && *p); // // write initial oct // picSpellWrite(a2oct(startAngle)); *(t++) = TOKEN_CREATE_SP( SSHP_PAUSE,0,0); if (dbg) { printf(" %s %02x\n",spellTokenStr(*(t-1)),*(t-1)); } for (p=s->mwanemes; *p; p++) { if (dbg) { printf("mwaneme %c\n",*p); } switch(*p) { case 'e': t = spellCircle(t,si,+2); break; case 'i': t = spellCircle(t,si,+3); break; case 'a': t = spellCircle(t,si,-1); break; case 'o': t = spellCircle(t,si,-2); break; case 'u': t = spellCircle(t,si,-3); break; case 'y': t = spellCircle(t,si,+1); break; case 'd': t = spellPulse(t,si,4); break; case 'k': t = spellPulse(t,si,2); break; case 'g': t = spellPulse(t,si,0); break; case 'f': t = spellPulse(t,si,6); break; case 'h': t = spellPulse(t,si,3); break; case 's': t = spellPulse(t,si,1); break; case 'm': t = spellPulse(t,si,7); break; case 'l': t = spellPulse(t,si,5); break; case ' ': t = spellPause(t,si); break; default: fatalError("ERROR: BAD PHONEME CHARACTER: %c\n in '%s'\n", *p,s->mwanemes); } if (t-s->tokens > sizeof(s->tokens)-10) { printf("ERROR\n\n\n"); fprintf(stderr,"\n\n\n"); fprintf(stderr,"ERROR: SPELL TOO LONG:\n"); fprintf(stderr," in '%s'\n", s->mwanemes); fprintf(stderr,"\n\n\n"); exit(1); } } // // write end of pic mwanemes // picSpellWrite(0); oct = a2oct(si->lastAngle); oct = (oct+4)&7; *(t++) = TOKEN_CREATE_SP(SSHP_OPULSE,0,oct2a(oct)); //*(t++) = TOKEN_CREATE_SP(SSHP_WILD, 0, 0); //*(t++) = TOKEN_CREATE_SP(SSHP_WILD, 0, 0); *t = STOKEN_END; s->len = t-s->tokens; //return t - s->tokens; } #if 0 //=========================================================================== // spellLen() - find # of tokens in spell //=========================================================================== static int spellLen(PSpell *s) { unsigned char *t = s->tokens; while(*t) t++; return t-s->tokens; } #endif //=========================================================================== // buildSpell() - //=========================================================================== static int buildSpell(PSpell *s) { ASSERT(s->mwanemes[0]); createSpell(s); ASSERT(s->tokens[0] != STOKEN_END); //return spellLen(s); return s->len; } //=========================================================================== // buildSpell_pic() - //=========================================================================== static void buildSpell_pic(PSpell *s) { int i; gCurrentSpell = s; gCurrentMwanemeIndex = 0; w_mo7_load_spell(); for (i=0;;i++) { int val = picRV(RAMBUF_STOKENS+i); s->pic_tokens[i] = val; if (!val) break; ASSERT(val < MAX_TOKENS); } gCurrentSpell = 0; gCurrentMwanemeIndex = 0; } #define SORT_BY_LEN 1 #if SORT_BY_LEN //=========================================================================== // spellCmpName() //=========================================================================== static int spellCmpName(const void *a, const void *b) { const PSpell *pa = (const PSpell*)a; const PSpell *pb = (const PSpell*)b; return strcmp(pa->name,pb->name); } //=========================================================================== // spellCmpSortId() //=========================================================================== static int spellCmpSortId(const void *a, const void *b) { const PSpell *pa = (const PSpell*)a; const PSpell *pb = (const PSpell*)b; int cmp = pa->sortId - pb->sortId; if (cmp) return cmp; return strcmp(pa->name,pb->name); } #endif //=========================================================================== // buildAllSpells() - //=========================================================================== static void buildAllSpells(PSpell *slist) { int spellinfo=2; int spellid = 1; PSpell *s; PSpell *badspell = 0; int maxlen = 0; int max_maxscore = 0; int max_holdoff = 0; gCurrentSpell = 0; gCurrentMwanemeIndex = 0; #if SORT_BY_LEN int spellcnt; // // count spells // create spells // for (s=slist; s->name; s++) { buildSpell(s); maxlen = s->len > maxlen ? s->len : maxlen; max_maxscore = s->maxscore > max_maxscore ? s->maxscore : max_maxscore; max_holdoff = s->holdoff > max_holdoff ? s->holdoff : max_holdoff; if (OPT_onespell) break; } spellcnt = OPT_onespell ? 1 : s-slist; // // sort spells // if (spellcnt > 1 ) { int i; // // sort spells by name // qsort(slist, spellcnt, sizeof(PSpell), spellCmpName); // // assign id & sortId // for (i=0; i<spellcnt; i++) { if (i && !strcmp(slist[i].baseName, slist[i-1].baseName)) { slist[i].id = slist[i-1].id; slist[i].sortId = slist[i-1].sortId; slist[i].flags &= ~SPELL_FLG_FIRST; } else { slist[i].id = spellid++; slist[i].flags |= SPELL_FLG_FIRST; slist[i].sortId = slist[i].len; } } // // sort spells by sortId (==len), name // qsort(slist, spellcnt, sizeof(PSpell), spellCmpSortId); } #endif gMaxMaxscore = max_maxscore; gMaxHoldoff = max_holdoff; // // build spells again and write info // for (s=slist; s->name; s++) { gCurrentSpell = s; gCurrentMwanemeIndex = 0; picSpellWrite(spellinfo&0xff); picSpellWrite(spellinfo>>8); picSpellWrite(s->maxscore); picSpellWrite(s->holdoff); ASSERT(s->id>0); ASSERT(s->id<0xff); picSpellWrite(s->id); s->spellinfo = spellinfo; buildSpell(s); if (OPT_onespell || !OPT_silent || OPT_showspell) { printf("Spell %25s LEN=%d\n",s->name,s->len); } if (s->len > maxlen) { maxlen = s->len; } spellinfo += 2; if (OPT_onespell) break; } if (!OPT_silent || OPT_showspell) { printf("MAX SPELL LEN=%d total spells=%d\n", maxlen, (spellinfo-2)/2); } ASSERT(maxlen < MAX_TOKEN_CNT); if (!OPT_do_picsim) { return; } // // try pic version // for (s=slist; s->name; s++) { int i,j,e; if (OPT_showspell) { printf("======= spell %s %s\n",s->name, s->mwanemes); } buildSpell(s); buildSpell_pic(s); if (OPT_showspell) { printf("MWN: "); for (i=0; s->pic_mwanemes[i] || i<2; i++) { printf("%02x ",s->pic_mwanemes[i]); } printf("%02x\n",0); printf(" Ctok PICtok\n"); } i = 1; j = 0; e = 1; while(e) { int tok_c = s->tokens[i]; int tok_pic = s->pic_tokens[j]; e=0; if (OPT_showspell) { printf("[%3d] ",(i>j)?i:j); } if (tok_c) { if (OPT_showspell) { printf(" %s %02x ", spellTokenStr(tok_c), tok_c); } i++; e=1; } else { if (OPT_showspell) { printf(" %s %02x ", spellTokenStr(0), 0); } } if (OPT_showspell) { printf("%s",tok_c == tok_pic?" ":"*"); } if (tok_c != tok_pic) { badspell = badspell ? badspell : s; } if (tok_pic) { if (OPT_showspell) { printf(" %02x %s\n", tok_pic, spellTokenStr(tok_pic)); } j++; e=1; } else { if (OPT_showspell) { printf(" %02x %s\n", 0, spellTokenStr(0)); } } } if (badspell) { fprintf(stderr,"ERROR IN w_check_motion_spell!!\n"); fprintf(stderr,"Run: fmtb_parse -s -q -w\n"); fprintf(stderr,"Run: fmtb_parse -s -q -w %s\n", s->name); } if (OPT_onespell) break; } if (badspell) { fprintf(stderr,"ERROR IN w_check_motion_spell!!\n"); fprintf(stderr,"Run: fmtb_parse -s -q -w\n"); fprintf(stderr,"Run: fmtb_parse -s -q -w %s\n", badspell->name); } else if (OPT_showspell && !OPT_onespell) { printf("\nAll spells loaded OK!\n\n"); } ASSERT(!badspell); gCurrentSpell = 0; gCurrentMwanemeIndex = 0; if (OPT_mwaneme_filename && !OPT_onespell) { int snum = 0; char *filename2; int last_byte = -1; int fnlen = strlen(OPT_mwaneme_filename); FILE *fp = fopen(OPT_mwaneme_filename,"w"); FILE *fp2; if (!fp) { fprintf(stderr,"Unable to write file '%s'\n",OPT_mwaneme_filename); ASSERT(!"Could not write file"); } filename2 = malloc(fnlen+2); memcpy(filename2,OPT_mwaneme_filename,fnlen+1); filename2[fnlen+1]=0; if (filename2[fnlen-4] == '.') { filename2[fnlen] = filename2[fnlen-1]; filename2[fnlen-1] = filename2[fnlen-2]; filename2[fnlen-2] = filename2[fnlen-3]; filename2[fnlen-3] = '.'; filename2[fnlen-4] = '2'; } else { filename2[fnlen] = '2'; } fp2 = fopen(filename2,"w"); gCurrentSpell = slist; gCurrentMwanemeIndex = 0; fprintf(fp,";\n"); fprintf(fp,"; AUTOGENERATED FILE - DO NOT EDIT\n"); fprintf(fp,";\n"); fprintf(fp,"; Created with: fmtb_parse -W%s\n",OPT_mwaneme_filename); fprintf(fp,";\n"); fprintf(fp,"\n"); ASSERT(max_maxscore <= 0xff); fprintf(fp,"MAX_MAXSCORE equ 0x%02x\n",max_maxscore); fprintf(fp,"MAX_HOLDOFF equ 0x%02x\n",max_holdoff); fprintf(fp,"\n"); fprintf(fp,"w_motion_spells:\n"); fprintf(fp2,";\n"); fprintf(fp2,"; AUTOGENERATED FILE - DO NOT EDIT\n"); fprintf(fp2,";\n"); fprintf(fp2,"; Created with: fmtb_parse -W%s\n",OPT_mwaneme_filename); fprintf(fp2,";\n"); fprintf(fp2,"\n"); fprintf(fp2,"w_motion_spell_strings:\n"); while(1) { int maxs, hold, id; int sil, sih, oct0,cnt=0; s = gCurrentSpell; sil = picSpellRead(); sih = picSpellRead(); maxs = picSpellRead(); hold = picSpellRead(); id = picSpellRead(); oct0 = picSpellRead(); if (s && s->name) { ASSERT(oct0 >=0 && oct0 <= 7); ASSERT(s->baseName && s->baseName[0]); if (s->flags & SPELL_FLG_FIRST) { fprintf(fp2,"\n"); if (s->flags & SPELL_FLG_INFO) { fprintf(fp2,"#if DBG_SPELL_MSG_IS_SPELL_NAME\n"); } fprintf(fp2,"w_spellinfo_%s:\t; (%04x)\n", s->baseName, snum); fprintf(fp2,"\tdb\t\"you cast %s\\0\"\n", s->baseName); if (s->flags & SPELL_FLG_INFO) { fprintf(fp2,"#endif\n"); } } fprintf(fp,"\n"); fprintf(fp,"; (%04x) spell %s (%s) len=%d %s\n", snum, s->name, s->mwanemes, s->len, mwanemeDescStr(s->mwanemes)); snum++; fprintf(fp,"; w_spellinfo_%s\n",s->baseName); fprintf(fp,"\tdb\t"); cnt = 2; if (last_byte >= 0) { fprintf(fp,"0x%02x, ",last_byte); last_byte = -1; cnt++; } fprintf(fp,"LOW w_spellinfo_%s, ",s->baseName); fprintf(fp,"HIGH w_spellinfo_%s, ",s->baseName); fprintf(fp,"0x%02x, ",maxs); fprintf(fp,"0x%02x, ",hold); fprintf(fp,"0x%02x, ",id); fprintf(fp,"0x%02x",oct0); cnt+=6; } else { ASSERT(gCurrentSpell==0); ASSERT(sih==(PIC_MWN_END_SPELLS>>8)); ASSERT(sil==(PIC_MWN_END_SPELLS&0xff)); ASSERT(oct0==-1); fprintf(fp,"; End of spells\n"); fprintf(fp," db "); if (last_byte >= 0) { fprintf(fp,"0x%02x, ",last_byte); last_byte = -1; } fprintf(fp,"0x%02x, 0x%02x\n", PIC_MWN_END_SPELLS&0xff, PIC_MWN_END_SPELLS>>8); fprintf(fp,"\n"); break; } while(1) { int val; if (last_byte == -1) { last_byte = picSpellRead(); } if (PIC_MWN_END(last_byte)) { fprintf(fp,"\n"); break; } if (cnt & 1) { fprintf(fp,", 0x%02x",last_byte); cnt++; last_byte = -1; continue; } val = picSpellRead(); if (cnt >= 8) { fprintf(fp,"\n\tdb\t0x%02x, 0x%02x",last_byte,val); cnt = 2; } else { fprintf(fp,", 0x%02x, 0x%02x",last_byte,val); cnt+=2; } last_byte = -1; if (PIC_MWN_END(val)) { fprintf(fp,"\n"); break; } } } fclose(fp); fprintf(fp2,"\n"); fclose(fp2); free(filename2); } gCurrentSpell = 0; gCurrentMwanemeIndex = 0; } //=========================================================================== // checkCompareTok() //=========================================================================== static void checkCompareTok(void) { OPT_check_comparetok = 1; int ignoreMotion; int ignoreSpell; int val; int ss,ms,sa,ma,stok,mtok; int cyc0 = picGetCycle(); int cyc1; int cnt = 0; int cyca,cycb; if (!OPT_silent) { printf("begin checkCompareTok\n"); } for (ma=0; ma<32; ma++) { for (sa=0; sa<32; sa+=2) { for (ss=0; ss<SSHP_CNT; ss++) { if (ss == SSHP_PAUSE) continue; if (ss == SSHP_WILD) continue; for (ms=0; ms<MSHP_CNT; ms++) { if (ms == MSHP_PAUSE) continue; stok = (ss<<4) | ((sa << 4) & 0x80) | ((sa << 1) & 0xe); mtok = (ms<<4) | ((ma << 3) & 0x80) | ((ma ) & 0xf); cyca = picGetCycle(); compareToken( &ignoreMotion, &ignoreSpell, &val, stok, mtok); cycb = picGetCycle(); if (OPT_showtime) { printf("cmptok: %d cyc\n",cycb-cyca); } cnt++; }}}} if (!OPT_silent) { printf("end checkCompareTok\n"); } cyc1 = picGetCycle(); if (!OPT_silent || OPT_showtime) { printf("Compare: %d token compares in %d cycles (%5.3f sec)\n", cnt, cyc1-cyc0, (cyc1-cyc0)/1000000.0); printf("%d cycles (%8.6f sec) per compare avg\n", (cyc1-cyc0)/cnt, ((cyc1-cyc0)/cnt)/1000000.0); } picSetCycle(cyc0); OPT_check_comparetok = 0; } //=========================================================================== // checkSpells() //=========================================================================== static int checkSpells(PSpell *slist, Motion *mlist, int mcnt) { Motion *m, *mp; char *path; PSpell *s, *best = 0, *best2=0; int scnt = 0; int startAngle = 0; if (OPT_do_picsim) { w_mo8_load_data_tables(); if (OPT_check_comparetok) { checkCompareTok(); OPT_check_comparetok = 0; } } // // ignore leading pause(s) // while(mlist && TOKEN_SHAPE(mlist->token) == MSHP_PAUSE) { mlist = mlist->c_next; } if (!mlist) return -1; // // ignore trailing pause(s) // for (mp=m=mlist; m; m=m->c_next) { if (TOKEN_SHAPE(m->token) != MSHP_PAUSE) { mp = m; } } mp->c_next = 0; if (!mlist) return -1; #if MINIMAL startAngle = -1; // not used #else // // find start angle // #if 0 for (m=mlist; m; m=m->c_next) { int shape = TOKEN_SHAPE(m->token); if (shape == MSHP_PULSE || shape == MSHP_PULSE_PLUS) { startAngle = TOKEN_ANGLE(m->token); break; } } #else startAngle = TOKEN_ANGLE(mlist->token); #endif #endif (void)startAngle; // // count len of max spell // for (s=slist; s->name; s++) { int len; len = buildSpell(s); if (len > scnt) { scnt = len; } if (OPT_onespell) break; } scnt++; path = malloc((mcnt+1) * scnt); for (s=slist; s->name; s++) { memset(path,0,mcnt*scnt); scoreSpell(s,mlist,path,-1); if (!OPT_silent || (OPT_onespell && !OPT_silent2) || OPT_result_filename) { // // 2nd time with printing // scoreSpell(s,mlist,path,2); scoreSpell(s,mlist,path,3); } if (!best || best->score > s->score) { if (best && best->id != s->id) { best2 = best; } best = s; } else if (best->id != s->id && (!best2 || best2->score > s->score)) { best2 = s; } #if 0 if (OPT_do_picsim) { scoreSpell_pic(s); } #endif if (OPT_onespell) break; } #if 0 if (!OPT_onespell && OPT_do_picsim) { // // check that load of last spell +1 returns PIC_MWN_END_SPELLS // w_mo7_load_spell(); ASSERT(picRV(picRegId(v_mo_spellinfol)) == (PIC_MWN_END_SPELLS&0xff)); ASSERT(picRV(picRegId(v_mo_spellinfoh)) == (PIC_MWN_END_SPELLS>>8)); } #endif free(path); #if 0 // // find 2nd best // best2 = 0; for (s=slist; s->name; s++) { if (s==best) continue; if (s->id==best->id) continue; if (!best2) best2 = s; if (best2->score > s->score) { best2 = s; } if (OPT_onespell) break; } #endif gBestSpell1 = best; gBestSpell2 = best2; gChooseSpell = 0; if (best->score <= best->maxscore && (!best2 || best2->score - best->score > best->holdoff)) { gChooseSpell = best; } if (!OPT_filelist && OPT_silent && !OPT_silent2) { printf("\nRESULT:Scores\n"); for (s=slist; s->name; s++) { printf("RESULT: %s %05d %s (%s) x(%s %s)%s\n", s==best ? "*": s==best2 ? "+":" ", s->score, s->name, s->mwanemes ? s->mwanemes : "", gCurrentSpell ? gCurrentSpell->name : "", gCurrentSpell && gCurrentSpell->mwanemes ? gCurrentSpell->mwanemes : "", (s==gCurrentSpell) ? "SAME" : ""); if (OPT_onespell) break; } } gBestSpell1_m = gBestSpell1; gBestSpell2_m = gBestSpell2; gChooseSpell_m = gChooseSpell; return 0; } //=========================================================================== // checkSpells_pic() //=========================================================================== static int checkSpells_pic(PSpell *slist, PSpell *best1, PSpell *best2) { int best1_info, best2_info; int best1_score, best2_score; int choose_info; int highest_score = gMaxMaxscore + gMaxHoldoff; gCurrentSpell = slist; gCurrentMwanemeIndex = 0; if (!OPT_use_picsim) { w_mo8_check_spells(); } best1_score = picRV(picRegId(v_mo_best1_score)); best2_score = picRV(picRegId(v_mo_best2_score)); best1_info = (picRV(picRegId(v_mo_best1_infoh)) << 8) | picRV(picRegId(v_mo_best1_infol)); best2_info = (picRV(picRegId(v_mo_best2_infoh)) << 8) | picRV(picRegId(v_mo_best2_infol)); choose_info = (picRV(picRegId(v_mo_spellinfoh)) << 8) | picRV(picRegId(v_mo_spellinfol)); ASSERT(!choose_info || choose_info == best1_info); if (best1 && best2) { ASSERT(best1_score == best1->score || (best1_score>=highest_score && best1->score>=highest_score)); if (!OPT_onespell) { ASSERT(best2_score == best2->score || (best2_score>=highest_score && best2->score>=highest_score)); } //ASSERT(best1_info == best1->spellinfo); //ASSERT(best2_info == best2->spellinfo); } if (!best1 || !best2 || best1_info != best1->spellinfo || best2_info != best2->spellinfo) { PSpell *s; best1 = best2 = 0; for (s=slist; s->name; s++) { if (best1_info == s->spellinfo) { best1 = s; if (best2) break; } if (best2_info == s->spellinfo) { best2 = s; if (best1) break; } if (OPT_onespell) break; } ASSERT(best1 || best1_info==0); ASSERT(best2 || best2_info==0); if (!OPT_use_original && !OPT_use_minimal) { gBestSpell1 = best1; gBestSpell2 = best2; if (best1) { best1->spellinfo = best1_info; best1->score = best1_score; } if (best2) { best2->spellinfo = best2_info; best2->score = best2_score; } } } if (!OPT_onespell && best1 && best2) { #if 1 if (choose_info == best1_info) { if (!(best1->score <= best1->maxscore)) { printf("FAILED best1->score <= best1->maxscore\n%d %d\n", best1->score,best1->maxscore); } #if 0 if (!(best2->score > best2->maxscore)) { printf("FAILED best2->score > best2->maxscore\n%d %d\n", best2->score,best2->maxscore); } #endif if (!(best2->score - best1->score > best1->holdoff)) { printf("FAILED best2->score - best1->score > best1->holdoff\n %d %d %d \n", best2->score, best1->score, best1->holdoff); } gChooseSpell = best1; } else { int proba = (best1->score <= best1->maxscore); #if 0 int probb = (best2->score > best2->maxscore); #else int probb = 1; #endif int probc = (best2->score - best1->score > best1->holdoff); ASSERT(!proba || !probb || !probc); gChooseSpell = 0; } #else if (best1->score <= best1->maxscore && best2->score + best1->holdoff > best1->score) { if (gChooseSpell) { ASSERT(gChooseSpell->score == best1->score); } gChooseSpell = best1; } else { gChooseSpell = 0; } #endif } gCurrentSpell = 0; gCurrentMwanemeIndex = 0; return 0; } //=========================================================================== // checkSpellName() //=========================================================================== static void checkSpellName(const char *name) { const char *s = name; // // Spell name must be all lowercase letters, optionally followed by 1 // or more digits (necessary for tryem script) // while(isalpha(*s) || *s=='_') s++; if (s == name) { fprintf(stderr,"Bad spell name: '%s'\n",name); ASSERT(!"must begin with letters"); } while(isdigit(*s)) s++; if (*s) { fprintf(stderr,"Bad spell name: '%s'\n",name); ASSERT(!"any digits must come at end of spell name"); } } //=========================================================================== // spellCmp() //=========================================================================== static int spellCmp(const void *a, const void *b) { const PSpell *pa = *((const PSpell**)a); const PSpell *pb = *((const PSpell**)b); return strcmp(pa->name,pb->name); } //=========================================================================== // initSpells() //=========================================================================== static PSpell *initSpells(Spell *s,PSpell *old) { #if SORT_BY_LEN PSpell **sortList; int id=1; #endif PSpell *slist; int scnt,dcnt; int i; if (old) free(old); for (scnt=0; s[scnt].name; scnt++); slist = calloc((scnt+1), sizeof(PSpell)); sortList = calloc((scnt+1), sizeof(PSpell*)); scnt = dcnt = 0; for (; s[scnt].name; scnt++) { char *np; checkSpellName(s[scnt].name); mwanemeDescStr(s[scnt].mwanemes); if (!OPT_allspells && (s[scnt].flags & SPELL_FLG_WAND)==0) continue; if (OPT_vital && (s[scnt].flags & SPELL_FLG_VITAL)==0) continue; slist[dcnt].flags = s[scnt].flags; slist[dcnt].maxscore = s[scnt].maxscore; slist[dcnt].holdoff = s[scnt].holdoff; slist[dcnt].name = s[scnt].name; slist[dcnt].mwanemes = s[scnt].mwanemes; slist[dcnt].baseName = strdup(s[scnt].name); for (np = slist[dcnt].baseName; *np; np++) { if (!islower(*np)) break; } *np = 0; sortList[dcnt] = &slist[dcnt]; ASSERT(s[scnt].maxscore + s[scnt].holdoff < 254); dcnt++; } #if SORT_BY_LEN qsort(sortList, dcnt, sizeof(PSpell*), spellCmp); for (i=0; i<dcnt; i++) { if (i && !strcmp(sortList[i]->baseName, sortList[i-1]->baseName)) { sortList[i]->id = sortList[i-1]->id; sortList[i]->flags &= ~SPELL_FLG_FIRST; } else { sortList[i]->id = id++; sortList[i]->flags |= SPELL_FLG_FIRST; } sortList[i]->sortId = sortList[i]->id; } free(sortList); #endif return slist; } //=========================================================================== // crosscheck() //=========================================================================== int crosscheck(PSpell *sp, PSpell *slist) { Motion mlist[CNT_MAX]; Motion *m; int tm = 1; unsigned char *t; // // bit mode // 0 include optional circles // 1 make pulses plus // 2 include optional pulses int mode = 0; printf("========== Crosscheck spell %s = %s\n",sp->name,sp->mwanemes); gCurrentSpell = sp; buildSpell(sp); t = sp->tokens; // // copy tokens to mlist // memset(mlist,0,sizeof(mlist)); m = mlist; tm = 1; while(1) { int shape = TOKEN_SHAPE(*t); int dir = TOKEN_DIR(*t); int angle = TOKEN_ANGLE(*t); if (*t == STOKEN_END) break; switch(shape) { case SSHP_CIRCLE: shape = MSHP_CLEAN_CIRCLE; break; case SSHP_OCIRCLE: shape = (mode & 0x1) ? MSHP_DIRTY_CIRCLE : -1; break; case SSHP_PULSE: shape = (mode & 0x2) ? MSHP_PULSE_PLUS : MSHP_PULSE; break; case SSHP_OPULSE: shape = (mode & 0x4) ? 1 : MSHP_PULSE; break; case SSHP_WILD: shape = -1; break; case SSHP_PAUSE: shape = -1; break; } if (shape != -1) { m->token = TOKEN_CREATE_MO(shape,dir,angle); m->b_atime = tm; m->c_next = m+1; m->c_prev = m-1; m++; } t++; tm++; } m->token = MTOKEN_END; m->c_next = 0; mlist->c_prev = 0; checkSpells(slist, mlist, 1 + m - mlist); gCurrentSpell = 0; return 0; } //=========================================================================== // x2d() //=========================================================================== int x2d(int c) { c = tolower(c); if (isdigit(c)) return c-'0'; if (islower(c)) return c-'a'+10; return 0; } //=========================================================================== // getRaw() //=========================================================================== int getRaw(Motion *mlist, FILE *in) { int v[8]; int idx=0; int half=0; int loop=1; Motion *m = mlist; int st = 0; while(loop) { int c = getc(in); if (c == EOF) break; switch(st) { case 0: if (c=='\'') st++; break; case 1: if (c=='m') st=102; else if (c=='a') st=202; else st=0; break; case 100: if (c=='\'') st++; break; case 101: if (c=='m') st++; else st=100; break; case 102: if (isxdigit(c)) { v[0] = x2d(c)<<4; st++; } else st=100; break; case 103: if (isxdigit(c)) { v[0] += x2d(c); st++; } else st=100; break; case 104: if (c=='\'') { m->c_prev = m-1; m->c_next = m+1; m->token = v[0]; m++; } st=100; break; case 199: half = 0; st++; case 200: if (c=='\'') st++; break; case 201: idx = 0; if (c=='a') st++; else st=199; break; case 202: if (isxdigit(c)) { v[idx] = x2d(c)<<4; st++; } else st=199; break; case 203: if (isxdigit(c)) { v[idx] += x2d(c); idx++; if (idx < 8) st=202; else st=204; } else st=199; break; case 204: if (c=='\'') { OPT_raw = 0; idx = 0; #if 0 printf("X: %02x %02x %02x %02x %02x %02x %02x %02x\n", v[idx+0], v[idx+1], v[idx+2], v[idx+3], v[idx+4], v[idx+5], v[idx+6], v[idx+7]); #endif while(idx < 8) { if (half) { #if 0 printf("B: %02x %02x %02x %02x\n", v[idx+0], v[idx+1], v[idx+2], v[idx+3]); #endif m->b_imp = (v[idx+0]<<8) + v[idx+1]; m->b_minmag = v[idx+2]; m->b_flags = v[idx+3]; if (m->b_flags & MFLG_ZERO) { m->b_deltamag = m->b_maxmag; } else { m->b_deltamag = m->b_maxmag - m->b_minmag; } m++; idx += 4; half = 0; continue; } memset(m,0,sizeof(*m)); #if 0 printf("A: %02x %02x %02x %02x\n", v[idx+0], v[idx+1], v[idx+2], v[idx+3]); #endif m->b_dtime = (v[idx+0]<<8) + v[idx+1]; m->b_angle = v[idx+3]; if (m == mlist) { m->b_atime = 0; } else { m->b_atime = (m-1)->b_atime + (m-1)->b_dtime; } if (m->b_angle < 0x20) { m->b_maxmag = v[idx+2]; half = 1; } else { m++; if (m->b_angle == 0xfe) { m--; memset(m,0,sizeof(*m)); loop = 0; break; } } idx += 4; } st=200; } else { st=199; } break; default: st=0; break; } } if (m==mlist) { fprintf(stderr,"ERROR: file has no data!\n"); exit(1); } if (OPT_export) { Motion *m2; if (OPT_raw) { fprintf(stderr,"ERROR: file is not in aXXXXXX format!\n"); exit(1); } for (m2=mlist; m2!=m; m2++) { printf("%8.1f %8.1f %8.1f %8.1f %8.1f %8.1f\n", (double)m2->b_atime, (double)m2->b_angle, (double)m2->b_imp, (double)m2->b_minmag, (double)m2->b_maxmag, (double)m2->b_flags); } m2--; if (m2->b_angle < 0x20) { printf("%8.1f %8.1f %8.1f %8.1f %8.1f %8.1f\n", (double)(m2->b_atime + m2->b_dtime), 255.0, 0.0, 0.0, 0.0, 0.0); } exit(0); } if (OPT_raw) { m->c_prev = m-1; m->c_next = m+1; m->token = MTOKEN_END; m++; mlist->c_prev = 0; (m-1)->c_next = 0; OPT_use_minimal = 1; OPT_do_picsim = 0; printf("Found %d tokens\n",m-mlist); } else { printf("Found %d acc records\n",m-mlist); } return m-mlist; } //=========================================================================== // runit() //=========================================================================== int runit(PSpell *slist, FILE *in) { Motion mlist[CNT_MAX]; int tokens_min[CNT_MAX]; int tokens_pic[CNT_MAX]; int atime_min[CNT_MAX]; int atime_pic[CNT_MAX]; int *tokens_use = 0; int *atime_use = 0; Motion *m; int *tc, *tp; int mcnt=0; memset(mlist,0,sizeof(mlist)); if (OPT_raw) { mcnt = getRaw(mlist,in); } else { mcnt = get(in,mlist,mlist+(sizeof(mlist)/sizeof(mlist[0]))); } if (mcnt) { memset(atime_min,0,sizeof(atime_min)); memset(atime_pic,0,sizeof(atime_pic)); tokens_min[0] = MTOKEN_END; tokens_pic[0] = MTOKEN_END; initialPrint(mlist); // // Use one of these functions here to generate tokens // // look(mlist,mcnt); // look_minimal(mlist, tokens); // look_pic(mlist, tokens); // look_both(mlist, mcnt, tokens); // look_all3(mlist, mcnt, tokens_min, tokens_pic); // if (OPT_raw) { tokens_use = 0; atime_use = 0; } else if (OPT_use_original) { tokens_use = 0; atime_use = 0; } else if (OPT_use_minimal) { tokens_use = tokens_min; atime_use = atime_min; } else if (OPT_use_picsim) { tokens_use = tokens_pic; atime_use = atime_pic; } else { tokens_use = tokens_pic; atime_use = atime_pic; } if (OPT_raw) { // no conersion needed } else if (OPT_use_original && !OPT_use_all) { look(mlist,mcnt); OPT_do_picsim = 0; } else if (OPT_use_minimal && !OPT_use_all) { look_minimal(mlist, tokens_min, atime_min); OPT_do_picsim = 0; } else if (OPT_use_picsim && !OPT_use_all) { look_pic(mlist, tokens_pic, atime_pic, slist); OPT_do_picsim = 1; } else { look_all3(mlist, mcnt, tokens_min, tokens_pic, atime_min, atime_pic); } if (!OPT_silent || OPT_show_tokens) { int *at_p = atime_pic; int *at_m = atime_min; // // print tokens // m = mlist; tc = tokens_min; tp = tokens_pic; printf(" %8s %11s %8s\n", "Original", "Minimal ", "Picsim "); printf(" %8s %11s %8s\n", "--------", "-----------", "--------"); while(1) { int mask = 0xff; if (!m && *tc==MTOKEN_END && *tp==MTOKEN_END) { break; } if (!m) { printf(" %5s %2s @ ","",""); } else if (m && TOKEN_SHAPE(m->token) != MSHP_CIRCLE_GAP && *tc!=MTOKEN_END && TOKEN_SHAPE(*tc) == MSHP_CIRCLE_GAP) { printf(" %5s %2s @ ","",""); } else { printf(" %5s %02x ", m?motionTokenStr(m->token):"END ", m?m->token:0); // pause? if (m && m->token == TOKEN_CREATE_MO(MSHP_PAUSE,0,0)) { printf("\n"); m = m?m->c_next:0; continue; } if (m && TOKEN_SHAPE(m->token) == MSHP_CIRCLE_GAP && *tc!=MTOKEN_END && TOKEN_SHAPE(*tc) != MSHP_CIRCLE_GAP) { printf(" @\n"); m = m?m->c_next:0; continue; } if (TOKEN_SHAPE(*tc) == MSHP_PULSE_PLUS || TOKEN_SHAPE(*tc) == MSHP_PULSE) { mask = 0x7f; } printf(" %s ", (*tc!=MTOKEN_END && m && ((*tc)&mask)==((m->token)&mask)) ? " " : "@"); m = m->c_next; } printf(" %02x %5s %02x", (*tc!=MTOKEN_END)?*tc:0, (*tc!=MTOKEN_END)?motionTokenStr(*tc):"END ", (*tc!=MTOKEN_END)?*tc:0); printf(" %s ",*tc==*tp ? " " : "*"); if (atime_use == atime_pic && *at_m && !*at_p) { atime_use = atime_min; } if(*tc!=MTOKEN_END) { tc++; at_m++; } printf(" %02x %5s token[%2d]\n", (*tp!=MTOKEN_END)?*tp:0, (*tp!=MTOKEN_END)?motionTokenStr(*tp):"END ", tp-tokens_pic); if(*tp!=MTOKEN_END) { tp++; at_p++; } } } if (!OPT_silent || OPT_show_tokens || OPT_showtime) { int cyc = picGetCycle(); if (cyc) { printf("tokenize: %7d cycles; %5.3f sec\n", cyc, (float)cyc/1000000); } } if (tokens_use) { int *t; int *tm; // // copy tokens to mlist // memset(mlist,0,sizeof(mlist[0])*mcnt); m = mlist; t = tokens_use; tm = atime_use; while(1) { m->token = *t; m->b_atime = *tm; if (*t == MTOKEN_END) break; if (m != mlist) (m-1)->c_next = m; m++; t++; tm++; } } if (!OPT_quick) { int err = 0; int cyc0 = picGetCycle(); if (OPT_use_all || !OPT_use_picsim) { err = checkSpells(slist, mlist,mcnt); } picSetCycle(cyc0); if (OPT_do_picsim && !err) { err = checkSpells_pic(slist, gBestSpell1, gBestSpell2); } if (!err) { printf("RESULT2:%-15s %-55s %4d %-15s %4d %-15s (%6.3f sec)\n", gChooseSpell?gChooseSpell->name:"NONE", OPT_input_filename?OPT_input_filename:"stdin", gBestSpell1?gBestSpell1->score:0, gBestSpell1?gBestSpell1->name:"NONE", gBestSpell2?gBestSpell2->score:0, gBestSpell2?gBestSpell2->name:"NONE", (float)picGetCycle()/1000000.0); if (OPT_use_all && (gChooseSpell != gChooseSpell_m || gBestSpell1 != gBestSpell1_m || gBestSpell2 != gBestSpell2_m)) { printf( "MISMTCH:%-15s %-55s %4d %-15s %4d %-15s\n", gChooseSpell_m?gChooseSpell_m->name:"NONE", OPT_input_filename?OPT_input_filename:"stdin", gBestSpell1_m?gBestSpell1_m->score:0, gBestSpell1_m?gBestSpell1_m->name:"NONE", gBestSpell2_m?gBestSpell2_m->score:0, gBestSpell2_m?gBestSpell2_m->name:"NONE"); printf("^cmdline: %s\n",gCmdline); } } } } return 0; } //=========================================================================== // runlist() //=========================================================================== int runlist(PSpell *slist, FILE *in) { PSpell *spell; int rv = 0; while(1) { char line[300]; char spellnamebuf[100]; char *s; char *filename = 0; char *spellname = 0; int spellnamelen = 0; FILE *fp; if (!getline2(in,line,line+sizeof(line))) { printf("Z overall score= %d",rv); return rv; } filename = line; for (s=line; *s && *s != ':'; s++); if (s[0] && s[1]) { spellname = s+1; *s = 0; } if (s-line <= 4) continue; s -= 4; if (strcmp(s,".txt")) continue; while(s!=line && *s!='/') s--; if (*s == '/') s++; if (!strncmp(s,"wpic",4)) { char *st = s + 4; for (; *st=='_'; st++); for (s=st; islower(*s); s++); if ((1 || isdigit(*s) || *s=='_' || *s=='.') && s != st) { memcpy(spellnamebuf,st,s-st); spellnamebuf[s-st] = 0; spellname = spellnamebuf; } } spell = 0; if (spellname) { spellnamelen = strlen(spellname); for (spell=slist; spell->name; spell++) { if (!strncmp(spell->name,spellname,spellnamelen)) break; if (OPT_onespell) { spell=0; break; } } if (!spellnamelen || !spell || !spell->name) { spell = 0; } } fp = fopen(filename,"r"); if (!fp) { fprintf(stderr,"Could not open file '%s'\n",filename); } else { int thresh1; int thresh2; int s1, s2; char *result1 = "?"; char *result2 = "???"; int color = -1; int score = 0; int score2 = 0; OPT_input_filename = filename; gBestSpell1 = 0; gBestSpell2 = 0; runit(slist,fp); thresh1 = 10; thresh2 = 10; s1 = gBestSpell1->score; s2 = gBestSpell2->score; if (spell) { if (!strncmp(spellname, gBestSpell1->name,spellnamelen)) { score2 = s1-s2; if ((gBestSpell1->flags & SPELL_FLG_DUMMY) && (gBestSpell2->flags & SPELL_FLG_DUMMY)) { result1 = "B"; result2 = "dummy"; color = 2; score = 0; } else if (s2 < thresh2*2) { result1 = "P"; result2 = "TOO CLOSE"; color = 3; score = 1000; } else if (s1 < thresh1) { result1 = "A"; result2 = "good"; color = 2; score = -1000; } else if ((s2-thresh2) - (s1-thresh1) <(thresh1+thresh2)){ result1 = "E"; result2 = "TOO CLOSE"; color = 3; score = 1000; } else if (s1 < thresh1*2) { result1 = "C"; result2 = "close"; color = 4; score = 1000; } else { result1 = "D"; result2 = "FAR"; color = 6; score = 100; } if (score < -100) score = -100; if (score > 100) score = 100; } else { score2 = -s1; if (gBestSpell1->flags & SPELL_FLG_DUMMY) { result1 = "B"; result2 = "dummy"; color = 2; score = 0; } else if (s1 < thresh1*1) { result1 = "T"; result2 = "FALSE +"; color = 1; score = 10000; } else if (s1 < thresh1*2) { result1 = "S"; result2 = "TOO CLOSE"; color = 1; score = 1000; } else { result1 = "Q"; result2 = "MISS"; color = 5; score = 100; } if (score < -100) score = -100; } } else { score = 0; score2 = s1-s2; if (score < -100) score = -100; result1 = "V"; result2 = "??"; color = -1; } printf("%s%s %05x %5d %5d %9s %4d %4d %20s %20s (%15s) %s %s\n", result1, colorStr(color), score + score2 + 0x40000, score, score2, result2, s1, s2, gBestSpell1->name, gBestSpell2->name, spellname?spellname:"", filename, colorStr(-1)); rv += score; OPT_input_filename = 0; } } } //=========================================================================== // usage() //=========================================================================== static void usage(void) { printf( "Usage: fmtb_parse [OPTIONS] < wpic_file.txt\n" "Usage: fmtb_parse [OPTIONS] <spell> < wpic_file.txt\n" " Parse motions from wpic_file.txt and compare against spells.\n" " If <spell> argument is supplied only compare against that\n" " one spell.\n" "Options:\n" " -d describe. Show all spells with mwanemes.\n" " -v vital. Only vital spells (default = all in wand)\n" " -A ALL. Use all spells (default = all in wand)\n" " -q quick. Parse but do not compare.\n" " -s silent. Just show results.\n" " -S very silent. Just show top 2 matches.\n" " -c no color. Do not use color escape characters.\n" " -a no addr. Do not print pointer addresses.\n" " -o original. Use tokens generated by original algorithm.\n" " -M classic-minimal. Use classic minimal algorithm.\n" " -m minimal. Use tokens generated by minimal algorithm.\n" " -x experimental-minimal. Use experimental minimal alg.\n" " -p picsim. Use tokens generated by picsim algorithm.\n" " -3 all3. Use all 3 algorithms & compare (default).\n" " -t show tokens & difference btwn old & new algorithm.\n" " -w show spell tokens & quit\n" " -C no crash. Do not crash on assert (just exit).\n" " -L cmdline. show command line.\n" " -f file list. Read file:spell list from stdin\n" " -T timing info. Print cycle times\n" " -R Raw data. Parse rawdata from wand out as motions\n" " -e export. Just spew wpic data to stdout (implies -R).\n" " -? print this usage message.\n" "\n" " -X cross check all spells\n" " -X<spell> cross check <spell>\n" " -XX<mwan> use <mwan> as mwaneme string\n" " -r<file> write results to <file> (for wg input)\n" " -W<file> write mwaneme file for assembly (wmspells.inc) to <file>\n" " -l supply literal mwanemes\n" ); exit(1); } //=========================================================================== // main() //=========================================================================== int main(int argc, char *argv[]) { PSpell lspell; PSpell lxspell; PSpell *slistAll; PSpell *slist = 0; PSpell *xspell = 0; PSpell *s; char **argp; FILE *infile = 0; int rv = 1; int OPT_cmdline=0; int save_allspells; int save_vital; save_vital= OPT_vital; save_allspells = OPT_allspells; OPT_allspells = 1; OPT_vital = 0; slistAll = initSpells(spells,0); OPT_allspells = save_allspells; OPT_vital = save_vital; for(argp=&argv[1]; *argp; argp++) { if (!strcmp(*argp,"-?")) { usage(); } else if (!strcmp(*argp,"-e")) { OPT_silent=1; OPT_silent2=1; OPT_export=1; OPT_raw=1; } else if (!strcmp(*argp,"-R")) { OPT_raw=1; } else if (!strcmp(*argp,"-L")) { OPT_cmdline=1; } else if (!strcmp(*argp,"-d")) { OPT_describe=1; } else if (!strcmp(*argp,"-A")) { OPT_allspells=1; } else if (!strcmp(*argp,"-v")) { OPT_vital=1; } else if (!strcmp(*argp,"-w")) { OPT_showspell=1; } else if (!strcmp(*argp,"-f")) { OPT_filelist=1; } else if (!strcmp(*argp,"-T")) { OPT_showtime=1; } else if (!strcmp(*argp,"-C")) { OPT_nocrash=1; } else if (!strcmp(*argp,"-a")) { OPT_noaddr=1; } else if (!strcmp(*argp,"-c")) { OPT_nocolor=1; } else if (!strcmp(*argp,"-s")) { OPT_silent=1; } else if (!strcmp(*argp,"-S")) { OPT_silent=1; OPT_silent2=1; } else if (!strcmp(*argp,"-q")) { OPT_quick=1; } else if (!strcmp(*argp,"-o")) { OPT_use_original=1; } else if (!strcmp(*argp,"-M")) { OPT_use_classic=1; } else if (!strcmp(*argp,"-x")) { OPT_use_experimental=1; } else if (!strcmp(*argp,"-m")) { OPT_use_minimal=1; } else if (!strcmp(*argp,"-p")) { OPT_use_picsim=1; } else if (!strcmp(*argp,"-3")) { OPT_use_all=1; } else if (!strcmp(*argp,"-t")) { OPT_show_tokens=1; } else if (!strncmp(*argp,"-X",2)) { if (OPT_crosscheck) { fprintf(stderr,"only use -X once\n"); usage(); } OPT_crosscheck=1; if (argp[0][2] == 'X') { memset(&lxspell,0,sizeof(lxspell)); lxspell.flags = SPELL_FLG_VITAL; lxspell.name = *argp + 3; lxspell.mwanemes = *argp + 3; checkSpellName(lxspell.mwanemes); xspell = &lspell; } else if (argp[0][2]) { for (s=slistAll; s->name; s++) { if (!strcmp(*argp+2,s->name)) { break; } } if (s->name) { xspell = s; } else { fprintf(stderr,"No spell named '%s'\n",*argp+2); usage(); } } } else if (!strncmp(*argp,"-W",2)) { OPT_mwaneme_filename = *argp + 2; } else if (!strncmp(*argp,"-r",2)) { OPT_result_filename = *argp + 2; } else if (!strncmp(*argp,"-l",2)) { if (!argp[0][2]) { fprintf(stderr,"Please supply mwanemes with -l\n"); usage(); } if (slist) { fprintf(stderr,"Do not use -l with spell-name\n"); usage(); } memset(&lspell,0,sizeof(lspell)); lspell.flags = SPELL_FLG_VITAL; lspell.name = *argp + 2; lspell.mwanemes = *argp + 2; checkSpellName(lspell.mwanemes); slist = &lspell; OPT_onespell=1; } else if (argp[0][0] == '-') { fprintf(stderr,"Option '%s' unknown\n",*argp); usage(); } else { s = 0; if (!slist) { for (s=slistAll; s->name; s++) { if (!strcmp(*argp,s->name)) { slist = s; OPT_onespell=1; break; } } } if (!s || !s->name) { if (infile) { fprintf(stderr,"extra argument: '%s'\n",*argp); usage(); } infile = fopen(*argp, "r"); if (infile) { OPT_input_filename=*argp; } else { fprintf(stderr,"bad argument: '%s'\n",*argp); usage(); } } } } { char *p = gCmdline; p += sprintf(p,"fmtb_parse "); for(argp=&argv[1]; *argp; argp++) { p += sprintf(p,"%s ",*argp); } acAssertSetUserFunc(fmtbAssertFailed); } if (OPT_cmdline) { printf("Cmdline: %s\n",gCmdline); } if (!slist) { slistAll = initSpells(spells,slistAll); } if (!slist) slist = slistAll; if (OPT_quick && OPT_silent) OPT_show_tokens=1; if (OPT_nocrash) { acAssertMode(AC_ASSERT_EXIT); } if (OPT_mwaneme_filename && OPT_onespell) { fprintf(stderr,"Do not use -W flag and specify a spell together\n"); usage(); } if (OPT_filelist && OPT_crosscheck) { fprintf(stderr,"Do not use -X and -f flags together\n"); usage(); } if (OPT_input_filename && OPT_crosscheck) { fprintf(stderr,"Do not use a filename with -X flag\n"); usage(); } if (OPT_input_filename && OPT_filelist) { fprintf(stderr,"Do not use a filename with -f flag\n"); usage(); } if (OPT_result_filename && !OPT_result_filename[0]) { fprintf(stderr,"-r requires filename (no space)\n"); usage(); } if (OPT_result_filename && !OPT_onespell) { OPT_result_motion_only = 1; OPT_onespell = 1; } if (OPT_use_original + OPT_use_classic + OPT_use_experimental + OPT_use_minimal + OPT_use_picsim > 1) { fprintf(stderr,"Only use one of -o -m -p or -3 options\n"); usage(); } if (OPT_use_classic || OPT_use_experimental) { OPT_use_minimal = 1; } if ((OPT_use_minimal || OPT_use_original) && !OPT_use_picsim && !OPT_use_all) { OPT_do_picsim = 0; } if (OPT_describe) { describeSpells(slist); exit(0); } init_pic(); buildAllSpells(slist); if (OPT_showspell) { int cyc = picGetCycle(); printf("BuildSpell done: %7d cycles %5.3f sec\n", cyc, (float)cyc/1000000); exit(0); } if (OPT_mwaneme_filename) { exit(0); } picSetCycle(0); if (OPT_crosscheck) { if (xspell) { rv = crosscheck(xspell,slist); } else { for (xspell=slistAll; xspell->name; xspell++) { rv |= crosscheck(xspell, slistAll); } } } else if (infile) { rv = runit(slist,infile); } else if (OPT_filelist) { rv = runlist(slist,stdin); } else { rv = runit(slist,stdin); } if (infile) { fclose(infile); infile = 0; } if (!OPT_silent || OPT_showtime) { printf("PIC: %7d cycles; %5.3f sec\n", picGetCycle(), (float)picGetCycle()/1000000.0); printf("%d token compares total\n",gCompareCnt); } return rv; } //=========================================================================== // preventWarnings() //=========================================================================== void preventWarnings(void) { readTokens(0,0); eraseLocalVars(); writeM2List(0,0); readM2List(0,0); w_a2oct(); w_oct2a(); writeM1List(0,0); w_mo_read(); w_adiff(); w_shp_write(); w_shp_prev(); quad2a(0); w_mo1_parse1(); w_mo2_savenext(); w_mo2_fill_circle_gaps(); w_mo3_find_weak_circles(); w_mo4_find_best_pulses(); w_mo5_marklast(); w_mo6_tokenize(); w_check_motion_spell(); scoreSpell_pic(0); } |
This file Copyright (C) 2006 by Nathan (Acorn) Pooley
Go to TOP Wand page
Go to Acorn's personal webpage
Go to Hogwarts website: www.gotohogwarts.com
Snout: www.snout.org/game
Gadgets of Justice Unlimited
Snout GC (Wiki)
Snout Wiki
File created by do_doc at Wed May 30 03:26:33 PDT 2007