#define PROGRAM_NAME "RASM" #define PROGRAM_VERSION "0.120" #define PROGRAM_DATE "xx/12/2019" #define PROGRAM_COPYRIGHT "© 2017 BERGE Edouard / roudoudou from Resistance" #define RASM_VERSION PROGRAM_NAME" v"PROGRAM_VERSION" (build "PROGRAM_DATE")" #define RASM_SNAP_VERSION PROGRAM_NAME" v"PROGRAM_VERSION #define TRACE_GENERALE 0 #define TRACE_PREPRO 0 #define TRACE_ASSEMBLE 0 #define TRACE_COMPUTE_EXPRESSION 0 #define TRACE_HEXBIN 0 #define TRACE_MAKEAMSDOSREAL 0 #define TRACE_STRUCT 0 #define TRACE_EDSK 0 /*** Rasm (roudoudou assembler) Z80 assembler doc & latest official release at: http://www.cpcwiki.eu/forum/programming/rasm-z80-assembler-in-beta/ You may send requests/bugs in the same topic ----------------------------------------------------------------------------------------------------- This software is using MIT "expat" license « Copyright © BERGE Edouard (roudoudou) Permission is hereby granted, free of charge,to any person obtaining a copy of this software and associated documentation/source files of RASM, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the Software. » ----------------------------------------------------------------------------------------------------- Linux compilation with GCC or Clang: cc rasm_v0116.c -O2 -lm -lrt -march=native -o rasm strip rasm Windows compilation with Visual studio: cl.exe rasm_v0116.c -O2 -Ob3 pure MS-DOS 32 bits compilation with Watcom: wcl386 rasm_v0116.c -6r -6s -fp6 -d0 -k4000000 -ox /bt=DOS /l=dos4g MorphOS compilation (ixemul): ppc-morphos-gcc-5 -O2 -c -o rasm rasm_v0116.c strip rasm MacOS compilation: cc rasm_v0116.c -O2 -lm -march=native -o rasm */ #ifdef __WATCOMC__ #define OS_WIN 1 #endif #ifdef _WIN32 #define OS_WIN 1 #endif #ifdef _WIN64 #define OS_WIN 1 #endif #ifndef RDD /* public lib */ #include"minilib.h" #else /* private dev lib wont be published */ #include"../tools/library.h" #define TxtSplitWithChar _internal_TxtSplitWithChar #endif #ifndef NO_3RD_PARTIES #define __FILENAME__ "3rd parties" /* 3rd parties compression */ #include"zx7.h" #include"lz4.h" #include"exomizer.h" #endif #ifdef __MORPHOS__ /* Add standard version string to executable */ const char __attribute__((section(".text"))) ver_version[]={ "\0$VER: "PROGRAM_NAME" "PROGRAM_VERSION" ("PROGRAM_DATE") "PROGRAM_COPYRIGHT"" }; #endif #undef __FILENAME__ #define __FILENAME__ "rasm.c" #ifndef OS_WIN #define KNORMAL "\x1B[0m" #define KERROR "\x1B[31m" #define KAYGREEN "\x1B[32m" #define KWARNING "\x1B[33m" #define KBLUE "\x1B[34m" #define KVERBOSE "\x1B[36m" #define KIO "\x1B[97m" #else #define KNORMAL "" #define KERROR "Error: " #define KAYGREEN "" #define KWARNING "Warning: " #define KBLUE "" #define KVERBOSE "" #define KIO "" #endif /******************************************************************* c o m m a n d l i n e p a r a m e t e r s *******************************************************************/ enum e_dependencies_type { E_DEPENDENCIES_NO=0, E_DEPENDENCIES_LIST, E_DEPENDENCIES_MAKE }; struct s_parameter { char **labelfilename; char *filename; char *outputfilename; int automatic_radix; int export_local; int export_var; int export_equ; int export_sym; int export_multisym; int export_tape; char *flexible_export; int export_sna; int export_snabrk; int export_brk; int nowarning; int checkmode; int dependencies; int maxerr; int macrovoid; int extended_error; int edskoverwrite; float rough; int as80,dams; int v2; int warn_unused; char *symbol_name; char *binary_name; char *cartridge_name; char *snapshot_name; char *tape_name; char *breakpoint_name; char **symboldef; int nsymb,msymb; char **pathdef; int npath,mpath; }; /******************************************************************* c o m p u t e o p e r a t i o n s f o r c a l c u l a t o r *******************************************************************/ enum e_compute_operation_type { E_COMPUTE_OPERATION_PUSH_DATASTC=0, E_COMPUTE_OPERATION_OPEN=1, E_COMPUTE_OPERATION_CLOSE=2, E_COMPUTE_OPERATION_ADD=3, E_COMPUTE_OPERATION_SUB=4, E_COMPUTE_OPERATION_DIV=5, E_COMPUTE_OPERATION_MUL=6, E_COMPUTE_OPERATION_AND=7, E_COMPUTE_OPERATION_OR=8, E_COMPUTE_OPERATION_MOD=9, E_COMPUTE_OPERATION_XOR=10, E_COMPUTE_OPERATION_NOT=11, E_COMPUTE_OPERATION_SHL=12, E_COMPUTE_OPERATION_SHR=13, E_COMPUTE_OPERATION_BAND=14, E_COMPUTE_OPERATION_BOR=15, E_COMPUTE_OPERATION_LOWER=16, E_COMPUTE_OPERATION_GREATER=17, E_COMPUTE_OPERATION_EQUAL=18, E_COMPUTE_OPERATION_NOTEQUAL=19, E_COMPUTE_OPERATION_LOWEREQ=20, E_COMPUTE_OPERATION_GREATEREQ=21, /* math functions */ E_COMPUTE_OPERATION_SIN=22, E_COMPUTE_OPERATION_COS=23, E_COMPUTE_OPERATION_INT=24, E_COMPUTE_OPERATION_FLOOR=25, E_COMPUTE_OPERATION_ABS=26, E_COMPUTE_OPERATION_LN=27, E_COMPUTE_OPERATION_LOG10=28, E_COMPUTE_OPERATION_SQRT=29, E_COMPUTE_OPERATION_ASIN=30, E_COMPUTE_OPERATION_ACOS=31, E_COMPUTE_OPERATION_ATAN=32, E_COMPUTE_OPERATION_EXP=33, E_COMPUTE_OPERATION_LOW=34, E_COMPUTE_OPERATION_HIGH=35, E_COMPUTE_OPERATION_PSG=36, E_COMPUTE_OPERATION_RND=37, E_COMPUTE_OPERATION_FRAC=38, E_COMPUTE_OPERATION_CEIL=39, E_COMPUTE_OPERATION_GET_R=40, E_COMPUTE_OPERATION_GET_V=41, E_COMPUTE_OPERATION_GET_B=42, E_COMPUTE_OPERATION_SET_R=43, E_COMPUTE_OPERATION_SET_V=44, E_COMPUTE_OPERATION_SET_B=45, E_COMPUTE_OPERATION_END=46 }; struct s_compute_element { enum e_compute_operation_type operator; double value; int priority; }; struct s_compute_core_data { /* evaluator v3 may be recursive */ char *varbuffer; int maxivar; struct s_compute_element *tokenstack; int maxtokenstack; struct s_compute_element *operatorstack; int maxoperatorstack; }; /*********************************************************** w a v h e a d e r f o r a u d i o i m p o r t ***********************************************************/ struct s_wav_header { unsigned char ChunkID[4]; unsigned char ChunkSize[4]; unsigned char Format[4]; unsigned char SubChunk1ID[4]; unsigned char SubChunk1Size[4]; unsigned char AudioFormat[2]; unsigned char NumChannels[2]; unsigned char SampleRate[4]; unsigned char ByteRate[4]; unsigned char BlockAlign[2]; unsigned char BitsPerSample[2]; unsigned char SubChunk2ID[4]; unsigned char SubChunk2Size[4]; }; enum e_audio_sample_type { AUDIOSAMPLE_SMP, AUDIOSAMPLE_SM2, AUDIOSAMPLE_SM4, AUDIOSAMPLE_DMA, AUDIOSAMPLE_END }; /*********************************************************************** e x p r e s s i o n t y p e s f o r d e l a y e d w r i t e ***********************************************************************/ enum e_expression { E_EXPRESSION_J8, /* relative 8bits jump */ E_EXPRESSION_0V8, /* 8 bits value to current adress */ E_EXPRESSION_V8, /* 8 bits value to current adress+1 */ E_EXPRESSION_V16, /* 16 bits value to current adress+1 */ E_EXPRESSION_V16C, /* 16 bits value to current adress+1 */ E_EXPRESSION_0V16, /* 16 bits value to current adress */ E_EXPRESSION_0V32, /* 32 bits value to current adress */ E_EXPRESSION_0VR, /* AMSDOS real value (5 bytes) to current adress */ E_EXPRESSION_IV8, /* 8 bits value to current adress+2 */ E_EXPRESSION_IV81, /* 8 bits value+1 to current adress+2 */ E_EXPRESSION_3V8, /* 8 bits value to current adress+3 used with LD (IX+n),n */ E_EXPRESSION_IV16, /* 16 bits value to current adress+2 */ E_EXPRESSION_RST, /* the offset of RST is translated to the opcode */ E_EXPRESSION_IM, /* the interrupt mode is translated to the opcode */ E_EXPRESSION_RUN, /* delayed RUN value */ E_EXPRESSION_ZXRUN, /* delayed RUN value for ZX snapshot */ E_EXPRESSION_ZXSTACK,/* delayed STACK value for ZX snapshot */ E_EXPRESSION_BRS /* delayed shifting for BIT, RES, SET */ }; struct s_expression { char *reference; /* backup when used inside loop (or macro?) */ int iw; /* word index in the main wordlist */ int o; /* offset de depart 0, 1 ou 3 selon l'opcode */ int ptr; /* offset courant pour calculs relatifs */ int wptr; /* where to write the result */ enum e_expression zetype; /* type of delayed write */ int lz; /* lz zone */ int ibank; /* ibank of expression */ int iorgzone; /* org of expression */ }; struct s_expr_dico { char *name; int crc; int autorise_export; double v; int used; int iw; }; struct s_label { char *name; /* is alloced for local repeat or struct OR generated global -> in this case iw=-1 */ int iw; /* index of the word of label name */ int crc; /* crc of the label name */ int ptr; /* "physical" adress */ int lz; /* is the label in a crunched section (or after)? */ int iorgzone; /* org of label */ int ibank; /* current CPR bank / always zero in classic mode */ int local; /* errmsg */ int fileidx; int fileline; int autorise_export,backidx; int used; }; struct s_alias { char *alias; char *translation; int crc,len,autorise_export; int iw; int used; }; struct s_ticker { char *varname; int crc; long nopstart; long tickerstart; }; /*********************************************************************** m e r k e l t r e e s f o r l a b e l, v a r, a l i a s ***********************************************************************/ struct s_crclabel_tree { struct s_crclabel_tree *radix[256]; struct s_label *label; int nlabel,mlabel; }; struct s_crcdico_tree { struct s_crcdico_tree *radix[256]; struct s_expr_dico *dico; int ndico,mdico; }; struct s_crcused_tree { struct s_crcused_tree *radix[256]; char **used; int nused,mused; }; struct s_crcstring_tree { struct s_crcstring_tree *radix[256]; char **text; int ntext,mtext; char **replace; int nreplace,mreplace; }; /************************************************* m e m o r y s e c t i o n *************************************************/ struct s_lz_section { int iw; int memstart,memend; int lzversion; /* 4 -> LZ4 / 7 -> ZX7 / 48 -> LZ48 / 49 -> LZ49 / 8 -> Exomizer */ int iorgzone; int ibank; /* idx backup */ int iexpr; int ilabel; }; struct s_orgzone { int ibank,protect; int memstart,memend; int ifile,iline; int nocode; }; /************************************************** i n c b i n s t o r a g e **************************************************/ struct s_hexbin { unsigned char *data; int datalen,rawlen; char *filename; int crunch; }; /************************************************** e d s k m a n a g e m e n t **************************************************/ struct s_edsk_sector_global_struct { unsigned char track; unsigned char side; unsigned char id; unsigned char size; unsigned char st1; unsigned char st2; unsigned short int length; unsigned char *data; }; struct s_edsk_track_global_struct { int sectornumber; /* information purpose */ int sectorsize; int gap3length; int fillerbyte; int datarate; int recordingmode; struct s_edsk_sector_global_struct *sector; }; struct s_edsk_global_struct { int tracknumber; int sidenumber; int tracksize; /* DSK legacy */ struct s_edsk_track_global_struct *track; }; struct s_edsk_wrapper_entry { unsigned char user; unsigned char filename[11]; unsigned char subcpt; unsigned char extendcounter; unsigned char reserved; unsigned char rc; unsigned char blocks[16]; }; struct s_edsk_wrapper { char *edsk_filename; struct s_edsk_wrapper_entry entry[64]; int nbentry; unsigned char blocks[178][1024]; /* DATA format */ int face; }; struct s_save { int ibank; int ioffset; int isize; int iw,irun; int amsdos,hobeta; int tape,dsk,face,iwdskname; }; /******************** L O O P S ********************/ enum e_loop_style { E_LOOPSTYLE_REPEATN, E_LOOPSTYLE_REPEATUNTIL, E_LOOPSTYLE_WHILE }; struct s_repeat { int start; int cpt; int value; int maxim; int repeat_counter; char *repeatvar; int repeatcrc; }; struct s_whilewend { int start; int cpt; int value; int maxim; int while_counter; }; struct s_switchcase { int refval; int execute; int casematch; }; struct s_repeat_index { int ifile; int ol,oidx; int cl,cidx; }; enum e_ifthen_type { E_IFTHEN_TYPE_IF=0, E_IFTHEN_TYPE_IFNOT=1, E_IFTHEN_TYPE_IFDEF=2, E_IFTHEN_TYPE_IFNDEF=3, E_IFTHEN_TYPE_ELSE=4, E_IFTHEN_TYPE_ELSEIF=5, E_IFTHEN_TYPE_IFUSED=6, E_IFTHEN_TYPE_IFNUSED=7, E_IFTHEN_TYPE_END }; struct s_ifthen { char *filename; int line,v; enum e_ifthen_type type; }; /************************************************** w o r d p r o c e s s i n g **************************************************/ struct s_wordlist { char *w; int l,t,e; /* e=1 si egalite dans le mot */ int ifile; }; struct s_macro { char *mnemo; int crc; /* une macro concatene des chaines et des parametres */ struct s_wordlist *wc; int nbword,maxword; /**/ char **param; int nbparam; }; struct s_macro_position { int start,end,value; }; /* preprocessing only */ struct s_macro_fast { char *mnemo; int crc; }; struct s_math_keyword { char *mnemo; int crc; enum e_compute_operation_type operation; }; struct s_expr_word { char *w; int aw; int op; int comma; int fct; double v; }; struct s_listing { char *listing; int ifile; int iline; }; enum e_tagtranslateoption { E_TAGOPTION_NONE=0, E_TAGOPTION_REMOVESPACE=1, E_TAGOPTION_PRESERVE=2 }; #ifdef RASM_THREAD struct s_rasm_thread { pthread_t thread; int lz; unsigned char *datain; int datalen; unsigned char *dataout; int lenout; int status; }; #endif /********************************************************* S N A P S H O T E X P O R T *********************************************************/ /* extension 4Mo = 256 slots + 4 slots 64K de RAM par défaut => 260 */ #define BANK_MAX_NUMBER 260 struct s_snapshot_symbol { unsigned char size; unsigned char name[256]; unsigned char reserved[6]; unsigned char bigendian_adress[2]; }; struct s_zxsnapshot { unsigned int run; unsigned int stack; }; struct s_snapshot { char idmark[8]; char unused1[8]; unsigned char version; /* 3 */ struct { struct { unsigned char F; unsigned char A; unsigned char C; unsigned char B; unsigned char E; unsigned char D; unsigned char L; unsigned char H; }general; unsigned char R; unsigned char regI; /* I incompatible with tgmath.h */ unsigned char IFF0; unsigned char IFF1; unsigned char LX; unsigned char HX; unsigned char LY; unsigned char HY; unsigned char LSP; unsigned char HSP; unsigned char LPC; unsigned char HPC; unsigned char IM; /* 0,1,2 */ struct { unsigned char F; unsigned char A; unsigned char C; unsigned char B; unsigned char E; unsigned char D; unsigned char L; unsigned char H; }alternate; }registers; struct { unsigned char selectedpen; unsigned char palette[17]; unsigned char multiconfiguration; }gatearray; unsigned char ramconfiguration; struct { unsigned char selectedregister; unsigned char registervalue[18]; }crtc; unsigned char romselect; struct { unsigned char portA; unsigned char portB; unsigned char portC; unsigned char control; }ppi; struct { unsigned char selectedregister; unsigned char registervalue[16]; }psg; unsigned char dumpsize[2]; /* 64 then use extended memory chunks */ unsigned char CPCType; /* 0=464 / 1=664 / 2=6128 / 4=6128+ / 5=464+ / 6=GX4000 */ unsigned char interruptnumber; unsigned char multimodebytes[6]; unsigned char unused2[0x9C-0x75]; /* offset #9C */ struct { unsigned char motorstate; unsigned char physicaltrack; }fdd; unsigned char unused3[3]; unsigned char printerstrobe; unsigned char unused4[2]; struct { unsigned char model; /* 0->4 */ unsigned char unused5[4]; unsigned char HCC; unsigned char unused; unsigned char CLC; unsigned char RLC; unsigned char VTC; unsigned char HSC; unsigned char VSC; unsigned short int flags; }crtcstate; unsigned char vsyncdelay; unsigned char interruptscanlinecounter; unsigned char interruptrequestflag; unsigned char unused6[0xFF-0xB5+1]; }; struct s_snapshot_chunks { unsigned char chunkname[4]; /* MEM1 -> MEM8 */ unsigned int chunksize; }; struct s_breakpoint { int address; int bank; }; /********************************* S T R U C T U R E S *********************************/ enum e_rasmstructfieldtype { E_RASMSTRUCTFIELD_BYTE, E_RASMSTRUCTFIELD_WORD, E_RASMSTRUCTFIELD_LONG, E_RASMSTRUCTFIELD_REAL, E_RASMSTRUCTFIELD_END }; struct s_rasmstructfield { char *fullname; char *name; int offset; int size; int crc; /* filler */ unsigned char *data; int idata,mdata; enum e_rasmstructfieldtype zetype; }; struct s_rasmstruct { char *name; int crc; int size; int ptr; int nbelem; /* fields */ struct s_rasmstructfield *rasmstructfield; int irasmstructfield,mrasmstructfield; }; /********************************* D E B U G *********************************/ struct s_debug_error { char *filename; int line; char *msg; int lenmsg,lenfilename; }; struct s_debug_symbol { char *name; int v; }; struct s_rasm_info { struct s_debug_error *error; int nberror,maxerror; struct s_debug_symbol *symbol; int nbsymbol,maxsymbol; }; /******************************************* G L O B A L S T R U C T *******************************************/ struct s_assenv { /* current memory */ int maxptr; /* CPR memory */ unsigned char **mem; int iwnamebank[BANK_MAX_NUMBER]; int nbbank,maxbank; int forcetape,forcezx,forcecpr,forceROM,bankmode,activebank,amsdos,forcesnapshot,packedbank; struct s_snapshot snapshot; struct s_zxsnapshot zxsnapshot; int bankset[BANK_MAX_NUMBER>>2]; /* 64K selected flag */ int bankused[BANK_MAX_NUMBER]; /* 16K selected flag */ int bankgate[BANK_MAX_NUMBER+1]; int setgate[BANK_MAX_NUMBER+1]; int rundefined; /* parsing */ struct s_wordlist *wl; int nbword; int idx,stage; char *label_filename; int label_line; char **filename; int ifile,maxfile; int nberr,flux; int fastmatch[256]; unsigned char charset[256]; int maxerr,extended_error,nowarning; /* ORG tracking */ int codeadr,outputadr,nocode; int codeadrbackup,outputadrbackup; int minadr,maxadr; struct s_orgzone *orgzone; int io,mo; /* Struct */ struct s_rasmstruct *rasmstruct; int irasmstruct,mrasmstruct; int getstruct; int backup_outputadr,backup_codeadr; char *backup_filename; int backup_line; struct s_rasmstruct *rasmstructalias; int irasmstructalias,mrasmstructalias; /* expressions */ struct s_expression *expression; int ie,me; int maxam,as80,dams; float rough; struct s_compute_core_data *computectx,ctx1,ctx2; struct s_crcstring_tree stringtree; /* label */ struct s_label *label; int il,ml; struct s_crclabel_tree labeltree; /* fast label access */ char *module; int modulen; struct s_breakpoint *breakpoint; int ibreakpoint,maxbreakpoint; char *lastgloballabel; char *lastsuperglobal; int lastgloballabellen, lastglobalalloc; /* repeat */ struct s_repeat *repeat; int ir,mr; /* while/wend */ struct s_whilewend *whilewend; int iw,mw; /* if/then/else */ //int *ifthen; struct s_ifthen *ifthen; int ii,mi; /* switch/case */ struct s_switchcase *switchcase; int isw,msw; /* expression dictionnary */ struct s_expr_dico *dico; int idic,mdic; struct s_crcdico_tree dicotree; /* fast dico access */ struct s_crcused_tree usedtree; /* fast used access */ /* ticker */ struct s_ticker *ticker; int iticker,mticker; long tick,nop; /* crunch section flag */ struct s_lz_section *lzsection; int ilz,mlz; int lz,curlz; /* macro */ struct s_macro *macro; int imacro,mmacro; int macrovoid; /* labels locaux */ int repeatcounter,whilecounter,macrocounter; struct s_macro_position *macropos; int imacropos,mmacropos; /* alias */ struct s_alias *alias; int ialias,malias; /* hexbin */ struct s_rasm_thread **rasm_thread; int irt,mrt; struct s_hexbin *hexbin; int ih,mh; char **includepath; int ipath,mpath; /* automates */ char AutomateExpressionValidCharExtended[256]; char AutomateExpressionValidCharFirst[256]; char AutomateExpressionValidChar[256]; char AutomateExpressionDecision[256]; char AutomateValidLabelFirst[256]; char AutomateValidLabel[256]; char AutomateDigit[256]; char AutomateHexa[256]; struct s_compute_element AutomateElement[256]; unsigned char psgtab[256]; unsigned char psgfine[256]; /* output */ char *outputfilename; int export_sym,export_local,export_multisym; int export_var,export_equ; int export_sna,export_snabrk; int export_brk,export_tape; int autorise_export; char *flexible_export; char *breakpoint_name; char *symbol_name; char *binary_name; char *cartridge_name; char *snapshot_name; struct s_save *save; int nbsave,maxsave; int current_run_idx; struct s_edsk_wrapper *edsk_wrapper; int nbedskwrapper,maxedskwrapper; int edskoverwrite; int checkmode,dependencies; int stop; int warn_unused; /* debug */ struct s_rasm_info debug; struct s_rasm_info **retdebug; int debug_total_len; }; /************************************* D I R E C T I V E S *************************************/ struct s_asm_keyword { char *mnemo; int crc; void (*makemnemo)(struct s_assenv *ae); }; struct s_math_keyword math_keyword[]={ {"SIN",0,E_COMPUTE_OPERATION_SIN}, {"COS",0,E_COMPUTE_OPERATION_COS}, {"INT",0,E_COMPUTE_OPERATION_INT}, {"ABS",0,E_COMPUTE_OPERATION_ABS}, {"LN",0,E_COMPUTE_OPERATION_LN}, {"LOG10",0,E_COMPUTE_OPERATION_LOG10}, {"SQRT",0,E_COMPUTE_OPERATION_SQRT}, {"FLOOR",0,E_COMPUTE_OPERATION_FLOOR}, {"ASIN",0,E_COMPUTE_OPERATION_ASIN}, {"ACOS",0,E_COMPUTE_OPERATION_ACOS}, {"ATAN",0,E_COMPUTE_OPERATION_ATAN}, {"EXP",0,E_COMPUTE_OPERATION_EXP}, {"LO",0,E_COMPUTE_OPERATION_LOW}, {"HI",0,E_COMPUTE_OPERATION_HIGH}, {"PSGVALUE",0,E_COMPUTE_OPERATION_PSG}, {"RND",0,E_COMPUTE_OPERATION_RND}, {"FRAC",0,E_COMPUTE_OPERATION_FRAC}, {"CEIL",0,E_COMPUTE_OPERATION_CEIL}, {"GETR",0,E_COMPUTE_OPERATION_GET_R}, {"GETV",0,E_COMPUTE_OPERATION_GET_V}, {"GETG",0,E_COMPUTE_OPERATION_GET_V}, {"GETB",0,E_COMPUTE_OPERATION_GET_B}, {"SETR",0,E_COMPUTE_OPERATION_SET_R}, {"SETV",0,E_COMPUTE_OPERATION_SET_V}, {"SETG",0,E_COMPUTE_OPERATION_SET_V}, {"SETB",0,E_COMPUTE_OPERATION_SET_B}, {"",0,-1} }; #define CRC_SWITCH 0x01AEDE4A #define CRC_CASE 0x0826B794 #define CRC_DEFAULT 0x9A0DAC7D #define CRC_BREAK 0xCD364DDD #define CRC_ENDSWITCH 0x18E9FB21 #define CRC_ELSEIF 0xE175E230 #define CRC_ELSE 0x3FF177A1 #define CRC_ENDIF 0xCD5265DE #define CRC_IF 0x4BD52507 #define CRC_IFDEF 0x4CB29DD6 #define CRC_UNDEF 0xCCD2FDEA #define CRC_IFNDEF 0xD9AD0824 #define CRC_IFNOT 0x4CCAC9F8 #define CRC_WHILE 0xBC268FF1 #define CRC_UNTIL 0xCC12A604 #define CRC_MEND 0xFFFD899C #define CRC_ENDM 0x3FF9559C #define CRC_MACRO 0x64AA85EA #define CRC_IFUSED 0x91752638 #define CRC_IFNUSED 0x1B39A886 #define CRC_SIN 0xE1B71962 #define CRC_COS 0xE077C55D #define CRC_0 0x7A98A6A8 #define CRC_1 0x7A98A6A9 #define CRC_2 0x7A98A6AA #define CRC_NC 0x4BD52B09 #define CRC_Z 0x7A98A6D2 #define CRC_NZ 0x4BD52B20 #define CRC_P 0x7A98A6C8 #define CRC_PO 0x4BD53717 #define CRC_PE 0x4BD5370D #define CRC_M 0x7A98A6C5 /* 8 bits registers */ #define CRC_F 0x7A98A6BE #define CRC_I 0x7A98A6C1 #define CRC_R 0x7A98A6CA #define CRC_A 0x7A98A6B9 #define CRC_B 0x7A98A6BA #define CRC_C 0x7A98A6BB #define CRC_D 0x7A98A6BC #define CRC_E 0x7A98A6BD #define CRC_H 0x7A98A6C0 #define CRC_L 0x7A98A6C4 /* dual naming */ #define CRC_XH 0x4BD50718 #define CRC_XL 0x4BD5071C #define CRC_YH 0x4BD50519 #define CRC_YL 0x4BD5051D #define CRC_HX 0x4BD52718 #define CRC_LX 0x4BD52F1C #define CRC_HY 0x4BD52719 #define CRC_LY 0x4BD52F1D #define CRC_IXL 0xE19F1765 #define CRC_IXH 0xE19F1761 #define CRC_IYL 0xE19F1166 #define CRC_IYH 0xE19F1162 /* 16 bits registers */ #define CRC_BC 0x4BD5D2FD #define CRC_DE 0x4BD5DF01 #define CRC_HL 0x4BD5270C #define CRC_IX 0x4BD52519 #define CRC_IY 0x4BD5251A #define CRC_SP 0x4BD5311B #define CRC_AF 0x4BD5D4FF /* memory convention */ #define CRC_MHL 0xD0765F5D #define CRC_MDE 0xD0467D52 #define CRC_MBC 0xD05E694E #define CRC_MIX 0xD072B76A #define CRC_MIY 0xD072B16B #define CRC_MSP 0xD01A876C #define CRC_MC 0xE018210C /* struct parsing */ #define CRC_DEFB 0x37D15389 #define CRC_DB 0x4BD5DEFE #define CRC_DEFW 0x37D1539E #define CRC_DW 0x4BD5DF13 #define CRC_DEFI 0x37D15390 #define CRC_DEFS 0x37D1539A #define CRC_DS 0x4BD5DF0F #define CRC_DEFR 0x37D15399 #define CRC_DR 0x4BD5DF0E /* struct declaration use special instructions for defines */ int ICRC_DEFB,ICRC_DEFW,ICRC_DEFI,ICRC_DEFR,ICRC_DEFS,ICRC_DB,ICRC_DW,ICRC_DR,ICRC_DS; /* need to pre-declare var */ extern struct s_asm_keyword instruction[]; /* # base=16 % base=2 0-9 base=10 A-Z variable ou fonction (cos, sin, tan, sqr, pow, mod, and, xor, mod, ...) +*-/&^m| operateur */ #define AutomateExpressionValidCharExtendedDefinition "0123456789.ABCDEFGHIJKLMNOPQRSTUVWXYZ_{}@+-*/~^$#%§<=>|&" #define AutomateExpressionValidCharFirstDefinition "#%0123456789.ABCDEFGHIJKLMNOPQRSTUVWXYZ_@${" #define AutomateExpressionValidCharDefinition "0123456789.ABCDEFGHIJKLMNOPQRSTUVWXYZ_{}@$" #define AutomateValidLabelFirstDefinition ".ABCDEFGHIJKLMNOPQRSTUVWXYZ_@" #define AutomateValidLabelDefinition "0123456789.ABCDEFGHIJKLMNOPQRSTUVWXYZ_@{}" #define AutomateDigitDefinition ".0123456789" #define AutomateHexaDefinition "0123456789ABCDEF" #ifndef NO_3RD_PARTIES unsigned char *LZ4_crunch(unsigned char *data, int zelen, int *retlen){ unsigned char *lzdest=NULL; lzdest=MemMalloc(65536); *retlen=LZ4_compress_HC((char*)data,(char*)lzdest,zelen,65536,9); return lzdest; } #endif unsigned char *LZ48_encode_legacy(unsigned char *data, int length, int *retlength); #define LZ48_crunch LZ48_encode_legacy unsigned char *LZ49_encode_legacy(unsigned char *data, int length, int *retlength); #define LZ49_crunch LZ49_encode_legacy /* * optimised reading of text file in one shot */ unsigned char *_internal_readbinaryfile(char *filename, int *filelength) { #undef FUNC #define FUNC "_internal_readbinaryfile" unsigned char *binary_data=NULL; *filelength=FileGetSize(filename); binary_data=MemMalloc((*filelength)+1); /* we try to read one byte more to close the file just after the read func */ if (FileReadBinary(filename,(char*)binary_data,(*filelength)+1)!=*filelength) { logerr("Cannot fully read %s",filename); exit(INTERNAL_ERROR); } return binary_data; } char **_internal_readtextfile(char *filename, char replacechar) { #undef FUNC #define FUNC "_internal_readtextfile" char **lines_buffer=NULL; unsigned char *bigbuffer; int nb_lines=0,max_lines=0,i=0,e=0; int file_size; bigbuffer=_internal_readbinaryfile(filename,&file_size); while (i=max_lines) { max_lines=max_lines*2+10; lines_buffer=MemRealloc(lines_buffer,(max_lines+1)*sizeof(char **)); } lines_buffer[nb_lines]=MemMalloc(e-i+1); memcpy(lines_buffer[nb_lines],bigbuffer+i,e-i); lines_buffer[nb_lines][e-i]=0; if (0) { int yy; for (yy=0;lines_buffer[nb_lines][yy];yy++) { if (lines_buffer[nb_lines][yy]>31) printf("%c",lines_buffer[nb_lines][yy]); else printf("(0x%X)",lines_buffer[nb_lines][yy]); } printf("\n"); } nb_lines++; i=e; } if (!max_lines) { lines_buffer=MemMalloc(sizeof(char**)); lines_buffer[0]=NULL; } else { lines_buffer[nb_lines]=NULL; } MemFree(bigbuffer); return lines_buffer; } #define FileReadLines(filename) _internal_readtextfile(filename,':') #define FileReadLinesRAW(filename) _internal_readtextfile(filename,0x0D) #define FileReadContent(filename,filesize) _internal_readbinaryfile(filename,filesize) /*** TxtReplace input: in_str: string where replace will occur in_substr: substring to look for out_substr: replace substring recurse: loop until no in_substr is found note: in_str MUST BE previously mallocated if out_substr is bigger than in_substr */ #ifndef RDD char *TxtReplace(char *in_str, char *in_substr, char *out_substr, int recurse) { #undef FUNC #define FUNC "TxtReplace" char *str_look,*m1,*m2; char *out_str; int sl,l1,l2,dif,cpt; if (in_str==NULL) return NULL; sl=strlen(in_str); l1=strlen(in_substr); /* empty string, nothing to do except return empty string */ if (!sl || !l1) return in_str; l2=strlen(out_substr); dif=l2-l1; /* replace string is small or equal in size, we dont realloc */ if (dif<=0) { /* we loop while there is a replace to do */ str_look=strstr(in_str,in_substr); while (str_look!=NULL) { /* we copy the new string if his len is not null */ if (l2) memcpy(str_look,out_substr,l2); /* only if len are different */ if (l1!=l2) { /* we move the end of the string byte per byte because memory locations overlap. This is faster than memmove */ m1=str_look+l1; m2=str_look+l2; while (*m1!=0) { *m2=*m1; m1++;m2++; } /* we must copy the EOL */ *m2=*m1; } /* look for next replace */ if (!recurse) str_look=strstr(str_look+l2,in_substr); else str_look=strstr(in_str,in_substr); } out_str=in_str; } else { /* we need to count each replace */ cpt=0; str_look=strstr(in_str,in_substr); while (str_look!=NULL) { cpt++; str_look=strstr(str_look+l1,in_substr); } /* is there anything to do? */ if (cpt) { /* we realloc to a size that will fit all replaces */ out_str=MemRealloc(in_str,sl+1+dif*cpt); str_look=strstr(out_str,in_substr); while (str_look!=NULL && cpt) { /* as the replace string is bigger we have to move memory first from the end */ m1=out_str+sl; m2=m1+dif; sl+=dif; while (m1!=str_look+l1-dif) { *m2=*m1; m1--;m2--; } /* then we copy the replace string (can't be NULL in this case) */ memcpy(str_look,out_substr,l2); /* look for next replace */ if (!recurse) str_look=strstr(str_look+l2,in_substr); else str_look=strstr(in_str,in_substr); /* to prevent from naughty overlap */ cpt--; } if (str_look!=NULL) { printf("INTERNAL ERROR - overlapping replace string (%s/%s), you can't use this one!\n",in_substr,out_substr); exit(ABORT_ERROR); } } else out_str=in_str; } return out_str; } #endif #ifndef min #define min(a,b) \ ({ __typeof__ (a) _a = (a); \ __typeof__ (b) _b = (b); \ _a < _b ? _a : _b; }) #endif /* Levenshtein implementation by TheRayTracer https://gist.github.com/TheRayTracer/2644387 */ int _internal_LevenshteinDistance(char *s, char *t) { int i,j,n,m,*d; int im,jn; int r; n=strlen(s)+1; m=strlen(t)+1; d=malloc(n*m*sizeof(int)); memset(d, 0, sizeof(int) * n * m); for (i = 1, im = 0; i < m; i++, im++) { for (j = 1, jn = 0; j < n; j++, jn++) { if (s[jn] == t[im]) { d[(i * n) + j] = d[((i - 1) * n) + (j - 1)]; } else { d[(i * n) + j] = min(d[(i - 1) * n + j] + 1, /* A deletion. */ min(d[i * n + (j - 1)] + 1, /* An insertion. */ d[(i - 1) * n + (j - 1)] + 1)); /* A substitution. */ } } } r = d[n * m - 1]; free(d); return r; } #ifdef RASM_THREAD /* threads used for crunching */ void _internal_ExecuteThreads(struct s_assenv *ae,struct s_rasm_thread *rasm_thread, void *(*fct)(void *)) { #undef FUNC #define FUNC "_internal_ExecuteThreads" pthread_attr_t attr; void *status; int rc; /* launch threads */ pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE); pthread_attr_setstacksize(&attr,65536); if ((rc=pthread_create(&image_threads[i].thread,&attr,fct,(void *)rasm_thread))) { rasm_printf(ae,"FATAL ERROR - Cannot create thread!\n"); exit(INTERNAL_ERROR); } } void _internal_WaitForThreads(struct s_assenv *ae,struct s_rasm_thread *rasm_thread) { #undef FUNC #define FUNC "_internal_WaitForThreads" int rc; if ((rc=pthread_join(rasm_thread->thread,&status))) { rasm_printf(ae,"FATAL ERROR - Cannot wait for thread\n"); exit(INTERNAL_ERROR); } } void PushCrunchedFile(struct s_assenv *ae, unsigned char *datain, int datalen, int lz) { #undef FUNC #define FUNC "PushCrunchedFile" struct s_rasm_thread *rasm_thread; rasm_thread=MemMalloc(sizeof(struct s_rasm_thread)); memset(rasm_thread,0,sizeof(struct s_rasm_thread)); rasm_thread->datain=datain; rasm_thread->datalen=datalen; rasm_thread->lz=lz; _internal_ExecuteThreads(ae,rasm_thread, void *(*fct)(void *)); ObjectArrayAddDynamicValueConcat((void**)&ae->rasm_thread,&ae->irt,&ae->mrt,&rasm_thread,sizeof(struct s_rasm_thread *)); } void PopAllCrunchedFiles(struct s_assenv *ae) { #undef FUNC #define FUNC "PopAllCrunchedFiles" int i; for (i=0;iirt;i++) { _internal_WaitForThreads(ae,ae->rasm_thread[i]); } } #endif void MaxError(struct s_assenv *ae); void rasm_printf(struct s_assenv *ae, ...) { #undef FUNC #define FUNC "(internal) rasm_printf" char *format; va_list argptr; if (!ae->flux && !ae->dependencies) { va_start(argptr,ae); format=va_arg(argptr,char *); vfprintf(stdout,format,argptr); va_end(argptr); fprintf(stdout,KNORMAL); } } /*** build the string of current line for error messages */ char *rasm_getline(struct s_assenv *ae, int offset) { #undef FUNC #define FUNC "rasm_getline" static char myline[40]={0}; int idx=0,icopy,first=1; while (!ae->wl[ae->idx+offset].t && idx<32) { for (icopy=0;idx<32 && ae->wl[ae->idx+offset].w[icopy];icopy++) { myline[idx++]=ae->wl[ae->idx+offset].w[icopy]; } if (!first) myline[idx++]=','; else first=0; offset++; } if (idx>=32) { strcpy(myline+29,"..."); } else { myline[idx++]=0; } return myline; } char *SimplifyPath(char *filename) { #undef FUNC #define FUNC "SimplifyPath" return filename; #if 0 char *pos,*repos; int i,len; char *rpath; rpath=realpath(filename,NULL); if (!rpath) { printf("rpath error!\n"); switch (errno) { case EACCES:printf("read permission failure\n");break; case EINVAL:printf("wrong argument\n");break; case EIO:printf("I/O error\n");break; case ELOOP:printf("too many symbolic links\n");break; case ENAMETOOLONG:printf("names too long\n");break; case ENOENT:printf("names does not exists\n");break; case ENOMEM:printf("out of memory\n");break; case ENOTDIR:printf("a component of the path is not a directory\n");break; default:printf("unknown error\n");break; } exit(1); } if (strlen(rpath)=filename) { if (*repos=='\\') { break; } repos--; } repos++; if (repos>=filename && repos!=pos) { len=strlen(pos)-4+1; pos+=4; for (i=0;i=filename) { if (*repos=='/') { break; } repos--; } repos++; if (repos>=filename && repos!=pos) { len=strlen(pos)-4+1; pos+=4; for (i=0;i=0 && filename[idx]!='\\') idx--; if (idx<0) { /* pas de chemin */ strcpy(curpath,".\\"); } else { /* chemin trouve */ strcpy(curpath,filename); curpath[idx+1]=0; } #else #ifdef __MORPHOS__ #define CURRENT_DIR "" #else #define CURRENT_DIR "./" #endif idx=zelen-1; while (idx>=0 && filename[idx]!='/') idx--; if (idx<0) { /* pas de chemin */ strcpy(curpath,CURRENT_DIR); } else { /* chemin trouve */ strcpy(curpath,filename); curpath[idx+1]=0; } #endif return curpath; } char *MergePath(struct s_assenv *ae,char *dadfilename, char *filename) { #undef FUNC #define FUNC "MergePath" static char curpath[PATH_MAX]; int zelen; #ifdef OS_WIN TxtReplace(filename,"/","\\",1); if (filename[0] && filename[1]==':' && filename[2]=='\\') { /* chemin absolu */ strcpy(curpath,filename); } else if (filename[0] && filename[1]==':') { rasm_printf(ae,KERROR"unsupported path style [%s]\n",filename); exit(-111); } else { if (filename[0]=='.' && filename[1]=='\\') { strcpy(curpath,GetPath(dadfilename)); strcat(curpath,filename+2); } else { strcpy(curpath,GetPath(dadfilename)); strcat(curpath,filename); } } #else if (filename[0]=='/') { /* chemin absolu */ strcpy(curpath,filename); } else if (filename[0]=='.' && filename[1]=='/') { strcpy(curpath,GetPath(dadfilename)); strcat(curpath,filename+2); } else { strcpy(curpath,GetPath(dadfilename)); strcat(curpath,filename); } #endif return curpath; } void InitAutomate(char *autotab, const unsigned char *def) { #undef FUNC #define FUNC "InitAutomate" int i; memset(autotab,0,256); for (i=0;def[i];i++) { autotab[(int)def[i]]=1; } } void StateMachineResizeBuffer(char **ABuf, int idx, int *ASize) { #undef FUNC #define FUNC "StateMachineResizeBuffer" if (idx>=*ASize) { if (*ASize<16384) { *ASize=(*ASize)*2; } else { *ASize=(*ASize)+16384; } *ABuf=MemRealloc(*ABuf,(*ASize)+2); } } int GetCRC(char *label) { #undef FUNC #define FUNC "GetCRC" int crc=0x12345678; int i=0; while (label[i]!=0) { crc=(crc<<9)^(crc+label[i++]); } return crc; } int IsRegister(char *zeexpression) { #undef FUNC #define FUNC "IsRegister" switch (GetCRC(zeexpression)) { case CRC_F:if (strcmp(zeexpression,"F")==0) return 1; else return 0; case CRC_I:if (strcmp(zeexpression,"I")==0) return 1; else return 0; case CRC_R:if (strcmp(zeexpression,"R")==0) return 1; else return 0; case CRC_A:if (strcmp(zeexpression,"A")==0) return 1; else return 0; case CRC_B:if (strcmp(zeexpression,"B")==0) return 1; else return 0; case CRC_C:if (strcmp(zeexpression,"C")==0) return 1; else return 0; case CRC_D:if (strcmp(zeexpression,"D")==0) return 1; else return 0; case CRC_E:if (strcmp(zeexpression,"E")==0) return 1; else return 0; case CRC_H:if (strcmp(zeexpression,"H")==0) return 1; else return 0; case CRC_L:if (strcmp(zeexpression,"L")==0) return 1; else return 0; case CRC_BC:if (strcmp(zeexpression,"BC")==0) return 1; else return 0; case CRC_DE:if (strcmp(zeexpression,"DE")==0) return 1; else return 0; case CRC_HL:if (strcmp(zeexpression,"HL")==0) return 1; else return 0; case CRC_IX:if (strcmp(zeexpression,"IX")==0) return 1; else return 0; case CRC_IY:if (strcmp(zeexpression,"IY")==0) return 1; else return 0; case CRC_SP:if (strcmp(zeexpression,"SP")==0) return 1; else return 0; case CRC_AF:if (strcmp(zeexpression,"AF")==0) return 1; else return 0; case CRC_XH:if (strcmp(zeexpression,"XH")==0) return 1; else return 0; case CRC_XL:if (strcmp(zeexpression,"XL")==0) return 1; else return 0; case CRC_YH:if (strcmp(zeexpression,"YH")==0) return 1; else return 0; case CRC_YL:if (strcmp(zeexpression,"YL")==0) return 1; else return 0; case CRC_HX:if (strcmp(zeexpression,"HX")==0) return 1; else return 0; case CRC_LX:if (strcmp(zeexpression,"LX")==0) return 1; else return 0; case CRC_HY:if (strcmp(zeexpression,"HY")==0) return 1; else return 0; case CRC_LY:if (strcmp(zeexpression,"LY")==0) return 1; else return 0; case CRC_IXL:if (strcmp(zeexpression,"IXL")==0) return 1; else return 0; case CRC_IXH:if (strcmp(zeexpression,"IXH")==0) return 1; else return 0; case CRC_IYL:if (strcmp(zeexpression,"IYL")==0) return 1; else return 0; case CRC_IYH:if (strcmp(zeexpression,"IYH")==0) return 1; else return 0; default:break; } return 0; } int StringIsMem(char *w) { #undef FUNC #define FUNC "StringIsMem" int p=1,idx=1; if (w[0]=='(') { while (w[idx]) { switch (w[idx]) { case '\\':if (w[idx+1]) idx++; break; case '\'':if (w[idx+1] && w[idx+1]!='\\') idx++; break; case '(':p++;break; case ')':p--; if (!p && w[idx+1]) return 0; break; default:break; } idx++; } if (w[idx-1]!=')') return 0; } else { return 0; } return 1; } int StringIsQuote(char *w) { #undef FUNC #define FUNC "StringIsQuote" int i,tquote,lens; if (w[0]=='\'' || w[0]=='"') { tquote=w[0]; lens=strlen(w); /* est-ce bien une chaine et uniquement une chaine? */ i=1; while (w[i] && w[i]!=tquote) { if (w[i]=='\\') i++; i++; } if (i==lens-1) { return tquote; } } return 0; } char *StringLooksLikeDicoRecurse(struct s_crcdico_tree *lt, int *score, char *str) { #undef FUNC #define FUNC "StringLooksLikeDicoRecurse" char *retstr=NULL,*tmpstr; int i,curs; for (i=0;i<256;i++) { if (lt->radix[i]) { tmpstr=StringLooksLikeDicoRecurse(lt->radix[i],score,str); if (tmpstr!=NULL) retstr=tmpstr; } } if (lt->mdico) { for (i=0;indico;i++) { if (strlen(lt->dico[i].name)>4) { curs=_internal_LevenshteinDistance(str,lt->dico[i].name); if (curs<*score) { *score=curs; retstr=lt->dico[i].name; } } } } return retstr; } char *StringLooksLikeDico(struct s_assenv *ae, int *score, char *str) { #undef FUNC #define FUNC "StringLooksLikeDico" char *retstr=NULL,*tmpstr; int i; for (i=0;i<256;i++) { if (ae->dicotree.radix[i]) { tmpstr=StringLooksLikeDicoRecurse(ae->dicotree.radix[i],score,str); if (tmpstr!=NULL) retstr=tmpstr; } } return retstr; } char *StringLooksLikeMacro(struct s_assenv *ae, char *str, int *retscore) { #undef FUNC #define FUNC "StringLooksLikeMacro" char *ret=NULL; int i,curs,score=3; /* search in macros */ for (i=0;iimacro;i++) { curs=_internal_LevenshteinDistance(ae->macro[i].mnemo,str); if (cursmacro[i].mnemo; } } if (retscore) *retscore=score; return ret; } char *StringLooksLike(struct s_assenv *ae, char *str) { #undef FUNC #define FUNC "StringLooksLike" char *ret=NULL,*tmpret; int i,curs,score=4; /* search in variables */ ret=StringLooksLikeDico(ae,&score,str); /* search in labels */ for (i=0;iil;i++) { if (!ae->label[i].name && strlen(ae->wl[ae->label[i].iw].w)>4) { curs=_internal_LevenshteinDistance(ae->wl[ae->label[i].iw].w,str); if (curswl[ae->label[i].iw].w; } } } /* search in alias */ for (i=0;iialias;i++) { if (strlen(ae->alias[i].alias)>4) { curs=_internal_LevenshteinDistance(ae->alias[i].alias,str); if (cursalias[i].alias; } } } tmpret=StringLooksLikeMacro(ae,str,&curs); if (cursflux) { /* in embedded Rasm all errors are stored in a debug struct */ struct s_debug_error curerror; char toosmalltotakeitall[2]={0}; int myalloc; char *errstr; va_start(argptr,format); myalloc=vsnprintf(toosmalltotakeitall,1,format,argptr); va_end(argptr); #if defined(_MSC_VER) && _MSC_VER < 1900 /* visual studio before 2015 does not fully support C99 */ if (myalloc<1 && strlen(format)) { va_start(argptr,format); myalloc=_vscprintf(format,argptr); va_end(argptr); } #endif if (myalloc<1) { /* do not crash */ return; } va_start(argptr,format); errstr=MemMalloc(myalloc+1); vsnprintf(errstr,myalloc,format,argptr); curerror.msg=errstr; curerror.lenmsg=myalloc; curerror.line=line; if (filename) curerror.filename=TxtStrDupLen(filename,&curerror.lenfilename); else curerror.filename=TxtStrDupLen("",&curerror.lenfilename); ObjectArrayAddDynamicValueConcat((void **)&ae->debug.error,&ae->debug.nberror,&ae->debug.maxerror,&curerror,sizeof(struct s_debug_error)); va_end(argptr); } else { fprintf(stdout,KERROR); va_start(argptr,format); if (filename && line) { printf("[%s:%d] ",filename,line); } else if (filename) { printf("[%s] ",filename); } vfprintf(stdout,format,argptr); va_end(argptr); fprintf(stdout,KNORMAL); } } /* convert v double value to Amstrad REAL */ unsigned char *__internal_MakeAmsdosREAL(struct s_assenv *ae, double v, int iexpression) { #undef FUNC #define FUNC "__internal_MakeAmsdosREAL" static unsigned char rc[5]; double tmpval; int j,ib,ibb,exp=0; unsigned int deci; int fracmax=0; double frac; int mesbits[32]; int ibit=0; unsigned int mask; memset(rc,0,sizeof(rc)); deci=fabs(floor(v)); frac=fabs(v)-deci; if (deci) { mask=0x80000000; while (!(deci & mask)) mask=mask/2; while (mask) { mesbits[ibit]=!!(deci & mask); #if TRACE_MAKEAMSDOSREAL printf("%d",mesbits[ibit]); #endif ibit++; mask=mask/2; } #if TRACE_MAKEAMSDOSREAL printf("\nexposant positif: %d\n",ibit); #endif exp=ibit; #if TRACE_MAKEAMSDOSREAL printf("."); #endif while (ibit<32 && frac!=0) { frac=frac*2; if (frac>=1.0) { mesbits[ibit++]=1; #if TRACE_MAKEAMSDOSREAL printf("1"); #endif frac-=1.0; } else { mesbits[ibit++]=0; #if TRACE_MAKEAMSDOSREAL printf("0"); #endif } fracmax++; } } else { #if TRACE_MAKEAMSDOSREAL printf("\nexposant negatif a definir:\n"); printf("x."); #endif /* handling zero */ if (frac==0.0) { exp=0; ibit=0; } else { /* looking for first significant bit */ while (1) { frac=frac*2; if (frac>=1.0) { mesbits[ibit++]=1; #if TRACE_MAKEAMSDOSREAL printf("1"); #endif frac-=1.0; break; /* first significant bit found, now looking for limit */ } else { #if TRACE_MAKEAMSDOSREAL printf("o"); #endif } fracmax++; exp--; } while (ibit<32 && frac!=0) { frac=frac*2; if (frac>=1.0) { mesbits[ibit++]=1; #if TRACE_MAKEAMSDOSREAL printf("1"); #endif frac-=1.0; } else { mesbits[ibit++]=0; #if TRACE_MAKEAMSDOSREAL printf("0"); #endif } fracmax++; } } } #if TRACE_MAKEAMSDOSREAL printf("\n%d bits utilises en mantisse\n",ibit); #endif /* pack bits */ ib=3;ibb=0x80; for (j=0;j255) { if (iexpression) MakeError(ae,GetExpFile(ae,iexpression),ae->wl[ae->expression[iexpression].iw].l,"Exponent overflow\n"); else MakeError(ae,GetExpFile(ae,0),ae->wl[ae->idx].l,"Exponent overflow\n"); exp=128; } rc[4]=exp; /* REAL sign */ if (v>=0) { rc[3]&=0x7F; } else { rc[3]|=0x80; } #if TRACE_MAKEAMSDOSREAL for (j=0;j<5;j++) printf("%02X ",rc[j]); printf("\n"); #endif return rc; } struct s_label *SearchLabel(struct s_assenv *ae, char *label, int crc); char *GetExpFile(struct s_assenv *ae,int didx){ #undef FUNC #define FUNC "GetExpFile" if (ae->label_filename) { return ae->label_filename; } if (didx<0) { return ae->filename[ae->wl[-didx].ifile]; } else if (!didx) { return ae->filename[ae->wl[ae->idx].ifile]; } else if (ae->expression && didxie) { return ae->filename[ae->wl[ae->expression[didx].iw].ifile]; } else { //return ae->filename[ae->wl[ae->idx].ifile]; return 0; } } int GetExpLine(struct s_assenv *ae,int didx){ #undef FUNC #define FUNC "GetExpLine" if (ae->label_line) return ae->label_line; if (didx<0) { return ae->wl[-didx].l; } else if (!didx) { return ae->wl[ae->idx].l; } else if (didxie) { return ae->wl[ae->expression[didx].iw].l; } else return 0; } char *GetCurrentFile(struct s_assenv *ae) { return GetExpFile(ae,0); } /******************************************************************************************* M E M O R Y C L E A N U P *******************************************************************************************/ void FreeLabelTree(struct s_assenv *ae); void FreeDicoTree(struct s_assenv *ae); void FreeUsedTree(struct s_assenv *ae); void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullreplace); char *TradExpression(char *zexp); void _internal_RasmFreeInfoStruct(struct s_rasm_info *debug) { #undef FUNC #define FUNC "RasmFreeInfoStruct" int i; if (debug->maxerror) { for (i=0;inberror;i++) { MemFree(debug->error[i].filename); MemFree(debug->error[i].msg); } MemFree(debug->error); } if (debug->maxsymbol) { for (i=0;inbsymbol;i++) { MemFree(debug->symbol[i].name); } MemFree(debug->symbol); } } void RasmFreeInfoStruct(struct s_rasm_info *debug) { _internal_RasmFreeInfoStruct(debug); MemFree(debug); } void FreeAssenv(struct s_assenv *ae) { #undef FUNC #define FUNC "FreeAssenv" int i,j; #ifndef RDD /* let the system free the memory in command line except when debug/dev */ if (!ae->flux) return; #endif /*** debug info ***/ if (!ae->retdebug) { _internal_RasmFreeInfoStruct(&ae->debug); } else { /* symbols */ struct s_debug_symbol debug_symbol={0}; for (i=0;iil;i++) { /* on exporte tout */ if (!ae->label[i].name) { /* les labels entiers */ debug_symbol.name=TxtStrDup(ae->wl[ae->label[i].iw].w); debug_symbol.v=ae->label[i].ptr; ObjectArrayAddDynamicValueConcat((void**)&ae->debug.symbol,&ae->debug.nbsymbol,&ae->debug.maxsymbol,&debug_symbol,sizeof(struct s_debug_symbol)); } else { /* les labels locaux et générés */ debug_symbol.name=TxtStrDup(ae->label[i].name); debug_symbol.v=ae->label[i].ptr; ObjectArrayAddDynamicValueConcat((void**)&ae->debug.symbol,&ae->debug.nbsymbol,&ae->debug.maxsymbol,&debug_symbol,sizeof(struct s_debug_symbol)); } } for (i=0;iialias;i++) { if (strcmp(ae->alias[i].alias,"IX") && strcmp(ae->alias[i].alias,"IY")) { debug_symbol.name=TxtStrDup(ae->alias[i].alias); debug_symbol.v=RoundComputeExpression(ae,ae->alias[i].translation,0,0,0); ObjectArrayAddDynamicValueConcat((void**)&ae->debug.symbol,&ae->debug.nbsymbol,&ae->debug.maxsymbol,&debug_symbol,sizeof(struct s_debug_symbol)); } } /* export struct */ *ae->retdebug=MemMalloc(sizeof(struct s_rasm_info)); memcpy(*ae->retdebug,&ae->debug,sizeof(struct s_rasm_info)); } /*** end debug ***/ for (i=0;inbbank;i++) { MemFree(ae->mem[i]); } MemFree(ae->mem); /* expression core buffer free */ ComputeExpressionCore(NULL,NULL,0,0); ExpressionFastTranslate(NULL,NULL,0); /* free labels, expression, orgzone, repeat, ... */ if (ae->mo) MemFree(ae->orgzone); if (ae->me) { for (i=0;iie;i++) if (ae->expression[i].reference) MemFree(ae->expression[i].reference); MemFree(ae->expression); } if (ae->mh) { for (i=0;iih;i++) { MemFree(ae->hexbin[i].data); MemFree(ae->hexbin[i].filename); } MemFree(ae->hexbin); } for (i=0;iil;i++) { if (ae->label[i].name && ae->label[i].iw==-1) MemFree(ae->label[i].name); } /* structures */ for (i=0;iirasmstructalias;i++) { MemFree(ae->rasmstructalias[i].name); } if (ae->mrasmstructalias) MemFree(ae->rasmstructalias); for (i=0;iirasmstruct;i++) { for (j=0;jrasmstruct[i].irasmstructfield;j++) { MemFree(ae->rasmstruct[i].rasmstructfield[j].fullname); MemFree(ae->rasmstruct[i].rasmstructfield[j].name); } if (ae->rasmstruct[i].mrasmstructfield) MemFree(ae->rasmstruct[i].rasmstructfield); MemFree(ae->rasmstruct[i].name); } if (ae->mrasmstruct) MemFree(ae->rasmstruct); /* other */ if (ae->maxbreakpoint) MemFree(ae->breakpoint); if (ae->ml) MemFree(ae->label); if (ae->mr) MemFree(ae->repeat); if (ae->mi) MemFree(ae->ifthen); if (ae->msw) MemFree(ae->switchcase); if (ae->mw) MemFree(ae->whilewend); if (ae->modulen || ae->module) { MemFree(ae->module); } /* deprecated for (i=0;iidic;i++) { MemFree(ae->dico[i].name); } if (ae->mdic) MemFree(ae->dico); */ if (ae->mlz) MemFree(ae->lzsection); for (i=0;iifile;i++) { MemFree(ae->filename[i]); } MemFree(ae->filename); for (i=0;iimacro;i++) { if (ae->macro[i].maxword) MemFree(ae->macro[i].wc); for (j=0;jmacro[i].nbparam;j++) MemFree(ae->macro[i].param[j]); if (ae->macro[i].nbparam) MemFree(ae->macro[i].param); } if (ae->mmacro) MemFree(ae->macro); for (i=0;iialias;i++) { MemFree(ae->alias[i].alias); MemFree(ae->alias[i].translation); } if (ae->malias) MemFree(ae->alias); for (i=0;ae->wl[i].t!=2;i++) { MemFree(ae->wl[i].w); } MemFree(ae->wl); if (ae->ctx1.varbuffer) { MemFree(ae->ctx1.varbuffer); } if (ae->ctx1.maxtokenstack) { MemFree(ae->ctx1.tokenstack); } if (ae->ctx1.maxoperatorstack) { MemFree(ae->ctx1.operatorstack); } if (ae->ctx2.varbuffer) { MemFree(ae->ctx2.varbuffer); } if (ae->ctx2.maxtokenstack) { MemFree(ae->ctx2.tokenstack); } if (ae->ctx2.maxoperatorstack) { MemFree(ae->ctx2.operatorstack); } for (i=0;iiticker;i++) { MemFree(ae->ticker[i].varname); } if (ae->mticker) MemFree(ae->ticker); MemFree(ae->outputfilename); FreeLabelTree(ae); FreeDicoTree(ae); FreeUsedTree(ae); if (ae->mmacropos) MemFree(ae->macropos); TradExpression(NULL); MemFree(ae); } void MaxError(struct s_assenv *ae) { #undef FUNC #define FUNC "MaxError" char **source_lines=NULL; int idx,crc,zeline; char c; /* extended error is useful with generated code we do not want to edit */ if (ae->extended_error && ae->wl) { /* super dupper slow but anyway, there is an error... */ if (ae->wl[ae->idx].l) { source_lines=FileReadLinesRAW(GetCurrentFile(ae)); zeline=0; while (zelinewl[ae->idx].l-1 && source_lines[zeline]) zeline++; if (zeline==ae->wl[ae->idx].l-1 && source_lines[zeline]) { rasm_printf(ae,KAYGREEN"-> %s",source_lines[zeline]); } else { rasm_printf(ae,KERROR"cannot read line %d of file [%s]\n",ae->wl[ae->idx].l,GetCurrentFile(ae)); } FreeArrayDynamicValue(&source_lines); } } ae->nberr++; if (ae->nberr==ae->maxerr) { rasm_printf(ae,KERROR"Too many errors!\n"); FreeAssenv(ae); exit(ae->nberr); } } void (*___output)(struct s_assenv *ae, unsigned char v); void ___internal_output_disabled(struct s_assenv *ae,unsigned char v) { #undef FUNC #define FUNC "fake ___output" } void ___internal_output(struct s_assenv *ae,unsigned char v) { #undef FUNC #define FUNC "___output" if (ae->outputadrmaxptr) { ae->mem[ae->activebank][ae->outputadr++]=v; ae->codeadr++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"output exceed limit %d\n",ae->maxptr); ae->stop=1; ___output=___internal_output_disabled; } } void ___internal_output_nocode(struct s_assenv *ae,unsigned char v) { #undef FUNC #define FUNC "___output (nocode)" if (ae->outputadrmaxptr) { /* struct definition always in NOCODE */ if (ae->getstruct) { int irs,irsf; irs=ae->irasmstruct-1; irsf=ae->rasmstruct[irs].irasmstructfield-1; /* ajouter les data du flux au champ de la structure */ ObjectArrayAddDynamicValueConcat((void**)&ae->rasmstruct[irs].rasmstructfield[irsf].data, &ae->rasmstruct[irs].rasmstructfield[irsf].idata, &ae->rasmstruct[irs].rasmstructfield[irsf].mdata, &v,sizeof(unsigned char)); } ae->outputadr++; ae->codeadr++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"output exceed limit %d\n",ae->maxptr); ae->stop=1; ___output=___internal_output_disabled; } } void ___output_set_limit(struct s_assenv *ae,int zelimit) { #undef FUNC #define FUNC "___output_set_limit" int limit=65535; if (zelimit<=limit) { /* apply limit */ limit=zelimit; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"limit exceed hardware limitation!"); ae->stop=1; } if (ae->outputadr>=0 && ae->outputadr>limit) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"limit too high for current output!"); ae->stop=1; } ae->maxptr=limit; } unsigned char *MakeAMSDOSHeader(int run, int minmem, int maxmem, char *amsdos_name) { #undef FUNC #define FUNC "MakeAMSDOSHeader" static unsigned char AmsdosHeader[128]; int checksum,i=0; /*** cpcwiki Byte 00: User number Byte 01 to 08: filename Byte 09 bis 11: Extension Byte 18: type-byte Byte 21 and 22: loading address Byte 24 and 25: file length Byte 26 and 27: execution address for machine code programs Byte 64 and 65: (file length) Byte 67 and 68: checksum for byte 00 to byte 66 To calculate the checksum, just add byte 00 to byte 66 to each other. */ memset(AmsdosHeader,0,sizeof(AmsdosHeader)); AmsdosHeader[0]=0; memcpy(AmsdosHeader+1,amsdos_name,11); AmsdosHeader[18]=2; /* 0 basic 1 basic protege 2 binaire */ AmsdosHeader[19]=(maxmem-minmem)&0xFF; AmsdosHeader[20]=(maxmem-minmem)>>8; AmsdosHeader[21]=minmem&0xFF; AmsdosHeader[22]=minmem>>8; AmsdosHeader[24]=AmsdosHeader[19]; AmsdosHeader[25]=AmsdosHeader[20]; AmsdosHeader[26]=run&0xFF; AmsdosHeader[27]=run>>8; AmsdosHeader[64]=AmsdosHeader[19]; AmsdosHeader[65]=AmsdosHeader[20]; AmsdosHeader[66]=0; for (i=checksum=0;i<=66;i++) { checksum+=AmsdosHeader[i]; } AmsdosHeader[67]=checksum&0xFF; AmsdosHeader[68]=checksum>>8; /* garbage / shadow values from sector buffer? */ memcpy(AmsdosHeader+0x47,amsdos_name,8); AmsdosHeader[0x4F]=0x24; AmsdosHeader[0x50]=0x24; AmsdosHeader[0x51]=0x24; AmsdosHeader[0x52]=0xFF; AmsdosHeader[0x54]=0xFF; AmsdosHeader[0x57]=0x02; AmsdosHeader[0x5A]=AmsdosHeader[21]; AmsdosHeader[0x5B]=AmsdosHeader[22]; AmsdosHeader[0x5D]=AmsdosHeader[24]; AmsdosHeader[0x5E]=AmsdosHeader[25]; sprintf((char *)AmsdosHeader+0x47+17," generated by %s ",RASM_SNAP_VERSION); return AmsdosHeader; } unsigned char *MakeHobetaHeader(int minmem, int maxmem, char *trdos_name) { #undef FUNC #define FUNC "MakeHobetaHeader" static unsigned char HobetaHeader[17]; int i,checksum=0; /*** http://rk.nvg.ntnu.no/sinclair/faq/fileform.html#HOBETA 0x00 FileName 0x08 TR-DOS file name 0x08 FileType 0x01 TR-DOS file type 0x09 StartAdr 0x02 start address of file 0x0A FlLength 0x02 length of file (in bytes) -> /!\ wrong offset!!! 0x0C FileSize 0x02 size of file (in sectors) 0x0E HdrCRC16 0x02 Control checksum of the 15 byte header (not sector data!) */ memset(HobetaHeader,0,sizeof(HobetaHeader)); strncpy(HobetaHeader,trdos_name,8); HobetaHeader[8]='C'; HobetaHeader[0x9]=(maxmem-minmem)&0xFF; HobetaHeader[0xA]=(maxmem-minmem)>>8; HobetaHeader[0xB]=(maxmem-minmem)&0xFF; HobetaHeader[0xC]=(maxmem-minmem)>>8; HobetaHeader[0xD]=((maxmem-minmem)+255)>>8; HobetaHeader[0xE]=0; for (i=0;i<0xF;i++) checksum+=HobetaHeader[i]*257+i; HobetaHeader[0xF]=checksum&0xFF; HobetaHeader[0x10]=(checksum>>8)&0xFF; return HobetaHeader; } int cmpAmsdosentry(const void * a, const void * b) { return memcmp(a,b,32); } int cmpmacros(const void * a, const void * b) { struct s_macro *sa,*sb; sa=(struct s_macro *)a; sb=(struct s_macro *)b; if (sa->crccrc) return -1; else return 1; } int SearchAlias(struct s_assenv *ae, int crc, char *zemot) { int dw,dm,du,i; //printf("SearchAlias [%s] ",zemot); /* inutile de tourner autour du pot pour un si petit nombre */ if (ae->ialias<5) { for (i=0;iialias;i++) { if (ae->alias[i].crc==crc && strcmp(ae->alias[i].alias,zemot)==0) { ae->alias[i].used=1; //printf("found\n"); return i; } } //printf("not found\n"); return -1; } dw=0; du=ae->ialias-1; while (dw<=du) { dm=(dw+du)/2; if (ae->alias[dm].crc==crc) { /* chercher le premier de la liste */ while (dm>0 && ae->alias[dm-1].crc==crc) dm--; /* controle sur le texte entier */ while (ae->alias[dm].crc==crc && strcmp(ae->alias[dm].alias,zemot)) dm++; if (ae->alias[dm].crc==crc && strcmp(ae->alias[dm].alias,zemot)==0) { ae->alias[dm].used=1; //printf("found\n"); return dm; } else return -1; } else if (ae->alias[dm].crc>crc) { du=dm-1; } else if (ae->alias[dm].crcimacro<5) { for (i=0;iimacro;i++) { if (ae->macro[i].crc==crc && strcmp(ae->macro[i].mnemo,zemot)==0) { return i; } } return -1; } dw=0; du=ae->imacro-1; while (dw<=du) { dm=(dw+du)/2; if (ae->macro[dm].crc==crc) { /* chercher le premier de la liste */ while (dm>0 && ae->macro[dm-1].crc==crc) dm--; /* controle sur le texte entier */ while (ae->macro[dm].crc==crc && strcmp(ae->macro[dm].mnemo,zemot)) dm++; if (ae->macro[dm].crc==crc && strcmp(ae->macro[dm].mnemo,zemot)==0) return dm; else return -1; } else if (ae->macro[dm].crc>crc) { du=dm-1; } else if (ae->macro[dm].crcialias-1;i++) { /* is there previous aliases in the new alias? */ if (strstr(ae->alias[ae->ialias-1].translation,ae->alias[i].alias)) { /* there is a match, apply alias translation */ ExpressionFastTranslate(ae,&ae->alias[ae->ialias-1].translation,2); /* need to compute again len */ ae->alias[ae->ialias-1].len=strlen(ae->alias[ae->ialias-1].translation); break; } } /* cas particuliers pour insertion en début ou fin de liste */ if (ae->ialias-1) { if (ae->alias[ae->ialias-1].crc>ae->alias[ae->ialias-2].crc) { /* pas de tri il est déjà au bon endroit */ } else if (ae->alias[ae->ialias-1].crcalias[0].crc) { /* insertion tout en bas de liste */ tmpalias=ae->alias[ae->ialias-1]; MemMove(&ae->alias[1],&ae->alias[0],sizeof(struct s_alias)*(ae->ialias-1)); ae->alias[0]=tmpalias; } else { /* on cherche ou inserer */ crc=ae->alias[ae->ialias-1].crc; dw=0; du=ae->ialias-1; while (dw<=du) { dm=(dw+du)/2; if (ae->alias[dm].crc==crc) { break; } else if (ae->alias[dm].crc>crc) { du=dm-1; } else if (ae->alias[dm].crcalias[dm].crcalias[ae->ialias-1]; MemMove(&ae->alias[dm+1],&ae->alias[dm],sizeof(struct s_alias)*(ae->ialias-1-dm)); ae->alias[dm]=tmpalias; } } else { /* one alias need no sort */ } } void InsertDicoToTree(struct s_assenv *ae, struct s_expr_dico *dico) { #undef FUNC #define FUNC "InsertDicoToTree" struct s_crcdico_tree *curdicotree; int radix,dek=32; curdicotree=&ae->dicotree; while (dek) { dek=dek-8; radix=(dico->crc>>dek)&0xFF; if (curdicotree->radix[radix]) { curdicotree=curdicotree->radix[radix]; } else { curdicotree->radix[radix]=MemMalloc(sizeof(struct s_crcdico_tree)); curdicotree=curdicotree->radix[radix]; memset(curdicotree,0,sizeof(struct s_crcdico_tree)); } } ObjectArrayAddDynamicValueConcat((void**)&curdicotree->dico,&curdicotree->ndico,&curdicotree->mdico,dico,sizeof(struct s_expr_dico)); } unsigned char *SnapshotDicoInsert(char *symbol_name, int ptr, int *retidx) { static unsigned char *subchunk=NULL; static int subchunksize=0; static int idx=0; int symbol_len; if (retidx) { if (symbol_name && strcmp(symbol_name,"FREE")==0) { subchunksize=0; idx=0; MemFree(subchunk); subchunk=NULL; } *retidx=idx; return subchunk; } if (idx+65536>subchunksize) { subchunksize=subchunksize+65536; subchunk=MemRealloc(subchunk,subchunksize); } symbol_len=strlen(symbol_name); if (symbol_len>255) symbol_len=255; subchunk[idx++]=symbol_len; memcpy(subchunk+idx,symbol_name,symbol_len); idx+=symbol_len; memset(subchunk+idx,0,6); idx+=6; subchunk[idx++]=(ptr&0xFF00)/256; subchunk[idx++]=ptr&0xFF; return NULL; } void SnapshotDicoTreeRecurse(struct s_crcdico_tree *lt) { #undef FUNC #define FUNC "SnapshottDicoTreeRecurse" int i; for (i=0;i<256;i++) { if (lt->radix[i]) { SnapshotDicoTreeRecurse(lt->radix[i]); } } if (lt->mdico) { for (i=0;indico;i++) { if (strcmp(lt->dico[i].name,"IX") && strcmp(lt->dico[i].name,"IY") && strcmp(lt->dico[i].name,"PI") && strcmp(lt->dico[i].name,"ASSEMBLER_RASM")) { SnapshotDicoInsert(lt->dico[i].name,(int)floor(lt->dico[i].v+0.5),NULL); } } } } unsigned char *SnapshotDicoTree(struct s_assenv *ae, int *retidx) { #undef FUNC #define FUNC "SnapshotDicoTree" unsigned char *sc; int idx; int i; for (i=0;i<256;i++) { if (ae->dicotree.radix[i]) { SnapshotDicoTreeRecurse(ae->dicotree.radix[i]); } } sc=SnapshotDicoInsert(NULL,0,&idx); *retidx=idx; return sc; } void WarnLabelTreeRecurse(struct s_assenv *ae, struct s_crclabel_tree *lt) { #undef FUNC #define FUNC "WarnLabelTreeRecurse" int i; for (i=0;i<256;i++) { if (lt->radix[i]) { WarnLabelTreeRecurse(ae,lt->radix[i]); } } for (i=0;inlabel;i++) { if (!lt->label[i].used) { if (!lt->label[i].name) { rasm_printf(ae,KWARNING"[%s:%d] Warning: label %s declared but not used\n",ae->filename[lt->label[i].fileidx],lt->label[i].fileline,ae->wl[lt->label[i].iw].w); } else { rasm_printf(ae,KWARNING"[%s:%d] Warning: label %s declared but not used\n",ae->filename[lt->label[i].fileidx],lt->label[i].fileline,lt->label[i].name); } } } } void WarnLabelTree(struct s_assenv *ae) { #undef FUNC #define FUNC "WarnLabelTree" int i; for (i=0;i<256;i++) { if (ae->labeltree.radix[i]) { WarnLabelTreeRecurse(ae,ae->labeltree.radix[i]); } } } void WarnDicoTreeRecurse(struct s_assenv *ae, struct s_crcdico_tree *lt) { #undef FUNC #define FUNC "WarnDicoTreeRecurse" char symbol_line[1024]; int i; for (i=0;i<256;i++) { if (lt->radix[i]) { WarnDicoTreeRecurse(ae,lt->radix[i]); } } for (i=0;indico;i++) { if (strcmp(lt->dico[i].name,"IX") && strcmp(lt->dico[i].name,"IY") && strcmp(lt->dico[i].name,"PI") && strcmp(lt->dico[i].name,"ASSEMBLER_RASM") && lt->dico[i].autorise_export) { rasm_printf(ae,KWARNING"[%s:%d] Warning: variable %s declared but not used\n",ae->filename[ae->wl[lt->dico[i].iw].ifile],ae->wl[lt->dico[i].iw].l,lt->dico[i].name); } } } void WarnDicoTree(struct s_assenv *ae) { #undef FUNC #define FUNC "ExportDicoTree" int i; for (i=0;i<256;i++) { if (ae->dicotree.radix[i]) { WarnDicoTreeRecurse(ae,ae->dicotree.radix[i]); } } } void ExportDicoTreeRecurse(struct s_crcdico_tree *lt, char *zefile, char *zeformat) { #undef FUNC #define FUNC "ExportDicoTreeRecurse" char symbol_line[1024]; int i; for (i=0;i<256;i++) { if (lt->radix[i]) { ExportDicoTreeRecurse(lt->radix[i],zefile,zeformat); } } if (lt->mdico) { for (i=0;indico;i++) { if (strcmp(lt->dico[i].name,"IX") && strcmp(lt->dico[i].name,"IY") && strcmp(lt->dico[i].name,"PI") && strcmp(lt->dico[i].name,"ASSEMBLER_RASM") && lt->dico[i].autorise_export) { snprintf(symbol_line,sizeof(symbol_line)-1,zeformat,lt->dico[i].name,(int)floor(lt->dico[i].v+0.5)); symbol_line[sizeof(symbol_line)-1]=0xD; FileWriteLine(zefile,symbol_line); } } } } void ExportDicoTree(struct s_assenv *ae, char *zefile, char *zeformat) { #undef FUNC #define FUNC "ExportDicoTree" int i; for (i=0;i<256;i++) { if (ae->dicotree.radix[i]) { ExportDicoTreeRecurse(ae->dicotree.radix[i],zefile,zeformat); } } } void FreeDicoTreeRecurse(struct s_crcdico_tree *lt) { #undef FUNC #define FUNC "FreeDicoTreeRecurse" int i; for (i=0;i<256;i++) { if (lt->radix[i]) { FreeDicoTreeRecurse(lt->radix[i]); } } if (lt->mdico) { for (i=0;indico;i++) { MemFree(lt->dico[i].name); } MemFree(lt->dico); } MemFree(lt); } void FreeDicoTree(struct s_assenv *ae) { #undef FUNC #define FUNC "FreeDicoTree" int i; for (i=0;i<256;i++) { if (ae->dicotree.radix[i]) { FreeDicoTreeRecurse(ae->dicotree.radix[i]); } } if (ae->dicotree.mdico) { for (i=0;idicotree.ndico;i++) MemFree(ae->dicotree.dico[i].name); MemFree(ae->dicotree.dico); } } struct s_expr_dico *SearchDico(struct s_assenv *ae, char *dico, int crc) { #undef FUNC #define FUNC "SearchDico" struct s_crcdico_tree *curdicotree; struct s_expr_dico *retdico=NULL; int i,radix,dek=32; curdicotree=&ae->dicotree; while (dek) { dek=dek-8; radix=(crc>>dek)&0xFF; if (curdicotree->radix[radix]) { curdicotree=curdicotree->radix[radix]; } else { /* radix not found, dico is not in index */ return NULL; } } for (i=0;indico;i++) { if (strcmp(curdicotree->dico[i].name,dico)==0) { curdicotree->dico[i].used=1; return &curdicotree->dico[i]; } } return NULL; } int DelDico(struct s_assenv *ae, char *dico, int crc) { #undef FUNC #define FUNC "DelDico" struct s_crcdico_tree *curdicotree; struct s_expr_dico *retdico=NULL; int i,radix,dek=32; curdicotree=&ae->dicotree; while (dek) { dek=dek-8; radix=(crc>>dek)&0xFF; if (curdicotree->radix[radix]) { curdicotree=curdicotree->radix[radix]; } else { /* radix not found, dico is not in index */ return 0; } } for (i=0;indico;i++) { if (strcmp(curdicotree->dico[i].name,dico)==0) { /* must free memory */ MemFree(curdicotree->dico[i].name); if (indico-1) { MemMove(&curdicotree->dico[i],&curdicotree->dico[i+1],(curdicotree->ndico-i-1)*sizeof(struct s_expr_dico)); } curdicotree->ndico--; return 1; } } return 0; } void InsertUsedToTree(struct s_assenv *ae, char *used, int crc) { #undef FUNC #define FUNC "InsertUsedToTree" struct s_crcused_tree *curusedtree; int radix,dek=32,i; curusedtree=&ae->usedtree; while (dek) { dek=dek-8; radix=(crc>>dek)&0xFF; if (curusedtree->radix[radix]) { curusedtree=curusedtree->radix[radix]; } else { curusedtree->radix[radix]=MemMalloc(sizeof(struct s_crcused_tree)); curusedtree=curusedtree->radix[radix]; memset(curusedtree,0,sizeof(struct s_crcused_tree)); } } for (i=0;inused;i++) if (strcmp(used,curusedtree->used[i])==0) break; /* no double */ if (i==curusedtree->nused) { FieldArrayAddDynamicValueConcat(&curusedtree->used,&curusedtree->nused,&curusedtree->mused,used); } } void FreeUsedTreeRecurse(struct s_crcused_tree *lt) { #undef FUNC #define FUNC "FreeUsedTreeRecurse" int i; for (i=0;i<256;i++) { if (lt->radix[i]) { FreeUsedTreeRecurse(lt->radix[i]); } } if (lt->mused) { for (i=0;inused;i++) MemFree(lt->used[i]); MemFree(lt->used); } MemFree(lt); } void FreeUsedTree(struct s_assenv *ae) { #undef FUNC #define FUNC "FreeUsedTree" int i; for (i=0;i<256;i++) { if (ae->usedtree.radix[i]) { FreeUsedTreeRecurse(ae->usedtree.radix[i]); } } } int SearchUsed(struct s_assenv *ae, char *used, int crc) { #undef FUNC #define FUNC "SearchUsed" struct s_crcused_tree *curusedtree; int i,radix,dek=32; curusedtree=&ae->usedtree; while (dek) { dek=dek-8; radix=(crc>>dek)&0xFF; if (curusedtree->radix[radix]) { curusedtree=curusedtree->radix[radix]; } else { /* radix not found, used is not in index */ return 0; } } for (i=0;inused;i++) { if (strcmp(curusedtree->used[i],used)==0) { return 1; } } return 0; } void InsertTextToTree(struct s_assenv *ae, char *text, char *replace, int crc) { #undef FUNC #define FUNC "InsertTextToTree" struct s_crcstring_tree *curstringtree; int radix,dek=32,i; curstringtree=&ae->stringtree; while (dek) { dek=dek-8; radix=(crc>>dek)&0xFF; if (curstringtree->radix[radix]) { curstringtree=curstringtree->radix[radix]; } else { curstringtree->radix[radix]=MemMalloc(sizeof(struct s_crcused_tree)); curstringtree=curstringtree->radix[radix]; memset(curstringtree,0,sizeof(struct s_crcused_tree)); } } for (i=0;intext;i++) if (strcmp(text,curstringtree->text[i])==0) break; /* no double */ if (i==curstringtree->ntext) { text=TxtStrDup(text); replace=TxtStrDup(replace); FieldArrayAddDynamicValueConcat(&curstringtree->text,&curstringtree->ntext,&curstringtree->mtext,text); FieldArrayAddDynamicValueConcat(&curstringtree->replace,&curstringtree->nreplace,&curstringtree->mreplace,replace); } } void FreeTextTreeRecurse(struct s_crcstring_tree *lt) { #undef FUNC #define FUNC "FreeTextTreeRecurse" int i; for (i=0;i<256;i++) { if (lt->radix[i]) { FreeTextTreeRecurse(lt->radix[i]); } } if (lt->mtext) { for (i=0;intext;i++) MemFree(lt->text[i]); MemFree(lt->text); } MemFree(lt); } void FreeTextTree(struct s_assenv *ae) { #undef FUNC #define FUNC "FreeTextTree" int i; for (i=0;i<256;i++) { if (ae->stringtree.radix[i]) { FreeTextTreeRecurse(ae->stringtree.radix[i]); } } if (ae->stringtree.mtext) MemFree(ae->stringtree.text); } int SearchText(struct s_assenv *ae, char *text, int crc) { #undef FUNC #define FUNC "SearchText" struct s_crcstring_tree *curstringtree; int i,radix,dek=32; curstringtree=&ae->stringtree; while (dek) { dek=dek-8; radix=(crc>>dek)&0xFF; if (curstringtree->radix[radix]) { curstringtree=curstringtree->radix[radix]; } else { /* radix not found, used is not in index */ return 0; } } for (i=0;intext;i++) { if (strcmp(curstringtree->text[i],text)==0) { return 1; } } return 0; } /* struct s_crclabel_tree { /* struct s_crclabel_tree { struct s_crclabel_tree *radix[256]; struct s_label *label; int nlabel,mlabel; }; */ void FreeLabelTreeRecurse(struct s_crclabel_tree *lt) { #undef FUNC #define FUNC "FreeLabelTreeRecurse" int i; for (i=0;i<256;i++) { if (lt->radix[i]) { FreeLabelTreeRecurse(lt->radix[i]); } } /* label.name already freed elsewhere as this one is a copy */ if (lt->mlabel) MemFree(lt->label); MemFree(lt); } void FreeLabelTree(struct s_assenv *ae) { #undef FUNC #define FUNC "FreeLabelTree" int i; for (i=0;i<256;i++) { if (ae->labeltree.radix[i]) { FreeLabelTreeRecurse(ae->labeltree.radix[i]); } } if (ae->labeltree.mlabel) MemFree(ae->labeltree.label); } struct s_label *SearchLabel(struct s_assenv *ae, char *label, int crc) { #undef FUNC #define FUNC "SearchLabel" struct s_crclabel_tree *curlabeltree; struct s_label *retlabel=NULL; int i,radix,dek=32; //printf("searchLabel [%s]",label); curlabeltree=&ae->labeltree; while (dek) { dek=dek-8; radix=(crc>>dek)&0xFF; if (curlabeltree->radix[radix]) { curlabeltree=curlabeltree->radix[radix]; } else { /* radix not found, label is not in index */ //printf(" not found\n"); return NULL; } } for (i=0;inlabel;i++) { if (!curlabeltree->label[i].name && strcmp(ae->wl[curlabeltree->label[i].iw].w,label)==0) { curlabeltree->label[i].used=1; //printf(" found (global)\n"); return &curlabeltree->label[i]; } else if (curlabeltree->label[i].name && strcmp(curlabeltree->label[i].name,label)==0) { curlabeltree->label[i].used=1; //printf(" found (local or proximity)\n"); return &curlabeltree->label[i]; } } return NULL; } char *MakeLocalLabel(struct s_assenv *ae,char *varbuffer, int *retdek) { #undef FUNC #define FUNC "MakeLocalLabel" char *locallabel; char hexdigit[32]; int lenbuf=0,dek,i,im; char *zepoint; lenbuf=strlen(varbuffer); /* not so local labels */ if (varbuffer[0]=='.') { /* create reference */ if (ae->lastgloballabel) { locallabel=MemMalloc(strlen(varbuffer)+1+ae->lastgloballabellen); sprintf(locallabel,"%s%s",ae->lastgloballabel,varbuffer); if (retdek) *retdek=0; return locallabel; } else { if (retdek) *retdek=0; return TxtStrDup(varbuffer); } } /*************************************************** without retdek -> build a local label with retdek -> build the hash string ***************************************************/ if (!retdek) { locallabel=MemMalloc(lenbuf+(ae->ir+ae->iw+3)*8+8); zepoint=strchr(varbuffer,'.'); if (zepoint) { *zepoint=0; } strcpy(locallabel,varbuffer); } else { locallabel=MemMalloc((ae->ir+ae->iw+3)*8+4); locallabel[0]=0; } //printf("locallabel=[%s] (draft)\n",locallabel); dek=0; dek+=strappend(locallabel,"R"); for (i=0;iir;i++) { sprintf(hexdigit,"%04X",ae->repeat[i].cpt); dek+=strappend(locallabel,hexdigit); } if (ae->ir) { sprintf(hexdigit,"%04X",ae->repeat[ae->ir-1].value); dek+=strappend(locallabel+dek,hexdigit); } dek+=strappend(locallabel,"W"); for (i=0;iiw;i++) { sprintf(hexdigit,"%04X",ae->whilewend[i].cpt); dek+=strappend(locallabel+dek,hexdigit); } if (ae->iw) { sprintf(hexdigit,"%04X",ae->whilewend[ae->iw-1].value); dek+=strappend(locallabel+dek,hexdigit); } /* where are we? */ if (ae->imacropos) { for (im=ae->imacropos-1;im>=0;im--) { if (ae->idx>=ae->macropos[im].start && ae->idxmacropos[im].end) break; } if (im>=0) { /* si on n'est pas dans une macro, on n'indique rien */ sprintf(hexdigit,"M%04X",ae->macropos[im].value); dek+=strappend(locallabel+dek,hexdigit); } } if (!retdek) { if (zepoint) { *zepoint='.'; strcat(locallabel+dek,zepoint); } } else { *retdek=dek; } //printf("locallabel=[%s] (end)\n",locallabel); return locallabel; } char *TradExpression(char *zexp) { #undef FUNC #define FUNC "TradExpression" static char *last_expression=NULL; char *wstr; if (last_expression) {MemFree(last_expression);last_expression=NULL;} if (!zexp) return NULL; wstr=TxtStrDup(zexp); wstr=TxtReplace(wstr,"[","<<",0); wstr=TxtReplace(wstr,"]",">>",0); wstr=TxtReplace(wstr,"m","%",0); last_expression=wstr; return wstr; } int TrimFloatingPointString(char *fps) { int i=0,pflag,zflag=0; while (fps[i]) { if (fps[i]=='.') { pflag=i; zflag=1; } else if (fps[i]!='0') { zflag=0; } i++; } /* truncate floating fract */ if (zflag) { fps[pflag]=0; } else { pflag=i; } return pflag; } /* translate tag or formula between curly brackets used in label declaration used in print directive */ char *TranslateTag(struct s_assenv *ae, char *varbuffer, int *touched, int enablefast, int tagoption) { /******************************************************* v a r i a b l e s i n s t r i n g s *******************************************************/ char *starttag,*endtag,*tagcheck,*expr; int newlen,lenw,taglen,tagidx,tagcount,validx; char curvalstr[256]={0}; char *equpos=NULL,*equback; //printf("TranslateTag [%s]\n",varbuffer); if (tagoption & E_TAGOPTION_PRESERVE) { if (ae->iw || ae->ir) { /* inside a loop we must care about variables */ //printf("TranslateTag [%s] with PRESERVE inside a loop!\n",varbuffer); return varbuffer; } } *touched=0; while ((starttag=strchr(varbuffer+1,'{'))!=NULL) { if ((endtag=strchr(starttag,'}'))==NULL) { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"invalid tag in string [%s]\n",varbuffer); return NULL; } /* allow inception */ tagcount=1; tagcheck=starttag+1; while (*tagcheck && tagcount) { if (*tagcheck=='}') tagcount--; else if (*tagcheck=='{') tagcount++; tagcheck++; } if (tagcount) { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"invalid brackets combination in string [%s]\n",varbuffer); return NULL; } else { endtag=tagcheck-1; } *touched=1; taglen=endtag-starttag+1; tagidx=starttag-varbuffer; lenw=strlen(varbuffer); // before the EOF write *endtag=0; /*** c o m p u t e e x p r e s s i o n ***/ expr=TxtStrDup(starttag+1); if (tagoption & E_TAGOPTION_REMOVESPACE) expr=TxtReplace(expr," ","",0); if (enablefast) ExpressionFastTranslate(ae,&expr,0); validx=(int)RoundComputeExpressionCore(ae,expr,ae->codeadr,0); if (validx<0) { strcpy(curvalstr,""); MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"indexed tag must NOT be a negative value [%s]\n",varbuffer); MemFree(expr); return NULL; } else { #ifdef OS_WIN snprintf(curvalstr,sizeof(curvalstr)-1,"%d",validx); newlen=strlen(curvalstr); #else newlen=snprintf(curvalstr,sizeof(curvalstr)-1,"%d",validx); #endif } MemFree(expr); if (newlen>taglen) { /* realloc */ varbuffer=MemRealloc(varbuffer,lenw+newlen-taglen+1); } if (newlen!=taglen ) { MemMove(varbuffer+tagidx+newlen,varbuffer+tagidx+taglen,lenw-taglen-tagidx+1); } strncpy(varbuffer+tagidx,curvalstr,newlen); /* copy without zero terminator */ } return varbuffer; } double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int ptr, int didx) { #undef FUNC #define FUNC "ComputeExpressionCore" /* static execution buffers */ static double *accu=NULL; static int maccu=0; static struct s_compute_element *computestack=NULL; static int maxcomputestack=0; int i,j,paccu=0; int nbtokenstack=0; int nbcomputestack=0; int nboperatorstack=0; struct s_compute_element stackelement; int o2,okclose,itoken; int idx=0,crc,icheck,is_binary,ivar=0; char asciivalue[11]; unsigned char c; int accu_err=0; /* backup alias replace */ char *zeexpression,*expr; int original=1; int ialias,startvar; int newlen,lenw; /* dictionnary */ struct s_expr_dico *curdic; struct s_label *curlabel; char *localname; int minusptr,imkey,bank,page,idxmacro; double curval; /* negative value */ int allow_minus_as_sign=0; /* extended replace in labels */ int curly=0,curlyflag=0; char *Automate; double dummint; /* memory cleanup */ if (!ae) { if (maccu) MemFree(accu); accu=NULL;maccu=0; if (maxcomputestack) MemFree(computestack); computestack=NULL;maxcomputestack=0; #if 0 if (maxivar) MemFree(varbuffer); if (maxtokenstack) MemFree(tokenstack); if (maxoperatorstack) MemFree(operatorstack); maxtokenstack=maxoperatorstack=0; maxivar=1; varbuffer=NULL; tokenstack=NULL; operatorstack=NULL; #endif return 0.0; } /* be sure to have at least some bytes allocated */ StateMachineResizeBuffer(&ae->computectx->varbuffer,128,&ae->computectx->maxivar); #if TRACE_COMPUTE_EXPRESSION printf("expression=[%s]\n",zeexpression); #endif zeexpression=original_zeexpression; if (!zeexpression[0]) { return 0; } /* double hack if the first value is negative */ if (zeexpression[0]=='-') { if (ae->AutomateExpressionValidCharFirst[(int)zeexpression[1]&0xFF]) { allow_minus_as_sign=1; } else { memset(&stackelement,0,sizeof(stackelement)); ObjectArrayAddDynamicValueConcat((void **)&ae->computectx->tokenstack,&nbtokenstack,&ae->computectx->maxtokenstack,&stackelement,sizeof(stackelement)); } } /* is there ascii char? */ while ((c=zeexpression[idx])!=0) { if (c=='\'' || c=='"') { /* echappement */ if (zeexpression[idx+1]=='\\') { if (zeexpression[idx+2] && zeexpression[idx+3]==c) { sprintf(asciivalue,"#%03X",zeexpression[idx+2]); memcpy(zeexpression+idx,asciivalue,4); idx+=3; } else { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"Only single escaped char may be quoted [%s]\n",TradExpression(zeexpression)); zeexpression[0]=0; return 0; } } else if (zeexpression[idx+1] && zeexpression[idx+2]==c) { sprintf(asciivalue,"#%02X",zeexpression[idx+1]); memcpy(zeexpression+idx,asciivalue,3); idx+=2; } else { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"Only single char may be quoted [%s]\n",TradExpression(zeexpression)); zeexpression[0]=0; return 0; } } idx++; } #if TRACE_COMPUTE_EXPRESSION printf("apres conversion des chars [%s]\n",zeexpression); #endif /*********************************************************** P A T C H F O R P O S I T I V E V A L U E ***********************************************************/ if (zeexpression[0]=='+') idx=1; else idx=0; /*********************************************************** C O M P U T E E X P R E S S I O N M A I N L O O P ***********************************************************/ while ((c=zeexpression[idx])!=0) { switch (c) { /* parenthesis */ case ')': /* next to a closing parenthesis, a minus is an operator */ allow_minus_as_sign=0; break; case '(': /* operator detection */ case '*': case '/': case '^': case '[': case 'm': case '+': case ']': allow_minus_as_sign=1; break; case '&': allow_minus_as_sign=1; if (c=='&' && zeexpression[idx+1]=='&') { idx++; c='a'; // boolean AND } break; case '|': allow_minus_as_sign=1; if (c=='|' && zeexpression[idx+1]=='|') { idx++; c='o'; // boolean OR } break; /* testing */ case '<': allow_minus_as_sign=1; if (zeexpression[idx+1]=='=') { idx++; c='k'; // boolean LOWEREQ } else if (zeexpression[idx+1]=='>') { idx++; c='n'; // boolean NOTEQUAL } else { c='l'; } break; case '>': allow_minus_as_sign=1; if (zeexpression[idx+1]=='=') { idx++; c='h'; // boolean GREATEREQ } else { c='g'; } break; case '!': allow_minus_as_sign=1; if (zeexpression[idx+1]=='=') { idx++; c='n'; // boolean NOTEQUAL } else { c='b'; } break; case '=': allow_minus_as_sign=1; /* expecting == */ if (zeexpression[idx+1]=='=') { idx++; c='e'; // boolean EQUAL /* except in maxam mode with a single = */ } else if (ae->maxam) { c='e'; // boolean EQUAL /* cannot affect data inside an expression */ } else { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] cannot set variable inside an expression\n",TradExpression(zeexpression)); return 0; } break; case '-': if (allow_minus_as_sign) { /* previous char was an opening parenthesis or an operator */ ivar=0; ae->computectx->varbuffer[ivar++]='-'; StateMachineResizeBuffer(&ae->computectx->varbuffer,ivar,&ae->computectx->maxivar); c=zeexpression[++idx]; if (ae->AutomateExpressionValidCharFirst[(int)c&0xFF]) { ae->computectx->varbuffer[ivar++]=c; StateMachineResizeBuffer(&ae->computectx->varbuffer,ivar,&ae->computectx->maxivar); c=zeexpression[++idx]; while (ae->AutomateExpressionValidChar[(int)c&0xFF]) { ae->computectx->varbuffer[ivar++]=c; StateMachineResizeBuffer(&ae->computectx->varbuffer,ivar,&ae->computectx->maxivar); c=zeexpression[++idx]; } } ae->computectx->varbuffer[ivar]=0; if (ivar<2) { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] invalid minus sign\n",TradExpression(zeexpression)); if (!original) { MemFree(zeexpression); } return 0; } break; } allow_minus_as_sign=1; break; /* operator OR binary value */ case '%': /* % symbol may be a modulo or a binary literal value */ is_binary=0; for (icheck=1;zeexpression[idx+icheck];icheck++) { switch (zeexpression[idx+icheck]) { case '1': case '0':/* still binary */ is_binary=1; break; case '+': case '-': case '/': case '*': case '|': case 'm': case '%': case '^': case '&': case '(': case ')': case '=': case '<': case '>': case '!': case '[': case ']': if (is_binary) is_binary=2; else is_binary=-1; break; default: is_binary=-1; } if (is_binary==2) { break; } if (is_binary==-1) { is_binary=0; break; } } if (!is_binary) { allow_minus_as_sign=1; c='m'; break; } default: allow_minus_as_sign=0; /* semantic analysis */ startvar=idx; ivar=0; /* first char does not allow same chars as next chars */ if (ae->AutomateExpressionValidCharFirst[((int)c)&0xFF]) { ae->computectx->varbuffer[ivar++]=c; if (c=='{') { /* not a formula but only a prefix tag */ curly++; } StateMachineResizeBuffer(&ae->computectx->varbuffer,ivar,&ae->computectx->maxivar); idx++; c=zeexpression[idx]; Automate=ae->AutomateExpressionValidChar; while (Automate[((int)c)&0xFF]) { if (c=='{') { curly++; curlyflag=1; Automate=ae->AutomateExpressionValidCharExtended; } else if (c=='}') { curly--; if (!curly) { Automate=ae->AutomateExpressionValidChar; } } ae->computectx->varbuffer[ivar++]=c; StateMachineResizeBuffer(&ae->computectx->varbuffer,ivar,&ae->computectx->maxivar); idx++; c=zeexpression[idx]; } } ae->computectx->varbuffer[ivar]=0; if (!ivar) { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"invalid char (%d=%c) expression [%s]\n",c,c>31?c:' ',TradExpression(zeexpression)); if (!original) { MemFree(zeexpression); } return 0; } else if (curly) { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"wrong curly brackets in expression [%s]\n",TradExpression(zeexpression)); if (!original) { MemFree(zeexpression); } return 0; } } if (c && !ivar) idx++; /************************************ S T A C K D I S P A T C H E R ************************************/ /* push operator or stack value */ if (!ivar) { /************************************ O P E R A T O R ************************************/ stackelement=ae->AutomateElement[c]; if (stackelement.operator>E_COMPUTE_OPERATION_GREATEREQ) { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] has unknown operator %c (%d)\n",TradExpression(zeexpression),c>31?c:'.',c); } /* stackelement.value isn't used */ } else { /************************************ V A L U E ************************************/ #if TRACE_COMPUTE_EXPRESSION printf("value [%s]\n",ae->computectx->varbuffer); #endif if (ae->computectx->varbuffer[0]=='-') minusptr=1; else minusptr=0; /* constantes ou variables/labels */ switch (ae->computectx->varbuffer[minusptr]) { case '0': /* 0x hexa value hack */ if (ae->computectx->varbuffer[minusptr+1]=='X' && ae->AutomateHexa[ae->computectx->varbuffer[minusptr+2]]) { for (icheck=minusptr+3;ae->computectx->varbuffer[icheck];icheck++) { if (ae->AutomateHexa[ae->computectx->varbuffer[icheck]]) continue; MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is not a valid hex number\n",TradExpression(zeexpression),ae->computectx->varbuffer); break; } curval=strtol(ae->computectx->varbuffer+minusptr+2,NULL,16); break; } else /* 0b binary value hack */ if (ae->computectx->varbuffer[minusptr+1]=='B' && (ae->computectx->varbuffer[minusptr+2]>='0' && ae->computectx->varbuffer[minusptr+2]<='1')) { for (icheck=minusptr+3;ae->computectx->varbuffer[icheck];icheck++) { if (ae->computectx->varbuffer[icheck]>='0' && ae->computectx->varbuffer[icheck]<='1') continue; MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is not a valid binary number\n",TradExpression(zeexpression),ae->computectx->varbuffer); break; } curval=strtol(ae->computectx->varbuffer+minusptr+2,NULL,2); break; } /* 0o octal value hack */ if (ae->computectx->varbuffer[minusptr+1]=='O' && (ae->computectx->varbuffer[minusptr+2]>='0' && ae->computectx->varbuffer[minusptr+2]<='5')) { for (icheck=minusptr+3;ae->computectx->varbuffer[icheck];icheck++) { if (ae->computectx->varbuffer[icheck]>='0' && ae->computectx->varbuffer[icheck]<='5') continue; MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is not a valid octal number\n",TradExpression(zeexpression),ae->computectx->varbuffer); break; } curval=strtol(ae->computectx->varbuffer+minusptr+2,NULL,2); break; } case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* check number */ for (icheck=minusptr;ae->computectx->varbuffer[icheck];icheck++) { if (ae->AutomateDigit[ae->computectx->varbuffer[icheck]]) continue; /* Intel hexa & binary style */ switch (ae->computectx->varbuffer[strlen(ae->computectx->varbuffer)-1]) { case 'H': for (icheck=minusptr;ae->computectx->varbuffer[icheck+1];icheck++) { if (ae->AutomateHexa[ae->computectx->varbuffer[icheck]]) continue; MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is not a valid hex number\n",TradExpression(zeexpression),ae->computectx->varbuffer); } curval=strtol(ae->computectx->varbuffer+minusptr,NULL,16); break; case 'B': for (icheck=minusptr;ae->computectx->varbuffer[icheck+1];icheck++) { if (ae->computectx->varbuffer[icheck]=='0' || ae->computectx->varbuffer[icheck]=='1') continue; MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is not a valid binary number\n",TradExpression(zeexpression),ae->computectx->varbuffer); } curval=strtol(ae->computectx->varbuffer+minusptr,NULL,2); break; default: MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is not a valid number\n",TradExpression(zeexpression),ae->computectx->varbuffer); } icheck=0; break; } if (!ae->computectx->varbuffer[icheck]) curval=atof(ae->computectx->varbuffer+minusptr); break; case '%': /* check number */ if (!ae->computectx->varbuffer[minusptr+1]) { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is an empty binary number\n",TradExpression(zeexpression),ae->computectx->varbuffer); } for (icheck=minusptr+1;ae->computectx->varbuffer[icheck];icheck++) { if (ae->computectx->varbuffer[icheck]=='0' || ae->computectx->varbuffer[icheck]=='1') continue; MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is not a valid binary number\n",TradExpression(zeexpression),ae->computectx->varbuffer); break; } curval=strtol(ae->computectx->varbuffer+minusptr+1,NULL,2); break; case '#': /* check number */ if (!ae->computectx->varbuffer[minusptr+1]) { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is an empty hex number\n",TradExpression(zeexpression),ae->computectx->varbuffer); } for (icheck=minusptr+1;ae->computectx->varbuffer[icheck];icheck++) { if (ae->AutomateHexa[ae->computectx->varbuffer[icheck]]) continue; MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is not a valid hex number\n",TradExpression(zeexpression),ae->computectx->varbuffer); break; } curval=strtol(ae->computectx->varbuffer+minusptr+1,NULL,16); break; default: if (1 || !curlyflag) { /* $ hex value hack */ if (ae->computectx->varbuffer[minusptr+0]=='$' && ae->AutomateHexa[ae->computectx->varbuffer[minusptr+1]]) { for (icheck=minusptr+2;ae->computectx->varbuffer[icheck];icheck++) { if (ae->AutomateHexa[ae->computectx->varbuffer[icheck]]) continue; MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is not a valid hex number\n",TradExpression(zeexpression),ae->computectx->varbuffer); break; } curval=strtol(ae->computectx->varbuffer+minusptr+1,NULL,16); break; } /* @ octal value hack */ if (ae->computectx->varbuffer[minusptr+0]=='@' && ((ae->computectx->varbuffer[minusptr+1]>='0' && ae->computectx->varbuffer[minusptr+1]<='7'))) { for (icheck=minusptr+2;ae->computectx->varbuffer[icheck];icheck++) { if (ae->computectx->varbuffer[icheck]>='0' && ae->computectx->varbuffer[icheck]<='7') continue; MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is not a valid octal number\n",TradExpression(zeexpression),ae->computectx->varbuffer); break; } curval=strtol(ae->computectx->varbuffer+minusptr+1,NULL,8); break; } /* Intel hexa value hack */ if (ae->AutomateHexa[ae->computectx->varbuffer[minusptr+0]]) { if (ae->computectx->varbuffer[strlen(ae->computectx->varbuffer)-1]=='H') { for (icheck=minusptr;ae->computectx->varbuffer[icheck+1];icheck++) { if (!ae->AutomateHexa[ae->computectx->varbuffer[icheck]]) break; } if (!ae->computectx->varbuffer[icheck+1]) { curval=strtol(ae->computectx->varbuffer+minusptr,NULL,16); break; } } } } if (curlyflag) { char *minivarbuffer; int touched; /* besoin d'un sous-contexte */ minivarbuffer=TxtStrDup(ae->computectx->varbuffer+minusptr); ae->computectx=&ae->ctx2; #if TRACE_COMPUTE_EXPRESSION printf("curly [%s]\n",minivarbuffer); #endif minivarbuffer=TranslateTag(ae,minivarbuffer, &touched,0,E_TAGOPTION_NONE); #if TRACE_COMPUTE_EXPRESSION printf("après curly [%s]\n",minivarbuffer); #endif ae->computectx=&ae->ctx1; if (!touched) { strcpy(ae->computectx->varbuffer+minusptr,minivarbuffer); } else { StateMachineResizeBuffer(&ae->computectx->varbuffer,strlen(minivarbuffer)+2,&ae->computectx->maxivar); strcpy(ae->computectx->varbuffer+minusptr,minivarbuffer); } MemFree(minivarbuffer); curlyflag=0; } crc=GetCRC(ae->computectx->varbuffer+minusptr); /*************************************************** L O O K I N G F O R A F U N C T I O N ***************************************************/ for (imkey=0;math_keyword[imkey].mnemo[0];imkey++) { if (crc==math_keyword[imkey].crc && strcmp(ae->computectx->varbuffer+minusptr,math_keyword[imkey].mnemo)==0) { if (c=='(') { /* push function as operator! */ stackelement.operator=math_keyword[imkey].operation; //stackelement.priority=0; /************************************************ C R E A T E E X T R A T O K E N ************************************************/ ObjectArrayAddDynamicValueConcat((void **)&ae->computectx->tokenstack,&nbtokenstack,&ae->computectx->maxtokenstack,&stackelement,sizeof(stackelement)); stackelement.operator=E_COMPUTE_OPERATION_OPEN; ObjectArrayAddDynamicValueConcat((void **)&ae->computectx->tokenstack,&nbtokenstack,&ae->computectx->maxtokenstack,&stackelement,sizeof(stackelement)); allow_minus_as_sign=1; idx++; } else { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is a reserved keyword!\n",TradExpression(zeexpression),math_keyword[imkey].mnemo); curval=0; idx++; } ivar=0; break; } } if (math_keyword[imkey].mnemo[0]) continue; if (ae->computectx->varbuffer[minusptr+0]=='$' && ae->computectx->varbuffer[minusptr+1]==0) { curval=ptr; } else { #if TRACE_COMPUTE_EXPRESSION printf("search dico [%s]\n",ae->computectx->varbuffer+minusptr); #endif curdic=SearchDico(ae,ae->computectx->varbuffer+minusptr,crc); if (curdic) { #if TRACE_COMPUTE_EXPRESSION printf("trouvé valeur=%.2lf\n",curdic->v); #endif curval=curdic->v; break; } else { /* getbank hack */ if (ae->computectx->varbuffer[minusptr]!='{') { bank=0; page=0; } else if (strncmp(ae->computectx->varbuffer+minusptr,"{BANK}",6)==0) { bank=6; page=0; /* obligé de recalculer le CRC */ crc=GetCRC(ae->computectx->varbuffer+minusptr+bank); } else if (strncmp(ae->computectx->varbuffer+minusptr,"{PAGE}",6)==0) { bank=6; page=1; /* obligé de recalculer le CRC */ crc=GetCRC(ae->computectx->varbuffer+minusptr+bank); } else if (strncmp(ae->computectx->varbuffer+minusptr,"{PAGESET}",9)==0) { bank=9; page=2; /* obligé de recalculer le CRC */ crc=GetCRC(ae->computectx->varbuffer+minusptr+bank); } else if (strncmp(ae->computectx->varbuffer+minusptr,"{SIZEOF}",8)==0) { bank=8; page=3; /* obligé de recalculer le CRC */ crc=GetCRC(ae->computectx->varbuffer+minusptr+bank); /* search in structures prototypes and subfields */ for (i=0;iirasmstruct;i++) { if (ae->rasmstruct[i].crc==crc && strcmp(ae->rasmstruct[i].name,ae->computectx->varbuffer+minusptr+bank)==0) { curval=ae->rasmstruct[i].size; break; } for (j=0;jrasmstruct[i].irasmstructfield;j++) { if (ae->rasmstruct[i].rasmstructfield[j].crc==crc && strcmp(ae->rasmstruct[i].rasmstructfield[j].fullname,ae->computectx->varbuffer+minusptr+bank)==0) { curval=ae->rasmstruct[i].rasmstructfield[j].size; i=ae->irasmstruct+1; break; } } } if (i==ae->irasmstruct) { /* search in structures aliases */ for (i=0;iirasmstructalias;i++) { if (ae->rasmstructalias[i].crc==crc && strcmp(ae->rasmstructalias[i].name,ae->computectx->varbuffer+minusptr+bank)==0) { curval=ae->rasmstructalias[i].size+ae->rasmstructalias[i].ptr; break; } } if (i==ae->irasmstructalias) { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"cannot SIZEOF unknown structure [%s]!\n",ae->computectx->varbuffer+minusptr+bank); curval=0; } } } else { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is an unknown prefix!\n",TradExpression(zeexpression),ae->computectx->varbuffer); } /* limited label translation while processing crunched blocks ae->curlz == current crunched block processed expression->crunch_block=0 -> oui expression->crunch_block=1 -> oui si même block expression->crunch_block=2 -> non car sera relogée */ if (page!=3) { #if TRACE_COMPUTE_EXPRESSION printf("search label [%s]\n",ae->computectx->varbuffer+minusptr+bank); #endif curlabel=SearchLabel(ae,ae->computectx->varbuffer+minusptr+bank,crc); if (curlabel) { if (ae->stage<2) { if (curlabel->lz==-1) { if (!bank) { curval=curlabel->ptr; } else { #if TRACE_COMPUTE_EXPRESSION printf("page=%d | ptr=%X ibank=%d\n",page,curlabel->ptr,curlabel->ibank); #endif switch (page) { case 2: /* PAGESET */ if (curlabel->ibanksetgate[curlabel->ibank]; } else { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] cannot use PAGESET - label [%s] is in a temporary space!\n",TradExpression(zeexpression),ae->computectx->varbuffer); curval=curlabel->ibank; } break; case 1:/* PAGE */ if (curlabel->ibankbankset[curlabel->ibank>>2]) { curval=ae->bankgate[(curlabel->ibank&0x1FC)+(curlabel->ptr>>14)]; } else { curval=ae->bankgate[curlabel->ibank]; } } else { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] cannot use PAGE - label [%s] is in a temporary space!\n",TradExpression(zeexpression),ae->computectx->varbuffer); curval=curlabel->ibank; } break; case 0: curval=curlabel->ibank; break; default:MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INTERNAL ERROR (unknown paging)\n",GetExpFile(ae,didx),GetExpLine(ae,didx));FreeAssenv(ae);exit(-664); } } } else { /* label MUST be in the crunched block */ if (curlabel->iorgzone==ae->expression[didx].iorgzone && curlabel->ibank==ae->expression[didx].ibank && curlabel->lz<=ae->expression[didx].lz) { if (!bank) { curval=curlabel->ptr; } else { if (page) { switch (page) { case 2: /* PAGESET */ if (curlabel->ibanksetgate[curlabel->ibank]; } else { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] cannot use PAGESET - label [%s] is in a temporary space!\n",TradExpression(zeexpression),ae->computectx->varbuffer); curval=curlabel->ibank; } break; case 1: /* PAGE */ if (curlabel->ibankbankset[curlabel->ibank>>2]) { curval=ae->bankgate[(curlabel->ibank&0x1FC)+(curlabel->ptr>>14)]; } else { curval=ae->bankgate[curlabel->ibank]; } } else { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] cannot use PAGE - label [%s] is in a temporary space!\n",TradExpression(zeexpression),ae->computectx->varbuffer); curval=curlabel->ibank; } break; case 0:curval=curlabel->ibank;break; default:MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INTERNAL ERROR (unknown paging)\n",GetExpFile(ae,didx),GetExpLine(ae,didx));FreeAssenv(ae);exit(-664); } } } } else { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"Label [%s](%d) cannot be computed because it is located after the crunched zone %d\n",ae->computectx->varbuffer,curlabel->lz,ae->expression[didx].lz); curval=0; } } } else { #if TRACE_COMPUTE_EXPRESSION printf("stage 2 | page=%d | ptr=%X ibank=%d\n",page,curlabel->ptr,curlabel->ibank); #endif if (bank) { //curval=curlabel->ibank; switch (page) { case 2: /* PAGESET */ if (curlabel->ibanksetgate[curlabel->ibank]; } else { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] cannot use PAGESET - label [%s] is in a temporary space!\n",TradExpression(zeexpression),ae->computectx->varbuffer); curval=curlabel->ibank; } break; case 1:/* PAGE */ if (curlabel->ibankbankset[curlabel->ibank>>2]) { curval=ae->bankgate[(curlabel->ibank&0x1FC)+(curlabel->ptr>>14)]; } else { curval=ae->bankgate[curlabel->ibank]; } } else { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] cannot use PAGE - label [%s] is in a temporary space!\n",TradExpression(zeexpression),ae->computectx->varbuffer); curval=curlabel->ibank; } break; case 0: curval=curlabel->ibank; break; default:MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INTERNAL ERROR (unknown paging)\n",GetExpFile(ae,didx),GetExpLine(ae,didx));FreeAssenv(ae);exit(-664); } } else { curval=curlabel->ptr; } } } else { /*********** to allow aliases declared after use ***********/ if ((ialias=SearchAlias(ae,crc,ae->computectx->varbuffer+minusptr))>=0) { newlen=ae->alias[ialias].len; lenw=strlen(zeexpression); if (newlen>ivar) { /* realloc bigger */ if (original) { expr=MemMalloc(lenw+newlen-ivar+1); memcpy(expr,zeexpression,lenw+1); zeexpression=expr; original=0; } else { zeexpression=MemRealloc(zeexpression,lenw+newlen-ivar+1); } } /* startvar? */ if (newlen!=ivar) { MemMove(zeexpression+startvar+newlen,zeexpression+startvar+ivar,lenw-startvar-ivar+1); } strncpy(zeexpression+startvar,ae->alias[ialias].translation,newlen); /* copy without zero terminator */ idx=startvar; ivar=0; continue; } else { /* index possible sur une struct? */ int reverse_idx,validx=-1; char *structlabel; reverse_idx=strlen(ae->computectx->varbuffer)-1; if (ae->computectx->varbuffer[reverse_idx]>='0' && ae->computectx->varbuffer[reverse_idx]<='9') { /* vu que ça ne PEUT PAS être une valeur litérale, on ne fait pas de test de débordement */ reverse_idx--; while (ae->computectx->varbuffer[reverse_idx]>='0' && ae->computectx->varbuffer[reverse_idx]<='9') { reverse_idx--; } reverse_idx++; validx=atoi(ae->computectx->varbuffer+reverse_idx); structlabel=TxtStrDup(ae->computectx->varbuffer+minusptr); structlabel[reverse_idx-minusptr]=0; #ifdef TRACE_STRUCT printf("EVOL 119 -> looking for struct %s IDX=%d\n",structlabel,validx); #endif /* unoptimized search in structures aliases */ crc=GetCRC(structlabel); for (i=0;iirasmstructalias;i++) { if (ae->rasmstructalias[i].crc==crc && strcmp(ae->rasmstructalias[i].name,structlabel)==0) { #ifdef TRACE_STRUCT printf("EVOL 119 -> found! ptr=%d size=%d\n",ae->rasmstructalias[i].ptr,ae->rasmstructalias[i].size); #endif curval=ae->rasmstructalias[i].size*validx+ae->rasmstructalias[i].ptr; if (validx>=ae->rasmstructalias[i].nbelem) { if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: index out of array size!\n",GetExpFile(ae,didx),GetExpLine(ae,didx)); } break; } } if (i==ae->irasmstructalias) { /* not found */ validx=-1; } MemFree(structlabel); } if (validx<0) { /* last chance to get a keyword */ if (strcmp(ae->computectx->varbuffer+minusptr,"REPEAT_COUNTER")==0) { if (ae->ir) { curval=ae->repeat[ae->ir-1].repeat_counter; } else { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"cannot use REPEAT_COUNTER keyword outside a repeat loop\n"); curval=0; } } else if (strcmp(ae->computectx->varbuffer+minusptr,"WHILE_COUNTER")==0) { if (ae->iw) { curval=ae->whilewend[ae->iw-1].while_counter; } else { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"cannot use WHILE_COUNTER keyword outside a while loop\n"); curval=0; } } else { /* in case the expression is a register */ if (IsRegister(ae->computectx->varbuffer+minusptr)) { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"cannot use register %s in this context\n",TradExpression(zeexpression)); } else { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] keyword [%s] not found in variables, labels or aliases\n",TradExpression(zeexpression),ae->computectx->varbuffer+minusptr); if (ae->extended_error) { char *lookstr; lookstr=StringLooksLike(ae,ae->computectx->varbuffer+minusptr); if (lookstr) { rasm_printf(ae,KERROR" did you mean [%s] ?\n",lookstr); } } } curval=0; } } } } } } } } if (minusptr) curval=-curval; stackelement.operator=E_COMPUTE_OPERATION_PUSH_DATASTC; stackelement.value=curval; /* priority isn't used */ allow_minus_as_sign=0; ivar=0; } /************************************ C R E A T E T O K E N ************************************/ ObjectArrayAddDynamicValueConcat((void **)&ae->computectx->tokenstack,&nbtokenstack,&ae->computectx->maxtokenstack,&stackelement,sizeof(stackelement)); } /******************************************************* C R E A T E E X E C U T I O N S T A C K *******************************************************/ #define DEBUG_STACK 0 #if DEBUG_STACK for (itoken=0;itokencomputectx->tokenstack[itoken].operator) { case E_COMPUTE_OPERATION_PUSH_DATASTC:printf("%lf ",ae->computectx->tokenstack[itoken].value);break; case E_COMPUTE_OPERATION_OPEN:printf("(");break; case E_COMPUTE_OPERATION_CLOSE:printf(")");break; case E_COMPUTE_OPERATION_ADD:printf("+ ");break; case E_COMPUTE_OPERATION_SUB:printf("- ");break; case E_COMPUTE_OPERATION_DIV:printf("/ ");break; case E_COMPUTE_OPERATION_MUL:printf("* ");break; case E_COMPUTE_OPERATION_AND:printf("and ");break; case E_COMPUTE_OPERATION_OR:printf("or ");break; case E_COMPUTE_OPERATION_MOD:printf("mod ");break; case E_COMPUTE_OPERATION_XOR:printf("xor ");break; case E_COMPUTE_OPERATION_NOT:printf("! ");break; case E_COMPUTE_OPERATION_SHL:printf("<< ");break; case E_COMPUTE_OPERATION_SHR:printf(">> ");break; case E_COMPUTE_OPERATION_BAND:printf("&& ");break; case E_COMPUTE_OPERATION_BOR:printf("|| ");break; case E_COMPUTE_OPERATION_LOWER:printf("< ");break; case E_COMPUTE_OPERATION_GREATER:printf("> ");break; case E_COMPUTE_OPERATION_EQUAL:printf("== ");break; case E_COMPUTE_OPERATION_NOTEQUAL:printf("!= ");break; case E_COMPUTE_OPERATION_LOWEREQ:printf("<= ");break; case E_COMPUTE_OPERATION_GREATEREQ:printf(">= ");break; case E_COMPUTE_OPERATION_SIN:printf("sin ");break; case E_COMPUTE_OPERATION_COS:printf("cos ");break; case E_COMPUTE_OPERATION_INT:printf("int ");break; case E_COMPUTE_OPERATION_FLOOR:printf("floor ");break; case E_COMPUTE_OPERATION_ABS:printf("abs ");break; case E_COMPUTE_OPERATION_LN:printf("ln ");break; case E_COMPUTE_OPERATION_LOG10:printf("log10 ");break; case E_COMPUTE_OPERATION_SQRT:printf("sqrt ");break; case E_COMPUTE_OPERATION_ASIN:printf("asin ");break; case E_COMPUTE_OPERATION_ACOS:printf("acos ");break; case E_COMPUTE_OPERATION_ATAN:printf("atan ");break; case E_COMPUTE_OPERATION_EXP:printf("exp ");break; case E_COMPUTE_OPERATION_LOW:printf("low ");break; case E_COMPUTE_OPERATION_HIGH:printf("high ");break; case E_COMPUTE_OPERATION_PSG:printf("psg ");break; case E_COMPUTE_OPERATION_RND:printf("rnd ");break; case E_COMPUTE_OPERATION_FRAC:printf("frac ");break; case E_COMPUTE_OPERATION_CEIL:printf("ceil ");break; case E_COMPUTE_OPERATION_GET_R:printf("get_r ");break; case E_COMPUTE_OPERATION_GET_V:printf("get_v ");break; case E_COMPUTE_OPERATION_GET_B:printf("get_b ");break; case E_COMPUTE_OPERATION_SET_R:printf("set_r ");break; case E_COMPUTE_OPERATION_SET_V:printf("set_v ");break; case E_COMPUTE_OPERATION_SET_B:printf("set_b ");break; default:printf("bug\n");break; } } printf("\n"); #endif for (itoken=0;itokencomputectx->tokenstack[itoken].operator) { case E_COMPUTE_OPERATION_PUSH_DATASTC: #if DEBUG_STACK printf("data\n"); #endif ObjectArrayAddDynamicValueConcat((void **)&computestack,&nbcomputestack,&maxcomputestack,&ae->computectx->tokenstack[itoken],sizeof(stackelement)); break; case E_COMPUTE_OPERATION_OPEN: ObjectArrayAddDynamicValueConcat((void **)&ae->computectx->operatorstack,&nboperatorstack,&ae->computectx->maxoperatorstack,&ae->computectx->tokenstack[itoken],sizeof(stackelement)); #if DEBUG_STACK printf("ajout (\n"); #endif break; case E_COMPUTE_OPERATION_CLOSE: #if DEBUG_STACK printf("close\n"); #endif /* pop out token until the opened parenthesis is reached */ o2=nboperatorstack-1; okclose=0; while (o2>=0) { if (ae->computectx->operatorstack[o2].operator!=E_COMPUTE_OPERATION_OPEN) { ObjectArrayAddDynamicValueConcat((void **)&computestack,&nbcomputestack,&maxcomputestack,&ae->computectx->operatorstack[o2],sizeof(stackelement)); nboperatorstack--; #if DEBUG_STACK printf("op--\n"); #endif o2--; } else { /* discard opening parenthesis as operator */ #if DEBUG_STACK printf("discard )\n"); #endif nboperatorstack--; okclose=1; o2--; break; } } if (!okclose) { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"missing parenthesis [%s]\n",TradExpression(zeexpression)); if (!original) { MemFree(zeexpression); } return 0; } /* if upper token is a function then pop from the stack */ if (o2>=0 && ae->computectx->operatorstack[o2].operator>=E_COMPUTE_OPERATION_SIN) { ObjectArrayAddDynamicValueConcat((void **)&computestack,&nbcomputestack,&maxcomputestack,&ae->computectx->operatorstack[o2],sizeof(stackelement)); nboperatorstack--; #if DEBUG_STACK printf("pop function\n"); #endif } break; case E_COMPUTE_OPERATION_ADD: case E_COMPUTE_OPERATION_SUB: case E_COMPUTE_OPERATION_DIV: case E_COMPUTE_OPERATION_MUL: case E_COMPUTE_OPERATION_AND: case E_COMPUTE_OPERATION_OR: case E_COMPUTE_OPERATION_MOD: case E_COMPUTE_OPERATION_XOR: case E_COMPUTE_OPERATION_NOT: case E_COMPUTE_OPERATION_SHL: case E_COMPUTE_OPERATION_SHR: case E_COMPUTE_OPERATION_BAND: case E_COMPUTE_OPERATION_BOR: case E_COMPUTE_OPERATION_LOWER: case E_COMPUTE_OPERATION_GREATER: case E_COMPUTE_OPERATION_EQUAL: case E_COMPUTE_OPERATION_NOTEQUAL: case E_COMPUTE_OPERATION_LOWEREQ: case E_COMPUTE_OPERATION_GREATEREQ: #if DEBUG_STACK printf("operator\n"); #endif o2=nboperatorstack-1; while (o2>=0 && ae->computectx->operatorstack[o2].operator!=E_COMPUTE_OPERATION_OPEN) { if (ae->computectx->tokenstack[itoken].priority>=ae->computectx->operatorstack[o2].priority || ae->computectx->operatorstack[o2].operator>=E_COMPUTE_OPERATION_SIN) { ObjectArrayAddDynamicValueConcat((void **)&computestack,&nbcomputestack,&maxcomputestack,&ae->computectx->operatorstack[o2],sizeof(stackelement)); nboperatorstack--; o2--; } else { break; } } ObjectArrayAddDynamicValueConcat((void **)&ae->computectx->operatorstack,&nboperatorstack,&ae->computectx->maxoperatorstack,&ae->computectx->tokenstack[itoken],sizeof(stackelement)); break; case E_COMPUTE_OPERATION_SIN: case E_COMPUTE_OPERATION_COS: case E_COMPUTE_OPERATION_INT: case E_COMPUTE_OPERATION_FLOOR: case E_COMPUTE_OPERATION_ABS: case E_COMPUTE_OPERATION_LN: case E_COMPUTE_OPERATION_LOG10: case E_COMPUTE_OPERATION_SQRT: case E_COMPUTE_OPERATION_ASIN: case E_COMPUTE_OPERATION_ACOS: case E_COMPUTE_OPERATION_ATAN: case E_COMPUTE_OPERATION_EXP: case E_COMPUTE_OPERATION_LOW: case E_COMPUTE_OPERATION_HIGH: case E_COMPUTE_OPERATION_PSG: case E_COMPUTE_OPERATION_RND: case E_COMPUTE_OPERATION_FRAC: case E_COMPUTE_OPERATION_CEIL: case E_COMPUTE_OPERATION_GET_R: case E_COMPUTE_OPERATION_GET_V: case E_COMPUTE_OPERATION_GET_B: case E_COMPUTE_OPERATION_SET_R: case E_COMPUTE_OPERATION_SET_V: case E_COMPUTE_OPERATION_SET_B: #if DEBUG_STACK printf("ajout de la fonction\n"); #endif ObjectArrayAddDynamicValueConcat((void **)&ae->computectx->operatorstack,&nboperatorstack,&ae->computectx->maxoperatorstack,&ae->computectx->tokenstack[itoken],sizeof(stackelement)); break; default:break; } } /* pop remaining operators */ while (nboperatorstack>0) { ObjectArrayAddDynamicValueConcat((void **)&computestack,&nbcomputestack,&maxcomputestack,&ae->computectx->operatorstack[--nboperatorstack],sizeof(stackelement)); } /******************************************** E X E C U T E S T A C K ********************************************/ if (ae->maxam || ae->as80) { int workinterval; if (ae->as80) workinterval=0xFFFFFFFF; else workinterval=0xFFFF; for (i=0;i1) accu[paccu-2]=((int)accu[paccu-2]+(int)accu[paccu-1])&workinterval;paccu--;break; case E_COMPUTE_OPERATION_SUB:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2]-(int)accu[paccu-1])&workinterval;paccu--;break; case E_COMPUTE_OPERATION_MUL:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2]*(int)accu[paccu-1])&workinterval;paccu--;break; case E_COMPUTE_OPERATION_DIV:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2]/(int)accu[paccu-1])&workinterval;paccu--;break; case E_COMPUTE_OPERATION_AND:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2]&(int)accu[paccu-1])&workinterval;paccu--;break; case E_COMPUTE_OPERATION_OR:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2]|(int)accu[paccu-1])&workinterval;paccu--;break; case E_COMPUTE_OPERATION_XOR:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2]^(int)accu[paccu-1])&workinterval;paccu--;break; case E_COMPUTE_OPERATION_MOD:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2]%(int)accu[paccu-1])&workinterval;paccu--;break; case E_COMPUTE_OPERATION_SHL:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2])<<((int)accu[paccu-1]); if (((int)accu[paccu-1])>31 || ((int)accu[paccu-1])<-31) { if (!ae->nowarning) { rasm_printf(ae,KWARNING"Warning - shifting %d is architecture dependant, result forced to ZERO\n",(int)accu[paccu-1]); } accu[paccu-2]=0; } paccu--;break; case E_COMPUTE_OPERATION_SHR:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2])>>((int)accu[paccu-1]); if (((int)accu[paccu-1])>31 || ((int)accu[paccu-1])<-31) { if (!ae->nowarning) { rasm_printf(ae,KWARNING"Warning - shifting %d is architecture dependant, result forced to ZERO\n",(int)accu[paccu-1]); } accu[paccu-2]=0; } paccu--;break; case E_COMPUTE_OPERATION_BAND:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2]&&(int)accu[paccu-1])&workinterval;paccu--;break; case E_COMPUTE_OPERATION_BOR:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2]||(int)accu[paccu-1])&workinterval;paccu--;break; /* comparison */ case E_COMPUTE_OPERATION_LOWER:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2]&workinterval)<((int)accu[paccu-1]&workinterval);paccu--;break; case E_COMPUTE_OPERATION_LOWEREQ:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2]&workinterval)<=((int)accu[paccu-1]&workinterval);paccu--;break; case E_COMPUTE_OPERATION_EQUAL:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2]&workinterval)==((int)accu[paccu-1]&workinterval);paccu--;break; case E_COMPUTE_OPERATION_NOTEQUAL:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2]&workinterval)!=((int)accu[paccu-1]&workinterval);paccu--;break; case E_COMPUTE_OPERATION_GREATER:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2]&workinterval)>((int)accu[paccu-1]&workinterval);paccu--;break; case E_COMPUTE_OPERATION_GREATEREQ:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2]&workinterval)>=((int)accu[paccu-1]&workinterval);paccu--;break; /* functions */ case E_COMPUTE_OPERATION_SIN:if (paccu>0) accu[paccu-1]=(int)sin(accu[paccu-1]*3.1415926545/180.0);break; case E_COMPUTE_OPERATION_COS:if (paccu>0) accu[paccu-1]=(int)cos(accu[paccu-1]*3.1415926545/180.0);break; case E_COMPUTE_OPERATION_ASIN:if (paccu>0) accu[paccu-1]=(int)asin(accu[paccu-1])*180.0/3.1415926545;break; case E_COMPUTE_OPERATION_ACOS:if (paccu>0) accu[paccu-1]=(int)acos(accu[paccu-1])*180.0/3.1415926545;break; case E_COMPUTE_OPERATION_ATAN:if (paccu>0) accu[paccu-1]=(int)atan(accu[paccu-1])*180.0/3.1415926545;break; case E_COMPUTE_OPERATION_INT:break; case E_COMPUTE_OPERATION_FLOOR:if (paccu>0) accu[paccu-1]=(int)floor(accu[paccu-1])&workinterval;break; case E_COMPUTE_OPERATION_ABS:if (paccu>0) accu[paccu-1]=(int)fabs(accu[paccu-1])&workinterval;break; case E_COMPUTE_OPERATION_EXP:if (paccu>0) accu[paccu-1]=(int)exp(accu[paccu-1])&workinterval;break; case E_COMPUTE_OPERATION_LN:if (paccu>0) accu[paccu-1]=(int)log(accu[paccu-1])&workinterval;break; case E_COMPUTE_OPERATION_LOG10:if (paccu>0) accu[paccu-1]=(int)log10(accu[paccu-1])&workinterval;break; case E_COMPUTE_OPERATION_SQRT:if (paccu>0) accu[paccu-1]=(int)sqrt(accu[paccu-1])&workinterval;break; case E_COMPUTE_OPERATION_LOW:if (paccu>0) accu[paccu-1]=((int)accu[paccu-1])&0xFF;break; case E_COMPUTE_OPERATION_HIGH:if (paccu>0) accu[paccu-1]=(((int)accu[paccu-1])&0xFF00)>>8;break; case E_COMPUTE_OPERATION_PSG:if (paccu>0) accu[paccu-1]=ae->psgfine[((int)accu[paccu-1])&0xFF];break; case E_COMPUTE_OPERATION_RND:if (paccu>0) accu[paccu-1]=rand()%((int)accu[paccu-1]);break; case E_COMPUTE_OPERATION_FRAC:if (paccu>0) accu[paccu-1]=((int)(accu[paccu-1]-(int)accu[paccu-1]));break; case E_COMPUTE_OPERATION_CEIL:if (paccu>0) accu[paccu-1]=(int)ceil(accu[paccu-1])&workinterval;break; case E_COMPUTE_OPERATION_GET_R:if (paccu>0) accu[paccu-1]=((((int)accu[paccu-1])&0xF0)>>4);break; case E_COMPUTE_OPERATION_GET_V:if (paccu>0) accu[paccu-1]=((((int)accu[paccu-1])&0xF00)>>8);break; case E_COMPUTE_OPERATION_GET_B:if (paccu>0) accu[paccu-1]=(((int)accu[paccu-1])&0xF);break; case E_COMPUTE_OPERATION_SET_R:if (paccu>0) accu[paccu-1]=MinMaxInt(accu[paccu-1],0,15)<<4;break; case E_COMPUTE_OPERATION_SET_V:if (paccu>0) accu[paccu-1]=MinMaxInt(accu[paccu-1],0,15)<<8;break; case E_COMPUTE_OPERATION_SET_B:if (paccu>0) accu[paccu-1]=MinMaxInt(accu[paccu-1],0,15);break; default:MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"invalid computing state! (%d)\n",GetExpFile(ae,didx),GetExpLine(ae,didx),computestack[i].operator);paccu=0; } if (!paccu) { if (zeexpression[0]=='&') { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"Missing operand for calculation [%s] Did you use & for an hexadecimal value?\n",TradExpression(zeexpression)); } else { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"Missing operand for calculation [%s]\n",TradExpression(zeexpression)); } accu_err=1; break; } } } else { for (i=0;i>": computestack[i].operator==E_COMPUTE_OPERATION_LOWER?"<": computestack[i].operator==E_COMPUTE_OPERATION_GREATER?">": computestack[i].operator==E_COMPUTE_OPERATION_EQUAL?"==": computestack[i].operator==E_COMPUTE_OPERATION_INT?"INT": computestack[i].operator==E_COMPUTE_OPERATION_LOWEREQ?"<=": computestack[i].operator==E_COMPUTE_OPERATION_GREATEREQ?">=": computestack[i].operator==E_COMPUTE_OPERATION_OPEN?"(": computestack[i].operator==E_COMPUTE_OPERATION_CLOSE?")": "",computestack[i].priority); } #endif switch (computestack[i].operator) { case E_COMPUTE_OPERATION_PUSH_DATASTC: if (maccu<=paccu) { maccu=16+paccu; accu=MemRealloc(accu,sizeof(double)*maccu); } accu[paccu]=computestack[i].value;paccu++; break; case E_COMPUTE_OPERATION_OPEN: case E_COMPUTE_OPERATION_CLOSE: /* cannot happend */ break; case E_COMPUTE_OPERATION_ADD:if (paccu>1) accu[paccu-2]+=accu[paccu-1];paccu--;break; case E_COMPUTE_OPERATION_SUB:if (paccu>1) accu[paccu-2]-=accu[paccu-1];paccu--;break; case E_COMPUTE_OPERATION_MUL:if (paccu>1) accu[paccu-2]*=accu[paccu-1];paccu--;break; case E_COMPUTE_OPERATION_DIV:if (paccu>1) accu[paccu-2]/=accu[paccu-1];paccu--;break; case E_COMPUTE_OPERATION_AND:if (paccu>1) accu[paccu-2]=((int)floor(accu[paccu-2]+0.5))&((int)floor(accu[paccu-1]+0.5));paccu--;break; case E_COMPUTE_OPERATION_OR:if (paccu>1) accu[paccu-2]=((int)floor(accu[paccu-2]+0.5))|((int)floor(accu[paccu-1]+0.5));paccu--;break; case E_COMPUTE_OPERATION_XOR:if (paccu>1) accu[paccu-2]=((int)floor(accu[paccu-2]+0.5))^((int)floor(accu[paccu-1]+0.5));paccu--;break; case E_COMPUTE_OPERATION_NOT:/* half operator, half function */ if (paccu>0) accu[paccu-1]=!((int)floor(accu[paccu-1]+0.5));break; case E_COMPUTE_OPERATION_MOD:if (paccu>1) accu[paccu-2]=((int)floor(accu[paccu-2]+0.5))%((int)floor(accu[paccu-1]+0.5));paccu--;break; case E_COMPUTE_OPERATION_SHL:if (paccu>1) accu[paccu-2]=((int)floor(accu[paccu-2]+0.5))<<((int)floor(accu[paccu-1]+0.5)); if (((int)accu[paccu-1])>31 || ((int)accu[paccu-1])<-31) { if (!ae->nowarning) { rasm_printf(ae,KWARNING"Warning - shifting %d is architecture dependant, result forced to ZERO\n",(int)accu[paccu-1]); } accu[paccu-2]=0; } paccu--;break; case E_COMPUTE_OPERATION_SHR:if (paccu>1) accu[paccu-2]=((int)floor(accu[paccu-2]+0.5))>>((int)floor(accu[paccu-1]+0.5)); if (((int)accu[paccu-1])>31 || ((int)accu[paccu-1])<-31) { if (!ae->nowarning) { rasm_printf(ae,KWARNING"Warning - shifting %d is architecture dependant, result forced to ZERO\n",(int)accu[paccu-1]); } accu[paccu-2]=0; } paccu--;break; case E_COMPUTE_OPERATION_BAND:if (paccu>1) accu[paccu-2]=((int)floor(accu[paccu-2]+0.5))&&((int)floor(accu[paccu-1]+0.5));paccu--;break; case E_COMPUTE_OPERATION_BOR:if (paccu>1) accu[paccu-2]=((int)floor(accu[paccu-2]+0.5))||((int)floor(accu[paccu-1]+0.5));paccu--;break; /* comparison */ case E_COMPUTE_OPERATION_LOWER:if (paccu>1) accu[paccu-2]=accu[paccu-2]1) accu[paccu-2]=accu[paccu-2]<=accu[paccu-1];paccu--;break; case E_COMPUTE_OPERATION_EQUAL:if (paccu>1) accu[paccu-2]=fabs(accu[paccu-2]-accu[paccu-1])<0.000001;paccu--;break; case E_COMPUTE_OPERATION_NOTEQUAL:if (paccu>1) accu[paccu-2]=accu[paccu-2]!=accu[paccu-1];paccu--;break; case E_COMPUTE_OPERATION_GREATER:if (paccu>1) accu[paccu-2]=accu[paccu-2]>accu[paccu-1];paccu--;break; case E_COMPUTE_OPERATION_GREATEREQ:if (paccu>1) accu[paccu-2]=accu[paccu-2]>=accu[paccu-1];paccu--;break; /* functions */ case E_COMPUTE_OPERATION_SIN:if (paccu>0) accu[paccu-1]=sin(accu[paccu-1]*3.1415926545/180.0);break; case E_COMPUTE_OPERATION_COS:if (paccu>0) accu[paccu-1]=cos(accu[paccu-1]*3.1415926545/180.0);break; case E_COMPUTE_OPERATION_ASIN:if (paccu>0) accu[paccu-1]=asin(accu[paccu-1])*180.0/3.1415926545;break; case E_COMPUTE_OPERATION_ACOS:if (paccu>0) accu[paccu-1]=acos(accu[paccu-1])*180.0/3.1415926545;break; case E_COMPUTE_OPERATION_ATAN:if (paccu>0) accu[paccu-1]=atan(accu[paccu-1])*180.0/3.1415926545;break; case E_COMPUTE_OPERATION_INT:if (paccu>0) accu[paccu-1]=floor(accu[paccu-1]+0.5);break; case E_COMPUTE_OPERATION_FLOOR:if (paccu>0) accu[paccu-1]=floor(accu[paccu-1]);break; case E_COMPUTE_OPERATION_ABS:if (paccu>0) accu[paccu-1]=fabs(accu[paccu-1]);break; case E_COMPUTE_OPERATION_EXP:if (paccu>0) accu[paccu-1]=exp(accu[paccu-1]);break; case E_COMPUTE_OPERATION_LN:if (paccu>0) accu[paccu-1]=log(accu[paccu-1]);break; case E_COMPUTE_OPERATION_LOG10:if (paccu>0) accu[paccu-1]=log10(accu[paccu-1]);break; case E_COMPUTE_OPERATION_SQRT:if (paccu>0) accu[paccu-1]=sqrt(accu[paccu-1]);break; case E_COMPUTE_OPERATION_LOW:if (paccu>0) accu[paccu-1]=((int)floor(accu[paccu-1]+0.5))&0xFF;break; case E_COMPUTE_OPERATION_HIGH:if (paccu>0) accu[paccu-1]=(((int)floor(accu[paccu-1]+0.5))&0xFF00)>>8;break; case E_COMPUTE_OPERATION_PSG:if (paccu>0) accu[paccu-1]=ae->psgfine[((int)floor(accu[paccu-1]+0.5))&0xFF];break; case E_COMPUTE_OPERATION_RND:if (paccu>0) accu[paccu-1]=rand()%((int)accu[paccu-1]);break; case E_COMPUTE_OPERATION_FRAC:if (paccu>0) accu[paccu-1]=modf(accu[paccu-1],&dummint);break; case E_COMPUTE_OPERATION_CEIL:if (paccu>0) accu[paccu-1]=ceil(accu[paccu-1]);break; case E_COMPUTE_OPERATION_GET_R:if (paccu>0) accu[paccu-1]=((((int)accu[paccu-1])&0xF0)>>4);break; case E_COMPUTE_OPERATION_GET_V:if (paccu>0) accu[paccu-1]=((((int)accu[paccu-1])&0xF00)>>8);break; case E_COMPUTE_OPERATION_GET_B:if (paccu>0) accu[paccu-1]=(((int)accu[paccu-1])&0xF);break; case E_COMPUTE_OPERATION_SET_R:if (paccu>0) accu[paccu-1]=MinMaxInt(accu[paccu-1],0,15)<<4;break; case E_COMPUTE_OPERATION_SET_V:if (paccu>0) accu[paccu-1]=MinMaxInt(accu[paccu-1],0,15)<<8;break; case E_COMPUTE_OPERATION_SET_B:if (paccu>0) accu[paccu-1]=MinMaxInt(accu[paccu-1],0,15);break; default:MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"invalid computing state! (%d)\n",GetExpFile(ae,didx),GetExpLine(ae,didx),computestack[i].operator);paccu=0; } if (!paccu) { if (zeexpression[0]=='&') { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"Missing operand for calculation [%s] Did you use & for an hexadecimal value?\n",TradExpression(zeexpression)); } else { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"Missing operand for calculation [%s]\n",TradExpression(zeexpression)); } accu_err=1; break; } } } if (!original) { MemFree(zeexpression); } if (paccu==1) { return accu[0]; } else if (!accu_err) { if (paccu) { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"Missing operator\n"); } else { MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"Missing operand for calculation\n"); } return 0; } else { return 0; } } int RoundComputeExpressionCore(struct s_assenv *ae,char *zeexpression,int ptr,int didx) { return floor(ComputeExpressionCore(ae,zeexpression,ptr,didx)+ae->rough); } void ExpressionSetDicoVar(struct s_assenv *ae,char *name, double v) { #undef FUNC #define FUNC "ExpressionSetDicoVar" struct s_expr_dico curdic; curdic.name=TxtStrDup(name); curdic.crc=GetCRC(name); curdic.v=v; curdic.iw=ae->idx; curdic.autorise_export=ae->autorise_export; //ObjectArrayAddDynamicValueConcat((void**)&ae->dico,&ae->idic,&ae->mdic,&curdic,sizeof(curdic)); if (SearchLabel(ae,curdic.name,curdic.crc)) { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"cannot create variable [%s] as there is already a label with the same name\n",name); MemFree(curdic.name); return; } InsertDicoToTree(ae,&curdic); } double ComputeExpression(struct s_assenv *ae,char *expr, int ptr, int didx, int expected_eval) { #undef FUNC #define FUNC "ComputeExpression" char *ptr_exp,*ptr_exp2,backupeval; int crc,idic,idx=0,ialias,touched,hasformula=0; double v,vl; struct s_alias curalias; struct s_expr_dico *curdic; char *minibuffer; while (!ae->AutomateExpressionDecision[((int)expr[idx])&0xFF]) idx++; switch (ae->AutomateExpressionDecision[((int)expr[idx])&0xFF]) { /***************************************** M A K E A L I A S *****************************************/ case '~': memset(&curalias,0,sizeof(curalias)); ptr_exp=expr+idx; *ptr_exp=0; // on scinde l'alias de son texte ptr_exp2=ptr_exp+1; #if TRACE_COMPUTE_EXPRESSION printf("MakeAlias (1) EXPR=[%s EQU %s]\n",expr,ptr_exp2); #endif /* alias locaux ou de proximité */ if (strchr("@.",expr[0])) { #if TRACE_COMPUTE_EXPRESSION printf("WARNING! alias is local! [%s]\n",expr); #endif /* local label creation does not handle formula in tags */ curalias.alias=TranslateTag(ae,TxtStrDup(expr),&touched,0,E_TAGOPTION_NONE); curalias.alias=MakeLocalLabel(ae,curalias.alias,NULL); hasformula=1; } else if (strchr(expr,'{')) { #if TRACE_COMPUTE_EXPRESSION printf("WARNING! alias has tag! [%s]\n",expr); #endif /* alias name contains formula */ curalias.alias=TranslateTag(ae,TxtStrDup(expr),&touched,0,E_TAGOPTION_NONE); #if TRACE_COMPUTE_EXPRESSION printf("MakeAlias (2) EXPR=[%s EQU %s]\n",expr,ptr_exp2); #endif hasformula=1; } else { curalias.alias=TxtStrDup(expr); } curalias.crc=GetCRC(curalias.alias); if ((ialias=SearchAlias(ae,curalias.crc,curalias.alias))>=0) { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"Duplicate alias [%s]\n",expr); MemFree(curalias.alias); } else if (SearchDico(ae,curalias.alias,curalias.crc)) { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"Alias cannot override existing variable [%s]\n",expr); MemFree(curalias.alias); } else { curalias.translation=MemMalloc(strlen(ptr_exp2)+1+2); sprintf(curalias.translation,"(%s)",ptr_exp2); #if TRACE_COMPUTE_EXPRESSION printf("MakeAlias (3) EXPR=[%s EQU %s]\n",expr,ptr_exp2); printf("alias translation [%s] -> ",curalias.translation);fflush(stdout); #endif ExpressionFastTranslate(ae,&curalias.translation,2); // FAST type 2 #if TRACE_COMPUTE_EXPRESSION printf("%s\n",curalias.translation); #endif curalias.len=strlen(curalias.translation); curalias.autorise_export=ae->autorise_export; curalias.iw=ae->idx; ObjectArrayAddDynamicValueConcat((void**)&ae->alias,&ae->ialias,&ae->malias,&curalias,sizeof(curalias)); CheckAndSortAliases(ae); } *ptr_exp='~'; // on remet l'alias en place #if TRACE_COMPUTE_EXPRESSION printf("MakeAlias end with alias=[%s]=[%s]\n",curalias.alias,curalias.translation); printf("***********\n"); #endif return 0; /***************************************** S E T V A R *****************************************/ case '=': /* patch NOT this is a variable assign if there is no other comparison operator after '=' BUT we may have ! which stand for NOT but is also a comparison operator... */ if (ae->AutomateExpressionDecision[((int)expr[idx+1])&0xFF]==0 || expr[idx+1]=='!') { if (expected_eval) { if (ae->maxam) { /* maxam mode AND expected a value -> force comparison */ } else { /* use of a single '=' but expected a comparison anyway */ MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"meaningless use of an expression [%s]\n",expr); return 0; } } else { /* ASSIGN */ if ((expr[0]<'A' || expr[0]>'Z') && expr[0]!='_') { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"variable name must begin by a letter or '_' [%s]\n",expr); return 0; } else { char operatorassignment; ptr_exp=expr+idx; v=ComputeExpressionCore(ae,ptr_exp+1,ptr,didx); *ptr_exp=0; /* patch operator+assign value */ switch (ptr_exp[-1]) { case '+': case '-': case '*': case '/': case '^': case '&': case '|': case '%': case ']': case '[': operatorassignment=ptr_exp[-1];ptr_exp[-1]=0;break; default:operatorassignment=0;break; } crc=GetCRC(expr); if ((ialias=SearchAlias(ae,crc,expr))>=0) { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"Variable cannot override existing alias [%s]\n",expr); return 0; } #if TRACE_ASSEMBLE printf("try to set [%s] with %lf operatorassignment=%c\n",expr,v,operatorassignment); #endif curdic=SearchDico(ae,expr,crc); if (curdic) { switch (operatorassignment) { default:printf("warning remover\n"); case 0:curdic->v=v;break; case '+':curdic->v+=v;ptr_exp[-1]='+';break; case '-':curdic->v-=v;ptr_exp[-1]='-';break; case '*':curdic->v*=v;ptr_exp[-1]='*';break; case '/':curdic->v/=v;ptr_exp[-1]='/';break; /* bit operations */ case '|':curdic->v=((int)curdic->v)|((int)v);ptr_exp[-1]='|';break; case '&':curdic->v=((int)curdic->v)&((int)v);ptr_exp[-1]='&';break; case '^':curdic->v=((int)curdic->v)^((int)v);ptr_exp[-1]='^';break; case '%':curdic->v=((int)curdic->v)%((int)v);ptr_exp[-1]='%';break; case ']':curdic->v=((int)curdic->v)>>((int)v);ptr_exp[-1]=']'; if (v>31 || v<-31) { if (!ae->nowarning) { rasm_printf(ae,KWARNING"Warning - shifting %d is architecture dependant, result forced to ZERO\n",(int)v); } curdic->v=0; } break; case '[':curdic->v=((int)curdic->v)<<((int)v);ptr_exp[-1]='['; if (v>31 || v<-31) { if (!ae->nowarning) { rasm_printf(ae,KWARNING"Warning - shifting %d is architecture dependant, result forced to ZERO\n",(int)v); } curdic->v=0; } break; } } else { switch (operatorassignment) { default: /* cannot do operator on non existing variable */ MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"Cannot do an operator assignment on non existing variable [%s]\n",expr); return 0; case 0: /* assign a new variable */ ExpressionSetDicoVar(ae,expr,v); break; } } *ptr_exp='='; return v; } } } break; /***************************************** P U R E E X P R E S S I O N *****************************************/ default:break; } #if TRACE_ASSEMBLE printf("pure expression to compute [%s]\n",expr); #endif return ComputeExpressionCore(ae,expr,ptr,didx); } int RoundComputeExpression(struct s_assenv *ae,char *expr, int ptr, int didx, int expression_expected) { return floor(ComputeExpression(ae,expr,ptr,didx,expression_expected)+ae->rough); } /* ExpressionFastTranslate purpose: translate all known symbols in an expression (especially variables acting like counters) */ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullreplace) { #undef FUNC #define FUNC "ExpressionFastTranslate" struct s_label *curlabel; struct s_expr_dico *curdic; static char *varbuffer=NULL; static int ivar=0,maxivar=1; char curval[256]={0}; int c,lenw=0,idx=0,crc,startvar,newlen,ialias,found_replace,yves,dek,reidx,lenbuf,rlen,tagoffset; double v; char tmpuchar[16]; char *expr,*locallabel; int curly=0,curlyflag=0; char *Automate; int recurse=-1,recursecount=0; if (!ae || !ptr_expr) { if (varbuffer) MemFree(varbuffer); varbuffer=NULL; maxivar=1; ivar=0; return; } /* be sure to have at least some bytes allocated */ StateMachineResizeBuffer(&varbuffer,128,&maxivar); expr=*ptr_expr; //printf("fast [%s]\n",expr); while (!ae->AutomateExpressionDecision[((int)expr[idx])&0xFF]) idx++; switch (ae->maxam) { default: case 0: /* full check */ if (expr[idx]=='~' || (expr[idx]=='=' && expr[idx+1]!='=')) {reidx=idx+1;break;} reidx=0; break; case 1: /* partial check with maxam */ if (expr[idx]=='~') {reidx=idx+1;break;} reidx=0; break; } idx=0; /* is there ascii char? */ while ((c=expr[idx])!=0) { if (c=='\'' || c=='"') { /* echappement */ if (expr[idx+1]=='\\') { if (expr[idx+2] && expr[idx+3]==c) { /* no charset conversion for escaped chars */ c=expr[idx+2]; switch (c) { case 'b':c='\b';break; case 'v':c='\v';break; case 'f':c='\f';break; case '0':c='\0';break; case 'r':c='\r';break; case 'n':c='\n';break; case 't':c='\t';break; default:break; } sprintf(tmpuchar,"#%03X",c); memcpy(expr+idx,tmpuchar,4); idx+=3; } else { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"expression [%s] - Only single escaped char may be quoted\n",expr); expr[0]=0; return; } } else if (expr[idx+1] && expr[idx+2]==c) { sprintf(tmpuchar,"#%02X",ae->charset[(int)expr[idx+1]]); memcpy(expr+idx,tmpuchar,3); idx+=2; } else { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"expression [%s] - Only single char may be quoted\n",expr); expr[0]=0; return; } } idx++; } idx=reidx; while ((c=expr[idx])!=0) { switch (c) { /* operator / parenthesis */ case '!': case '=': case '>': case '<': case '(': case ')': case ']': case '[': case '*': case '/': case '+': case '~': case '-': case '^': case 'm': case '|': case '&': idx++; break; default: startvar=idx; if (ae->AutomateExpressionValidCharFirst[((int)c)&0xFF]) { varbuffer[ivar++]=c; if (c=='{') { /* this is only tag and not a formula */ curly++; } StateMachineResizeBuffer(&varbuffer,ivar,&maxivar); idx++; c=expr[idx]; Automate=ae->AutomateExpressionValidChar; while (Automate[((int)c)&0xFF]) { if (c=='{') { curly++; curlyflag=1; Automate=ae->AutomateExpressionValidCharExtended; } else if (c=='}') { curly--; if (!curly) { Automate=ae->AutomateExpressionValidChar; } } varbuffer[ivar++]=c; StateMachineResizeBuffer(&varbuffer,ivar,&maxivar); idx++; c=expr[idx]; } } varbuffer[ivar]=0; if (!ivar) { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"invalid expression [%s] c=[%c] idx=%d\n",expr,c,idx); return; } else if (curly) { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"wrong curly brackets in expression [%s]\n",expr); return; } } if (ivar && (varbuffer[0]<'0' || varbuffer[0]>'9')) { /* numbering var or label */ if (curlyflag) { char *minivarbuffer; int touched; //printf("ExpressionFastTranslate curly\n"); minivarbuffer=TranslateTag(ae,TxtStrDup(varbuffer), &touched,0,E_TAGOPTION_NONE|(fullreplace?0:E_TAGOPTION_PRESERVE)); StateMachineResizeBuffer(&varbuffer,strlen(minivarbuffer)+1,&maxivar); strcpy(varbuffer,minivarbuffer); newlen=strlen(varbuffer); lenw=strlen(expr); /* must update source */ if (newlen>ivar) { /* realloc bigger */ expr=*ptr_expr=MemRealloc(expr,lenw+newlen-ivar+1); } if (newlen!=ivar ) { lenw=strlen(expr); MemMove(expr+startvar+newlen,expr+startvar+ivar,lenw-startvar-ivar+1); } strncpy(expr+startvar,minivarbuffer,newlen); /* copy without zero terminator */ idx=startvar+newlen; /***/ MemFree(minivarbuffer); curlyflag=0; /******* ivar must be updated in case of label or alias following ***********/ ivar=newlen; } /* recherche dans dictionnaire et remplacement */ crc=GetCRC(varbuffer); found_replace=0; /* pour les affectations ou les tests conditionnels on ne remplace pas le dico (pour le Push oui par contre!) */ if (fullreplace) { if (varbuffer[0]=='$' && !varbuffer[1]) { #ifdef OS_WIN snprintf(curval,sizeof(curval)-1,"%d",ae->codeadr); newlen=strlen(curval); #else newlen=snprintf(curval,sizeof(curval)-1,"%d",ae->codeadr); #endif lenw=strlen(expr); if (newlen>ivar) { /* realloc bigger */ expr=*ptr_expr=MemRealloc(expr,lenw+newlen-ivar+1); } if (newlen!=ivar ) { MemMove(expr+startvar+newlen,expr+startvar+ivar,lenw-startvar-ivar+1); found_replace=1; } strncpy(expr+startvar,curval,newlen); /* copy without zero terminator */ idx=startvar+newlen; ivar=0; found_replace=1; } else { curdic=SearchDico(ae,varbuffer,crc); if (curdic) { v=curdic->v; //printf("ExpressionFastTranslate (full) -> replace var (%s=%0.1lf)\n",varbuffer,v); #ifdef OS_WIN snprintf(curval,sizeof(curval)-1,"%lf",v); newlen=TrimFloatingPointString(curval); #else snprintf(curval,sizeof(curval)-1,"%lf",v); newlen=TrimFloatingPointString(curval); #endif lenw=strlen(expr); if (newlen>ivar) { /* realloc bigger */ expr=*ptr_expr=MemRealloc(expr,lenw+newlen-ivar+1); } if (newlen!=ivar ) { MemMove(expr+startvar+newlen,expr+startvar+ivar,lenw-startvar-ivar+1); } strncpy(expr+startvar,curval,newlen); /* copy without zero terminator */ idx=startvar+newlen; ivar=0; found_replace=1; } } } /* on cherche aussi dans les labels existants */ if (!found_replace) { curlabel=SearchLabel(ae,varbuffer,crc); if (curlabel) { if (!curlabel->lz || ae->stage>1) { yves=curlabel->ptr; #ifdef OS_WIN snprintf(curval,sizeof(curval)-1,"%d",yves); newlen=strlen(curval); #else newlen=snprintf(curval,sizeof(curval)-1,"%d",yves); #endif lenw=strlen(expr); if (newlen>ivar) { /* realloc bigger */ expr=*ptr_expr=MemRealloc(expr,lenw+newlen-ivar+1); } if (newlen!=ivar ) { MemMove(expr+startvar+newlen,expr+startvar+ivar,lenw-startvar-ivar+1); } strncpy(expr+startvar,curval,newlen); /* copy without zero terminator */ found_replace=1; idx=startvar+newlen; ivar=0; } } } /* non trouve on cherche dans les alias */ if (!found_replace) { if ((ialias=SearchAlias(ae,crc,varbuffer))>=0) { newlen=ae->alias[ialias].len; lenw=strlen(expr); /* infinite replacement check */ if (recurse<=startvar) { /* recurse maximum count is a mix of alias len and alias number */ if (recursecount>ae->ialias+ae->alias[ialias].len) { if (strchr(expr,'~')!=NULL) *strchr(expr,'~')=0; MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"alias definition of %s has infinite recursivity\n",expr); expr[0]=0; /* avoid some errors due to shitty definition */ return; } else { recursecount++; } } if (newlen>ivar) { /* realloc bigger */ expr=*ptr_expr=MemRealloc(expr,lenw+newlen-ivar+1); } if (newlen!=ivar) { MemMove(expr+startvar+newlen,expr+startvar+ivar,lenw-startvar-ivar+1); } strncpy(expr+startvar,ae->alias[ialias].translation,newlen); /* copy without zero terminator */ found_replace=1; /* need to parse again alias because of delayed declarations */ recurse=startvar; idx=startvar; ivar=0; } else { } } if (!found_replace) { //printf("fasttranslate test local label\n"); /* non trouve c'est peut-etre un label local - mais pas de l'octal */ if (varbuffer[0]=='@' && (varbuffer[1]<'0' || varbuffer[1]>'9')) { char *zepoint; lenbuf=strlen(varbuffer); //printf("MakeLocalLabel(ae,varbuffer,&dek); (1)\n"); locallabel=MakeLocalLabel(ae,varbuffer,&dek); //printf("exprin =[%s] rlen=%d dek-lenbuf=%d\n",expr,rlen,dek-lenbuf); /*** le grand remplacement ***/ /* local to macro or loop */ rlen=strlen(expr+startvar+lenbuf)+1; expr=*ptr_expr=MemRealloc(expr,strlen(expr)+dek+1); /* move end of expression in order to insert local ID */ zepoint=strchr(varbuffer,'.'); if (zepoint) { /* far proximity access */ int suffixlen,dotpos; dotpos=(zepoint-varbuffer); suffixlen=lenbuf-dotpos; MemMove(expr+startvar+dotpos+dek,expr+startvar+dotpos,rlen+suffixlen); strncpy(expr+startvar+dotpos,locallabel,dek); } else { /* legacy */ MemMove(expr+startvar+lenbuf+dek,expr+startvar+lenbuf,rlen); strncpy(expr+startvar+lenbuf,locallabel,dek); } idx+=dek; MemFree(locallabel); found_replace=1; //printf("exprout=[%s]\n",expr); } else if (varbuffer[0]=='.' && (varbuffer[1]<'0' || varbuffer[1]>'9')) { /* proximity label */ lenbuf=strlen(varbuffer); //printf("MakeLocalLabel(ae,varbuffer,&dek); (2)\n"); locallabel=MakeLocalLabel(ae,varbuffer,&dek); /*** le grand remplacement ***/ rlen=strlen(expr+startvar+lenbuf)+1; dek=strlen(locallabel); //printf("exprin =[%s] rlen=%d dek-lenbuf=%d\n",expr,rlen,dek-lenbuf); expr=*ptr_expr=MemRealloc(expr,strlen(expr)+dek-lenbuf+1); MemMove(expr+startvar+dek,expr+startvar+lenbuf,rlen); strncpy(expr+startvar,locallabel,dek); idx+=dek-lenbuf; MemFree(locallabel); //printf("exprout=[%s]\n",expr); //@@TODO ajouter une recherche d'alias? } else if (varbuffer[0]=='{') { if (strncmp(varbuffer,"{BANK}",6)==0 || strncmp(varbuffer,"{PAGE}",6)==0) tagoffset=6; else if (strncmp(varbuffer,"{PAGESET}",9)==0) tagoffset=9; else if (strncmp(varbuffer,"{SIZEOF}",8)==0) tagoffset=8; else { tagoffset=0; MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"Unknown prefix tag\n"); } if (varbuffer[tagoffset]=='@') { char *zepoint; startvar+=tagoffset; lenbuf=strlen(varbuffer+tagoffset); //printf("MakeLocalLabel(ae,varbuffer,&dek); (3)\n"); locallabel=MakeLocalLabel(ae,varbuffer+tagoffset,&dek); /*** le grand remplacement ***/ rlen=strlen(expr+startvar+lenbuf)+1; expr=*ptr_expr=MemRealloc(expr,strlen(expr)+dek+1); /* move end of expression in order to insert local ID */ zepoint=strchr(varbuffer,'.'); if (zepoint) { /* far proximity access */ int suffixlen,dotpos; dotpos=(zepoint-varbuffer); suffixlen=lenbuf-dotpos; MemMove(expr+startvar+dotpos+dek,expr+startvar+dotpos,rlen+suffixlen); strncpy(expr+startvar+dotpos,locallabel,dek); } else { /* legacy */ MemMove(expr+startvar+lenbuf+dek,expr+startvar+lenbuf,rlen); strncpy(expr+startvar+lenbuf,locallabel,dek); } idx+=dek; MemFree(locallabel); found_replace=1; } else if (varbuffer[tagoffset]=='$') { int tagvalue=-1; if (strcmp(varbuffer,"{BANK}$")==0) { if (ae->forcecpr) { if (ae->activebank<32) { tagvalue=ae->activebank; } else { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"expression [%s] cannot use BANK $ in a temporary space!\n",TradExpression(expr)); tagvalue=0; } } else if (ae->forcesnapshot) { if (ae->activebankbankset[ae->activebank>>2]) { tagvalue=ae->activebank+(ae->codeadr>>14); /* dans un bankset on tient compte de l'adresse */ } else { tagvalue=ae->activebank; } } else { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"expression [%s] cannot use BANK $ in a temporary space!\n",TradExpression(expr)); tagvalue=0; } } } else if (strcmp(varbuffer,"{PAGE}$")==0) { if (ae->activebankbankset[ae->activebank>>2]) { tagvalue=ae->bankgate[(ae->activebank&0x1FC)+(ae->codeadr>>14)]; } else { tagvalue=ae->bankgate[ae->activebank]; } } else { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"expression [%s] cannot use PAGE $ in a temporary space!\n",TradExpression(expr)); tagvalue=ae->activebank; } } else if (strcmp(varbuffer,"{PAGESET}$")==0) { if (ae->activebanksetgate[ae->activebank]; //if (ae->activebank>3) tagvalue=((ae->activebank>>2)-1)*8+0xC2; else tagvalue=0xC0; } else { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"expression [%s] cannot use PAGESET $ in a temporary space!\n",TradExpression(expr)); tagvalue=ae->activebank; } } /* replace */ #ifdef OS_WIN snprintf(curval,sizeof(curval)-1,"%d",tagvalue); newlen=strlen(curval); #else newlen=snprintf(curval,sizeof(curval)-1,"%d",tagvalue); #endif lenw=strlen(expr); if (newlen>ivar) { /* realloc bigger */ expr=*ptr_expr=MemRealloc(expr,lenw+newlen-ivar+1); } if (newlen!=ivar ) { MemMove(expr+startvar+newlen,expr+startvar+ivar,lenw-startvar-ivar+1); found_replace=1; } strncpy(expr+startvar,curval,newlen); /* copy without zero terminator */ idx=startvar+newlen; ivar=0; found_replace=1; } } } if (!found_replace && strcmp(varbuffer,"REPEAT_COUNTER")==0) { if (ae->ir) { yves=ae->repeat[ae->ir-1].repeat_counter; #ifdef OS_WIN snprintf(curval,sizeof(curval)-1,"%d",yves); newlen=strlen(curval); #else newlen=snprintf(curval,sizeof(curval)-1,"%d",yves); #endif lenw=strlen(expr); if (newlen>ivar) { /* realloc bigger */ expr=*ptr_expr=MemRealloc(expr,lenw+newlen-ivar+1); } if (newlen!=ivar ) { MemMove(expr+startvar+newlen,expr+startvar+ivar,lenw-startvar-ivar+1); found_replace=1; } strncpy(expr+startvar,curval,newlen); /* copy without zero terminator */ found_replace=1; idx=startvar+newlen; ivar=0; } else { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"cannot use REPEAT_COUNTER outside repeat loop\n"); } } if (!found_replace && strcmp(varbuffer,"WHILE_COUNTER")==0) { if (ae->iw) { yves=ae->whilewend[ae->iw-1].while_counter; #ifdef OS_WIN snprintf(curval,sizeof(curval)-1,"%d",yves); newlen=strlen(curval); #else newlen=snprintf(curval,sizeof(curval)-1,"%d",yves); #endif lenw=strlen(expr); if (newlen>ivar) { /* realloc bigger */ expr=*ptr_expr=MemRealloc(expr,lenw+newlen-ivar+1); } if (newlen!=ivar ) { MemMove(expr+startvar+newlen,expr+startvar+ivar,lenw-startvar-ivar+1); found_replace=1; } strncpy(expr+startvar,curval,newlen); /* copy without zero terminator */ found_replace=1; idx=startvar+newlen; ivar=0; } else { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"cannot use WHILE_COUNTER outside repeat loop\n"); } } /* unknown symbol -> add to used symbol pool */ if (!found_replace) { InsertUsedToTree(ae,varbuffer,crc); } } ivar=0; } } void PushExpression(struct s_assenv *ae,int iw,enum e_expression zetype) { #undef FUNC #define FUNC "PushExpression" struct s_expression curexp={0}; int startptr=0; if (!ae->nocode) { curexp.iw=iw; curexp.wptr=ae->outputadr; curexp.zetype=zetype; curexp.ibank=ae->activebank; curexp.iorgzone=ae->io-1; curexp.lz=ae->lz; /* on traduit de suite les variables du dictionnaire pour les boucles et increments SAUF si c'est une affectation */ if (!ae->wl[iw].e) { switch (zetype) { case E_EXPRESSION_V16C: /* check non register usage */ switch (GetCRC(ae->wl[iw].w)) { case CRC_IX: case CRC_IY: case CRC_MIX: case CRC_MIY: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"invalid register usage\n",ae->maxptr); default:break; } case E_EXPRESSION_J8: case E_EXPRESSION_V8: case E_EXPRESSION_V16: case E_EXPRESSION_IM:startptr=-1; break; case E_EXPRESSION_IV8: case E_EXPRESSION_IV81: case E_EXPRESSION_IV16:startptr=-2; break; case E_EXPRESSION_3V8:startptr=-3; break; case E_EXPRESSION_RUN: case E_EXPRESSION_ZXRUN: case E_EXPRESSION_ZXSTACK: case E_EXPRESSION_BRS:break; default:break; } /* hack pourri pour gérer le $ */ ae->codeadr+=startptr; /* ok mais les labels locaux des macros? */ if (ae->ir || ae->iw || ae->imacro) { curexp.reference=TxtStrDup(ae->wl[iw].w); ExpressionFastTranslate(ae,&curexp.reference,1); } else { ExpressionFastTranslate(ae,&ae->wl[iw].w,1); } ae->codeadr-=startptr; } /* calcul adresse de reference et post-incrementation pour sauter les data */ switch (zetype) { case E_EXPRESSION_J8:curexp.ptr=ae->codeadr-1;ae->outputadr++;ae->codeadr++;break; case E_EXPRESSION_0V8:curexp.ptr=ae->codeadr;ae->outputadr++;ae->codeadr++;break; case E_EXPRESSION_V8:curexp.ptr=ae->codeadr-1;ae->outputadr++;ae->codeadr++;break; case E_EXPRESSION_0V16:curexp.ptr=ae->codeadr;ae->outputadr+=2;ae->codeadr+=2;break; case E_EXPRESSION_0V32:curexp.ptr=ae->codeadr;ae->outputadr+=4;ae->codeadr+=4;break; case E_EXPRESSION_0VR:curexp.ptr=ae->codeadr;ae->outputadr+=5;ae->codeadr+=5;break; case E_EXPRESSION_V16C: case E_EXPRESSION_V16:curexp.ptr=ae->codeadr-1;ae->outputadr+=2;ae->codeadr+=2;break; case E_EXPRESSION_IV81:curexp.ptr=ae->codeadr-2;ae->outputadr++;ae->codeadr++;break; case E_EXPRESSION_IV8:curexp.ptr=ae->codeadr-2;ae->outputadr++;ae->codeadr++;break; case E_EXPRESSION_3V8:curexp.ptr=ae->codeadr-3;ae->outputadr++;ae->codeadr++;break; case E_EXPRESSION_IV16:curexp.ptr=ae->codeadr-2;ae->outputadr+=2;ae->codeadr+=2;break; case E_EXPRESSION_RST:curexp.ptr=ae->codeadr;ae->outputadr++;ae->codeadr++;break; case E_EXPRESSION_IM:curexp.ptr=ae->codeadr-1;ae->outputadr++;ae->codeadr++;break; case E_EXPRESSION_RUN:break; case E_EXPRESSION_ZXRUN:break; case E_EXPRESSION_ZXSTACK:break; case E_EXPRESSION_BRS:curexp.ptr=ae->codeadr;break; // minimum syndical default:break; } /* le contrôle n'est pas bon avec les DEFB, DEFW, ... -> @@TODO */ if (ae->outputadr<=ae->maxptr) { ObjectArrayAddDynamicValueConcat((void **)&ae->expression,&ae->ie,&ae->me,&curexp,sizeof(curexp)); } else { /* to avoid double error message */ if (!ae->stop) MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"output exceed limit %d\n",ae->maxptr); else MaxError(ae); ae->stop=1; return; } } else { switch (zetype) { case E_EXPRESSION_J8:ae->outputadr++;ae->codeadr++;break; case E_EXPRESSION_0V8:ae->outputadr++;ae->codeadr++;break; case E_EXPRESSION_V8:ae->outputadr++;ae->codeadr++;break; case E_EXPRESSION_0V16:ae->outputadr+=2;ae->codeadr+=2;break; case E_EXPRESSION_0V32:ae->outputadr+=4;ae->codeadr+=4;break; case E_EXPRESSION_0VR:ae->outputadr+=5;ae->codeadr+=5;break; case E_EXPRESSION_V16C: case E_EXPRESSION_V16:ae->outputadr+=2;ae->codeadr+=2;break; case E_EXPRESSION_IV81:ae->outputadr++;ae->codeadr++;break; case E_EXPRESSION_IV8:ae->outputadr++;ae->codeadr++;break; case E_EXPRESSION_3V8:ae->outputadr++;ae->codeadr++;break; case E_EXPRESSION_IV16:ae->outputadr+=2;ae->codeadr+=2;break; case E_EXPRESSION_RST:ae->outputadr++;ae->codeadr++;break; case E_EXPRESSION_IM:ae->outputadr++;ae->codeadr++;break; case E_EXPRESSION_RUN:break; case E_EXPRESSION_ZXRUN:break; case E_EXPRESSION_ZXSTACK:break; case E_EXPRESSION_BRS:break; } if (ae->outputadr<=ae->maxptr) { } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"NOCODE output exceed limit %d\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->maxptr); FreeAssenv(ae);exit(3); } } } /* The CP/M 2.2 directory has only one type of entry: UU F1 F2 F3 F4 F5 F6 F7 F8 T1 T2 T3 EX S1 S2 RC .FILENAMETYP.... AL AL AL AL AL AL AL AL AL AL AL AL AL AL AL AL ................ UU = User number. 0-15 (on some systems, 0-31). The user number allows multiple files of the same name to coexist on the disc. User number = 0E5h => File deleted Fn - filename Tn - filetype. The characters used for these are 7-bit ASCII. The top bit of T1 (often referred to as T1') is set if the file is read-only. T2' is set if the file is a system file (this corresponds to "hidden" on other systems). EX = Extent counter, low byte - takes values from 0-31 S2 = Extent counter, high byte. An extent is the portion of a file controlled by one directory entry. If a file takes up more blocks than can be listed in one directory entry, it is given multiple entries, distinguished by their EX and S2 bytes. The formula is: Entry number = ((32*S2)+EX) / (exm+1) where exm is the extent mask value from the Disc Parameter Block. S1 - reserved, set to 0. RC - Number of records (1 record=128 bytes) used in this extent, low byte. The total number of records used in this extent is (EX & exm) * 128 + RC If RC is 80h, this extent is full and there may be another one on the disc. File lengths are only saved to the nearest 128 bytes. AL - Allocation. Each AL is the number of a block on the disc. If an AL number is zero, that section of the file has no storage allocated to it (ie it does not exist). For example, a 3k file might have allocation 5,6,8,0,0.... - the first 1k is in block 5, the second in block 6, the third in block 8. AL numbers can either be 8-bit (if there are fewer than 256 blocks on the disc) or 16-bit (stored low byte first). */ int EDSK_getblockid(int *fb) { #undef FUNC #define FUNC "EDSK_getblockid" int i; for (i=0;i<180;i++) { if (fb[i]) { return i; } } return -1; } int EDSK_getdirid(struct s_edsk_wrapper *curwrap) { #undef FUNC #define FUNC "EDSK_getdirid" int ie; for (ie=0;ie<64;ie++) { if (curwrap->entry[ie].user==0xE5) { #if TRACE_EDSK printf("getdirid returns %d\n",ie); #endif return ie; } } return -1; } char *MakeAMSDOS_name(struct s_assenv *ae, char *filename) { #undef FUNC #define FUNC "MakeAMSDOS_name" static char amsdos_name[12]; int i,ia; char *pp; /* warning */ if (strlen(filename)>12) { if (!ae->nowarning) rasm_printf(ae,KWARNING"Warning - filename [%s] too long for AMSDOS, will be truncated\n",filename); } else if ((pp=strchr(filename,'.'))!=NULL) { if (pp-filename>8) { if (!ae->nowarning) rasm_printf(ae,KWARNING"Warning - filename [%s] too long for AMSDOS, will be truncated\n",filename); } } /* copy filename */ for (i=0;filename[i]!=0 && filename[i]!='.' && i<8;i++) { amsdos_name[i]=toupper(filename[i]); } /* fill with spaces */ for (ia=i;ia<8;ia++) { amsdos_name[ia]=0x20; } /* looking for extension */ for (;filename[i]!=0 && filename[i]!='.';i++); /* then copy it if any */ if (filename[i]=='.') { i++; for (ia=0;filename[i]!=0 && ia<3;ia++) { amsdos_name[8+ia]=toupper(filename[i++]); } } amsdos_name[11]=0; #if TRACE_EDSK printf("MakeAMSDOS_name [%s] -> [%s]\n",filename,amsdos_name); #endif return amsdos_name; } void EDSK_load(struct s_assenv *ae,struct s_edsk_wrapper *curwrap, char *edskfilename, int face) { #undef FUNC #define FUNC "EDSK_load" unsigned char header[256]; unsigned char *data; int tracknumber,sidenumber,tracksize,disksize; int i,b,s,f,t,curtrack,sectornumber,sectorsize,sectorid,reallength; int currenttrackposition=0,currentsectorposition,tmpcurrentsectorposition; unsigned char checksectorid[9]; int curblock=0,curoffset=0; #if TRACE_EDSK printf("EDSK_Load('%s',%d);",edskfilename,face); #endif if (FileReadBinary(edskfilename,(char*)&header,0x100)!=0x100) { rasm_printf(ae,KERROR"Cannot read EDSK header of [%s]!\n",edskfilename); FreeAssenv(ae);exit(ABORT_ERROR); } if (strncmp((char *)header,"MV - CPC",8)==0) { rasm_printf(ae,KAYGREEN"updating DSK to EDSK [%s] / creator: %s",edskfilename,header+34); tracknumber=header[34+14]; sidenumber=header[34+14+1]; tracksize=header[34+14+1+1]+header[34+14+1+1+1]*256; rasm_printf(ae,"tracks: %d sides:%d track size:%d",tracknumber,sidenumber,tracksize); if (tracknumber>40 || sidenumber>2) { rasm_printf(ae,KERROR"[%s] DSK format is not supported in update mode (ntrack=%d nside=%d)\n",edskfilename,tracknumber,sidenumber); FreeAssenv(ae);exit(ABORT_ERROR); } if (face>=sidenumber) { rasm_printf(ae,KWARNING"[%s] Warning - DSK has no face %d - DSK updated\n",edskfilename,face); return; } data=MemMalloc(tracksize*tracknumber*sidenumber); memset(data,0,tracksize*tracknumber*sidenumber); if (FileReadBinary(edskfilename,(char *)data,tracksize*tracknumber*sidenumber)!=tracksize*tracknumber*sidenumber) { rasm_printf(ae,"Cannot read DSK tracks!"); FreeAssenv(ae);exit(ABORT_ERROR); } //loginfo("track data read (%dkb)",tracksize*tracknumber*sidenumber/1024); f=face; for (t=0;t0xC9) { rasm_printf(ae,"Invalid sector ID in sector %02X track %d",data[i+24+8*s+2],t); FreeAssenv(ae);exit(ABORT_ERROR); } else { checksectorid[data[i+24+8*s+2]-0xC1]=1; } if (data[i+24+8*s+3]!=2) { rasm_printf(ae,"Invalid sector size in sector %02X track %d",data[i+24+8*s+2],t); FreeAssenv(ae);exit(ABORT_ERROR); } } for (s=0;sblocks[curblock][curoffset],&data[i+0x100+s*512],512); curoffset+=512; if (curoffset>=1024) { curoffset=0; curblock++; } } } } } else if (strncmp((char *)header,"EXTENDED",8)==0) { rasm_printf(ae,KAYGREEN"updating EDSK [%s] / creator: %-14.14s\n",edskfilename,header+34); tracknumber=header[34+14]; sidenumber=header[34+14+1]; // not in EDSK tracksize=header[34+14+1+1]+header[34+14+1+1+1]*256; #if TRACE_EDSK loginfo("tracks: %d sides:%d",tracknumber,sidenumber); #endif if (sidenumber>2) { rasm_printf(ae,KERROR"[%s] EDSK format is not supported in update mode (ntrack=%d nside=%d)\n",edskfilename,tracknumber,sidenumber); FreeAssenv(ae);exit(ABORT_ERROR); } if (face>=sidenumber) { rasm_printf(ae,KWARNING"[%s] EDSK has no face %d - DSK updated\n",edskfilename,face); return; } for (i=disksize=0;i=0xC1 && sectorid<=0xC9) checksectorid[sectorid-0xC1]=1; else { rasm_printf(ae,KERROR"invalid sector id %02X for DATA track %d\n",sectorid,t); return; } sectorsize=data[i+24+8*s+3]; if (sectorsize!=2) { rasm_printf(ae,KERROR"invalid sector size track %d\n",t); return; } reallength=data[i+24+8*s+6]+data[i+24+8*s+7]*256; /* real length stored */ if (reallength!=512) { rasm_printf(ae,KERROR"invalid sector length %d for track %d\n",reallength,t); return; } #if TRACE_EDSK printf("%02X ",sectorid); #endif } if (track_sectorsize!=2) { rasm_printf(ae,KWARNING"track %02d has invalid sector size but sectors are OK\n",t); } #if TRACE_EDSK printf("\n"); #endif /* piste à piste on lit les blocs DANS L'ORDRE LOGIQUE!!! */ for (b=0xC1;b<=0xC9;b++) { tmpcurrentsectorposition=currentsectorposition; for (s=0;sblocks[curblock][curoffset],&data[tmpcurrentsectorposition],512); curoffset+=512; if (curoffset>=1024) { curoffset=0; curblock++; } } reallength=data[i+24+8*s+6]+data[i+24+8*s+7]*256; tmpcurrentsectorposition+=reallength; } } } } } else { rasm_printf(ae,KERROR"file [%s] is not a valid (E)DSK floppy image\n",edskfilename); FreeAssenv(ae);exit(-923); } FileReadBinaryClose(edskfilename); /* Rasm management of (e)DSK files is AMSDOS compatible, just need to copy CATalog blocks but sort them... */ memcpy(&curwrap->entry[0],curwrap->blocks[0],1024); memcpy(&curwrap->entry[32],curwrap->blocks[1],1024); /* tri des entrées selon le user */ qsort(curwrap->entry,64,sizeof(struct s_edsk_wrapper_entry),cmpAmsdosentry); curwrap->nbentry=64; for (i=0;i<64;i++) { if (curwrap->entry[i].user==0xE5) { curwrap->nbentry=i; break; } } #if TRACE_EDSK printf("%d entr%s found\n",curwrap->nbentry,curwrap->nbentry>1?"ies":"y"); for (i=0;inbentry;i++) { printf("[%02d] - ",i); if (curwrap->entry[i].user<16) { printf("U%02d [%-8.8s.%c%c%c] %c%c subcpt=#%02X rc=#%02X blocks=",curwrap->entry[i].user,curwrap->entry[i].filename, curwrap->entry[i].filename[8]&0x7F,curwrap->entry[i].filename[9]&0x7F,curwrap->entry[i].filename[10], curwrap->entry[i].filename[8]&0x80?'P':'-',curwrap->entry[i].filename[9]&0x80?'H':'-', curwrap->entry[i].subcpt,curwrap->entry[i].rc); for (b=0;b<16;b++) if (curwrap->entry[i].blocks[b]) printf("%s%02X",b>0?" ":"",curwrap->entry[i].blocks[b]); else printf("%s ",b>0?" ":""); if (i&1) printf("\n"); else printf(" | "); } else { printf("free entry = rc= blocks= "); if (i&1) printf("\n"); else printf(" | "); } } if (i&1) printf("\n"); #endif } struct s_edsk_wrapper *EDSK_select(struct s_assenv *ae,char *edskfilename, int facenumber) { #undef FUNC #define FUNC "EDSK_select" struct s_edsk_wrapper newwrap={0},*curwrap=NULL; int i; #if TRACE_EDSK printf("EDSK_select('%s',%d);\n",edskfilename,facenumber); #endif /* check if there is a DSK in memory */ for (i=0;inbedskwrapper;i++) { if (!strcmp(ae->edsk_wrapper[i].edsk_filename,edskfilename)) { #if TRACE_EDSK printf("Found! return %d\n",i); #endif return &ae->edsk_wrapper[i]; } } /* not in memory, create an empty struct */ newwrap.edsk_filename=TxtStrDup(edskfilename); memset(newwrap.entry,0xE5,sizeof(struct s_edsk_wrapper_entry)*64); memset(newwrap.blocks[0],0xE5,1024); memset(newwrap.blocks[1],0xE5,1024); #if TRACE_EDSK printf("Not found! create empty struct\n"); #endif newwrap.face=facenumber; ObjectArrayAddDynamicValueConcat((void**)&ae->edsk_wrapper,&ae->nbedskwrapper,&ae->maxedskwrapper,&newwrap,sizeof(struct s_edsk_wrapper)); /* and load files if the DSK exists on disk */ curwrap=&ae->edsk_wrapper[ae->nbedskwrapper-1]; if (FileExists(edskfilename)) { EDSK_load(ae,curwrap,edskfilename,facenumber); } return curwrap; } int EDSK_addfile(struct s_assenv *ae,char *edskfilename,int facenumber, char *filename,unsigned char *indata,int insize, int offset, int run) { #undef FUNC #define FUNC "EDSK_addfile" struct s_edsk_wrapper *curwrap=NULL; char amsdos_name[12]={0}; int j,i,ia,ib,ie,filesize,idxdata; int fb[180],rc,idxb; unsigned char *data=NULL; int size=0; int firstblock; curwrap=EDSK_select(ae,edskfilename,facenumber); /* update struct */ size=insize+128; data=MemMalloc(size); strcpy(amsdos_name,MakeAMSDOS_name(ae,filename)); memcpy(data,MakeAMSDOSHeader(run,offset,offset+insize,amsdos_name),128); memcpy(data+128,indata,insize); /* overwrite check */ #if TRACE_EDSK printf("EDSK_addfile will checks %d entr%s for [%s]\n",curwrap->nbentry,curwrap->nbentry>1?"ies":"y",amsdos_name); #endif for (i=0;inbentry;i++) { if (!strncmp((char *)curwrap->entry[i].filename,amsdos_name,11)) { if (!ae->edskoverwrite) { MakeError(ae,NULL,0,"Error - Cannot save [%s] in edsk [%s] with overwrite disabled as the file already exists\n",amsdos_name,edskfilename); MemFree(data); return 0; } else { /* overwriting previous file */ #if TRACE_EDSK printf(" -> reset previous entry %d with 0xE5\n",i); #endif memset(&curwrap->entry[i],0xE5,sizeof(struct s_edsk_wrapper_entry)); } } } /* find free blocks */ #if TRACE_EDSK printf("EDSK_addfile find free blocks\n"); #endif fb[0]=fb[1]=0; for (i=2;i<180;i++) fb[i]=1; for (i=0;inbentry;i++) { if (curwrap->entry[i].rc!=0xE5 && curwrap->entry[i].rc!=0) { /* entry found, compute number of blocks to read */ rc=curwrap->entry[i].rc/8; if (curwrap->entry[i].rc%8) rc++; /* adjust value */ /* mark as used */ for (j=0;jentry[i].blocks[j]]=0; } } } /* set directory, blocks and data in blocks */ firstblock=-1; filesize=size; idxdata=0; ia=0; #if TRACE_EDSK printf("Writing [%s] size=%d\n",amsdos_name,size); #endif while (filesize>0) { if (filesize>16384) { /* extended entry */ #if TRACE_EDSK printf("extended entry for file (filesize=%d)\nblocklist: ",filesize); #endif if ((ie=EDSK_getdirid(curwrap))==-1) { MakeError(ae,NULL,0,"Error - edsk [%s] DIRECTORY FULL\n",edskfilename); MemFree(data); return 0; } if (curwrap->nbentry<=ie) curwrap->nbentry=ie+1; idxb=0; for (i=0;i<16;i++) { if ((ib=EDSK_getblockid(fb))==-1) { MakeError(ae,NULL,0,"Error - edsk [%s] DISK FULL\n",edskfilename); MemFree(data); return 0; } else { if (firstblock==-1) firstblock=ib; #if TRACE_EDSK printf("%02X ",ib); #endif memcpy(curwrap->blocks[ib],data+idxdata,1024); idxdata+=1024; filesize-=1024; fb[ib]=0; curwrap->entry[ie].blocks[idxb++]=ib; } } #if TRACE_EDSK printf("\n"); #endif memcpy(curwrap->entry[ie].filename,amsdos_name,11); curwrap->entry[ie].subcpt=ia; curwrap->entry[ie].rc=0x80; curwrap->entry[ie].user=0; ia++; idxb=0; } else { /* last entry */ #if TRACE_EDSK printf("last entry for file (filesize=%d)\nblocklist: ",filesize); #endif if ((ie=EDSK_getdirid(curwrap))==-1) { MakeError(ae,NULL,0,"Error - edsk [%s] DIRECTORY FULL\n",edskfilename); MemFree(data); return 0; } if (curwrap->nbentry<=ie) curwrap->nbentry=ie+1; /* calcul du nombre de sous blocs de 128 octets */ curwrap->entry[ie].rc=filesize/128; if (filesize%128) { curwrap->entry[ie].rc+=1; } idxb=0; for (i=0;i<16 && filesize>0;i++) { if ((ib=EDSK_getblockid(fb))==-1) { MakeError(ae,NULL,0,"Error - edsk [%s] DISK FULL\n",edskfilename); MemFree(data); return 0; } else { if (firstblock==-1) firstblock=ib; #if TRACE_EDSK printf("%02X ",ib); #endif memcpy(curwrap->blocks[ib],&data[idxdata],filesize>1024?1024:filesize); idxdata+=1024; filesize-=1024; fb[ib]=0; curwrap->entry[ie].blocks[idxb++]=ib; } } #if TRACE_EDSK printf("\n"); #endif filesize=0; memcpy(curwrap->entry[ie].filename,amsdos_name,11); curwrap->entry[ie].subcpt=ia; curwrap->entry[ie].user=0; } } MemFree(data); return 1; } void EDSK_build_amsdos_directory(struct s_edsk_wrapper *face) { #undef FUNC #define FUNC "EDSK_build_amsdos_directory" unsigned char amsdosdir[2048]={0}; int i,idx=0,b; if (!face) return; #if TRACE_EDSK printf("build amsdos dir with %d entries\n",face->nbentry); #endif for (i=0;inbentry;i++) { if (face->entry[i].rc && face->entry[i].rc!=0xE5) { amsdosdir[idx]=face->entry[i].user; memcpy(amsdosdir+idx+1,face->entry[i].filename,11); amsdosdir[idx+12]=face->entry[i].subcpt; amsdosdir[idx+13]=0; amsdosdir[idx+14]=0; amsdosdir[idx+15]=face->entry[i].rc; #if TRACE_EDSK printf("%-11.11s [%02X.%02X] blocks:",amsdosdir+idx+1,amsdosdir[idx+12],amsdosdir[idx+15]); #endif for (b=0;b<16;b++) { if (face->entry[i].blocks[b]!=0xE5) { amsdosdir[idx+16+b]=face->entry[i].blocks[b]; #if TRACE_EDSK printf("%s%02X",b>0?".":"",amsdosdir[idx+16+b]); #endif } else { amsdosdir[idx+16+b]=0; } } #if TRACE_EDSK printf("\n"); #endif } idx+=32; } #if TRACE_EDSK printf("filling amsdos remaining entries (%d) with #E5\n",64-face->nbentry); #endif memset(amsdosdir+idx,0xE5,32*(64-face->nbentry)); /* AMSDOS directory copy to blocks! */ memcpy(face->blocks[0],amsdosdir,1024); memcpy(face->blocks[1],amsdosdir+1024,1024); } void EDSK_write_file(struct s_assenv *ae,struct s_edsk_wrapper *faceA,struct s_edsk_wrapper *faceB) { #undef FUNC #define FUNC "EDSK_write_file" struct s_edsk_wrapper emptyface={0}; unsigned char header[256]={0}; unsigned char trackblock[256]={0}; int idblock,blockoffset; int i,t; if (!faceA && !faceB) return; /* création des deux blocs du directory par face */ EDSK_build_amsdos_directory(faceA); EDSK_build_amsdos_directory(faceB); /* écriture header */ strcpy((char *)header,"EXTENDED CPC DSK File\r\nDisk-Info\r\n"); strcpy((char *)header+0x22,RASM_SNAP_VERSION); header[0x30]=40; if (!faceA) { faceA=&emptyface; faceA->edsk_filename=TxtStrDup(faceB->edsk_filename); } #if TRACE_EDSK printf("deleting [%s]\n",faceA->edsk_filename); #endif FileRemoveIfExists(faceA->edsk_filename); if (faceB!=NULL) header[0x31]=2; else header[0x31]=1; for (i=0;iedsk_filename,(char *)header,256); /* écriture des pistes */ for (t=0;t<40;t++) { strcpy((char *)trackblock,"Track-Info\r\n"); trackblock[0x10]=t; trackblock[0x11]=0; trackblock[0x14]=2; trackblock[0x15]=9; trackblock[0x16]=0x4E; trackblock[0x17]=0xE5; i=0; while (1) { trackblock[0x18+i*8+0]=trackblock[0x10]; trackblock[0x18+i*8+1]=trackblock[0x11]; trackblock[0x18+i*8+2]=(i>>1)+0xC1; #if TRACE_EDSK if (t<3) printf("%02X ",trackblock[0x18+i*8+2]); #endif trackblock[0x18+i*8+3]=2; trackblock[0x18+i*8+4]=0; trackblock[0x18+i*8+5]=0; trackblock[0x18+i*8+6]=0; trackblock[0x18+i*8+7]=2; i++; if (i==9) break; /* interleave */ trackblock[0x18+i*8+0]=trackblock[0x10]; trackblock[0x18+i*8+1]=trackblock[0x11]; trackblock[0x18+i*8+2]=(i>>1)+0xC6; /* start at C6 */ #if TRACE_EDSK if (t<3) printf("%02X ",trackblock[0x18+i*8+2]); #endif trackblock[0x18+i*8+3]=2; trackblock[0x18+i*8+4]=0; trackblock[0x18+i*8+5]=0; trackblock[0x18+i*8+6]=0; trackblock[0x18+i*8+7]=2; i++; } #if TRACE_EDSK if (t<3) printf("\n"); else if (t==3) printf("...\n"); #endif /* écriture du track info */ FileWriteBinary(faceA->edsk_filename,(char *)trackblock,256); /* il faut convertir les blocs logiques en secteurs physiques ET entrelacés */ idblock=t*9/2; blockoffset=((t*9)%2)*512; /* le premier secteur de la piste est à cheval sur le bloc logique une fois sur deux */ FileWriteBinary(faceA->edsk_filename,(char *)&faceA->blocks[idblock][0]+blockoffset,512); /* C1 */ if (!blockoffset) { FileWriteBinary(faceA->edsk_filename,(char *)&faceA->blocks[idblock+2][0]+512,512); /* C6 */ FileWriteBinary(faceA->edsk_filename,(char *)&faceA->blocks[idblock+0][0]+512,512); /* C2 */ FileWriteBinary(faceA->edsk_filename,(char *)&faceA->blocks[idblock+3][0]+0,512); /* C7 */ FileWriteBinary(faceA->edsk_filename,(char *)&faceA->blocks[idblock+1][0]+0,512); /* C3 */ FileWriteBinary(faceA->edsk_filename,(char *)&faceA->blocks[idblock+3][0]+512,512); /* C8 */ FileWriteBinary(faceA->edsk_filename,(char *)&faceA->blocks[idblock+1][0]+512,512); /* C4 */ FileWriteBinary(faceA->edsk_filename,(char *)&faceA->blocks[idblock+4][0]+0,512); /* C9 */ FileWriteBinary(faceA->edsk_filename,(char *)&faceA->blocks[idblock+2][0]+0,512); /* C5 */ } else { FileWriteBinary(faceA->edsk_filename,(char *)&faceA->blocks[idblock+3][0]+0,512); /* C6 */ FileWriteBinary(faceA->edsk_filename,(char *)&faceA->blocks[idblock+1][0]+0,512); /* C2 */ FileWriteBinary(faceA->edsk_filename,(char *)&faceA->blocks[idblock+3][0]+512,512); /* C7 */ FileWriteBinary(faceA->edsk_filename,(char *)&faceA->blocks[idblock+1][0]+512,512); /* C3 */ FileWriteBinary(faceA->edsk_filename,(char *)&faceA->blocks[idblock+4][0]+0,512); /* C8 */ FileWriteBinary(faceA->edsk_filename,(char *)&faceA->blocks[idblock+2][0]+0,512); /* C4 */ FileWriteBinary(faceA->edsk_filename,(char *)&faceA->blocks[idblock+4][0]+512,512); /* C9 */ FileWriteBinary(faceA->edsk_filename,(char *)&faceA->blocks[idblock+2][0]+512,512); /* C5 */ } /* @@TODO ça semble un peu foireux comme procédé */ if (faceB) { #if TRACE_EDSK printf("writing EDSK face B /!\\ probably NOT WORKING !!!\n"); #endif trackblock[0x11]=1; for (i=0;i<9;i++) { trackblock[0x18+i*8+0]=trackblock[0x10]; trackblock[0x18+i*8+1]=trackblock[0x11]; } /* écriture du track info */ FileWriteBinary(faceB->edsk_filename,(char *)trackblock,256); /* écriture des secteurs */ idblock=t*9/2; blockoffset=((t*9)%2)*512; FileWriteBinary(faceB->edsk_filename,(char *)&faceB->blocks[idblock][0]+blockoffset,512); if (!blockoffset) { FileWriteBinary(faceB->edsk_filename,(char *)&faceB->blocks[idblock+2][0]+512,512); /* C6 */ FileWriteBinary(faceB->edsk_filename,(char *)&faceB->blocks[idblock+0][0]+512,512); /* C2 */ FileWriteBinary(faceB->edsk_filename,(char *)&faceB->blocks[idblock+3][0]+0,512); /* C7 */ FileWriteBinary(faceB->edsk_filename,(char *)&faceB->blocks[idblock+1][0]+0,512); /* C3 */ FileWriteBinary(faceB->edsk_filename,(char *)&faceB->blocks[idblock+3][0]+512,512); /* C8 */ FileWriteBinary(faceB->edsk_filename,(char *)&faceB->blocks[idblock+1][0]+512,512); /* C4 */ FileWriteBinary(faceB->edsk_filename,(char *)&faceB->blocks[idblock+4][0]+0,512); /* C9 */ FileWriteBinary(faceB->edsk_filename,(char *)&faceB->blocks[idblock+2][0]+0,512); /* C5 */ } else { FileWriteBinary(faceB->edsk_filename,(char *)&faceB->blocks[idblock+3][0]+0,512); /* C6 */ FileWriteBinary(faceB->edsk_filename,(char *)&faceB->blocks[idblock+1][0]+0,512); /* C2 */ FileWriteBinary(faceB->edsk_filename,(char *)&faceB->blocks[idblock+3][0]+512,512); /* C7 */ FileWriteBinary(faceB->edsk_filename,(char *)&faceB->blocks[idblock+1][0]+512,512); /* C3 */ FileWriteBinary(faceB->edsk_filename,(char *)&faceB->blocks[idblock+4][0]+0,512); /* C8 */ FileWriteBinary(faceB->edsk_filename,(char *)&faceB->blocks[idblock+2][0]+0,512); /* C4 */ FileWriteBinary(faceB->edsk_filename,(char *)&faceB->blocks[idblock+4][0]+512,512); /* C9 */ FileWriteBinary(faceB->edsk_filename,(char *)&faceB->blocks[idblock+2][0]+512,512); /* C5 */ } } } FileWriteBinaryClose(faceA->edsk_filename); rasm_printf(ae,KIO"Write edsk file %s\n",faceA->edsk_filename); } void EDSK_write(struct s_assenv *ae) { #undef FUNC #define FUNC "EDSK_write" struct s_edsk_wrapper *faceA,*faceB; char *edskfilename; int i,j; /* on passe en revue toutes les structs */ for (i=0;inbedskwrapper;i++) { /* already done */ if (ae->edsk_wrapper[i].face==-1) continue; switch (ae->edsk_wrapper[i].face) { default: case 0:faceA=&ae->edsk_wrapper[i];faceB=NULL;break; case 1:faceA=NULL;faceB=&ae->edsk_wrapper[i];break; } /* doit-on fusionner avec une autre face? */ for (j=i+1;jnbedskwrapper;j++) { if (!strcmp(ae->edsk_wrapper[i].edsk_filename,ae->edsk_wrapper[j].edsk_filename)) { /* found another face for the floppy */ switch (ae->edsk_wrapper[j].face) { default: case 0:faceA=&ae->edsk_wrapper[j];break; case 1:faceB=&ae->edsk_wrapper[j];break; } } } EDSK_write_file(ae,faceA,faceB); } } void PopAllSave(struct s_assenv *ae) { #undef FUNC #define FUNC "PopAllSave" unsigned char *AmsdosHeader; char *dskfilename; char *filename; int offset,size,run; int i,is,erreur=0,touched; for (is=0;isnbsave;is++) { /* avoid quotes */ filename=ae->wl[ae->save[is].iw].w; filename[strlen(filename)-1]=0; filename=TxtStrDup(filename+1); /* translate tags! */ filename=TranslateTag(ae,filename,&touched,1,E_TAGOPTION_REMOVESPACE); #if TRACE_EDSK printf("woff=[%s](%d) wsize=[%s](%d)\n",ae->wl[ae->save[is].ioffset].w,ae->save[is].ioffset,ae->wl[ae->save[is].isize].w,ae->save[is].isize); #endif ae->idx=ae->save[is].ioffset; /* exp hack */ ExpressionFastTranslate(ae,&ae->wl[ae->idx].w,0); offset=RoundComputeExpression(ae,ae->wl[ae->idx].w,0,0,0); ae->idx=ae->save[is].isize; /* exp hack */ ExpressionFastTranslate(ae,&ae->wl[ae->idx].w,0); size=RoundComputeExpression(ae,ae->wl[ae->idx].w,0,0,0); ae->idx=ae->save[is].irun; /* exp hack */ if (ae->idx) { ExpressionFastTranslate(ae,&ae->wl[ae->idx].w,0); run=RoundComputeExpression(ae,ae->wl[ae->idx].w,0,0,0); } else { run=offset; } if (size<1 || size>65536) { MakeError(ae,NULL,0,"cannot save [%s] as the size is invalid!\n",filename); continue; } if (offset<0 || offset>65535) { MakeError(ae,NULL,0,"cannot save [%s] as the offset is invalid!\n",filename); continue; } if (offset+size>65536) { MakeError(ae,NULL,0,"cannot save [%s] as the offset+size will be out of bounds!\n",filename); continue; } /* DSK management */ if (ae->save[is].dsk) { if (ae->save[is].iwdskname!=-1) { /* obligé de dupliquer à cause du reuse */ dskfilename=TxtStrDup(ae->wl[ae->save[is].iwdskname].w); dskfilename[strlen(dskfilename)-1]=0; if (!EDSK_addfile(ae,dskfilename+1,ae->save[is].face,filename,ae->mem[ae->save[is].ibank]+offset,size,offset,run)) { erreur++; break; } MemFree(dskfilename); } } else if (ae->save[is].tape) { char TZX_header[10]; unsigned char IDval[2]; int wrksize,nbblock; /* output file on filesystem */ FileRemoveIfExists(filename); strcpy(TZX_header,"ZXTape!"); TZX_header[7]=0x1A; TZX_header[8]=1; TZX_header[9]=20; FileWriteBinary(filename,(char *)TZX_header,10); IDval[0]=0x20; FileWriteBinary(filename,(char *)IDval,1); IDval[0]=0x03; IDval[1]=0x03; FileWriteBinary(filename,(char *)IDval,2); // first silence IDval[0]=0x10; FileWriteBinary(filename,(char *)IDval,1); IDval[0]=0x03; IDval[1]=0x03; FileWriteBinary(filename,(char *)IDval,2); // little silence if (size+128<=2048) wrksize=size+128; else wrksize=2048; IDval[0]=(wrksize+128) & 0xFF; IDval[1]=((wrksize+128)>>8) & 0xFF; FileWriteBinary(filename,(char *)IDval,2); // block len nbblock=1; AmsdosHeader=MakeAMSDOSHeader(run,offset,offset+size,MakeAMSDOS_name(ae,filename)); FileWriteBinary(filename,(char *)AmsdosHeader,128); if (size<=2048-128) { FileWriteBinary(filename,(char*)ae->mem[ae->save[is].ibank]+offset,size); } else { FileWriteBinary(filename,(char*)ae->mem[ae->save[is].ibank]+offset,2048-128); size=size-2048+128; while (size>0) { nbblock++; /* additionnal block */ IDval[0]=0x10; FileWriteBinary(filename,(char *)IDval,1); IDval[0]=0x04; IDval[1]=0x04; FileWriteBinary(filename,(char *)IDval,2); // silence 1s delay if (size<=2048) wrksize=size; else wrksize=2048; IDval[0]=(wrksize+128) & 0xFF; IDval[1]=((wrksize+128)>>8) & 0xFF; FileWriteBinary(filename,(char *)IDval,2); // block len FileWriteBinary(filename,(char*)ae->mem[ae->save[is].ibank]+offset,wrksize); /* adjust */ size=size-2048; } } FileWriteBinaryClose(filename); rasm_printf(ae,KIO"Write tape file %s (%d block%s)\n",filename,nbblock,nbblock>1?"s":""); } else { /* output file on filesystem */ rasm_printf(ae,KIO"Write binary file %s (%d byte%s)\n",filename,size,size>1?"s":""); FileRemoveIfExists(filename); if (ae->save[is].amsdos) { AmsdosHeader=MakeAMSDOSHeader(run,offset,offset+size,MakeAMSDOS_name(ae,filename)); FileWriteBinary(filename,(char *)AmsdosHeader,128); } FileWriteBinary(filename,(char*)ae->mem[ae->save[is].ibank]+offset,size); FileWriteBinaryClose(filename); } MemFree(filename); } if (!erreur) EDSK_write(ae); for (i=0;inbedskwrapper;i++) { MemFree(ae->edsk_wrapper[i].edsk_filename); } if (ae->maxedskwrapper) MemFree(ae->edsk_wrapper); if (ae->nbsave) { MemFree(ae->save); } } void PopAllExpression(struct s_assenv *ae, int crunched_zone) { #undef FUNC #define FUNC "PopAllExpression" static int first=1; double v; long r; int i; unsigned char *mem; char *expr; /* pop all expressions BUT thoses who where already computed (in crunched blocks) */ /* calcul des labels et expressions en zone crunch (et locale?) les labels doivent pointer: - une valeur absolue (numerique ou variable calculee) -> completement transparent - un label dans la meme zone de crunch -> label->lz=1 && verif de la zone crunch - un label hors zone crunch MAIS avant toute zone de crunch de la bank destination (!label->lz) idealement on doit tolerer les adresses situees apres le crunch dans une autre ORG zone! on utilise ae->stage pour créer un état intermédiaire dans le ComputeExpressionCore */ if (crunched_zone>=0) { ae->stage=1; } else { /* on rescanne tout pour combler les trous */ ae->stage=2; first=1; } for (i=first;iie;i++) { /* first compute only crunched expression (0,1,2,3,...) then (-1) at the end */ if (crunched_zone>=0) { /* calcul des expressions en zone crunch */ if (ae->expression[i].lzexpression[i].lz>crunched_zone) { first=i; break; } } else { if (ae->expression[i].lz>=0) continue; } mem=ae->mem[ae->expression[i].ibank]; if (ae->expression[i].reference) { expr=ae->expression[i].reference; } else { expr=ae->wl[ae->expression[i].iw].w; } v=ComputeExpressionCore(ae,expr,ae->expression[i].ptr,i); r=(long)floor(v+ae->rough); switch (ae->expression[i].zetype) { case E_EXPRESSION_J8: r=r-ae->expression[i].ptr-2; if (r<-128 || r>127) { MakeError(ae,GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,"relative offset %d too far [%s]\n",r,ae->wl[ae->expression[i].iw].w); } mem[ae->expression[i].wptr]=(unsigned char)r; break; case E_EXPRESSION_IV81: /* for enhanced 16bits instructions */ r++; case E_EXPRESSION_0V8: case E_EXPRESSION_IV8: case E_EXPRESSION_3V8: case E_EXPRESSION_V8: if (r>255 || r<-128) { if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: truncating value #%X to #%X\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,r&0xFF); } mem[ae->expression[i].wptr]=(unsigned char)r; break; case E_EXPRESSION_IV16: case E_EXPRESSION_V16: case E_EXPRESSION_V16C: case E_EXPRESSION_0V16: if (r>65535 || r<-32768) { if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: truncating value #%X to #%X\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,r&0xFFFF); } mem[ae->expression[i].wptr]=(unsigned char)r&0xFF; mem[ae->expression[i].wptr+1]=(unsigned char)((r&0xFF00)>>8); break; case E_EXPRESSION_0V32: /* meaningless in 32 bits architecture... */ if (v>4294967295 || v<-2147483648) { if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: truncating value\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l); } mem[ae->expression[i].wptr]=(unsigned char)r&0xFF; mem[ae->expression[i].wptr+1]=(unsigned char)((r>>8)&0xFF); mem[ae->expression[i].wptr+2]=(unsigned char)((r>>16)&0xFF); mem[ae->expression[i].wptr+3]=(unsigned char)((r>>24)&0xFF); break; case E_EXPRESSION_0VR: /* convert v double value to Amstrad REAL */ memcpy(&mem[ae->expression[i].wptr],__internal_MakeAmsdosREAL(ae,v,i),5); break; case E_EXPRESSION_IM: switch (r) { case 0x00:mem[ae->expression[i].wptr]=0x46;break; case 0x01:mem[ae->expression[i].wptr]=0x56;break; case 0x02:mem[ae->expression[i].wptr]=0x5E;break; default: MakeError(ae,GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,"IM 0,1 or 2 only\n"); mem[ae->expression[i].wptr]=0; } break; case E_EXPRESSION_RST: switch (r) { case 0x00:mem[ae->expression[i].wptr]=0xC7;break; case 0x08:mem[ae->expression[i].wptr]=0xCF;break; case 0x10:mem[ae->expression[i].wptr]=0xD7;break; case 0x18:mem[ae->expression[i].wptr]=0xDF;break; case 0x20:mem[ae->expression[i].wptr]=0xE7;break; case 0x28:mem[ae->expression[i].wptr]=0xEF;break; case 0x30:mem[ae->expression[i].wptr]=0xF7;break; case 0x38:mem[ae->expression[i].wptr]=0xFF;break; default: MakeError(ae,GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,"RST #0,#8,#10,#18,#20,#28,#30,#38 only\n"); mem[ae->expression[i].wptr]=0; } break; case E_EXPRESSION_RUN: if (r<0 || r>65535) { if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: run adress truncated from %X to %X\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,r&0xFFFF); } ae->snapshot.registers.LPC=r&0xFF; ae->snapshot.registers.HPC=(r>>8)&0xFF; break; case E_EXPRESSION_ZXRUN: if (r<0 || r>65535) { if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: run adress truncated from %X to %X\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,r&0xFFFF); } ae->zxsnapshot.run=r&0xFFFF; break; case E_EXPRESSION_ZXSTACK: if (r<0 || r>65535) { if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: stack adress truncated from %X to %X\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,r&0xFFFF); } ae->zxsnapshot.stack=r&0xFFFF; break; case E_EXPRESSION_BRS: if (r>=0 && r<8) { mem[ae->expression[i].wptr]+=r*8; } else { MakeError(ae,GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,"SET,RES,BIT shift value from 0 to 7 only\n"); } break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - unknown expression type\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l); FreeAssenv(ae);exit(-8); } } } void InsertLabelToTree(struct s_assenv *ae, struct s_label *label) { #undef FUNC #define FUNC "InsertLabelToTree" struct s_crclabel_tree *curlabeltree; int radix,dek=32; curlabeltree=&ae->labeltree; while (dek) { dek=dek-8; radix=(label->crc>>dek)&0xFF; if (curlabeltree->radix[radix]) { curlabeltree=curlabeltree->radix[radix]; } else { curlabeltree->radix[radix]=MemMalloc(sizeof(struct s_crclabel_tree)); curlabeltree=curlabeltree->radix[radix]; memset(curlabeltree,0,sizeof(struct s_crclabel_tree)); } } ObjectArrayAddDynamicValueConcat((void**)&curlabeltree->label,&curlabeltree->nlabel,&curlabeltree->mlabel,&label[0],sizeof(struct s_label)); } /* use by structure mechanism and label import to add fake labels */ void PushLabelLight(struct s_assenv *ae, struct s_label *curlabel) { #undef FUNC #define FUNC "PushLabelLight" struct s_label *searched_label; /* PushLabel light */ if ((searched_label=SearchLabel(ae,curlabel->name,curlabel->crc))!=NULL) { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"%s caused duplicate label [%s]\n",ae->idx?"Structure insertion":"Label import",curlabel->name); MemFree(curlabel->name); } else { curlabel->backidx=ae->il; ObjectArrayAddDynamicValueConcat((void **)&ae->label,&ae->il,&ae->ml,curlabel,sizeof(struct s_label)); InsertLabelToTree(ae,curlabel); } } void PushLabel(struct s_assenv *ae) { #undef FUNC #define FUNC "PushLabel" struct s_label curlabel={0},*searched_label; char *curlabelname; int i; /* label with counters */ struct s_expr_dico *curdic; char curval[32]; char *varbuffer,*expr; char *starttag,*endtag,*tagcheck; int taglen,tagidx,lenw,tagcount=0; int crc,newlen,touched; if (ae->AutomateValidLabelFirst[ae->wl[ae->idx].w[0]]) { for (i=1;ae->wl[ae->idx].w[i];i++) { if (ae->wl[ae->idx].w[i]=='{') tagcount++; else if (ae->wl[ae->idx].w[i]=='}') tagcount--; if (!tagcount) { if (!ae->AutomateValidLabel[ae->wl[ae->idx].w[i]]) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Invalid char in label declaration (%c)\n",ae->wl[ae->idx].w[i]); return; } } } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Invalid first char in label declaration (%c)\n",ae->wl[ae->idx].w[0]); return; } switch (i) { case 1: switch (ae->wl[ae->idx].w[0]) { case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'H': case 'L': case 'I': case 'R': MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot use reserved word [%s] for label\n",ae->wl[ae->idx].w); return; default:break; } break; case 2: if (strcmp(ae->wl[ae->idx].w,"AF")==0 || strcmp(ae->wl[ae->idx].w,"BC")==0 || strcmp(ae->wl[ae->idx].w,"DE")==0 || strcmp(ae->wl[ae->idx].w,"HL")==0 || strcmp(ae->wl[ae->idx].w,"IX")==0 || strcmp(ae->wl[ae->idx].w,"IY")==0 || strcmp(ae->wl[ae->idx].w,"SP")==0 || strcmp(ae->wl[ae->idx].w,"LX")==0 || strcmp(ae->wl[ae->idx].w,"HX")==0 || strcmp(ae->wl[ae->idx].w,"XL")==0 || strcmp(ae->wl[ae->idx].w,"XH")==0 || strcmp(ae->wl[ae->idx].w,"LY")==0 || strcmp(ae->wl[ae->idx].w,"HY")==0 || strcmp(ae->wl[ae->idx].w,"YL")==0 || strcmp(ae->wl[ae->idx].w,"YH")==0) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot use reserved word [%s] for label\n",ae->wl[ae->idx].w); return; } break; case 3: if (strcmp(ae->wl[ae->idx].w,"IXL")==0 || strcmp(ae->wl[ae->idx].w,"IYL")==0 || strcmp(ae->wl[ae->idx].w,"IXH")==0 || strcmp(ae->wl[ae->idx].w,"IYH")==0) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot use reserved word [%s] for label\n",ae->wl[ae->idx].w); return; } break; case 4: if (strcmp(ae->wl[ae->idx].w,"VOID")==0) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot use reserved word [%s] for label\n",ae->wl[ae->idx].w); return; } default:break; } /******************************************************* v a r i a b l e s i n l a b e l n a m e *******************************************************/ varbuffer=TranslateTag(ae,TxtStrDup(ae->wl[ae->idx].w),&touched,1,E_TAGOPTION_NONE); /************************************************** s t r u c t u r e d e c l a r a t i o n **************************************************/ if (ae->getstruct) { struct s_rasmstructfield rasmstructfield={0}; if (varbuffer[0]=='@') { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Please no local label in a struct [%s]\n",ae->wl[ae->idx].w); return; } /* copy label+offset in the structure */ rasmstructfield.name=TxtStrDup(varbuffer); rasmstructfield.offset=ae->codeadr; ObjectArrayAddDynamicValueConcat((void **)&ae->rasmstruct[ae->irasmstruct-1].rasmstructfield, &ae->rasmstruct[ae->irasmstruct-1].irasmstructfield,&ae->rasmstruct[ae->irasmstruct-1].mrasmstructfield, &rasmstructfield,sizeof(rasmstructfield)); /* label is structname+field */ curlabelname=curlabel.name=MemMalloc(strlen(ae->rasmstruct[ae->irasmstruct-1].name)+strlen(varbuffer)+2); sprintf(curlabel.name,"%s.%s",ae->rasmstruct[ae->irasmstruct-1].name,varbuffer); curlabel.iw=-1; /* legacy */ curlabel.crc=GetCRC(curlabel.name); curlabel.ptr=ae->codeadr; #if TRACE_STRUCT printf("pushLabel (struct) [%X] [%s]\n",curlabel.ptr,curlabel.name); #endif } else { /************************************************** l a b e l s **************************************************/ /* labels locaux */ if (varbuffer[0]=='@' && (ae->ir || ae->iw || ae->imacro)) { curlabel.iw=-1; curlabel.local=1; curlabelname=curlabel.name=MakeLocalLabel(ae,varbuffer,NULL); curlabel.crc=GetCRC(curlabel.name); /* local labels ALSO set new reference */ if (ae->lastglobalalloc) { //printf("push LOCAL is freeing lastgloballabel\n"); MemFree(ae->lastgloballabel); } ae->lastgloballabel=TxtStrDup(curlabelname); //printf("push LOCAL as reference for proximity label -> [%s]\n",ae->lastgloballabel); ae->lastgloballabellen=strlen(ae->lastgloballabel); ae->lastglobalalloc=1; } else { switch (varbuffer[0]) { case '.': if (ae->dams) { /* old Dams style declaration (remove the dot) */ i=0; do { varbuffer[i]=varbuffer[i+1]; ae->wl[ae->idx].w[i]=ae->wl[ae->idx].w[i+1]; i++; } while (varbuffer[i]!=0); if (!touched) { curlabel.iw=ae->idx; } else { curlabel.iw=-1; curlabel.name=varbuffer; } curlabel.crc=GetCRC(varbuffer); curlabelname=varbuffer; } else { /* proximity labels */ if (ae->lastgloballabel) { curlabelname=MemMalloc(strlen(varbuffer)+1+ae->lastgloballabellen); sprintf(curlabelname,"%s%s",ae->lastgloballabel,varbuffer); MemFree(varbuffer); touched=1; // cause realloc! curlabel.iw=-1; curlabel.name=varbuffer=curlabelname; curlabel.crc=GetCRC(varbuffer); //printf("push proximity label that may be exported [%s]->[%s]\n",ae->wl[ae->idx].w,varbuffer); } else { /* MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"cannot create proximity label [%s] as there is no previous global label\n",varbuffer); return; */ // not optimal but! curlabelname=TxtStrDup(varbuffer); MemFree(varbuffer); touched=1; // cause realloc! curlabel.iw=-1; curlabel.name=varbuffer=curlabelname; curlabel.crc=GetCRC(varbuffer); } } break; default: if (!touched) { curlabel.iw=ae->idx; } else { curlabel.iw=-1; curlabel.name=varbuffer; } curlabel.crc=GetCRC(varbuffer); curlabelname=varbuffer; /* global labels set new reference */ if (ae->lastglobalalloc) MemFree(ae->lastgloballabel); ae->lastgloballabel=ae->wl[ae->idx].w; ae->lastsuperglobal=ae->wl[ae->idx].w; ae->lastgloballabellen=strlen(ae->wl[ae->idx].w); ae->lastglobalalloc=0; //printf("SET global label [%s] l=%d\n",ae->lastgloballabel,ae->lastgloballabellen); break; } /* contrôle dico uniquement avec des labels non locaux */ if (SearchDico(ae,curlabelname,curlabel.crc)) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"cannot create label [%s] as there is already a variable with the same name\n",curlabelname); return; } if(SearchAlias(ae,curlabel.crc,curlabelname)!=-1) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"cannot create label [%s] as there is already an alias with the same name\n",curlabelname); return; } } curlabel.ptr=ae->codeadr; curlabel.ibank=ae->activebank; curlabel.iorgzone=ae->io-1; curlabel.lz=ae->lz; } if ((searched_label=SearchLabel(ae,curlabelname,curlabel.crc))!=NULL) { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"Duplicate label [%s] - previously defined in [%s:%d]\n",curlabelname,ae->filename[searched_label->fileidx],searched_label->fileline); if (curlabel.iw==-1) MemFree(curlabelname); } else { //printf("PushLabel(%s) name=%s crc=%X\n",curlabelname,curlabel.name?curlabel.name:"null",curlabel.crc); curlabel.fileidx=ae->wl[ae->idx].ifile; curlabel.fileline=ae->wl[ae->idx].l; curlabel.autorise_export=ae->autorise_export; curlabel.backidx=ae->il; ObjectArrayAddDynamicValueConcat((void **)&ae->label,&ae->il,&ae->ml,&curlabel,sizeof(curlabel)); InsertLabelToTree(ae,&curlabel); } if (!touched) MemFree(varbuffer); } unsigned char *EncodeSnapshotRLE(unsigned char *memin, int *lenout) { #undef FUNC #define FUNC "EncodeSnapshotRLE" int i,cpt,idx=0; unsigned char *memout=NULL; memout=MemMalloc(65540); for (i=0;i<65536;) { for (cpt=1;cpt<255;cpt++) if (memin[i]!=memin[i+cpt]) break; if (cpt>=3 || memin[i]==0xE5) { memout[idx++]=0xE5; memout[idx++]=cpt; memout[idx++]=memin[i]; i+=cpt; } else { memout[idx++]=memin[i++]; } } if (lenout) *lenout=idx; if (idx<65536) return memout; MemFree(memout); return NULL; } #undef FUNC #define FUNC "Instruction CORE" void _IN(struct s_assenv *ae) { if (!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) { if (strcmp(ae->wl[ae->idx+2].w,"(C)")==0) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_0: case CRC_F:___output(ae,0xED);___output(ae,0x70);ae->nop+=4;break; case CRC_A:___output(ae,0xED);___output(ae,0x78);ae->nop+=3;break; case CRC_B:___output(ae,0xED);___output(ae,0x40);ae->nop+=4;break; case CRC_C:___output(ae,0xED);___output(ae,0x48);ae->nop+=4;break; case CRC_D:___output(ae,0xED);___output(ae,0x50);ae->nop+=4;break; case CRC_E:___output(ae,0xED);___output(ae,0x58);ae->nop+=4;break; case CRC_H:___output(ae,0xED);___output(ae,0x60);ae->nop+=4;break; case CRC_L:___output(ae,0xED);___output(ae,0x68);ae->nop+=4;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is IN [0,F,A,B,C,D,E,H,L],(C)\n"); } } else if (strcmp(ae->wl[ae->idx+1].w,"A")==0 && StringIsMem(ae->wl[ae->idx+2].w)) { ___output(ae,0xDB); PushExpression(ae,ae->idx+2,E_EXPRESSION_V8); ae->nop+=3; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IN [0,F,A,B,C,D,E,H,L],(C) or IN A,(n) only\n"); } ae->idx+=2; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IN [0,F,A,B,C,D,E,H,L],(C) or IN A,(n) only\n"); } } void _OUT(struct s_assenv *ae) { if (!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) { if (strcmp(ae->wl[ae->idx+1].w,"(C)")==0) { switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_0:___output(ae,0xED);___output(ae,0x71);ae->nop+=4;break; case CRC_A:___output(ae,0xED);___output(ae,0x79);ae->nop+=4;break; case CRC_B:___output(ae,0xED);___output(ae,0x41);ae->nop+=4;break; case CRC_C:___output(ae,0xED);___output(ae,0x49);ae->nop+=4;break; case CRC_D:___output(ae,0xED);___output(ae,0x51);ae->nop+=4;break; case CRC_E:___output(ae,0xED);___output(ae,0x59);ae->nop+=4;break; case CRC_H:___output(ae,0xED);___output(ae,0x61);ae->nop+=4;break; case CRC_L:___output(ae,0xED);___output(ae,0x69);ae->nop+=4;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is OUT (C),[0,A,B,C,D,E,H,L]\n"); } } else if (strcmp(ae->wl[ae->idx+2].w,"A")==0 && StringIsMem(ae->wl[ae->idx+1].w)) { ___output(ae,0xD3); PushExpression(ae,ae->idx+1,E_EXPRESSION_V8); ae->nop+=3; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"OUT (C),[0,A,B,C,D,E,H,L] or OUT (n),A only\n"); } ae->idx+=2; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"OUT (C),[0,A,B,C,D,E,H,L] or OUT (n),A only\n"); } } void _EX(struct s_assenv *ae) { if (!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_HL: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_DE:___output(ae,0xEB);ae->nop+=1;break; case CRC_MSP:___output(ae,0xE3);ae->nop+=6;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is EX HL,[(SP),DE]\n"); } break; case CRC_AF: if (strcmp(ae->wl[ae->idx+2].w,"AF'")==0) { ___output(ae,0x08);ae->nop+=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is EX AF,AF'\n"); } break; case CRC_MSP: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_HL:___output(ae,0xE3);ae->nop+=6;break; case CRC_IX:___output(ae,0xDD);___output(ae,0xE3);ae->nop+=7;break; case CRC_IY:___output(ae,0xFD);___output(ae,0xE3);ae->nop+=7;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is EX (SP),[HL,IX,IY]\n"); } break; case CRC_DE: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_HL:___output(ae,0xEB);ae->nop+=1;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is EX DE,HL\n"); } break; case CRC_IX: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_MSP:___output(ae,0xDD);___output(ae,0xE3);ae->nop+=7;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is EX IX,(SP)\n"); } break; case CRC_IY: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_MSP:___output(ae,0xFD);___output(ae,0xE3);ae->nop+=7;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is EX IY,(SP)\n"); } break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is EX [AF,DE,HL,(SP),IX,IY],reg16\n"); } ae->idx+=2; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use EX reg16,reg16\n"); } } void _SBC(struct s_assenv *ae) { if ((!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) || ((!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) && strcmp(ae->wl[ae->idx+1].w,"A")==0)) { if (!ae->wl[ae->idx+1].t) ae->idx++; /* do implicit A */ switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_A:___output(ae,0x9F);ae->nop+=1;break; case CRC_MHL:___output(ae,0x9E);ae->nop+=2;break; case CRC_B:___output(ae,0x98);ae->nop+=1;break; case CRC_C:___output(ae,0x99);ae->nop+=1;break; case CRC_D:___output(ae,0x9A);ae->nop+=1;break; case CRC_E:___output(ae,0x9B);ae->nop+=1;break; case CRC_H:___output(ae,0x9C);ae->nop+=1;break; case CRC_L:___output(ae,0x9D);ae->nop+=1;break; case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x9C);ae->nop+=2;break; case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x9D);ae->nop+=2;break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x9C);ae->nop+=2;break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x9D);ae->nop+=2;break; case CRC_IX:case CRC_IY: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use SBC with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n"); ae->idx++; return; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0x9E); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=3; } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0x9E); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=3; } else { ___output(ae,0xDE); PushExpression(ae,ae->idx+1,E_EXPRESSION_V8); ae->nop+=2; } } ae->idx++; } else if (!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_HL: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_BC:___output(ae,0xED);___output(ae,0x42);ae->nop+=4;break; case CRC_DE:___output(ae,0xED);___output(ae,0x52);ae->nop+=4;break; case CRC_HL:___output(ae,0xED);___output(ae,0x62);ae->nop+=4;break; case CRC_SP:___output(ae,0xED);___output(ae,0x72);ae->nop+=4;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SBC HL,[BC,DE,HL,SP]\n"); } break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SBC HL,[BC,DE,HL,SP]\n"); } ae->idx+=2; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Invalid syntax for SBC\n"); } } void _ADC(struct s_assenv *ae) { if ((!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) || ((!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) && strcmp(ae->wl[ae->idx+1].w,"A")==0)) { if (!ae->wl[ae->idx+1].t) ae->idx++; /* also implicit A */ switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_A:___output(ae,0x8F);ae->nop+=1;break; case CRC_MHL:___output(ae,0x8E);ae->nop+=2;break; case CRC_B:___output(ae,0x88);ae->nop+=1;break; case CRC_C:___output(ae,0x89);ae->nop+=1;break; case CRC_D:___output(ae,0x8A);ae->nop+=1;break; case CRC_E:___output(ae,0x8B);ae->nop+=1;break; case CRC_H:___output(ae,0x8C);ae->nop+=1;break; case CRC_L:___output(ae,0x8D);ae->nop+=1;break; case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x8C);ae->nop+=2;break; case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x8D);ae->nop+=2;break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x8C);ae->nop+=2;break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x8D);ae->nop+=2;break; case CRC_IX:case CRC_IY: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use ADC with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n"); ae->idx++; return; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0x8E); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=3; } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0x8E); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=3; } else { ___output(ae,0xCE); PushExpression(ae,ae->idx+1,E_EXPRESSION_V8); ae->nop+=2; } } ae->idx++; } else if (!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_HL: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_BC:___output(ae,0xED);___output(ae,0x4A);ae->nop+=4;break; case CRC_DE:___output(ae,0xED);___output(ae,0x5A);ae->nop+=4;break; case CRC_HL:___output(ae,0xED);___output(ae,0x6A);ae->nop+=4;break; case CRC_SP:___output(ae,0xED);___output(ae,0x7A);ae->nop+=4;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is ADC HL,[BC,DE,HL,SP]\n"); } break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is ADC HL,[BC,DE,HL,SP]\n"); } ae->idx+=2; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Invalid syntax for ADC\n"); } } void _ADD(struct s_assenv *ae) { if ((!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) || ((!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) && strcmp(ae->wl[ae->idx+1].w,"A")==0)) { if (!ae->wl[ae->idx+1].t) ae->idx++; /* also implicit A */ switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_A:___output(ae,0x87);ae->nop+=1;break; case CRC_MHL:___output(ae,0x86);ae->nop+=2;break; case CRC_B:___output(ae,0x80);ae->nop+=1;break; case CRC_C:___output(ae,0x81);ae->nop+=1;break; case CRC_D:___output(ae,0x82);ae->nop+=1;break; case CRC_E:___output(ae,0x83);ae->nop+=1;break; case CRC_H:___output(ae,0x84);ae->nop+=1;break; case CRC_L:___output(ae,0x85);ae->nop+=1;break; case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x84);ae->nop+=2;break; case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x85);ae->nop+=2;break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x84);ae->nop+=2;break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x85);ae->nop+=2;break; case CRC_IX:case CRC_IY: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use ADD with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n"); ae->idx++; return; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0x86); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=5; } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0x86); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=5; } else { ___output(ae,0xC6); PushExpression(ae,ae->idx+1,E_EXPRESSION_V8); ae->nop+=2; } } ae->idx++; } else if (!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_HL: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_BC:___output(ae,0x09);ae->nop+=3;break; case CRC_DE:___output(ae,0x19);ae->nop+=3;break; case CRC_HL:___output(ae,0x29);ae->nop+=3;break; case CRC_SP:___output(ae,0x39);ae->nop+=3;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is ADD HL,[BC,DE,HL,SP]\n"); } break; case CRC_IX: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_BC:___output(ae,0xDD);___output(ae,0x09);ae->nop+=4;break; case CRC_DE:___output(ae,0xDD);___output(ae,0x19);ae->nop+=4;break; case CRC_IX:___output(ae,0xDD);___output(ae,0x29);ae->nop+=4;break; case CRC_SP:___output(ae,0xDD);___output(ae,0x39);ae->nop+=4;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is ADD IX,[BC,DE,IX,SP]\n"); } break; case CRC_IY: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_BC:___output(ae,0xFD);___output(ae,0x09);ae->nop+=4;break; case CRC_DE:___output(ae,0xFD);___output(ae,0x19);ae->nop+=4;break; case CRC_IY:___output(ae,0xFD);___output(ae,0x29);ae->nop+=4;break; case CRC_SP:___output(ae,0xFD);___output(ae,0x39);ae->nop+=4;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is ADD IY,[BC,DE,IY,SP]\n"); } break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is ADD [HL,IX,IY],reg16\n"); } ae->idx+=2; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Invalid syntax for ADD\n"); } } void _CP(struct s_assenv *ae) { if ((!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) || ((!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) && strcmp(ae->wl[ae->idx+1].w,"A")==0)) { if (!ae->wl[ae->idx+1].t) ae->idx++; /* also implicit A */ switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_A:___output(ae,0xBF);ae->nop+=1;break; case CRC_MHL:___output(ae,0xBE);ae->nop+=2;break; case CRC_B:___output(ae,0xB8);ae->nop+=1;break; case CRC_C:___output(ae,0xB9);ae->nop+=1;break; case CRC_D:___output(ae,0xBA);ae->nop+=1;break; case CRC_E:___output(ae,0xBB);ae->nop+=1;break; case CRC_H:___output(ae,0xBC);ae->nop+=1;break; case CRC_L:___output(ae,0xBD);ae->nop+=1;break; case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0xBC);ae->nop+=2;break; case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0xBD);ae->nop+=2;break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0xBC);ae->nop+=2;break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0xBD);ae->nop+=2;break; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0xBE); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=5; } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0xBE); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=5; } else { ___output(ae,0xFE); PushExpression(ae,ae->idx+1,E_EXPRESSION_V8); ae->nop+=2; } } ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Syntax is CP reg8/(reg16)\n"); } } void _RET(struct s_assenv *ae) { if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_NZ:___output(ae,0xC0);ae->nop+=2;break; case CRC_Z:___output(ae,0xC8);ae->nop+=2;break; case CRC_C:___output(ae,0xD8);ae->nop+=2;break; case CRC_NC:___output(ae,0xD0);ae->nop+=2;break; case CRC_PE:___output(ae,0xE8);ae->nop+=2;break; case CRC_PO:___output(ae,0xE0);ae->nop+=2;break; case CRC_P:___output(ae,0xF0);ae->nop+=2;break; case CRC_M:___output(ae,0xF8);ae->nop+=2;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Available flags for RET are C,NC,Z,NZ,PE,PO,P,M\n"); } ae->idx++; } else if (ae->wl[ae->idx].t==1) { ___output(ae,0xC9); ae->nop+=3; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Invalid RET syntax\n"); } } void _CALL(struct s_assenv *ae) { if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==0 && ae->wl[ae->idx+2].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_C:___output(ae,0xDC);ae->nop+=3;break; case CRC_Z:___output(ae,0xCC);ae->nop+=3;break; case CRC_NZ:___output(ae,0xC4);ae->nop+=3;break; case CRC_NC:___output(ae,0xD4);ae->nop+=3;break; case CRC_PE:___output(ae,0xEC);ae->nop+=3;break; case CRC_PO:___output(ae,0xE4);ae->nop+=3;break; case CRC_P:___output(ae,0xF4);ae->nop+=3;break; case CRC_M:___output(ae,0xFC);ae->nop+=3;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Available flags for CALL are C,NC,Z,NZ,PE,PO,P,M\n"); } PushExpression(ae,ae->idx+2,E_EXPRESSION_V16C); ae->idx+=2; } else if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { ___output(ae,0xCD); PushExpression(ae,ae->idx+1,E_EXPRESSION_V16C); ae->idx++; ae->nop+=5; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Invalid CALL syntax\n"); } } void _JR(struct s_assenv *ae) { if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==0 && ae->wl[ae->idx+2].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_NZ:___output(ae,0x20);ae->nop+=2;break; case CRC_C:___output(ae,0x38);ae->nop+=2;break; case CRC_Z:___output(ae,0x28);ae->nop+=2;break; case CRC_NC:___output(ae,0x30);ae->nop+=2;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Available flags for JR are C,NC,Z,NZ\n"); } PushExpression(ae,ae->idx+2,E_EXPRESSION_J8); ae->idx+=2; } else if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { ___output(ae,0x18); PushExpression(ae,ae->idx+1,E_EXPRESSION_J8); ae->idx++; ae->nop+=3; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Invalid JR syntax\n"); } } void _JP(struct s_assenv *ae) { if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==0 && ae->wl[ae->idx+2].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_C:___output(ae,0xDA);ae->nop+=3;break; case CRC_Z:___output(ae,0xCA);ae->nop+=3;break; case CRC_NZ:___output(ae,0xC2);ae->nop+=3;break; case CRC_NC:___output(ae,0xD2);ae->nop+=3;break; case CRC_PE:___output(ae,0xEA);ae->nop+=3;break; case CRC_PO:___output(ae,0xE2);ae->nop+=3;break; case CRC_P:___output(ae,0xF2);ae->nop+=3;break; case CRC_M:___output(ae,0xFA);ae->nop+=3;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Available flags for JP are C,NC,Z,NZ,PE,PO,P,M\n"); } if (!strcmp(ae->wl[ae->idx+2].w,"(IX)") || !strcmp(ae->wl[ae->idx+2].w,"(IY)")) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"conditionnal JP cannot use register adressing\n"); } else { PushExpression(ae,ae->idx+2,E_EXPRESSION_V16); } ae->idx+=2; } else if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_HL:case CRC_MHL:___output(ae,0xE9);ae->nop+=1;break; case CRC_IX:case CRC_MIX:___output(ae,0xDD);___output(ae,0xE9);ae->nop+=2;break; case CRC_IY:case CRC_MIY:___output(ae,0xFD);___output(ae,0xE9);ae->nop+=2;break; default: ___output(ae,0xC3); PushExpression(ae,ae->idx+1,E_EXPRESSION_V16); } ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Invalid JP syntax\n"); } } void _DEC(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { do { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_A:___output(ae,0x3D);ae->nop+=1;break; case CRC_B:___output(ae,0x05);ae->nop+=1;break; case CRC_C:___output(ae,0x0D);ae->nop+=1;break; case CRC_D:___output(ae,0x15);ae->nop+=1;break; case CRC_E:___output(ae,0x1D);ae->nop+=1;break; case CRC_H:___output(ae,0x25);ae->nop+=1;break; case CRC_L:___output(ae,0x2D);ae->nop+=1;break; case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x25);ae->nop+=2;break; case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x2D);ae->nop+=2;break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x25);ae->nop+=2;break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x2D);ae->nop+=2;break; case CRC_BC:___output(ae,0x0B);ae->nop+=2;break; case CRC_DE:___output(ae,0x1B);ae->nop+=2;break; case CRC_HL:___output(ae,0x2B);ae->nop+=2;break; case CRC_IX:___output(ae,0xDD);___output(ae,0x2B);ae->nop+=3;break; case CRC_IY:___output(ae,0xFD);___output(ae,0x2B);ae->nop+=3;break; case CRC_SP:___output(ae,0x3B);ae->nop+=2;break; case CRC_MHL:___output(ae,0x35);ae->nop+=3;break; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0x35); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=6; } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0x35); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=6; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use DEC with A,B,C,D,E,H,L,XH,XL,YH,YL,BC,DE,HL,SP,(HL),(IX),(IY)\n"); } } ae->idx++; } while (ae->wl[ae->idx].t==0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use DEC with A,B,C,D,E,H,L,XH,XL,YH,YL,BC,DE,HL,SP,(HL),(IX),(IY)\n"); } } void _INC(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { do { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_A:___output(ae,0x3C);ae->nop+=1;break; case CRC_B:___output(ae,0x04);ae->nop+=1;break; case CRC_C:___output(ae,0x0C);ae->nop+=1;break; case CRC_D:___output(ae,0x14);ae->nop+=1;break; case CRC_E:___output(ae,0x1C);ae->nop+=1;break; case CRC_H:___output(ae,0x24);ae->nop+=1;break; case CRC_L:___output(ae,0x2C);ae->nop+=1;break; case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x24);ae->nop+=2;break; case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x2C);ae->nop+=2;break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x24);ae->nop+=2;break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x2C);ae->nop+=2;break; case CRC_BC:___output(ae,0x03);ae->nop+=2;break; case CRC_DE:___output(ae,0x13);ae->nop+=2;break; case CRC_HL:___output(ae,0x23);ae->nop+=2;break; case CRC_IX:___output(ae,0xDD);___output(ae,0x23);ae->nop+=3;break; case CRC_IY:___output(ae,0xFD);___output(ae,0x23);ae->nop+=3;break; case CRC_SP:___output(ae,0x33);ae->nop+=2;break; case CRC_MHL:___output(ae,0x34);ae->nop+=3;break; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0x34); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=6; } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0x34); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=6; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use INC with A,B,C,D,E,H,L,XH,XL,YH,YL,BC,DE,HL,SP,(HL),(IX),(IY)\n"); } } ae->idx++; } while (ae->wl[ae->idx].t==0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use INC with A,B,C,D,E,H,L,XH,XL,YH,YL,BC,DE,HL,SP,(HL),(IX),(IY)\n"); } } void _SUB(struct s_assenv *ae) { #ifdef OPCODE #undef OPCODE #endif #define OPCODE 0x90 if ((!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) || ((!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) && strcmp(ae->wl[ae->idx+1].w,"A")==0)) { if (!ae->wl[ae->idx+1].t) ae->idx++; switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_A:___output(ae,OPCODE+7);ae->nop+=1;break; case CRC_MHL:___output(ae,OPCODE+6);ae->nop+=2;break; case CRC_B:___output(ae,OPCODE);ae->nop+=1;break; case CRC_C:___output(ae,OPCODE+1);ae->nop+=1;break; case CRC_D:___output(ae,OPCODE+2);ae->nop+=1;break; case CRC_E:___output(ae,OPCODE+3);ae->nop+=1;break; case CRC_H:___output(ae,OPCODE+4);ae->nop+=1;break; case CRC_L:___output(ae,OPCODE+5);ae->nop+=1;break; case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,OPCODE+4);ae->nop+=2;break; case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,OPCODE+5);ae->nop+=2;break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,OPCODE+4);ae->nop+=2;break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,OPCODE+5);ae->nop+=2;break; case CRC_IX:case CRC_IY: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use SUB with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n"); ae->idx++; return; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,OPCODE+6); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=5; } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,OPCODE+6); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=5; } else { ___output(ae,0xD6); PushExpression(ae,ae->idx+1,E_EXPRESSION_V8); ae->nop+=2; } } ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use SUB with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n"); } } void _AND(struct s_assenv *ae) { #ifdef OPCODE #undef OPCODE #endif #define OPCODE 0xA0 if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_A:___output(ae,OPCODE+7);ae->nop+=1;break; case CRC_MHL:___output(ae,OPCODE+6);ae->nop+=2;break; case CRC_B:___output(ae,OPCODE);ae->nop+=1;break; case CRC_C:___output(ae,OPCODE+1);ae->nop+=1;break; case CRC_D:___output(ae,OPCODE+2);ae->nop+=1;break; case CRC_E:___output(ae,OPCODE+3);ae->nop+=1;break; case CRC_H:___output(ae,OPCODE+4);ae->nop+=1;break; case CRC_L:___output(ae,OPCODE+5);ae->nop+=1;break; case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,OPCODE+4);ae->nop+=2;break; case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,OPCODE+5);ae->nop+=2;break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,OPCODE+4);ae->nop+=2;break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,OPCODE+5);ae->nop+=2;break; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,OPCODE+6); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=5; } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,OPCODE+6); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=5; } else { ___output(ae,0xE6); PushExpression(ae,ae->idx+1,E_EXPRESSION_V8); ae->nop+=2; } } ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use AND with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n"); } } void _OR(struct s_assenv *ae) { #ifdef OPCODE #undef OPCODE #endif #define OPCODE 0xB0 if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_A:___output(ae,OPCODE+7);ae->nop+=1;break; case CRC_MHL:___output(ae,OPCODE+6);ae->nop+=2;break; case CRC_B:___output(ae,OPCODE);ae->nop+=1;break; case CRC_C:___output(ae,OPCODE+1);ae->nop+=1;break; case CRC_D:___output(ae,OPCODE+2);ae->nop+=1;break; case CRC_E:___output(ae,OPCODE+3);ae->nop+=1;break; case CRC_H:___output(ae,OPCODE+4);ae->nop+=1;break; case CRC_L:___output(ae,OPCODE+5);ae->nop+=1;break; case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,OPCODE+4);ae->nop+=2;break; case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,OPCODE+5);ae->nop+=2;break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,OPCODE+4);ae->nop+=2;break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,OPCODE+5);ae->nop+=2;break; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,OPCODE+6); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=5; } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,OPCODE+6); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=5; } else { ___output(ae,0xF6); PushExpression(ae,ae->idx+1,E_EXPRESSION_V8); ae->nop+=2; } } ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use OR with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n"); } } void _XOR(struct s_assenv *ae) { #ifdef OPCODE #undef OPCODE #endif #define OPCODE 0xA8 if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_A:___output(ae,OPCODE+7);ae->nop+=1;break; case CRC_MHL:___output(ae,OPCODE+6);ae->nop+=2;break; case CRC_B:___output(ae,OPCODE);ae->nop+=1;break; case CRC_C:___output(ae,OPCODE+1);ae->nop+=1;break; case CRC_D:___output(ae,OPCODE+2);ae->nop+=1;break; case CRC_E:___output(ae,OPCODE+3);ae->nop+=1;break; case CRC_H:___output(ae,OPCODE+4);ae->nop+=1;break; case CRC_L:___output(ae,OPCODE+5);ae->nop+=1;break; case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,OPCODE+4);ae->nop+=2;break; case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,OPCODE+5);ae->nop+=2;break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,OPCODE+4);ae->nop+=2;break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,OPCODE+5);ae->nop+=2;break; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,OPCODE+6); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=5; } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,OPCODE+6); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ae->nop+=5; } else { ___output(ae,0xEE); PushExpression(ae,ae->idx+1,E_EXPRESSION_V8); ae->nop+=2; } } ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use XOR with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n"); } } void _POP(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { do { ae->idx++; switch (GetCRC(ae->wl[ae->idx].w)) { case CRC_AF:___output(ae,0xF1);ae->nop+=3;break; case CRC_BC:___output(ae,0xC1);ae->nop+=3;break; case CRC_DE:___output(ae,0xD1);ae->nop+=3;break; case CRC_HL:___output(ae,0xE1);ae->nop+=3;break; case CRC_IX:___output(ae,0xDD);___output(ae,0xE1);ae->nop+=4;break; case CRC_IY:___output(ae,0xFD);___output(ae,0xE1);ae->nop+=4;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use POP with AF,BC,DE,HL,IX,IY\n"); } } while (ae->wl[ae->idx].t!=1); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"POP need at least one parameter\n"); } } void _PUSH(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { do { ae->idx++; switch (GetCRC(ae->wl[ae->idx].w)) { case CRC_AF:___output(ae,0xF5);ae->nop+=4;break; case CRC_BC:___output(ae,0xC5);ae->nop+=4;break; case CRC_DE:___output(ae,0xD5);ae->nop+=4;break; case CRC_HL:___output(ae,0xE5);ae->nop+=4;break; case CRC_IX:___output(ae,0xDD);___output(ae,0xE5);ae->nop+=5;break; case CRC_IY:___output(ae,0xFD);___output(ae,0xE5);ae->nop+=5;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use PUSH with AF,BC,DE,HL,IX,IY\n"); } } while (ae->wl[ae->idx].t!=1); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"PUSH need at least one parameter\n"); } } void _IM(struct s_assenv *ae) { if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { /* la valeur du parametre va definir l'opcode du IM */ ___output(ae,0xED); PushExpression(ae,ae->idx+1,E_EXPRESSION_IM); ae->idx++; ae->nop+=2; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IM need one parameter\n"); } } void _RLCA(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0x7); ae->nop+=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RLCA does not need parameter\n"); } } void _RRCA(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xF); ae->nop+=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RRCA does not need parameter\n"); } } void _NEG(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xED); ___output(ae,0x44); ae->nop+=2; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"NEG does not need parameter\n"); } } void _DAA(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0x27); ae->nop+=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DAA does not need parameter\n"); } } void _CPL(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0x2F); ae->nop+=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CPL does not need parameter\n"); } } void _RETI(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xED); ___output(ae,0x4D); ae->nop+=4; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RETI does not need parameter\n"); } } void _SCF(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0x37); ae->nop+=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SCF does not need parameter\n"); } } void _LDD(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xED); ___output(ae,0xA8); ae->nop+=5; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LDD does not need parameter\n"); } } void _LDDR(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xED); ___output(ae,0xB8); ae->nop+=5; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LDDR does not need parameter\n"); } } void _LDI(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xED); ___output(ae,0xA0); ae->nop+=5; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LDI does not need parameter\n"); } } void _LDIR(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xED); ___output(ae,0xB0); ae->nop+=5; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LDIR does not need parameter\n"); } } void _CCF(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0x3F); ae->nop+=5; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CCF does not need parameter\n"); } } void _CPD(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xED); ___output(ae,0xA9); ae->nop+=4; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CPD does not need parameter\n"); } } void _CPDR(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xED); ___output(ae,0xB9); ae->nop+=4; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CPDR does not need parameter\n"); } } void _CPI(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xED); ___output(ae,0xA1); ae->nop+=4; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CPI does not need parameter\n"); } } void _CPIR(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xED); ___output(ae,0xB1); ae->nop+=4; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CPIR does not need parameter\n"); } } void _OUTD(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xED); ___output(ae,0xAB); ae->nop+=5; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"OUTD does not need parameter\n"); } } void _OTDR(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xED); ___output(ae,0xBB); ae->nop+=5; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"OTDR does not need parameter\n"); } } void _OUTI(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xED); ___output(ae,0xA3); ae->nop+=5; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"OUTI does not need parameter\n"); } } void _OTIR(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xED); ___output(ae,0xB3); ae->nop+=5; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"OTIR does not need parameter\n"); } } void _RETN(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xED); ___output(ae,0x45); ae->nop+=4; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RETN does not need parameter\n"); } } void _IND(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xED); ___output(ae,0xAA); ae->nop+=5; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IND does not need parameter\n"); } } void _INDR(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xED); ___output(ae,0xBA); ae->nop+=5; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INDR does not need parameter\n"); } } void _INI(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xED); ___output(ae,0xA2); ae->nop+=5; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INI does not need parameter\n"); } } void _INIR(struct s_assenv *ae) { if (ae->wl[ae->idx].t==1) { ___output(ae,0xED); ___output(ae,0xB2); ae->nop+=5; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INIR does not need parameter\n"); } } void _EXX(struct s_assenv *ae) { if (ae->wl[ae->idx].t==1) { ___output(ae,0xD9); ae->nop+=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"EXX does not need parameter\n"); } } void _HALT(struct s_assenv *ae) { if (ae->wl[ae->idx].t==1) { ___output(ae,0x76); ae->nop+=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"HALT does not need parameter\n"); } } void _RLA(struct s_assenv *ae) { if (ae->wl[ae->idx].t==1) { ___output(ae,0x17); ae->nop+=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RLA does not need parameter\n"); } } void _RRA(struct s_assenv *ae) { if (ae->wl[ae->idx].t==1) { ___output(ae,0x1F); ae->nop+=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RRA does not need parameter\n"); } } void _RLD(struct s_assenv *ae) { if (ae->wl[ae->idx].t==1) { ___output(ae,0xED); ___output(ae,0x6F); ae->nop+=5; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RLD does not need parameter\n"); } } void _RRD(struct s_assenv *ae) { if (ae->wl[ae->idx].t==1) { ___output(ae,0xED); ___output(ae,0x67); ae->nop+=5; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RRD does not need parameter\n"); } } void _EXA(struct s_assenv *ae) { if (ae->wl[ae->idx].t==1) { ___output(ae,0x08);ae->nop+=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"EXA alias does not need parameter\n"); } } void _NOP(struct s_assenv *ae) { int o; if (ae->wl[ae->idx].t) { ___output(ae,0x00); ae->nop+=1; } else if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); o=RoundComputeExpressionCore(ae,ae->wl[ae->idx+1].w,ae->codeadr,0); if (o>=0) { while (o>0) { ___output(ae,0x00); ae->nop+=1; o--; } } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"NOP is supposed to be used without parameter or with one optional parameter\n"); } } void _DI(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xF3); ae->nop+=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DI does not need parameter\n"); } } void _EI(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xFB); ae->nop+=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"EI does not need parameter\n"); } } void _RST(struct s_assenv *ae) { if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t!=2) { if (!strcmp(ae->wl[ae->idx+1].w,"(IY)") || !strcmp(ae->wl[ae->idx+1].w,"(IX)")) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RST cannot use IX or IY\n"); } else { /* la valeur du parametre va definir l'opcode du RST */ PushExpression(ae,ae->idx+1,E_EXPRESSION_RST); } ae->idx++; ae->nop+=4; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RST need one parameter\n"); } } void _DJNZ(struct s_assenv *ae) { if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { if (IsRegister(ae->wl[ae->idx+1].w)) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DJNZ cannot use register\n"); } else if (strcmp("(IX)",ae->wl[ae->idx+1].w)==0 || strcmp("(IY)",ae->wl[ae->idx+1].w)==0) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DJNZ cannot use register\n"); } else { ___output(ae,0x10); PushExpression(ae,ae->idx+1,E_EXPRESSION_J8); ae->nop+=3; } ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DJNZ need one parameter\n"); } } void _LD(struct s_assenv *ae) { /* on check qu'il y a au moins deux parametres */ if (!ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_A: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_I:___output(ae,0xED);___output(ae,0x57);ae->nop+=3;break; case CRC_R:___output(ae,0xED);___output(ae,0x5F);ae->nop+=3;break; case CRC_B:___output(ae,0x78);ae->nop+=1;break; case CRC_C:___output(ae,0x79);ae->nop+=1;break; case CRC_D:___output(ae,0x7A);ae->nop+=1;break; case CRC_E:___output(ae,0x7B);ae->nop+=1;break; case CRC_H:___output(ae,0x7C);ae->nop+=1;break; case CRC_L:___output(ae,0x7D);ae->nop+=1;break; case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x7C);ae->nop+=2;break; case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x7D);ae->nop+=2;break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x7C);ae->nop+=2;break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x7D);ae->nop+=2;break; case CRC_MHL:___output(ae,0x7E);ae->nop+=2;break; case CRC_A:___output(ae,0x7F);ae->nop+=1;break; case CRC_MBC:___output(ae,0x0A);ae->nop+=2;break; case CRC_MDE:___output(ae,0x1A);ae->nop+=2;break; default: /* (ix+expression) (iy+expression) (expression) expression */ if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0x7E); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=5; } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0x7E); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=5; } else if (StringIsMem(ae->wl[ae->idx+2].w)) { ___output(ae,0x3A); PushExpression(ae,ae->idx+2,E_EXPRESSION_V16); ae->nop+=4; } else { ___output(ae,0x3E); PushExpression(ae,ae->idx+2,E_EXPRESSION_V8); ae->nop+=2; } } break; case CRC_I: if (GetCRC(ae->wl[ae->idx+2].w)==CRC_A) { ___output(ae,0xED);___output(ae,0x47); ae->nop+=3; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD I,A only\n"); } break; case CRC_R: if (GetCRC(ae->wl[ae->idx+2].w)==CRC_A) { ___output(ae,0xED);___output(ae,0x4F); ae->nop+=3; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD R,A only\n"); } break; case CRC_B: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:___output(ae,0x40);ae->nop+=1;break; case CRC_C:___output(ae,0x41);ae->nop+=1;break; case CRC_D:___output(ae,0x42);ae->nop+=1;break; case CRC_E:___output(ae,0x43);ae->nop+=1;break; case CRC_H:___output(ae,0x44);ae->nop+=1;break; case CRC_L:___output(ae,0x45);ae->nop+=1;break; case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x44);ae->nop+=2;break; case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x45);ae->nop+=2;break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x44);ae->nop+=2;break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x45);ae->nop+=2;break; case CRC_MHL:___output(ae,0x46);ae->nop+=2;break; case CRC_A:___output(ae,0x47);ae->nop+=1;break; default: /* (ix+expression) (iy+expression) expression */ if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0x46); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=5; } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0x46); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=5; } else { ___output(ae,0x06); PushExpression(ae,ae->idx+2,E_EXPRESSION_V8); ae->nop+=2; } } break; case CRC_C: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:___output(ae,0x48);ae->nop+=1;break; case CRC_C:___output(ae,0x49);ae->nop+=1;break; case CRC_D:___output(ae,0x4A);ae->nop+=1;break; case CRC_E:___output(ae,0x4B);ae->nop+=1;break; case CRC_H:___output(ae,0x4C);ae->nop+=1;break; case CRC_L:___output(ae,0x4D);ae->nop+=1;break; case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x4C);ae->nop+=2;break; case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x4D);ae->nop+=2;break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x4C);ae->nop+=2;break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x4D);ae->nop+=2;break; case CRC_MHL:___output(ae,0x4E);ae->nop+=2;break; case CRC_A:___output(ae,0x4F);ae->nop+=1;break; default: /* (ix+expression) (iy+expression) expression */ if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0x4E); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=5; } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0x4E); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=5; } else { ___output(ae,0x0E); PushExpression(ae,ae->idx+2,E_EXPRESSION_V8); ae->nop+=2; } } break; case CRC_D: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:___output(ae,0x50);ae->nop+=1;break; case CRC_C:___output(ae,0x51);ae->nop+=1;break; case CRC_D:___output(ae,0x52);ae->nop+=1;break; case CRC_E:___output(ae,0x53);ae->nop+=1;break; case CRC_H:___output(ae,0x54);ae->nop+=1;break; case CRC_L:___output(ae,0x55);ae->nop+=1;break; case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x54);ae->nop+=2;break; case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x55);ae->nop+=2;break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x54);ae->nop+=2;break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x55);ae->nop+=2;break; case CRC_MHL:___output(ae,0x56);ae->nop+=2;break; case CRC_A:___output(ae,0x57);ae->nop+=1;break; default: /* (ix+expression) (iy+expression) expression */ if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0x56); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=5; } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0x56); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=5; } else { ___output(ae,0x16); PushExpression(ae,ae->idx+2,E_EXPRESSION_V8); ae->nop+=2; } } break; case CRC_E: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:___output(ae,0x58);ae->nop+=1;break; case CRC_C:___output(ae,0x59);ae->nop+=1;break; case CRC_D:___output(ae,0x5A);ae->nop+=1;break; case CRC_E:___output(ae,0x5B);ae->nop+=1;break; case CRC_H:___output(ae,0x5C);ae->nop+=1;break; case CRC_L:___output(ae,0x5D);ae->nop+=1;break; case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x5C);ae->nop+=2;break; case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x5D);ae->nop+=2;break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x5C);ae->nop+=2;break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x5D);ae->nop+=2;break; case CRC_MHL:___output(ae,0x5E);ae->nop+=2;break; case CRC_A:___output(ae,0x5F);ae->nop+=1;break; default: /* (ix+expression) (iy+expression) expression */ if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0x5E); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=5; } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0x5E); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=5; } else { ___output(ae,0x1E); PushExpression(ae,ae->idx+2,E_EXPRESSION_V8); ae->nop+=2; } } break; case CRC_IYH:case CRC_HY:case CRC_YH: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:___output(ae,0xFD);___output(ae,0x60);ae->nop+=2;break; case CRC_C:___output(ae,0xFD);___output(ae,0x61);ae->nop+=2;break; case CRC_D:___output(ae,0xFD);___output(ae,0x62);ae->nop+=2;break; case CRC_E:___output(ae,0xFD);___output(ae,0x63);ae->nop+=2;break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x64);ae->nop+=2;break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x65);ae->nop+=2;break; case CRC_A:___output(ae,0xFD);___output(ae,0x67);ae->nop+=2;break; default: ___output(ae,0xFD);___output(ae,0x26); PushExpression(ae,ae->idx+2,E_EXPRESSION_V8); ae->nop+=3; } break; case CRC_IYL:case CRC_LY:case CRC_YL: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:___output(ae,0xFD);___output(ae,0x68);ae->nop+=2;break; case CRC_C:___output(ae,0xFD);___output(ae,0x69);ae->nop+=2;break; case CRC_D:___output(ae,0xFD);___output(ae,0x6A);ae->nop+=2;break; case CRC_E:___output(ae,0xFD);___output(ae,0x6B);ae->nop+=2;break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x6C);ae->nop+=2;break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x6D);ae->nop+=2;break; case CRC_A:___output(ae,0xFD);___output(ae,0x6F);ae->nop+=2;break; default: ___output(ae,0xFD);___output(ae,0x2E); PushExpression(ae,ae->idx+2,E_EXPRESSION_V8); ae->nop+=3; } break; case CRC_IXH:case CRC_HX:case CRC_XH: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:___output(ae,0xDD);___output(ae,0x60);ae->nop+=2;break; case CRC_C:___output(ae,0xDD);___output(ae,0x61);ae->nop+=2;break; case CRC_D:___output(ae,0xDD);___output(ae,0x62);ae->nop+=2;break; case CRC_E:___output(ae,0xDD);___output(ae,0x63);ae->nop+=2;break; case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x64);ae->nop+=2;break; case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x65);ae->nop+=2;break; case CRC_A:___output(ae,0xDD);___output(ae,0x67);ae->nop+=2;break; default: ___output(ae,0xDD);___output(ae,0x26); PushExpression(ae,ae->idx+2,E_EXPRESSION_V8); ae->nop+=3; } break; case CRC_IXL:case CRC_LX:case CRC_XL: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:___output(ae,0xDD);___output(ae,0x68);ae->nop+=2;break; case CRC_C:___output(ae,0xDD);___output(ae,0x69);ae->nop+=2;break; case CRC_D:___output(ae,0xDD);___output(ae,0x6A);ae->nop+=2;break; case CRC_E:___output(ae,0xDD);___output(ae,0x6B);ae->nop+=2;break; case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x6C);ae->nop+=2;break; case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x6D);ae->nop+=2;break; case CRC_A:___output(ae,0xDD);___output(ae,0x6F);ae->nop+=2;break; default: ___output(ae,0xDD);___output(ae,0x2E); PushExpression(ae,ae->idx+2,E_EXPRESSION_V8); ae->nop+=3; } break; case CRC_H: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:___output(ae,0x60);ae->nop+=1;break; case CRC_C:___output(ae,0x61);ae->nop+=1;break; case CRC_D:___output(ae,0x62);ae->nop+=1;break; case CRC_E:___output(ae,0x63);ae->nop+=1;break; case CRC_H:___output(ae,0x64);ae->nop+=1;break; case CRC_L:___output(ae,0x65);ae->nop+=1;break; case CRC_MHL:___output(ae,0x66);ae->nop+=2;break; case CRC_A:___output(ae,0x67);ae->nop+=1;break; default: /* (ix+expression) (iy+expression) expression */ if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0x66); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=5; } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0x66); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=5; } else { ___output(ae,0x26); PushExpression(ae,ae->idx+2,E_EXPRESSION_V8); ae->nop+=2; } } break; case CRC_L: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:___output(ae,0x68);ae->nop+=1;break; case CRC_C:___output(ae,0x69);ae->nop+=1;break; case CRC_D:___output(ae,0x6A);ae->nop+=1;break; case CRC_E:___output(ae,0x6B);ae->nop+=1;break; case CRC_H:___output(ae,0x6C);ae->nop+=1;break; case CRC_L:___output(ae,0x6D);ae->nop+=1;break; case CRC_MHL:___output(ae,0x6E);ae->nop+=2;break; case CRC_A:___output(ae,0x6F);ae->nop+=1;break; default: /* (ix+expression) (iy+expression) expression */ if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0x6E); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=5; } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0x6E); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=5; } else { ___output(ae,0x2E); PushExpression(ae,ae->idx+2,E_EXPRESSION_V8); ae->nop+=2; } } break; case CRC_MHL: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:___output(ae,0x70);ae->nop+=2;break; case CRC_C:___output(ae,0x71);ae->nop+=2;break; case CRC_D:___output(ae,0x72);ae->nop+=2;break; case CRC_E:___output(ae,0x73);ae->nop+=2;break; case CRC_H:___output(ae,0x74);ae->nop+=2;break; case CRC_L:___output(ae,0x75);ae->nop+=2;break; case CRC_A:___output(ae,0x77);ae->nop+=2;break; default: /* expression */ ___output(ae,0x36); PushExpression(ae,ae->idx+2,E_EXPRESSION_V8); ae->nop+=3; } break; case CRC_MBC: if (GetCRC(ae->wl[ae->idx+2].w)==CRC_A) { ___output(ae,0x02); ae->nop+=2; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD (BC),A only\n"); } break; case CRC_MDE: if (GetCRC(ae->wl[ae->idx+2].w)==CRC_A) { ___output(ae,0x12); ae->nop+=2; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD (DE),A only\n"); } break; case CRC_HL: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_BC:___output(ae,0x60);___output(ae,0x69);ae->nop+=2;break; case CRC_DE:___output(ae,0x62);___output(ae,0x6B);ae->nop+=2;break; case CRC_HL:___output(ae,0x64);___output(ae,0x6D);ae->nop+=2;break; default: if (strncmp(ae->wl[ae->idx+2].w,"(IX+",4)==0) { /* enhanced LD HL,(IX+nn) */ ___output(ae,0xDD);___output(ae,0x66); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV81); ___output(ae,0xDD);___output(ae,0x6E); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=10; } else if (strncmp(ae->wl[ae->idx+2].w,"(IY+",4)==0) { /* enhanced LD HL,(IY+nn) */ ___output(ae,0xFD);___output(ae,0x66); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV81); ___output(ae,0xFD);___output(ae,0x6E); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=10; } else if (StringIsMem(ae->wl[ae->idx+2].w)) { ___output(ae,0x2A); PushExpression(ae,ae->idx+2,E_EXPRESSION_V16); ae->nop+=5; } else { ___output(ae,0x21); PushExpression(ae,ae->idx+2,E_EXPRESSION_V16); ae->nop+=3; } } break; case CRC_BC: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_BC:___output(ae,0x40);___output(ae,0x49);ae->nop+=2;break; case CRC_DE:___output(ae,0x42);___output(ae,0x4B);ae->nop+=2;break; case CRC_HL:___output(ae,0x44);___output(ae,0x4D);ae->nop+=2;break; default: if (strncmp(ae->wl[ae->idx+2].w,"(IX+",4)==0) { /* enhanced LD BC,(IX+nn) */ ___output(ae,0xDD);___output(ae,0x46); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV81); ___output(ae,0xDD);___output(ae,0x4E); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=10; } else if (strncmp(ae->wl[ae->idx+2].w,"(IY+",4)==0) { /* enhanced LD BC,(IY+nn) */ ___output(ae,0xFD);___output(ae,0x46); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV81); ___output(ae,0xFD);___output(ae,0x4E); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=10; } else if (StringIsMem(ae->wl[ae->idx+2].w)) { ___output(ae,0xED);___output(ae,0x4B); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16); ae->nop+=6; } else { ___output(ae,0x01); PushExpression(ae,ae->idx+2,E_EXPRESSION_V16); ae->nop+=3; } } break; case CRC_DE: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_BC:___output(ae,0x50);___output(ae,0x59);ae->nop+=2;break; case CRC_DE:___output(ae,0x52);___output(ae,0x5B);ae->nop+=2;break; case CRC_HL:___output(ae,0x54);___output(ae,0x5D);ae->nop+=2;break; default: if (strncmp(ae->wl[ae->idx+2].w,"(IX+",4)==0) { /* enhanced LD DE,(IX+nn) */ ___output(ae,0xDD);___output(ae,0x56); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV81); ___output(ae,0xDD);___output(ae,0x5E); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=10; } else if (strncmp(ae->wl[ae->idx+2].w,"(IY+",4)==0) { /* enhanced LD DE,(IY+nn) */ ___output(ae,0xFD);___output(ae,0x56); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV81); ___output(ae,0xFD);___output(ae,0x5E); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ae->nop+=10; } else if (StringIsMem(ae->wl[ae->idx+2].w)) { ___output(ae,0xED);___output(ae,0x5B); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16); ae->nop+=6; } else { ___output(ae,0x11); PushExpression(ae,ae->idx+2,E_EXPRESSION_V16); ae->nop+=3; } } break; case CRC_IX: if (StringIsMem(ae->wl[ae->idx+2].w)) { ___output(ae,0xDD);___output(ae,0x2A); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16); ae->nop+=6; } else { ___output(ae,0xDD);___output(ae,0x21); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16); ae->nop+=4; } break; case CRC_IY: if (StringIsMem(ae->wl[ae->idx+2].w)) { ___output(ae,0xFD);___output(ae,0x2A); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16); ae->nop+=6; } else { ___output(ae,0xFD);___output(ae,0x21); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16); ae->nop+=4; } break; case CRC_SP: switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_HL:___output(ae,0xF9);ae->nop+=2;break; case CRC_IX:___output(ae,0xDD);___output(ae,0xF9);ae->nop+=3;break; case CRC_IY:___output(ae,0xFD);___output(ae,0xF9);ae->nop+=3;break; default: if (StringIsMem(ae->wl[ae->idx+2].w)) { ___output(ae,0xED);___output(ae,0x7B); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16); ae->nop+=6; } else { ___output(ae,0x31); PushExpression(ae,ae->idx+2,E_EXPRESSION_V16); ae->nop+=3; } } break; default: /* (ix+expression) (iy+expression) (expression) expression */ if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:___output(ae,0xDD);___output(ae,0x70);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break; case CRC_C:___output(ae,0xDD);___output(ae,0x71);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break; case CRC_D:___output(ae,0xDD);___output(ae,0x72);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break; case CRC_E:___output(ae,0xDD);___output(ae,0x73);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break; case CRC_H:___output(ae,0xDD);___output(ae,0x74);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break; case CRC_L:___output(ae,0xDD);___output(ae,0x75);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break; case CRC_A:___output(ae,0xDD);___output(ae,0x77);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break; case CRC_HL:___output(ae,0xDD);___output(ae,0x74);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV81);___output(ae,0xDD);___output(ae,0x75);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=10;break; case CRC_DE:___output(ae,0xDD);___output(ae,0x72);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV81);___output(ae,0xDD);___output(ae,0x73);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=10;break; case CRC_BC:___output(ae,0xDD);___output(ae,0x70);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV81);___output(ae,0xDD);___output(ae,0x71);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=10;break; default:___output(ae,0xDD);___output(ae,0x36); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); PushExpression(ae,ae->idx+2,E_EXPRESSION_3V8); ae->nop+=6; } } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:___output(ae,0xFD);___output(ae,0x70);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break; case CRC_C:___output(ae,0xFD);___output(ae,0x71);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break; case CRC_D:___output(ae,0xFD);___output(ae,0x72);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break; case CRC_E:___output(ae,0xFD);___output(ae,0x73);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break; case CRC_H:___output(ae,0xFD);___output(ae,0x74);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break; case CRC_L:___output(ae,0xFD);___output(ae,0x75);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break; case CRC_A:___output(ae,0xFD);___output(ae,0x77);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break; case CRC_HL:___output(ae,0xFD);___output(ae,0x74);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV81);___output(ae,0xFD);___output(ae,0x75);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=10;break; case CRC_DE:___output(ae,0xFD);___output(ae,0x72);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV81);___output(ae,0xFD);___output(ae,0x73);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=10;break; case CRC_BC:___output(ae,0xFD);___output(ae,0x70);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV81);___output(ae,0xFD);___output(ae,0x71);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=10;break; default:___output(ae,0xFD);___output(ae,0x36); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); PushExpression(ae,ae->idx+2,E_EXPRESSION_3V8); ae->nop+=6; } } else if (StringIsMem(ae->wl[ae->idx+1].w)) { switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_A:___output(ae,0x32);PushExpression(ae,ae->idx+1,E_EXPRESSION_V16);ae->nop+=4;break; case CRC_BC:___output(ae,0xED);___output(ae,0x43);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV16);ae->nop+=6;break; case CRC_DE:___output(ae,0xED);___output(ae,0x53);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV16);ae->nop+=6;break; case CRC_HL:___output(ae,0x22);PushExpression(ae,ae->idx+1,E_EXPRESSION_V16);ae->nop+=5;break; case CRC_IX:___output(ae,0xDD);___output(ae,0x22);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV16);ae->nop+=6;break; case CRC_IY:___output(ae,0xFD);___output(ae,0x22);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV16);ae->nop+=6;break; case CRC_SP:___output(ae,0xED);___output(ae,0x73);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV16);ae->nop+=6;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD (#nnnn),[A,BC,DE,HL,SP,IX,IY] only\n"); } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Unknown LD format\n"); } break; } ae->idx+=2; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD needs two parameters\n"); } } void _RLC(struct s_assenv *ae) { /* on check qu'il y a un ou deux parametres */ if (ae->wl[ae->idx+1].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_B:___output(ae,0xCB);___output(ae,0x0);ae->nop+=2;break; case CRC_C:___output(ae,0xCB);___output(ae,0x1);ae->nop+=2;break; case CRC_D:___output(ae,0xCB);___output(ae,0x2);ae->nop+=2;break; case CRC_E:___output(ae,0xCB);___output(ae,0x3);ae->nop+=2;break; case CRC_H:___output(ae,0xCB);___output(ae,0x4);ae->nop+=2;break; case CRC_L:___output(ae,0xCB);___output(ae,0x5);ae->nop+=2;break; case CRC_MHL:___output(ae,0xCB);___output(ae,0x6);ae->nop+=4;break; case CRC_A:___output(ae,0xCB);___output(ae,0x7);ae->nop+=2;break; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0xCB); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x6); ae->nop+=7; } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0xCB); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x6); ae->nop+=7; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RLC reg8/(HL)/(IX+n)/(IY+n)\n"); } } ae->idx++; } else if (!ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t!=2) { if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD); } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RLC (IX+n),reg8\n"); } ___output(ae,0xCB); switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x0);ae->nop+=7;break; case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1);ae->nop+=7;break; case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2);ae->nop+=7;break; case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3);ae->nop+=7;break; case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x4);ae->nop+=7;break; case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x5);ae->nop+=7;break; case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x7);ae->nop+=7;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RLC (IX+n),reg8\n"); } ae->idx++; ae->idx++; } } void _RRC(struct s_assenv *ae) { /* on check qu'il y a un ou deux parametres */ if (ae->wl[ae->idx+1].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_B:___output(ae,0xCB);___output(ae,0x8);ae->nop+=2;break; case CRC_C:___output(ae,0xCB);___output(ae,0x9);ae->nop+=2;break; case CRC_D:___output(ae,0xCB);___output(ae,0xA);ae->nop+=2;break; case CRC_E:___output(ae,0xCB);___output(ae,0xB);ae->nop+=2;break; case CRC_H:___output(ae,0xCB);___output(ae,0xC);ae->nop+=2;break; case CRC_L:___output(ae,0xCB);___output(ae,0xD);ae->nop+=2;break; case CRC_MHL:___output(ae,0xCB);___output(ae,0xE);ae->nop+=4;break; case CRC_A:___output(ae,0xCB);___output(ae,0xF);ae->nop+=2;break; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0xCB); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0xE); ae->nop+=7; } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0xCB); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0xE); ae->nop+=7; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RRC reg8/(HL)/(IX+n)/(IY+n)\n"); } } ae->idx++; } else if (!ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t!=2) { if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD); } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RRC (IX+n),reg8\n"); } ___output(ae,0xCB); switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x8);ae->nop+=7;break; case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x9);ae->nop+=7;break; case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0xA);ae->nop+=7;break; case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0xB);ae->nop+=7;break; case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0xC);ae->nop+=7;break; case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0xD);ae->nop+=7;break; case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0xF);ae->nop+=7;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RRC (IX+n),reg8\n"); } ae->idx++; ae->idx++; } } void _RL(struct s_assenv *ae) { /* on check qu'il y a un ou deux parametres */ if (ae->wl[ae->idx+1].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_BC:___output(ae,0xCB);___output(ae,0x10);___output(ae,0xCB);___output(ae,0x11);ae->nop+=4;break; case CRC_B:___output(ae,0xCB);___output(ae,0x10);ae->nop+=2;break; case CRC_C:___output(ae,0xCB);___output(ae,0x11);ae->nop+=2;break; case CRC_DE:___output(ae,0xCB);___output(ae,0x12);___output(ae,0xCB);___output(ae,0x13);ae->nop+=4;break; case CRC_D:___output(ae,0xCB);___output(ae,0x12);ae->nop+=2;break; case CRC_E:___output(ae,0xCB);___output(ae,0x13);ae->nop+=2;break; case CRC_HL:___output(ae,0xCB);___output(ae,0x14);___output(ae,0xCB);___output(ae,0x15);ae->nop+=4;break; case CRC_H:___output(ae,0xCB);___output(ae,0x14);ae->nop+=2;break; case CRC_L:___output(ae,0xCB);___output(ae,0x15);ae->nop+=2;break; case CRC_MHL:___output(ae,0xCB);___output(ae,0x16);ae->nop+=4;break; case CRC_A:___output(ae,0xCB);___output(ae,0x17);ae->nop+=2;break; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0xCB); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x16); ae->nop+=7; } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0xCB); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x16); ae->nop+=7; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RL reg8/(HL)/(IX+n)/(IY+n)\n"); } } ae->idx++; } else if (!ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t!=2) { if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD); } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RL (IX+n),reg8\n"); } ___output(ae,0xCB); switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x10);ae->nop+=7;break; case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x11);ae->nop+=7;break; case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x12);ae->nop+=7;break; case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x13);ae->nop+=7;break; case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x14);ae->nop+=7;break; case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x15);ae->nop+=7;break; case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x17);ae->nop+=7;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RL (IX+n),reg8\n"); } ae->idx++; ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RL (IX+n),reg8 or RL reg8/(HL)/(IX+n)/(IY+n)\n"); } } void _RR(struct s_assenv *ae) { /* on check qu'il y a un ou deux parametres */ if (ae->wl[ae->idx+1].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_BC:___output(ae,0xCB);___output(ae,0x18);___output(ae,0xCB);___output(ae,0x19);ae->nop+=4;break; case CRC_B:___output(ae,0xCB);___output(ae,0x18);ae->nop+=2;break; case CRC_C:___output(ae,0xCB);___output(ae,0x19);ae->nop+=2;break; case CRC_DE:___output(ae,0xCB);___output(ae,0x1A);___output(ae,0xCB);___output(ae,0x1B);ae->nop+=4;break; case CRC_D:___output(ae,0xCB);___output(ae,0x1A);ae->nop+=2;break; case CRC_E:___output(ae,0xCB);___output(ae,0x1B);ae->nop+=2;break; case CRC_HL:___output(ae,0xCB);___output(ae,0x1C);___output(ae,0xCB);___output(ae,0x1D);ae->nop+=4;break; case CRC_H:___output(ae,0xCB);___output(ae,0x1C);ae->nop+=2;break; case CRC_L:___output(ae,0xCB);___output(ae,0x1D);ae->nop+=2;break; case CRC_MHL:___output(ae,0xCB);___output(ae,0x1E);ae->nop+=4;break; case CRC_A:___output(ae,0xCB);___output(ae,0x1F);ae->nop+=2;break; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0xCB); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x1E); ae->nop+=7; } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0xCB); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x1E); ae->nop+=7; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RR reg8/(HL)/(IX+n)/(IY+n)\n"); } } ae->idx++; } else if (!ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t!=2) { if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD); } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RR (IX+n),reg8\n"); } ___output(ae,0xCB); switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x18);ae->nop+=7;break; case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x19);ae->nop+=7;break; case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1A);ae->nop+=7;break; case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1B);ae->nop+=7;break; case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1C);ae->nop+=7;break; case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1D);ae->nop+=7;break; case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1F);ae->nop+=7;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RR (IX+n),reg8\n"); } ae->idx++; ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RR (IX+n),reg8 or RR reg8/(HL)/(IX+n)/(IY+n)\n"); } } void _SLA(struct s_assenv *ae) { /* on check qu'il y a un ou deux parametres */ if (ae->wl[ae->idx+1].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_BC:___output(ae,0xCB);___output(ae,0x21);___output(ae,0xCB);___output(ae,0x10);ae->nop+=4;break; /* SLA C : RL B */ case CRC_B:___output(ae,0xCB);___output(ae,0x20);ae->nop+=2;break; case CRC_C:___output(ae,0xCB);___output(ae,0x21);ae->nop+=2;break; case CRC_DE:___output(ae,0xCB);___output(ae,0x23);___output(ae,0xCB);___output(ae,0x12);ae->nop+=4;break; /* SLA E : RL D */ case CRC_D:___output(ae,0xCB);___output(ae,0x22);ae->nop+=2;break; case CRC_E:___output(ae,0xCB);___output(ae,0x23);ae->nop+=2;break; case CRC_HL:___output(ae,0xCB);___output(ae,0x25);___output(ae,0xCB);___output(ae,0x14);ae->nop+=4;break; /* SLA L : RL H */ case CRC_H:___output(ae,0xCB);___output(ae,0x24);ae->nop+=2;break; case CRC_L:___output(ae,0xCB);___output(ae,0x25);ae->nop+=2;break; case CRC_MHL:___output(ae,0xCB);___output(ae,0x26);ae->nop+=4;break; case CRC_A:___output(ae,0xCB);___output(ae,0x27);ae->nop+=2;break; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0xCB); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x26); ae->nop+=7; } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0xCB); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x26); ae->nop+=7; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SLA reg8/(HL)/(IX+n)/(IY+n)\n"); } } ae->idx++; } else if (!ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t!=2) { if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD); } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SLL (IX+n),reg8\n"); } ___output(ae,0xCB); switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x20);ae->nop+=7;break; case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x21);ae->nop+=7;break; case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x22);ae->nop+=7;break; case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x23);ae->nop+=7;break; case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x24);ae->nop+=7;break; case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x25);ae->nop+=7;break; case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x27);ae->nop+=7;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SLA (IX+n),reg8\n"); } ae->idx++; ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SLA reg8/(HL)/(IX+n)/(IY+n) or SLA (IX+n),reg8\n"); } } void _SRA(struct s_assenv *ae) { /* on check qu'il y a un ou deux parametres */ if (ae->wl[ae->idx+1].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_BC:___output(ae,0xCB);___output(ae,0x28);___output(ae,0xCB);___output(ae,0x19);ae->nop+=4;break; /* SRA B : RR C */ case CRC_B:___output(ae,0xCB);___output(ae,0x28);ae->nop+=2;break; case CRC_C:___output(ae,0xCB);___output(ae,0x29);ae->nop+=2;break; case CRC_DE:___output(ae,0xCB);___output(ae,0x2A);___output(ae,0xCB);___output(ae,0x1B);ae->nop+=4;break; /* SRA D : RR E */ case CRC_D:___output(ae,0xCB);___output(ae,0x2A);ae->nop+=2;break; case CRC_E:___output(ae,0xCB);___output(ae,0x2B);ae->nop+=2;break; case CRC_HL:___output(ae,0xCB);___output(ae,0x2C);___output(ae,0xCB);___output(ae,0x1D);ae->nop+=4;break; /* SRA H : RR L */ case CRC_H:___output(ae,0xCB);___output(ae,0x2C);ae->nop+=2;break; case CRC_L:___output(ae,0xCB);___output(ae,0x2D);ae->nop+=2;break; case CRC_MHL:___output(ae,0xCB);___output(ae,0x2E);ae->nop+=4;break; case CRC_A:___output(ae,0xCB);___output(ae,0x2F);ae->nop+=2;break; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0xCB); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x2E); ae->nop+=7; } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0xCB); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x2E); ae->nop+=7; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SRA reg8/(HL)/(IX+n)/(IY+n)\n"); } } ae->idx++; } else if (!ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t!=2) { if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD); } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SRA (IX+n),reg8\n"); } ___output(ae,0xCB); switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x28);ae->nop+=7;break; case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x29);ae->nop+=7;break; case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2A);ae->nop+=7;break; case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2B);ae->nop+=7;break; case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2C);ae->nop+=7;break; case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2D);ae->nop+=7;break; case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2F);ae->nop+=7;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SRA (IX+n),reg8\n"); } ae->idx++; ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SRA reg8/(HL)/(IX+n)/(IY+n) or SRA (IX+n),reg8\n"); } } void _SLL(struct s_assenv *ae) { /* on check qu'il y a un ou deux parametres */ if (ae->wl[ae->idx+1].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_BC:___output(ae,0xCB);___output(ae,0x31);___output(ae,0xCB);___output(ae,0x10);ae->nop+=4;break; /* SLL C : RL B */ case CRC_B:___output(ae,0xCB);___output(ae,0x30);ae->nop+=2;break; case CRC_C:___output(ae,0xCB);___output(ae,0x31);ae->nop+=2;break; case CRC_DE:___output(ae,0xCB);___output(ae,0x33);___output(ae,0xCB);___output(ae,0x12);ae->nop+=4;break; /* SLL E : RL D */ case CRC_D:___output(ae,0xCB);___output(ae,0x32);ae->nop+=2;break; case CRC_E:___output(ae,0xCB);___output(ae,0x33);ae->nop+=2;break; case CRC_HL:___output(ae,0xCB);___output(ae,0x35);___output(ae,0xCB);___output(ae,0x14);ae->nop+=4;break; /* SLL L : RL H */ case CRC_H:___output(ae,0xCB);___output(ae,0x34);ae->nop+=2;break; case CRC_L:___output(ae,0xCB);___output(ae,0x35);ae->nop+=2;break; case CRC_MHL:___output(ae,0xCB);___output(ae,0x36);ae->nop+=4;break; case CRC_A:___output(ae,0xCB);___output(ae,0x37);ae->nop+=2;break; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0xCB); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x36); ae->nop+=7; } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0xCB); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x36); ae->nop+=7; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SLL reg8/(HL)/(IX+n)/(IY+n)\n"); } } ae->idx++; } else if (!ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t!=2) { if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD); } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SLL (IX+n),reg8\n"); } ___output(ae,0xCB); switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x30);ae->nop+=7;break; case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x31);ae->nop+=7;break; case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x32);ae->nop+=7;break; case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x33);ae->nop+=7;break; case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x34);ae->nop+=7;break; case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x35);ae->nop+=7;break; case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x37);ae->nop+=7;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SLL (IX+n),reg8\n"); } ae->idx++; ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SLL reg8/(HL)/(IX+n)/(IY+n) or SLL (IX+n),reg8\n"); } } void _SRL(struct s_assenv *ae) { /* on check qu'il y a un ou deux parametres */ if (ae->wl[ae->idx+1].t==1) { switch (GetCRC(ae->wl[ae->idx+1].w)) { case CRC_BC:___output(ae,0xCB);___output(ae,0x38);___output(ae,0xCB);___output(ae,0x11);ae->nop+=4;break; /* SRL B : RL C */ case CRC_B:___output(ae,0xCB);___output(ae,0x38);ae->nop+=2;break; case CRC_C:___output(ae,0xCB);___output(ae,0x39);ae->nop+=2;break; case CRC_DE:___output(ae,0xCB);___output(ae,0x3A);___output(ae,0xCB);___output(ae,0x13);ae->nop+=4;break; /* SRL D : RL E */ case CRC_D:___output(ae,0xCB);___output(ae,0x3A);ae->nop+=2;break; case CRC_E:___output(ae,0xCB);___output(ae,0x3B);ae->nop+=2;break; case CRC_HL:___output(ae,0xCB);___output(ae,0x3C);___output(ae,0xCB);___output(ae,0x15);ae->nop+=4;break; /* SRL H : RL L */ case CRC_H:___output(ae,0xCB);___output(ae,0x3C);ae->nop+=2;break; case CRC_L:___output(ae,0xCB);___output(ae,0x3D);ae->nop+=2;break; case CRC_MHL:___output(ae,0xCB);___output(ae,0x3E);ae->nop+=4;break; case CRC_A:___output(ae,0xCB);___output(ae,0x3F);ae->nop+=2;break; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0xCB); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x3E); ae->nop+=7; } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0xCB); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x3E); ae->nop+=7; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SRL reg8/(HL)/(IX+n)/(IY+n)\n"); } } ae->idx++; } else if (!ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t!=2) { if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD); } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SRL (IX+n),reg8\n"); } ___output(ae,0xCB); switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x38);ae->nop+=7;break; case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x39);ae->nop+=7;break; case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3A);ae->nop+=7;break; case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3B);ae->nop+=7;break; case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3C);ae->nop+=7;break; case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3D);ae->nop+=7;break; case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3F);ae->nop+=7;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SRL (IX+n),reg8\n"); } ae->idx++; ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SRL reg8/(HL)/(IX+n)/(IY+n) or SRL (IX+n),reg8\n"); } } void _BIT(struct s_assenv *ae) { int o; /* on check qu'il y a deux ou trois parametres ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); o=RoundComputeExpressionCore(ae,ae->wl[ae->idx+1].w,ae->codeadr,0);*/ o=0; if (o<0 || o>7) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is BIT ,... (%d)\n",o); } else { o=0x40+o*8; if (ae->wl[ae->idx+1].t==0 && ae->wl[ae->idx+2].t==1) { switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x0+o);ae->nop+=2;break; case CRC_C:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x1+o);ae->nop+=2;break; case CRC_D:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x2+o);ae->nop+=2;break; case CRC_E:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x3+o);ae->nop+=2;break; case CRC_H:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x4+o);ae->nop+=2;break; case CRC_L:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x5+o);ae->nop+=2;break; case CRC_MHL:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o);ae->nop+=3;break; case CRC_A:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x7+o);ae->nop+=2;break; default: if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0xCB); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o); ae->nop+=6; } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0xCB); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o); ae->nop+=6; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is BIT n,reg8/(HL)/(IX+n)/(IY+n)\n"); } } ae->idx+=2; } else if (!ae->wl[ae->idx+1].t && !ae->wl[ae->idx+2].t && ae->wl[ae->idx+3].t==1) { if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) { ___output(ae,0xDD); } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) { ___output(ae,0xFD); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is BIT (IX+n),reg8\n"); } ___output(ae,0xCB); switch (GetCRC(ae->wl[ae->idx+3].w)) { case CRC_B:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x0+o);ae->nop+=6;break; case CRC_C:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x1+o);ae->nop+=6;break; case CRC_D:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x2+o);ae->nop+=6;break; case CRC_E:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x3+o);ae->nop+=6;break; case CRC_H:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x4+o);ae->nop+=6;break; case CRC_L:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x5+o);ae->nop+=6;break; case CRC_A:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x7+o);ae->nop+=6;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is BIT n,(IX+n),reg8\n"); } ae->idx+=3; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is BIT n,reg8/(HL)/(IX+n)[,reg8]/(IY+n)[,reg8]\n"); } } } void _RES(struct s_assenv *ae) { int o; /* on check qu'il y a deux ou trois parametres ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); o=RoundComputeExpressionCore(ae,ae->wl[ae->idx+1].w,ae->codeadr,0); */ o=0; if (o<0 || o>7) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RES ,... (%d)\n",o); } else { o=0x80+o*8; if (ae->wl[ae->idx+1].t==0 && ae->wl[ae->idx+2].t==1) { switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x0+o);ae->nop+=2;break; case CRC_C:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x1+o);ae->nop+=2;break; case CRC_D:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x2+o);ae->nop+=2;break; case CRC_E:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x3+o);ae->nop+=2;break; case CRC_H:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x4+o);ae->nop+=2;break; case CRC_L:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x5+o);ae->nop+=2;break; case CRC_MHL:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o);ae->nop+=4;break; case CRC_A:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x7+o);ae->nop+=2;break; default: if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0xCB); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o); ae->nop+=7; } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0xCB); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o); ae->nop+=7; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RES n,reg8/(HL)/(IX+n)/(IY+n)\n"); } } ae->idx+=2; } else if (!ae->wl[ae->idx+1].t && !ae->wl[ae->idx+2].t && ae->wl[ae->idx+3].t==1) { if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) { ___output(ae,0xDD); } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) { ___output(ae,0xFD); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RES n,(IX+n),reg8\n"); } ___output(ae,0xCB); switch (GetCRC(ae->wl[ae->idx+3].w)) { case CRC_B:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x0+o);ae->nop+=7;break; case CRC_C:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x1+o);ae->nop+=7;break; case CRC_D:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x2+o);ae->nop+=7;break; case CRC_E:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x3+o);ae->nop+=7;break; case CRC_H:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x4+o);ae->nop+=7;break; case CRC_L:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x5+o);ae->nop+=7;break; case CRC_A:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x7+o);ae->nop+=7;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RES n,(IX+n),reg8\n"); } ae->idx+=3; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RES n,reg8/(HL)/(IX+n)[,reg8]/(IY+n)[,reg8]\n"); } } } void _SET(struct s_assenv *ae) { int o; /* on check qu'il y a deux ou trois parametres ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); o=RoundComputeExpressionCore(ae,ae->wl[ae->idx+1].w,ae->codeadr,0); */ o=0; if (o<0 || o>7) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SET ,... (%d)\n",o); } else { o=0xC0+o*8; if (ae->wl[ae->idx+1].t==0 && ae->wl[ae->idx+2].t==1) { switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_B:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x0+o);ae->nop+=2;break; case CRC_C:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x1+o);ae->nop+=2;break; case CRC_D:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x2+o);ae->nop+=2;break; case CRC_E:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x3+o);ae->nop+=2;break; case CRC_H:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x4+o);ae->nop+=2;break; case CRC_L:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x5+o);ae->nop+=2;break; case CRC_MHL:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o);ae->nop+=4;break; case CRC_A:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x7+o);ae->nop+=2;break; default: if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0xCB); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o); ae->nop+=7; } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) { ___output(ae,0xFD);___output(ae,0xCB); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o); ae->nop+=7; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SET n,reg8/(HL)/(IX+n)/(IY+n)\n"); } } ae->idx+=2; } else if (!ae->wl[ae->idx+1].t && !ae->wl[ae->idx+2].t && ae->wl[ae->idx+3].t==1) { if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) { ___output(ae,0xDD); } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) { ___output(ae,0xFD); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SET n,(IX+n),reg8\n"); } ___output(ae,0xCB); switch (GetCRC(ae->wl[ae->idx+3].w)) { case CRC_B:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x0+o);ae->nop+=7;break; case CRC_C:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x1+o);ae->nop+=7;break; case CRC_D:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x2+o);ae->nop+=7;break; case CRC_E:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x3+o);ae->nop+=7;break; case CRC_H:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x4+o);ae->nop+=7;break; case CRC_L:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x5+o);ae->nop+=7;break; case CRC_A:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x7+o);ae->nop+=7;break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SET n,(IX+n),reg8\n"); } ae->idx+=3; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SET n,reg8/(HL)/(IX+n)[,reg8]/(IY+n)[,reg8]\n"); } } } void _DEFS(struct s_assenv *ae) { int i,r,v; if (ae->wl[ae->idx].t) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Syntax is DEFS repeat,value or DEFS repeat\n"); } else do { ae->idx++; if (!ae->wl[ae->idx].t) { ExpressionFastTranslate(ae,&ae->wl[ae->idx].w,0); ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); /* doing FastTranslate but not a complete evaluation */ r=RoundComputeExpressionCore(ae,ae->wl[ae->idx].w,ae->codeadr,0); if (r<0) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFS size must be greater or equal to zero\n"); } for (i=0;iidx+1,E_EXPRESSION_0V8); ae->nop+=1; } ae->idx++; } else if (ae->wl[ae->idx].t==1) { ExpressionFastTranslate(ae,&ae->wl[ae->idx].w,0); r=RoundComputeExpressionCore(ae,ae->wl[ae->idx].w,ae->codeadr,0); v=0; if (r<0) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFS size must be greater or equal to zero\n"); } for (i=0;inop+=1; } } } while (!ae->wl[ae->idx].t); } void _DEFS_struct(struct s_assenv *ae) { int i,r,v; if (ae->wl[ae->idx].t) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Syntax is DEFS repeat,value or DEFS repeat\n"); } else do { ae->idx++; if (!ae->wl[ae->idx].t) { ExpressionFastTranslate(ae,&ae->wl[ae->idx].w,0); ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); r=RoundComputeExpressionCore(ae,ae->wl[ae->idx].w,ae->codeadr,0); v=RoundComputeExpressionCore(ae,ae->wl[ae->idx+1].w,ae->codeadr,0); if (r<0) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFS size must be greater or equal to zero\n"); } for (i=0;inop+=1; } ae->idx++; } else if (ae->wl[ae->idx].t==1) { ExpressionFastTranslate(ae,&ae->wl[ae->idx].w,0); r=RoundComputeExpressionCore(ae,ae->wl[ae->idx].w,ae->codeadr,0); v=0; if (r<0) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFS size must be greater or equal to zero\n"); } for (i=0;inop+=1; } } } while (!ae->wl[ae->idx].t); } void _STR(struct s_assenv *ae) { unsigned char c; int i,tquote; if (!ae->wl[ae->idx].t) { do { ae->idx++; if ((tquote=StringIsQuote(ae->wl[ae->idx].w))!=0) { i=1; while (ae->wl[ae->idx].w[i] && ae->wl[ae->idx].w[i]!=tquote) { if (ae->wl[ae->idx].w[i]=='\\') { i++; /* no conversion on escaped chars */ c=ae->wl[ae->idx].w[i]; switch (c) { case 'b':c='\b';break; case 'v':c='\v';break; case 'f':c='\f';break; case '0':c='\0';break; case 'r':c='\r';break; case 'n':c='\n';break; case 't':c='\t';break; default:break; } if (ae->wl[ae->idx].w[i+1]!=tquote) { ___output(ae,c); } else { ___output(ae,c|0x80); } } else { /* charset conversion on the fly */ if (ae->wl[ae->idx].w[i+1]!=tquote) { ___output(ae,ae->charset[(int)ae->wl[ae->idx].w[i]]); } else { ___output(ae,ae->charset[(int)ae->wl[ae->idx].w[i]]|0x80); } } i++; } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"STR handle only quoted strings!\n"); } } while (ae->wl[ae->idx].t==0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"STR needs one or more quotes parameters\n"); } } void _DEFR(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { do { ae->idx++; PushExpression(ae,ae->idx,E_EXPRESSION_0VR); } while (ae->wl[ae->idx].t==0); } else { if (ae->getstruct) { ___output(ae,0);___output(ae,0);___output(ae,0);___output(ae,0);___output(ae,0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFR needs one or more parameters\n"); } } } void _DEFR_struct(struct s_assenv *ae) { unsigned char *rc; double v; if (!ae->wl[ae->idx].t) { do { ae->idx++; /* conversion des symboles connus */ ExpressionFastTranslate(ae,&ae->wl[ae->idx].w,0); /* calcul de la valeur définitive de l'expression */ v=ComputeExpressionCore(ae,ae->wl[ae->idx].w,ae->outputadr,0); /* conversion en réel Amsdos */ rc=__internal_MakeAmsdosREAL(ae,v,0); ___output(ae,rc[0]);___output(ae,rc[1]);___output(ae,rc[2]);___output(ae,rc[3]);___output(ae,rc[4]); } while (ae->wl[ae->idx].t==0); } else { if (ae->getstruct) { ___output(ae,0);___output(ae,0);___output(ae,0);___output(ae,0);___output(ae,0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFR needs one or more parameters\n"); } } } void _DEFB(struct s_assenv *ae) { int i,tquote; unsigned char c; if (!ae->wl[ae->idx].t) { do { ae->idx++; if ((tquote=StringIsQuote(ae->wl[ae->idx].w))!=0) { i=1; while (ae->wl[ae->idx].w[i] && ae->wl[ae->idx].w[i]!=tquote) { if (ae->wl[ae->idx].w[i]=='\\') { i++; /* no conversion on escaped chars */ c=ae->wl[ae->idx].w[i]; switch (c) { case 'b':___output(ae,'\b');break; case 'v':___output(ae,'\v');break; case 'f':___output(ae,'\f');break; case '0':___output(ae,'\0');break; case 'r':___output(ae,'\r');break; case 'n':___output(ae,'\n');break; case 't':___output(ae,'\t');break; default: ___output(ae,c); ae->nop+=1; } } else { /* charset conversion on the fly */ ___output(ae,ae->charset[(int)ae->wl[ae->idx].w[i]]); ae->nop+=1; } i++; } } else { PushExpression(ae,ae->idx,E_EXPRESSION_0V8); ae->nop+=1; } } while (ae->wl[ae->idx].t==0); } else { if (ae->getstruct) { ___output(ae,0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFB needs one or more parameters\n"); } } } void _DEFB_struct(struct s_assenv *ae) { int i,tquote; unsigned char c; if (!ae->wl[ae->idx].t) { do { ae->idx++; if ((tquote=StringIsQuote(ae->wl[ae->idx].w))!=0) { i=1; while (ae->wl[ae->idx].w[i] && ae->wl[ae->idx].w[i]!=tquote) { if (ae->wl[ae->idx].w[i]=='\\') { i++; /* no conversion on escaped chars */ c=ae->wl[ae->idx].w[i]; switch (c) { case 'b':___output(ae,'\b');break; case 'v':___output(ae,'\v');break; case 'f':___output(ae,'\f');break; case '0':___output(ae,'\0');break; case 'r':___output(ae,'\r');break; case 'n':___output(ae,'\n');break; case 't':___output(ae,'\t');break; default: ___output(ae,c); ae->nop+=1; } } else { /* charset conversion on the fly */ ___output(ae,ae->charset[(int)ae->wl[ae->idx].w[i]]); ae->nop+=1; } i++; } } else { int v; ExpressionFastTranslate(ae,&ae->wl[ae->idx].w,0); v=RoundComputeExpressionCore(ae,ae->wl[ae->idx].w,ae->outputadr,0); ___output(ae,v); ae->nop+=1; } } while (ae->wl[ae->idx].t==0); } else { if (ae->getstruct) { ___output(ae,0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFB needs one or more parameters\n"); } } } void _DEFW(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { do { ae->idx++; PushExpression(ae,ae->idx,E_EXPRESSION_0V16); } while (ae->wl[ae->idx].t==0); } else { if (ae->getstruct) { ___output(ae,0);___output(ae,0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFW needs one or more parameters\n"); } } } void _DEFW_struct(struct s_assenv *ae) { int v; if (!ae->wl[ae->idx].t) { do { ae->idx++; ExpressionFastTranslate(ae,&ae->wl[ae->idx].w,0); v=RoundComputeExpressionCore(ae,ae->wl[ae->idx].w,ae->outputadr,0); ___output(ae,v&0xFF);___output(ae,(v>>8)&0xFF); } while (ae->wl[ae->idx].t==0); } else { if (ae->getstruct) { ___output(ae,0);___output(ae,0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFW needs one or more parameters\n"); } } } void _DEFI(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { do { ae->idx++; PushExpression(ae,ae->idx,E_EXPRESSION_0V32); } while (ae->wl[ae->idx].t==0); } else { if (ae->getstruct) { ___output(ae,0);___output(ae,0);___output(ae,0);___output(ae,0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFI needs one or more parameters\n"); } } } void _DEFI_struct(struct s_assenv *ae) { int v; if (!ae->wl[ae->idx].t) { do { ae->idx++; ExpressionFastTranslate(ae,&ae->wl[ae->idx].w,0); v=RoundComputeExpressionCore(ae,ae->wl[ae->idx].w,ae->outputadr,0); ___output(ae,v&0xFF);___output(ae,(v>>8)&0xFF);___output(ae,(v>>16)&0xFF);___output(ae,(v>>24)&0xFF); } while (ae->wl[ae->idx].t==0); } else { if (ae->getstruct) { ___output(ae,0);___output(ae,0);___output(ae,0);___output(ae,0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFI needs one or more parameters\n"); } } } void _DEFB_as80(struct s_assenv *ae) { int i,tquote; int modadr=0; if (!ae->wl[ae->idx].t) { do { ae->idx++; if ((tquote=StringIsQuote(ae->wl[ae->idx].w))!=0) { i=1; while (ae->wl[ae->idx].w[i] && ae->wl[ae->idx].w[i]!=tquote) { if (ae->wl[ae->idx].w[i]=='\\') i++; /* charset conversion on the fly */ ___output(ae,ae->charset[(int)ae->wl[ae->idx].w[i]]); ae->nop+=1; ae->codeadr--;modadr++; i++; } } else { PushExpression(ae,ae->idx,E_EXPRESSION_0V8); ae->codeadr--;modadr++; ae->nop+=1; } } while (ae->wl[ae->idx].t==0); ae->codeadr+=modadr; } else { if (ae->getstruct) { ___output(ae,0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFB needs one or more parameters\n"); } } } void _DEFW_as80(struct s_assenv *ae) { int modadr=0; if (!ae->wl[ae->idx].t) { do { ae->idx++; PushExpression(ae,ae->idx,E_EXPRESSION_0V16); ae->codeadr-=2;modadr+=2; } while (ae->wl[ae->idx].t==0); ae->codeadr+=modadr; } else { if (ae->getstruct) { ___output(ae,0);___output(ae,0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFW needs one or more parameters\n"); } } } void _DEFI_as80(struct s_assenv *ae) { int modadr=0; if (!ae->wl[ae->idx].t) { do { ae->idx++; PushExpression(ae,ae->idx,E_EXPRESSION_0V32); ae->codeadr-=4;modadr+=4; } while (ae->wl[ae->idx].t==0); ae->codeadr+=modadr; } else { if (ae->getstruct) { ___output(ae,0);___output(ae,0);___output(ae,0);___output(ae,0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFI needs one or more parameters\n"); } } } #if 0 void _DEFSTR(struct s_assenv *ae) { int i,tquote; unsigned char c; if (!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) { if (StringIsQuote(ae->wl[ae->idx+1].w) && StringIsQuote(ae->wl[ae->idx+2].w)) { i=1; while (ae->wl[ae->idx].w[i] && ae->wl[ae->idx].w[i]!=tquote) { if (ae->wl[ae->idx].w[i]=='\\') { i++; /* no conversion on escaped chars */ c=ae->wl[ae->idx].w[i]; switch (c) { case 'b':___output(ae,'\b');break; case 'v':___output(ae,'\v');break; case 'f':___output(ae,'\f');break; case '0':___output(ae,'\0');break; case 'r':___output(ae,'\r');break; case 'n':___output(ae,'\n');break; case 't':___output(ae,'\t');break; default: ___output(ae,c); } } else { /* charset conversion on the fly */ ___output(ae,ae->charset[(int)ae->wl[ae->idx].w[i]]); } i++; } } ae->idx+=2; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFSTR needs two parameters\n"); } } #endif #undef FUNC #define FUNC "Directive CORE" void __internal_UpdateLZBlockIfAny(struct s_assenv *ae) { /* there was a crunched block opened in the previous bank */ if (ae->lz>=0) { //ae->lzsection[ae->ilz-1].iorgzone=ae->io-1; //ae->lzsection[ae->ilz-1].ibank=ae->activebank; } ae->lz=-1; } void __AMSDOS(struct s_assenv *ae) { ae->amsdos=1; } void __internal_EXPORT(struct s_assenv *ae, int exportval) { struct s_label *curlabel; struct s_expr_dico *curdic; int ialias,crc,freeflag; char *localname; if (ae->wl[ae->idx].t) { /* without parameter enable/disable export */ ae->autorise_export=exportval; } else while (!ae->wl[ae->idx].t) { ae->idx++; freeflag=0; /* local label */ if (ae->wl[ae->idx].w[0]=='.' && ae->lastgloballabel) { localname=MemMalloc(strlen(ae->wl[ae->idx].w)+1+ae->lastgloballabellen); sprintf(localname,"%s%s",ae->lastgloballabel,ae->wl[ae->idx].w); freeflag=1; } else { localname=ae->wl[ae->idx].w; } crc=GetCRC(localname); if ((curlabel=SearchLabel(ae,localname,crc))!=NULL) { curlabel->autorise_export=exportval; ae->label[curlabel->backidx].autorise_export=exportval; } else { if ((curdic=SearchDico(ae,ae->wl[ae->idx].w,crc))!=NULL) { curdic->autorise_export=exportval; } else { if ((ialias=SearchAlias(ae,crc,ae->wl[ae->idx].w))!=-1) { ae->alias[ialias].autorise_export=exportval; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"(E)NOEXPORT did not found [%s] in variables, labels or aliases\n",ae->wl[ae->idx].w); } } } if (freeflag) MemFree(localname); } } void __NOEXPORT(struct s_assenv *ae) { __internal_EXPORT(ae,0); } void __ENOEXPORT(struct s_assenv *ae) { __internal_EXPORT(ae,1); } void __BUILDZX(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BUILDZX does not need a parameter\n"); } if (!ae->forcesnapshot && !ae->forcetape && !ae->forcecpr) { ae->forcezx=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot select ZX output when already in Amstrad cartridge/snapshot/tape output\n"); } } void __BUILDCPR(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BUILDCPR does not need a parameter\n"); } if (!ae->forcesnapshot && !ae->forcetape && !ae->forcezx) { ae->forcecpr=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot select Amstrad cartridge output when already in snapshot/tape output\n"); } } void __BUILDSNA(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { if (strcmp(ae->wl[ae->idx+1].w,"V2")==0) { ae->snapshot.version=2; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BUILDSNA unrecognized option\n"); } } if (!ae->forcecpr && !ae->forcetape && !ae->forcezx) { ae->forcesnapshot=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot select snapshot output when already in cartridge/tape output\n"); } } void __BUILDROM(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BUILDROM does not need a parameter\n"); } if (!ae->forcesnapshot && !ae->forcetape && !ae->forcezx && !ae->forcecpr) { ae->forceROM=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot select Amstrad ROM output when already in snapshot/tape/zx/cartridge output\n"); } } void __BUILDTAPE(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BUILDTAPE does not need a parameter\n"); } if (!ae->forcesnapshot && !ae->forcecpr && !ae->forcezx) { ae->forcetape=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot select tape output when already in snapshot/cartridge output\n"); } } void __LZ4(struct s_assenv *ae) { struct s_lz_section curlz; if (!ae->wl[ae->idx].t) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LZ directive does not need any parameter\n"); return; } #ifdef NO_3RD_PARTIES MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot use 3rd parties cruncher with this version of RASM\n",GetCurrentFile(ae),ae->wl[ae->idx].l); FreeAssenv(ae); exit(-5); #endif if (ae->lz>=0 && ae->lzilz) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->lz); FreeAssenv(ae); exit(-5); } curlz.iw=ae->idx; curlz.iorgzone=ae->io-1; curlz.ibank=ae->activebank; curlz.memstart=ae->outputadr; curlz.memend=-1; curlz.lzversion=4; ae->lz=ae->ilz; ObjectArrayAddDynamicValueConcat((void**)&ae->lzsection,&ae->ilz,&ae->mlz,&curlz,sizeof(curlz)); } void __LZX7(struct s_assenv *ae) { struct s_lz_section curlz; if (!ae->wl[ae->idx].t) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LZ directive does not need any parameter\n"); return; } #ifdef NO_3RD_PARTIES MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot use 3rd parties cruncher with this version of RASM\n",GetCurrentFile(ae),ae->wl[ae->idx].l); FreeAssenv(ae); exit(-5); #endif if (ae->lz>=0 && ae->lzilz) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->lz); FreeAssenv(ae); exit(-5); } curlz.iw=ae->idx; curlz.iorgzone=ae->io-1; curlz.ibank=ae->activebank; curlz.memstart=ae->outputadr; curlz.memend=-1; curlz.lzversion=7; ae->lz=ae->ilz; ObjectArrayAddDynamicValueConcat((void**)&ae->lzsection,&ae->ilz,&ae->mlz,&curlz,sizeof(curlz)); } void __LZEXO(struct s_assenv *ae) { struct s_lz_section curlz; if (!ae->wl[ae->idx].t) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LZ directive does not need any parameter\n"); return; } #ifdef NO_3RD_PARTIES MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot use 3rd parties cruncher with this version of RASM\n",GetCurrentFile(ae),ae->wl[ae->idx].l); FreeAssenv(ae); exit(-5); #endif if (ae->lz>=0 && ae->lzilz) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->lz); FreeAssenv(ae); exit(-5); } curlz.iw=ae->idx; curlz.iorgzone=ae->io-1; curlz.ibank=ae->activebank; curlz.memstart=ae->outputadr; curlz.memend=-1; curlz.lzversion=8; ae->lz=ae->ilz; ObjectArrayAddDynamicValueConcat((void**)&ae->lzsection,&ae->ilz,&ae->mlz,&curlz,sizeof(curlz)); } void __LZ48(struct s_assenv *ae) { struct s_lz_section curlz; if (!ae->wl[ae->idx].t) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LZ directive does not need any parameter\n"); return; } if (ae->lz>=0 && ae->lzilz) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->lz); FreeAssenv(ae); exit(-5); } curlz.iw=ae->idx; curlz.iorgzone=ae->io-1; curlz.ibank=ae->activebank; curlz.memstart=ae->outputadr; curlz.memend=-1; curlz.lzversion=48; ae->lz=ae->ilz; ObjectArrayAddDynamicValueConcat((void**)&ae->lzsection,&ae->ilz,&ae->mlz,&curlz,sizeof(curlz)); } void __LZ49(struct s_assenv *ae) { struct s_lz_section curlz; if (!ae->wl[ae->idx].t) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LZ directive does not need any parameter\n"); return; } if (ae->lz>=0 && ae->lzilz) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->lz); FreeAssenv(ae); exit(-5); } curlz.iw=ae->idx; curlz.iorgzone=ae->io-1; curlz.ibank=ae->activebank; curlz.memstart=ae->outputadr; curlz.memend=-1; curlz.lzversion=49; ae->lz=ae->ilz; ObjectArrayAddDynamicValueConcat((void**)&ae->lzsection,&ae->ilz,&ae->mlz,&curlz,sizeof(curlz)); } void __LZCLOSE(struct s_assenv *ae) { if (!ae->ilz || ae->lz==-1) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot close LZ section as it wasn't opened\n"); return; } ae->lzsection[ae->ilz-1].memend=ae->outputadr; ae->lzsection[ae->ilz-1].ilabel=ae->il; ae->lzsection[ae->ilz-1].iexpr=ae->ie; //ae->lz=ae->ilz; ae->lz=-1; } void __LIMIT(struct s_assenv *ae) { if (ae->wl[ae->idx+1].t!=2) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); ___output_set_limit(ae,RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->outputadr,0,0)); ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LIMIT directive need one integer parameter\n"); } } void OverWriteCheck(struct s_assenv *ae) { #undef FUNC #define FUNC "OverWriteCheck" int i,j; /* overwrite checking */ i=ae->io-1; { if (ae->orgzone[i].memstart!=ae->orgzone[i].memend) { for (j=0;jio-1;j++) { if (ae->orgzone[j].memstart!=ae->orgzone[j].memend && !ae->orgzone[j].nocode) { if (ae->orgzone[i].ibank==ae->orgzone[j].ibank) { if ((ae->orgzone[i].memstart>=ae->orgzone[j].memstart && ae->orgzone[i].memstartorgzone[j].memend) || (ae->orgzone[i].memend>ae->orgzone[j].memstart && ae->orgzone[i].memendorgzone[j].memend) || (ae->orgzone[i].memstart<=ae->orgzone[j].memstart && ae->orgzone[i].memend>=ae->orgzone[j].memend)) { ae->idx--; if (ae->orgzone[j].protect) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"PROTECTED section error [%s] L%d [#%04X-#%04X-B%d] with [%s] L%d [#%04X/#%04X]\n",ae->filename[ae->orgzone[j].ifile],ae->orgzone[j].iline,ae->orgzone[j].memstart,ae->orgzone[j].memend,ae->orgzone[j].ibank<32?ae->orgzone[j].ibank:0,ae->filename[ae->orgzone[i].ifile],ae->orgzone[i].iline,ae->orgzone[i].memstart,ae->orgzone[i].memend); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Assembling overwrite [%s] L%d [#%04X-#%04X-B%d] with [%s] L%d [#%04X/#%04X]\n",ae->filename[ae->orgzone[j].ifile],ae->orgzone[j].iline,ae->orgzone[j].memstart,ae->orgzone[j].memend,ae->orgzone[j].ibank<32?ae->orgzone[j].ibank:0,ae->filename[ae->orgzone[i].ifile],ae->orgzone[i].iline,ae->orgzone[i].memstart,ae->orgzone[i].memend); } i=j=ae->io; break; } } } } } } } void ___new_memory_space(struct s_assenv *ae) { #undef FUNC #define FUNC "___new_memory_space" unsigned char *mem; struct s_orgzone orgzone={0}; __internal_UpdateLZBlockIfAny(ae); if (ae->io) { ae->orgzone[ae->io-1].memend=ae->outputadr; } if (ae->lz>=0) { if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: LZ section wasn't closed before a new memory space directive\n",GetCurrentFile(ae),ae->wl[ae->idx].l); __LZCLOSE(ae); } ae->activebank=ae->nbbank; mem=MemMalloc(65536); memset(mem,0,65536); ObjectArrayAddDynamicValueConcat((void**)&ae->mem,&ae->nbbank,&ae->maxbank,&mem,sizeof(mem)); ae->outputadr=0; ae->codeadr=0; orgzone.memstart=0; orgzone.ibank=ae->activebank; orgzone.nocode=ae->nocode=0; ObjectArrayAddDynamicValueConcat((void**)&ae->orgzone,&ae->io,&ae->mo,&orgzone,sizeof(orgzone)); OverWriteCheck(ae); } void __BANK(struct s_assenv *ae) { struct s_orgzone orgzone={0}; int oldcode=0,oldoutput=0; int i; __internal_UpdateLZBlockIfAny(ae); if (ae->io) { ae->orgzone[ae->io-1].memend=ae->outputadr; } /* without parameter, create a new empty space */ if (ae->wl[ae->idx].t==1) { ___new_memory_space(ae); return; } ae->bankmode=1; if (!ae->forceROM && !ae->forcecpr && !ae->forcesnapshot && !ae->forcezx) ae->forcecpr=1; if (ae->wl[ae->idx+1].t!=2) { if (strcmp(ae->wl[ae->idx+1].w,"NEXT")==0) { /* are we in a temporary space or in the very last bank? */ if (ae->activebank>=260-1) { ___new_memory_space(ae); return; } /* switch to next bank! */ ae->activebank++; } else { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); ae->activebank=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0); } if (ae->forcecpr && (ae->activebank<0 || ae->activebank>31)) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - Bank selection must be from 0 to 31 in cartridge mode\n",GetCurrentFile(ae),ae->wl[ae->idx].l); FreeAssenv(ae); exit(2); } else if (ae->forcezx && (ae->activebank<0 || ae->activebank>7)) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - Bank selection must be from 0 to 7 in ZX Spectrum mode\n",GetCurrentFile(ae),ae->wl[ae->idx].l); FreeAssenv(ae); exit(2); } else if (ae->forceROM && (ae->activebank<0 || ae->activebank>=256)) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - Bank selection must be from 0 to 255 in ROM mode\n",GetCurrentFile(ae),ae->wl[ae->idx].l); FreeAssenv(ae); exit(2); } else if (ae->forcesnapshot && (ae->activebank<0 || ae->activebank>=260)) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - Bank selection must be from 0 to 259 in snapshot mode\n",GetCurrentFile(ae),ae->wl[ae->idx].l); FreeAssenv(ae); exit(2); } /* bankset control */ if (ae->forcesnapshot && ae->bankset[ae->activebank/4]) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot BANK %d was already select by a previous BANKSET %d\n",ae->activebank,(int)ae->activebank/4); ae->idx++; return; } else { ae->bankused[ae->activebank]=1; } ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BANK directive need one integer parameter\n"); return; } if (ae->lz>=0) { if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: LZ section wasn't closed before a new BANK directive\n",GetCurrentFile(ae),ae->wl[ae->idx].l); __LZCLOSE(ae); } /* try to get an old ORG settings backward */ for (i=ae->io-1;i>=0;i--) { if (ae->orgzone[i].ibank==ae->activebank) { oldcode=ae->orgzone[i].memend; oldoutput=ae->orgzone[i].memend; break; } } ae->outputadr=oldoutput; ae->codeadr=oldcode; orgzone.memstart=ae->outputadr; /* legacy */ orgzone.ibank=ae->activebank; orgzone.nocode=ae->nocode=0; ObjectArrayAddDynamicValueConcat((void**)&ae->orgzone,&ae->io,&ae->mo,&orgzone,sizeof(orgzone)); OverWriteCheck(ae); } void __BANKSET(struct s_assenv *ae) { struct s_orgzone orgzone={0}; int ibank; __internal_UpdateLZBlockIfAny(ae); if (!ae->forcesnapshot && !ae->forcecpr && !ae->forcezx) ae->forcesnapshot=1; if (!ae->forcesnapshot) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BANKSET directive is specific to snapshot output\n"); return; } if (ae->io) { ae->orgzone[ae->io-1].memend=ae->outputadr; } ae->bankmode=1; if (ae->wl[ae->idx+1].t!=2) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); ae->activebank=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0); ae->activebank*=4; if (ae->forcesnapshot && (ae->activebank<0 || ae->activebank>=260)) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - Bank set selection must be from 0 to 64 in snapshot mode\n",GetCurrentFile(ae),ae->wl[ae->idx].l); FreeAssenv(ae); exit(2); } /* control */ ibank=ae->activebank; if (ae->bankused[ibank] || ae->bankused[ibank+1]|| ae->bankused[ibank+2]|| ae->bankused[ibank+3]) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot BANKSET because bank %d was already selected in single page mode\n",ibank); ae->idx++; return; } else { ae->bankset[ae->activebank/4]=1; /* pas très heureux mais bon... */ } ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BANKSET directive need one integer parameter\n"); return; } if (ae->lz>=0) { if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: LZ section wasn't closed before a new BANKSET directive\n",GetCurrentFile(ae),ae->wl[ae->idx].l); __LZCLOSE(ae); } ae->outputadr=0; ae->codeadr=0; orgzone.memstart=0; orgzone.ibank=ae->activebank; orgzone.nocode=ae->nocode=0; ObjectArrayAddDynamicValueConcat((void**)&ae->orgzone,&ae->io,&ae->mo,&orgzone,sizeof(orgzone)); OverWriteCheck(ae); } void __NameBANK(struct s_assenv *ae) { int ibank; ae->bankmode=1; if (!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) { if (!StringIsQuote(ae->wl[ae->idx+2].w)) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Syntax is NAMEBANK ,''\n"); } else { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); ibank=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0); if (ibank<0 || ibank>=BANK_MAX_NUMBER) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"NAMEBANK selection must be from 0 to %d\n",BANK_MAX_NUMBER); } else { ae->iwnamebank[ibank]=ae->idx+2; } } ae->idx+=2; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"NAMEBANK directive need one integer parameter and a string\n"); } } /*** Winape little compatibility for CPR writing! */ void __WRITE(struct s_assenv *ae) { int ok=0; int lower=-1,upper=-1,bank=-1; if (!ae->wl[ae->idx].t && strcmp(ae->wl[ae->idx+1].w,"DIRECT")==0 && !ae->wl[ae->idx+1].t) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+2].w,0); lower=RoundComputeExpression(ae,ae->wl[ae->idx+2].w,ae->codeadr,0,0); if (!ae->wl[ae->idx+2].t) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+3].w,0); upper=RoundComputeExpression(ae,ae->wl[ae->idx+3].w,ae->codeadr,0,0); } if (!ae->wl[ae->idx+3].t) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+4].w,0); bank=RoundComputeExpression(ae,ae->wl[ae->idx+4].w,ae->codeadr,0,0); } if (ae->maxam) { if (lower==65535) lower=-1; if (upper==65535) upper=-1; if (bank==65535) bank=-1; } if (lower!=-1) { if (lower>=0 && lower<8) { ae->idx+=1; __BANK(ae); ok=1; } else { if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: WRITE DIRECT lower ROM ignored (value %d out of bounds 0-7)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,lower); } } else if (upper!=-1) { if (upper>=0 && ((ae->forcecpr && upper<32) || (ae->forcesnapshot && upperidx+=2; __BANK(ae); ok=1; } else { if (!ae->forcecpr && !ae->forcesnapshot) { if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: WRITE DIRECT select a ROM without cartridge output\n",GetCurrentFile(ae),ae->wl[ae->idx].l); } else { if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: WRITE DIRECT upper ROM ignored (value %d out of bounds 0-31)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,upper); } } } else if (bank!=-1) { /* selection de bank on ouvre un nouvel espace */ } else { if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: meaningless WRITE DIRECT\n",GetCurrentFile(ae),ae->wl[ae->idx].l); } } while (!ae->wl[ae->idx].t) ae->idx++; if (!ok) { ___new_memory_space(ae); } } void __CHARSET(struct s_assenv *ae) { int i,s,e,v,tquote; if (ae->wl[ae->idx].t==1) { /* reinit charset */ for (i=0;i<256;i++) ae->charset[i]=i; } else if (!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) { /* string,value | byte,value */ ExpressionFastTranslate(ae,&ae->wl[ae->idx+2].w,0); v=RoundComputeExpression(ae,ae->wl[ae->idx+2].w,ae->codeadr,0,0); if (ae->wl[ae->idx+1].w[0]=='\'' || ae->wl[ae->idx+1].w[0]=='"') { tquote=ae->wl[ae->idx+1].w[0]; if (ae->wl[ae->idx+1].w[strlen(ae->wl[ae->idx+1].w)-1]==tquote) { i=1; while (ae->wl[ae->idx+1].w[i] && ae->wl[ae->idx+1].w[i]!=tquote) { if (ae->wl[ae->idx+1].w[i]=='\\') i++; ae->charset[(int)ae->wl[ae->idx+1].w[i]]=(unsigned char)v++; i++; } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CHARSET string,value has invalid quote!\n"); } } else { i=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0); if (i>=0 && i<256) { ae->charset[i]=(unsigned char)v; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CHARSET byte value must be 0-255\n"); } } ae->idx+=2; } else if (!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && !ae->wl[ae->idx+2].t && ae->wl[ae->idx+3].t==1) { /* start,end,value */ ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); ExpressionFastTranslate(ae,&ae->wl[ae->idx+2].w,0); ExpressionFastTranslate(ae,&ae->wl[ae->idx+3].w,0); s=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0); e=RoundComputeExpression(ae,ae->wl[ae->idx+2].w,ae->codeadr,0,0); v=RoundComputeExpression(ae,ae->wl[ae->idx+3].w,ae->codeadr,0,0); ae->idx+=3; if (s<=e && s>=0 && e<256) { for (i=s;i<=e;i++) { ae->charset[i]=(unsigned char)v++; } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CHARSET winape directive wrong interval value\n"); } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CHARSET winape directive wrong parameter count\n"); } } void __MACRO(struct s_assenv *ae) { struct s_macro curmacro={0}; char *referentfilename,*zeparam; int refidx,idx,getparam=1; struct s_wordlist curwl; if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t!=2) { /* get the name */ curmacro.mnemo=ae->wl[ae->idx+1].w; curmacro.crc=GetCRC(curmacro.mnemo); if (ae->wl[ae->idx+1].t) { getparam=0; } /* overload forbidden */ if (SearchMacro(ae,curmacro.crc,curmacro.mnemo)>=0) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Macro already defined with this name\n"); } idx=ae->idx+2; while (ae->wl[idx].t!=2 && (GetCRC(ae->wl[idx].w)!=CRC_MEND || strcmp(ae->wl[idx].w,"MEND")!=0) && (GetCRC(ae->wl[idx].w)!=CRC_ENDM || strcmp(ae->wl[idx].w,"ENDM")!=0)) { if (GetCRC(ae->wl[idx].w)==CRC_MACRO || strcmp(ae->wl[idx].w,"MACRO")==0) { /* inception interdite */ referentfilename=GetCurrentFile(ae); refidx=ae->idx; ae->idx=idx; MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"You cannot define a macro inside another one (MACRO %s in [%s] L%d)\n",ae->wl[refidx+1].w,referentfilename,ae->wl[refidx].l); __STOP(ae); } if (getparam) { /* on prepare les parametres au remplacement */ zeparam=MemMalloc(strlen(ae->wl[idx].w)+3); if (ae->as80) { sprintf(zeparam,"%s",ae->wl[idx].w); } else { sprintf(zeparam,"{%s}",ae->wl[idx].w); } curmacro.nbparam++; curmacro.param=MemRealloc(curmacro.param,curmacro.nbparam*sizeof(char **)); curmacro.param[curmacro.nbparam-1]=zeparam; if (ae->wl[idx].t) { /* duplicate parameters without brackets MUST be an OPTION */ getparam=0; } } else { /* copie la liste de mots */ curwl=ae->wl[idx]; ObjectArrayAddDynamicValueConcat((void **)&curmacro.wc,&curmacro.nbword,&curmacro.maxword,&curwl,sizeof(struct s_wordlist)); } idx++; } if (ae->wl[idx].t==2) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Macro was not closed\n"); } ObjectArrayAddDynamicValueConcat((void**)&ae->macro,&ae->imacro,&ae->mmacro,&curmacro,sizeof(curmacro)); /* le quicksort n'est pas optimal mais on n'est pas supposé en créer des milliers */ qsort(ae->macro,ae->imacro,sizeof(struct s_macro),cmpmacros); /* ajustement des mots lus */ if (ae->wl[idx].t==2) idx--; ae->idx=idx; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"MACRO definition need at least one parameter\n"); } } struct s_wordlist *__MACRO_EXECUTE(struct s_assenv *ae, int imacro) { struct s_wordlist *cpybackup; int nbparam=0,idx,i,j,idad; int ifile,iline,iu,lenparam; double v; struct s_macro_position curmacropos={0}; char *zeparam=NULL,*txtparamlist; int reload=0; idx=ae->idx; while (!ae->wl[idx].t) { nbparam++; idx++; } /* hack to secure macro without parameters with void argument */ if (!ae->macro[imacro].nbparam) { if (nbparam) { if (nbparam==1 && strcmp(ae->wl[ae->idx+1].w,"(VOID)")==0) { nbparam=0; reload=1; } } else { if (ae->macrovoid) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"MACRO [%s] used without (void) and option -void used!\n",ae->macro[imacro].mnemo); while (!ae->wl[ae->idx].t) { ae->idx++; } ae->idx++; } } } /* macro must avoid extra params! */ /* cannot VOID a macro with parameters! */ if (ae->macro[imacro].nbparam && strcmp(ae->wl[ae->idx+1].w,"(VOID)")==0) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"MACRO [%s] has %d parameter%s\n",ae->macro[imacro].mnemo,ae->macro[imacro].nbparam,ae->macro[imacro].nbparam>1?"s":""); while (!ae->wl[ae->idx].t) { ae->idx++; } ae->idx++; } else { if (nbparam!=ae->macro[imacro].nbparam) { lenparam=1; // macro without parameters! for (i=0;imacro[imacro].nbparam;i++) { lenparam+=strlen(ae->macro[imacro].param[i])+3; } txtparamlist=MemMalloc(lenparam); txtparamlist[0]=0; for (i=0;imacro[imacro].nbparam;i++) { strcat(txtparamlist,ae->macro[imacro].param[i]); strcat(txtparamlist," "); } MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"MACRO [%s] was defined with %d parameter%s %s\n",ae->macro[imacro].mnemo,ae->macro[imacro].nbparam,ae->macro[imacro].nbparam>1?"s":"",txtparamlist); while (!ae->wl[ae->idx].t) { ae->idx++; } ae->idx++; } else { /* free macro call as we will overwrite it */ MemFree(ae->wl[ae->idx].w); /* is there a void to free? */ if (reload) { MemFree(ae->wl[ae->idx+1].w); } /* eval parameters? */ for (i=0;iwl[ae->idx+1+i].w,"{EVAL}",6)==0) { /* parametre entre chevrons, il faut l'interpreter d'abord */ zeparam=TxtStrDup(ae->wl[ae->idx+1+i].w+6); ExpressionFastTranslate(ae,&zeparam,1); v=ComputeExpressionCore(ae,zeparam,ae->codeadr,0); MemFree(zeparam); zeparam=MemMalloc(32); snprintf(zeparam,31,"%lf",v); zeparam[31]=0; MemFree(ae->wl[ae->idx+1+i].w); ae->wl[ae->idx+1+i].w=zeparam; } } /* backup parameters */ cpybackup=MemMalloc((nbparam+1)*sizeof(struct s_wordlist)); for (i=0;iwl[ae->idx+1+i]; } /* insert macro position */ curmacropos.start=ae->idx; curmacropos.end=ae->idx+ae->macro[imacro].nbword; curmacropos.value=ae->macrocounter; ObjectArrayAddDynamicValueConcat((void**)&ae->macropos,&ae->imacropos,&ae->mmacropos,&curmacropos,sizeof(curmacropos)); /* are we in a repeat/while block? */ for (iu=0;iuir;iu++) if (ae->repeat[iu].maximimacropos) ae->repeat[iu].maxim=ae->imacropos; for (iu=0;iuiw;iu++) if (ae->whilewend[iu].maximimacropos) ae->whilewend[iu].maxim=ae->imacropos; /* update daddy macropos */ for (idad=0;idadimacropos-1;idad++) { if (ae->macropos[idad].end>curmacropos.start) { ae->macropos[idad].end+=ae->macro[imacro].nbword-1-nbparam-reload; /* coz la macro compte un mot! */ } } #if 0 for (idad=0;idadimacropos;idad++) { printf("macropos[%d]=%d -> %d\n",idad,ae->macropos[idad].start,ae->macropos[idad].end); } #endif /* insert at macro position and replace macro+parameters */ if (ae->macro[imacro].nbword>1+nbparam+reload) { ae->nbword+=ae->macro[imacro].nbword-1-nbparam-reload; ae->wl=MemRealloc(ae->wl,ae->nbword*sizeof(struct s_wordlist)); } else { /* si on réduit pas de realloc pour ne pas perdre de donnees */ ae->nbword+=ae->macro[imacro].nbword-1-nbparam-reload; } iline=ae->wl[ae->idx].l; ifile=ae->wl[ae->idx].ifile; MemMove(&ae->wl[ae->idx+ae->macro[imacro].nbword],&ae->wl[ae->idx+reload+nbparam+1],(ae->nbword-ae->idx-ae->macro[imacro].nbword)*sizeof(struct s_wordlist)); for (i=0;imacro[imacro].nbword;i++) { ae->wl[i+ae->idx].w=TxtStrDup(ae->macro[imacro].wc[i].w); ae->wl[i+ae->idx].l=iline; ae->wl[i+ae->idx].ifile=ifile; /* @@@sujet a evolution, ou double controle */ ae->wl[i+ae->idx].t=ae->macro[imacro].wc[i].t; ae->wl[i+ae->idx].e=ae->macro[imacro].wc[i].e; } /* replace */ idx=ae->idx; for (i=0;imacro[imacro].nbword;j++) { /* tags in upper case for replacement in quotes */ if (StringIsQuote(ae->wl[j].w)) { int lm,touched; for (lm=touched=0;ae->wl[j].w[lm];lm++) { if (ae->wl[j].w[lm]=='{') touched++; else if (ae->wl[j].w[lm]=='}') touched--; else if (touched) ae->wl[j].w[lm]=toupper(ae->wl[j].w[lm]); } } ae->wl[j].w=TxtReplace(ae->wl[j].w,ae->macro[imacro].param[i],cpybackup[i].w,0); } MemFree(cpybackup[i].w); } MemFree(cpybackup); /* macro replaced, need to rollback index */ //ae->idx--; } } /* a chaque appel de macro on incremente le compteur pour les labels locaux */ ae->macrocounter++; return ae->wl; } /* ticker start, ticker stop, */ void __TICKER(struct s_assenv *ae) { struct s_expr_dico *tvar; struct s_ticker ticker; int crc,i; if (!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) { crc=GetCRC(ae->wl[ae->idx+2].w); if (strcmp(ae->wl[ae->idx+1].w,"START")==0) { /* is there already a counter? */ for (i=0;iiticker;i++) { if (ae->ticker[i].crc==crc && strcmp(ae->wl[ae->idx+2].w,ae->ticker[i].varname)==0) { break; } } if (i==ae->iticker) { ticker.varname=TxtStrDup(ae->wl[ae->idx+2].w); ticker.crc=crc; ObjectArrayAddDynamicValueConcat((void **)&ae->ticker,&ae->iticker,&ae->mticker,&ticker,sizeof(struct s_ticker)); } ae->ticker[i].nopstart=ae->nop; } else if (strcmp(ae->wl[ae->idx+1].w,"STOP")==0) { for (i=0;iiticker;i++) { if (ae->ticker[i].crc==crc && strcmp(ae->wl[ae->idx+2].w,ae->ticker[i].varname)==0) { break; } } if (iiticker) { /* set var */ if ((tvar=SearchDico(ae,ae->wl[ae->idx+2].w,crc))!=NULL) { /* compute nop count */ tvar->v=ae->nop-ae->ticker[i].nopstart; } else { /* create var with nop count */ ExpressionSetDicoVar(ae,ae->wl[ae->idx+2].w,ae->nop-ae->ticker[i].nopstart); } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"TICKER not found\n"); } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is TICKER start/stop,\n"); } ae->idx+=2; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is TICKER start/stop,\n"); } } void __LET(struct s_assenv *ae) { if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { ae->idx++; ExpressionFastTranslate(ae,&ae->wl[ae->idx].w,0); RoundComputeExpression(ae,ae->wl[ae->idx].w,ae->codeadr,0,0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LET useless winape directive need one expression\n"); } } void __RUN(struct s_assenv *ae) { int ramconf=0xC0; if (!ae->wl[ae->idx].t) { ae->current_run_idx=ae->idx+1; if (ae->forcezx) { if (!ae->wl[ae->idx].t) { PushExpression(ae,ae->idx+1,E_EXPRESSION_ZXRUN); // delayed RUN value PushExpression(ae,ae->idx+2,E_EXPRESSION_ZXSTACK); // delayed STACK value ae->idx+=2; } else { ae->idx++; MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is RUN , (ZX mode)\n"); } } else { PushExpression(ae,ae->idx+1,E_EXPRESSION_RUN); // delayed RUN value ae->idx++; if (!ae->wl[ae->idx].t) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); ramconf=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0); ae->idx++; if (ramconf<0xC0 || ramconf>0xFF) { if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: ram configuration out of bound %X forced to #C0\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ramconf); } } } } else { if (ae->forcezx) MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is RUN , (ZX mode)\n"); else MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is RUN [,]\n"); } ae->snapshot.ramconfiguration=ramconf; if (ae->rundefined && !ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: run adress redefinition\n",GetCurrentFile(ae),ae->wl[ae->idx].l); ae->rundefined=1; } void __BREAKPOINT(struct s_assenv *ae) { struct s_breakpoint breakpoint={0}; if (ae->activebank>3) breakpoint.bank=1; if (ae->wl[ae->idx].t) { breakpoint.address=ae->codeadr; ObjectArrayAddDynamicValueConcat((void **)&ae->breakpoint,&ae->ibreakpoint,&ae->maxbreakpoint,&breakpoint,sizeof(struct s_breakpoint)); } else if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { breakpoint.address=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0); ObjectArrayAddDynamicValueConcat((void **)&ae->breakpoint,&ae->ibreakpoint,&ae->maxbreakpoint,&breakpoint,sizeof(struct s_breakpoint)); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is BREAKPOINT [adress]\n"); } } void __SETCPC(struct s_assenv *ae) { int mycpc; if (!ae->forcecpr) { ae->forcesnapshot=1; } else { if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: Cannot SETCPC when already in cartridge output\n",GetCurrentFile(ae),ae->wl[ae->idx].l); } if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); mycpc=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0); ae->idx++; switch (mycpc) { case 0: case 1: case 2: case 4: case 5: case 6: ae->snapshot.CPCType=mycpc; break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SETCPC directive has wrong value (0,1,2,4,5,6 only)\n"); } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SETCPC directive need one integer parameter\n"); } } void __SETCRTC(struct s_assenv *ae) { int mycrtc; if (!ae->forcecpr) { ae->forcesnapshot=1; } else { if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: Cannot SETCRTC when already in cartridge output\n",GetCurrentFile(ae),ae->wl[ae->idx].l); } if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); mycrtc=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0); ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SETCRTC directive need one integer parameter\n"); } switch (mycrtc) { case 0: case 1: case 2: case 3: case 4: ae->snapshot.crtcstate.model=mycrtc; break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SETCRTC directive has wrong value (0,1,2,3,4 only)\n"); } } void __LIST(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LIST winape directive do not need parameter\n"); } } void __NOLIST(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"NOLIST winape directive do not need parameter\n"); } } void __BRK(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BRK winape directive do not need parameter\n"); } } void __STOP(struct s_assenv *ae) { rasm_printf(ae,"[%s:%d] STOP assembling requested\n",GetCurrentFile(ae),ae->wl[ae->idx].l); while (ae->wl[ae->idx].t!=2) ae->idx++; ae->idx--; ae->stop=1; } void __PRINT(struct s_assenv *ae) { while (ae->wl[ae->idx].t!=1) { if (!StringIsQuote(ae->wl[ae->idx+1].w)) { char *string2print=NULL; int hex=0,bin=0,entier=0; if (strncmp(ae->wl[ae->idx+1].w,"{HEX}",5)==0) { string2print=TxtStrDup(ae->wl[ae->idx+1].w+5); hex=1; } else if (strncmp(ae->wl[ae->idx+1].w,"{HEX2}",6)==0) { string2print=TxtStrDup(ae->wl[ae->idx+1].w+6); hex=2; } else if (strncmp(ae->wl[ae->idx+1].w,"{HEX4}",6)==0) { string2print=TxtStrDup(ae->wl[ae->idx+1].w+6); hex=4; } else if (strncmp(ae->wl[ae->idx+1].w,"{HEX8}",6)==0) { string2print=TxtStrDup(ae->wl[ae->idx+1].w+6); hex=8; } else if (strncmp(ae->wl[ae->idx+1].w,"{BIN}",5)==0) { string2print=TxtStrDup(ae->wl[ae->idx+1].w+5); bin=1; } else if (strncmp(ae->wl[ae->idx+1].w,"{BIN8}",6)==0) { string2print=TxtStrDup(ae->wl[ae->idx+1].w+6); bin=8; } else if (strncmp(ae->wl[ae->idx+1].w,"{BIN16}",7)==0) { string2print=TxtStrDup(ae->wl[ae->idx+1].w+7); bin=16; } else if (strncmp(ae->wl[ae->idx+1].w,"{BIN32}",7)==0) { string2print=TxtStrDup(ae->wl[ae->idx+1].w+7); bin=32; } else if (strncmp(ae->wl[ae->idx+1].w,"{INT}",5)==0) { string2print=TxtStrDup(ae->wl[ae->idx+1].w+5); entier=1; } else { string2print=TxtStrDup(ae->wl[ae->idx+1].w); } ExpressionFastTranslate(ae,&string2print,1); if (hex) { int zv; zv=RoundComputeExpressionCore(ae,string2print,ae->codeadr,0); switch (hex) { case 1: if (zv&0xFFFFFF00) { if (zv&0xFFFF0000) { rasm_printf(ae,"#%-8.08X ",zv); } else { rasm_printf(ae,"#%-4.04X ",zv); } } else { rasm_printf(ae,"#%-2.02X ",zv); } break; case 2:rasm_printf(ae,"#%-2.02X ",zv);break; case 4:rasm_printf(ae,"#%-4.04X ",zv);break; case 8:rasm_printf(ae,"#%-8.08X ",zv);break; } } else if (bin) { int zv,d; zv=RoundComputeExpressionCore(ae,string2print,ae->codeadr,0); /* remove useless sign bits */ if (bin<32 && (zv&0xFFFF0000)==0xFFFF0000) { zv&=0xFFFF; } switch (bin) { case 1:if (zv&0xFF00) d=15; else d=7;break; case 8:d=7;break; case 16:d=15;break; case 32:d=31;break; } rasm_printf(ae,"%%"); for (;d>=0;d--) { if ((zv>>d)&1) rasm_printf(ae,"1"); else rasm_printf(ae,"0"); } rasm_printf(ae," "); } else if (entier) { rasm_printf(ae,"%d ",(int)RoundComputeExpressionCore(ae,string2print,ae->codeadr,0)); } else { rasm_printf(ae,"%.2lf ",ComputeExpressionCore(ae,string2print,ae->codeadr,0)); } MemFree(string2print); } else { char *varbuffer; int lm,touched; lm=strlen(ae->wl[ae->idx+1].w)-2; if (lm) { varbuffer=MemMalloc(lm+2); sprintf(varbuffer,"%-*.*s ",lm,lm,ae->wl[ae->idx+1].w+1); /* need to upper case tags */ for (lm=touched=0;varbuffer[lm];lm++) { if (varbuffer[lm]=='{') touched++; else if (varbuffer[lm]=='}') touched--; else if (touched) varbuffer[lm]=toupper(varbuffer[lm]); } /* translate tag will check tag consistency */ varbuffer=TranslateTag(ae,varbuffer,&touched,1,E_TAGOPTION_REMOVESPACE); varbuffer=TxtReplace(varbuffer,"\\b","\b",0); varbuffer=TxtReplace(varbuffer,"\\v","\v",0); varbuffer=TxtReplace(varbuffer,"\\f","\f",0); varbuffer=TxtReplace(varbuffer,"\\r","\r",0); varbuffer=TxtReplace(varbuffer,"\\n","\n",0); varbuffer=TxtReplace(varbuffer,"\\t","\t",0); rasm_printf(ae,"%s ",varbuffer); MemFree(varbuffer); } } ae->idx++; } rasm_printf(ae,"\n"); } void __FAIL(struct s_assenv *ae) { __PRINT(ae); __STOP(ae); MaxError(ae); } void __ALIGN(struct s_assenv *ae) { int aval,ifill=-1; if (ae->io) { ae->orgzone[ae->io-1].memend=ae->outputadr; } if (!ae->wl[ae->idx].t) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); aval=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0); ae->idx++; /* align with fill ? */ if (!ae->wl[ae->idx].t) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); ifill=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0); ae->idx++; if (ifill<0 || ifill>255) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"ALIGN fill value must be 0 to 255\n"); ifill=0; } } if (aval<1 || aval>65535) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"ALIGN boundary must be greater than zero and lower than 65536\n"); aval=1; } /* touch codeadr only if adress is misaligned */ if (ae->codeadr%aval) { if (ifill==-1) { /* virtual ALIGN is moving outputadr the same value as codeadr move */ ae->outputadr=ae->outputadr-(ae->codeadr%aval)+aval; ae->codeadr=ae->codeadr-(ae->codeadr%aval)+aval; } else { /* physical ALIGN fill bytes */ while (ae->codeadr%aval) { ___output(ae,ifill); ae->nop+=1; } } } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"ALIGN [,fill] directive need one or two integers parameters\n"); } } void ___internal_skip_loop_block(struct s_assenv *ae, int eloopstyle) { int *loopstyle=NULL; int iloop=0,mloop=0; int cidx; cidx=ae->idx+2; IntArrayAddDynamicValueConcat(&loopstyle,&iloop,&mloop,eloopstyle); /* look for WEND */ while (iloop) { if (strcmp(ae->wl[cidx].w,"REPEAT")==0) { if (ae->wl[cidx].t) { IntArrayAddDynamicValueConcat(&loopstyle,&iloop,&mloop,E_LOOPSTYLE_REPEATUNTIL); } else if (ae->wl[cidx+1].t) { IntArrayAddDynamicValueConcat(&loopstyle,&iloop,&mloop,E_LOOPSTYLE_REPEATN); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Invalid REPEAT syntax\n"); } } else if (strcmp(ae->wl[cidx].w,"WHILE")==0) { if (!ae->wl[cidx].t && ae->wl[cidx+1].t) { IntArrayAddDynamicValueConcat(&loopstyle,&iloop,&mloop,E_LOOPSTYLE_WHILE); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Invalid WHILE syntax\n"); } } else if (strcmp(ae->wl[cidx].w,"WEND")==0) { iloop--; if (iloop<0) { iloop=0; MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"WEND encountered that was not expected\n"); } else if (loopstyle[iloop]!=E_LOOPSTYLE_WHILE) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"WEND encountered but expecting %s\n",loopstyle[iloop]==E_LOOPSTYLE_REPEATN?"REND":"UNTIL"); } } else if (strcmp(ae->wl[cidx].w,"REND")==0) { iloop--; if (iloop<0) { iloop=0; MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"REND encountered that was not expected\n"); } else if (loopstyle[iloop]!=E_LOOPSTYLE_REPEATN) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"REND encountered but expecting %s\n",loopstyle[iloop]==E_LOOPSTYLE_REPEATUNTIL?"UNTIL":"WEND"); } } else if (strcmp(ae->wl[cidx].w,"UNTIL")==0) { iloop--; if (iloop<0) { iloop=0; MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"UNTIL encountered that was not expected\n"); } else if (loopstyle[iloop]!=E_LOOPSTYLE_REPEATUNTIL) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"UNTIL encountered but expecting %s\n",loopstyle[iloop]==E_LOOPSTYLE_REPEATN?"REND":"WEND"); } } while (!ae->wl[cidx].t) cidx++; cidx++; } MemFree(loopstyle); ae->idx=cidx-1; } void __WHILE(struct s_assenv *ae) { struct s_whilewend whilewend={0}; if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); if (!ComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,2)) { /* skip while block */ ___internal_skip_loop_block(ae,E_LOOPSTYLE_WHILE); return; } else { ae->idx++; whilewend.start=ae->idx; whilewend.cpt=0; whilewend.value=ae->whilecounter; whilewend.maxim=ae->imacropos; whilewend.while_counter=1; ae->whilecounter++; /* pour gérer les macros situés dans le while précedent après un repeat/while courant */ if (ae->iw) whilewend.maxim=ae->whilewend[ae->iw-1].maxim; if (ae->ir && ae->repeat[ae->ir-1].maxim>whilewend.maxim) whilewend.maxim=ae->repeat[ae->ir-1].maxim; ObjectArrayAddDynamicValueConcat((void**)&ae->whilewend,&ae->iw,&ae->mw,&whilewend,sizeof(whilewend)); } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is WHILE \n"); } } void __WEND(struct s_assenv *ae) { if (ae->iw>0) { if (ae->wl[ae->idx].t==1) { if (ComputeExpression(ae,ae->wl[ae->whilewend[ae->iw-1].start].w,ae->codeadr,0,2)) { if (ae->whilewend[ae->iw-1].while_counter>65536) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Bypass infinite WHILE loop\n"); ae->iw--; /* refresh macro check index */ if (ae->iw) ae->imacropos=ae->whilewend[ae->iw-1].maxim; } else { ae->whilewend[ae->iw-1].cpt++; /* for local label */ ae->whilewend[ae->iw-1].while_counter++; ae->idx=ae->whilewend[ae->iw-1].start; /* refresh macro check index */ ae->imacropos=ae->whilewend[ae->iw-1].maxim; } } else { ae->iw--; /* refresh macro check index */ if (ae->iw) ae->imacropos=ae->whilewend[ae->iw-1].maxim; } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"WEND does not need any parameter\n"); } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"WEND encounter whereas there is no referent WHILE\n"); } } void __REPEAT(struct s_assenv *ae) { struct s_repeat currepeat={0}; struct s_expr_dico *rvar; int *loopstyle; int iloop,mloop; int cidx,crc; if (ae->wl[ae->idx+1].t!=2) { if (ae->wl[ae->idx].t==0) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); currepeat.cpt=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,0,0,0); if (!currepeat.cpt) { /* skip repeat block */ ___internal_skip_loop_block(ae,E_LOOPSTYLE_REPEATN); return; } else if (currepeat.cpt<1 || currepeat.cpt>65536) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Repeat value (%d) must be from 1 to 65535. Skipping block\n",currepeat.cpt); ___internal_skip_loop_block(ae,E_LOOPSTYLE_REPEATN); return; } ae->idx++; currepeat.start=ae->idx; if (ae->wl[ae->idx].t==0) { ae->idx++; if (ae->wl[ae->idx].t==1) { /* la variable peut exister -> OK */ crc=GetCRC(ae->wl[ae->idx].w); if ((rvar=SearchDico(ae,ae->wl[ae->idx].w,crc))!=NULL) { rvar->v=1; } else { /* mais ne peut être un label ou un alias */ ExpressionSetDicoVar(ae,ae->wl[ae->idx].w, 1); } currepeat.repeatvar=ae->wl[ae->idx].w; currepeat.repeatcrc=crc; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"extended syntax is REPEAT ,\n"); } } } else { currepeat.start=ae->idx; currepeat.cpt=-1; } currepeat.value=ae->repeatcounter; currepeat.repeat_counter=1; ae->repeatcounter++; /* pour gérer les macros situés dans le repeat précedent après le repeat courant */ if (ae->ir) currepeat.maxim=ae->repeat[ae->ir-1].maxim; if (ae->iw && ae->whilewend[ae->iw-1].maxim>currepeat.maxim) currepeat.maxim=ae->whilewend[ae->iw-1].maxim; if (ae->imacropos>currepeat.maxim) currepeat.maxim=ae->imacropos; ObjectArrayAddDynamicValueConcat((void**)&ae->repeat,&ae->ir,&ae->mr,&currepeat,sizeof(currepeat)); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"wrong REPEAT usage\n"); } } void __REND(struct s_assenv *ae) { struct s_expr_dico *rvar; if (ae->ir>0) { if (ae->repeat[ae->ir-1].cpt==-1) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"REND encounter whereas referent REPEAT was waiting for UNTIL\n"); } else { ae->repeat[ae->ir-1].cpt--; ae->repeat[ae->ir-1].repeat_counter++; if ((rvar=SearchDico(ae,ae->repeat[ae->ir-1].repeatvar,ae->repeat[ae->ir-1].repeatcrc))!=NULL) { rvar->v=ae->repeat[ae->ir-1].repeat_counter; } if (ae->repeat[ae->ir-1].cpt) { ae->idx=ae->repeat[ae->ir-1].start; /* refresh macro check index */ ae->imacropos=ae->repeat[ae->ir-1].maxim; } else { ae->ir--; /* refresh macro check index */ if (ae->ir) ae->imacropos=ae->repeat[ae->ir-1].maxim; } } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"REND encounter whereas there is no referent REPEAT\n"); } } void __UNTIL(struct s_assenv *ae) { if (ae->ir>0) { if (ae->repeat[ae->ir-1].cpt>=0) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"[%s:%d] UNTIL encounter whereas referent REPEAT n was waiting for REND\n"); } else { if (ae->wl[ae->idx].t==0 && ae->wl[ae->idx+1].t==1) { ae->repeat[ae->ir-1].repeat_counter++; ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); if (!ComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,2)) { if (ae->repeat[ae->ir-1].repeat_counter>65536) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Bypass infinite REPEAT loop\n"); ae->ir--; /* refresh macro check index */ if (ae->ir) ae->imacropos=ae->repeat[ae->ir-1].maxim; } else { ae->idx=ae->repeat[ae->ir-1].start; ae->repeat[ae->ir-1].cpt--; /* for local label */ /* refresh macro check index */ ae->imacropos=ae->repeat[ae->ir-1].maxim; } } else { ae->ir--; /* refresh macro check index */ if (ae->ir) ae->imacropos=ae->repeat[ae->ir-1].maxim; } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"UNTIL need one expression/evaluation as parameter\n"); } } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"UNTIL encounter whereas there is no referent REPEAT\n"); } } void __ASSERT(struct s_assenv *ae) { char Dot3[4]; int rexpr; if (!ae->wl[ae->idx].t) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); if (strlen(ae->wl[ae->idx+1].w)>29) strcpy(Dot3,"..."); else strcpy(Dot3,""); rexpr=!!RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,1); if (!rexpr) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx+1].l,"ASSERT %.29s%s failed with ",ae->wl[ae->idx+1].w,Dot3); ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,1); rasm_printf(ae,"%s\n",ae->wl[ae->idx+1].w); if (!ae->wl[ae->idx+1].t) { ae->idx++; rasm_printf(ae,"-> "); __PRINT(ae); } __STOP(ae); } else { while (!ae->wl[ae->idx].t) ae->idx++; } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"ASSERT need one expression\n"); } } void __IF(struct s_assenv *ae) { struct s_ifthen ifthen={0}; int rexpr; if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); rexpr=!!RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,1); ifthen.v=rexpr; ifthen.filename=GetCurrentFile(ae); ifthen.line=ae->wl[ae->idx].l; ifthen.type=E_IFTHEN_TYPE_IF; ObjectArrayAddDynamicValueConcat((void **)&ae->ifthen,&ae->ii,&ae->mi,&ifthen,sizeof(ifthen)); ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IF need one expression\n"); } } void __IF_light(struct s_assenv *ae) { struct s_ifthen ifthen={0}; if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { /* do not need to compute the value in shadow execution */ ifthen.v=0; ifthen.filename=GetCurrentFile(ae); ifthen.line=ae->wl[ae->idx].l; ifthen.type=E_IFTHEN_TYPE_IF; ObjectArrayAddDynamicValueConcat((void **)&ae->ifthen,&ae->ii,&ae->mi,&ifthen,sizeof(ifthen)); ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IF need one expression\n"); } } /* test if a label or a variable where used before */ void __IFUSED(struct s_assenv *ae) { struct s_ifthen ifthen={0}; int rexpr,crc; if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { crc=GetCRC(ae->wl[ae->idx+1].w); if ((SearchDico(ae,ae->wl[ae->idx+1].w,crc))!=NULL) { rexpr=1; } else { if ((SearchLabel(ae,ae->wl[ae->idx+1].w,crc))!=NULL) { rexpr=1; } else { if ((SearchAlias(ae,crc,ae->wl[ae->idx+1].w))!=-1) { rexpr=1; } else { rexpr=SearchUsed(ae,ae->wl[ae->idx+1].w,crc); } } } ifthen.v=rexpr; ifthen.filename=GetCurrentFile(ae); ifthen.line=ae->wl[ae->idx].l; ifthen.type=E_IFTHEN_TYPE_IFUSED; ObjectArrayAddDynamicValueConcat((void **)&ae->ifthen,&ae->ii,&ae->mi,&ifthen,sizeof(ifthen)); ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IFUSED need one variable or label\n"); } } void __IFNUSED(struct s_assenv *ae) { __IFUSED(ae); ae->ifthen[ae->ii-1].v=1-ae->ifthen[ae->ii-1].v; ae->ifthen[ae->ii-1].type=E_IFTHEN_TYPE_IFNUSED; } void __IFUSED_light(struct s_assenv *ae) { struct s_ifthen ifthen={0}; if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { ifthen.v=0; ifthen.filename=GetCurrentFile(ae); ifthen.line=ae->wl[ae->idx].l; ifthen.type=E_IFTHEN_TYPE_IFUSED; ObjectArrayAddDynamicValueConcat((void **)&ae->ifthen,&ae->ii,&ae->mi,&ifthen,sizeof(ifthen)); ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IFUSED need one variable or label\n"); } } void __IFNUSED_light(struct s_assenv *ae) { __IFUSED_light(ae); ae->ifthen[ae->ii-1].type=E_IFTHEN_TYPE_IFNUSED; } /* test if a label or a variable exists */ void __IFDEF(struct s_assenv *ae) { struct s_ifthen ifthen={0}; int rexpr,crc; if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { crc=GetCRC(ae->wl[ae->idx+1].w); if ((SearchDico(ae,ae->wl[ae->idx+1].w,crc))!=NULL) { rexpr=1; } else { if ((SearchLabel(ae,ae->wl[ae->idx+1].w,crc))!=NULL) { rexpr=1; } else { if ((SearchAlias(ae,crc,ae->wl[ae->idx+1].w))!=-1) { rexpr=1; } else { if (SearchMacro(ae,crc,ae->wl[ae->idx+1].w)>=0) { rexpr=1; } else { rexpr=0; } } } } ifthen.v=rexpr; ifthen.filename=GetCurrentFile(ae); ifthen.line=ae->wl[ae->idx].l; ifthen.type=E_IFTHEN_TYPE_IFDEF; ObjectArrayAddDynamicValueConcat((void **)&ae->ifthen,&ae->ii,&ae->mi,&ifthen,sizeof(ifthen)); ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IFDEF need one variable or label\n"); } } void __IFDEF_light(struct s_assenv *ae) { struct s_ifthen ifthen={0}; if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { ifthen.v=0; ifthen.filename=GetCurrentFile(ae); ifthen.line=ae->wl[ae->idx].l; ifthen.type=E_IFTHEN_TYPE_IFDEF; ObjectArrayAddDynamicValueConcat((void **)&ae->ifthen,&ae->ii,&ae->mi,&ifthen,sizeof(ifthen)); ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"GetCurrentFile(ae),ae->wl[ae->idx].l[%s:%d] FATAL - IFDEF need one variable or label\n"); } } void __IFNDEF(struct s_assenv *ae) { struct s_expr_dico *curdic=NULL; struct s_label *curlabel=NULL; struct s_ifthen ifthen={0}; int rexpr,crc; if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { crc=GetCRC(ae->wl[ae->idx+1].w); if ((SearchDico(ae,ae->wl[ae->idx+1].w,crc))!=NULL) { rexpr=0; } else { if ((SearchLabel(ae,ae->wl[ae->idx+1].w,crc))!=NULL) { rexpr=0; } else { if ((SearchAlias(ae,crc,ae->wl[ae->idx+1].w))!=-1) { rexpr=0; } else { if (SearchMacro(ae,crc,ae->wl[ae->idx+1].w)>=0) { rexpr=0; } else { rexpr=1; } } } } ifthen.v=rexpr; ifthen.filename=GetCurrentFile(ae); ifthen.line=ae->wl[ae->idx].l; ifthen.type=E_IFTHEN_TYPE_IFNDEF; ObjectArrayAddDynamicValueConcat((void **)&ae->ifthen,&ae->ii,&ae->mi,&ifthen,sizeof(ifthen)); ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IFNDEF need one variable or label\n"); } } void __IFNDEF_light(struct s_assenv *ae) { struct s_expr_dico *curdic=NULL; struct s_label *curlabel=NULL; struct s_ifthen ifthen={0}; if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { ifthen.v=0; ifthen.filename=GetCurrentFile(ae); ifthen.line=ae->wl[ae->idx].l; ifthen.type=E_IFTHEN_TYPE_IFNDEF; ObjectArrayAddDynamicValueConcat((void **)&ae->ifthen,&ae->ii,&ae->mi,&ifthen,sizeof(ifthen)); ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IFNDEF need one variable or label\n",GetCurrentFile(ae),ae->wl[ae->idx].l); } } void __UNDEF(struct s_assenv *ae) { if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { /* no error when the variable to UNDEF does not exist */ DelDico(ae,ae->wl[ae->idx+1].w,GetCRC(ae->wl[ae->idx+1].w)); ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is UNDEF \n"); } } void __SWITCH(struct s_assenv *ae) { struct s_switchcase curswitch={0}; if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { /* switch store the value */ ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); curswitch.refval=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,1); ObjectArrayAddDynamicValueConcat((void**)&ae->switchcase,&ae->isw,&ae->msw,&curswitch,sizeof(curswitch)); ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SWITCH need one expression\n"); } } void __CASE(struct s_assenv *ae) { int rexpr; if (ae->isw) { if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); rexpr=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,1); if (ae->switchcase[ae->isw-1].refval==rexpr) { ae->switchcase[ae->isw-1].execute=1; ae->switchcase[ae->isw-1].casematch=1; } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CASE not need one parameter\n"); } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CASE encounter whereas there is no referent SWITCH\n"); } } void __DEFAULT(struct s_assenv *ae) { if (ae->isw) { if (ae->wl[ae->idx].t==1) { /* aucun match avant, on active, sinon on laisse tel quel */ if (!ae->switchcase[ae->isw-1].casematch) { ae->switchcase[ae->isw-1].execute=1; } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFAULT do not need parameter\n"); } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFAULT encounter whereas there is no referent SWITCH\n"); } } void __BREAK(struct s_assenv *ae) { if (ae->isw) { if (ae->wl[ae->idx].t==1) { ae->switchcase[ae->isw-1].execute=0; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BREAK do not need parameter\n"); } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BREAK encounter whereas there is no referent SWITCH\n"); } } void __SWITCH_light(struct s_assenv *ae) { struct s_switchcase curswitch={0}; if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { /* shadow execution */ curswitch.refval=0; curswitch.execute=0; ObjectArrayAddDynamicValueConcat((void**)&ae->switchcase,&ae->isw,&ae->msw,&curswitch,sizeof(curswitch)); ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SWITCH need one expression\n"); } } void __CASE_light(struct s_assenv *ae) { if (ae->isw) { /* shadowed execution */ } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CASE encounter whereas there is no referent SWITCH\n"); } } void __DEFAULT_light(struct s_assenv *ae) { if (ae->isw) { /* shadowed execution */ } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFAULT encounter whereas there is no referent SWITCH\n"); } } void __BREAK_light(struct s_assenv *ae) { if (ae->isw) { /* shadowed execution */ } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BREAK encounter whereas there is no referent SWITCH\n"); } } void __ENDSWITCH(struct s_assenv *ae) { if (ae->isw) { if (ae->wl[ae->idx].t==1) { ae->isw--; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"ENDSWITCH does not need any parameter\n"); } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"ENDSWITCH encounter whereas there is no referent SWITCH\n"); } } void __IFNOT(struct s_assenv *ae) { struct s_ifthen ifthen={0}; int rexpr; if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); rexpr=!RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,1); ifthen.v=rexpr; ifthen.filename=GetCurrentFile(ae); ifthen.line=ae->wl[ae->idx].l; ifthen.type=E_IFTHEN_TYPE_IFNOT; ObjectArrayAddDynamicValueConcat((void **)&ae->ifthen,&ae->ii,&ae->mi,&ifthen,sizeof(ifthen)); //IntArrayAddDynamicValueConcat(&ae->ifthen,&ae->ii,&ae->mi,rexpr); ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IFNOT need one expression\n"); } } void __IFNOT_light(struct s_assenv *ae) { struct s_ifthen ifthen={0}; if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { ifthen.v=0; ifthen.filename=GetCurrentFile(ae); ifthen.line=ae->wl[ae->idx].l; ifthen.type=E_IFTHEN_TYPE_IFNOT; ObjectArrayAddDynamicValueConcat((void **)&ae->ifthen,&ae->ii,&ae->mi,&ifthen,sizeof(ifthen)); //IntArrayAddDynamicValueConcat(&ae->ifthen,&ae->ii,&ae->mi,rexpr); ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IFNOT need one expression\n"); } } void __ELSE(struct s_assenv *ae) { if (ae->ii) { if (ae->wl[ae->idx].t==1) { /* ELSE a executer seulement si celui d'avant est a zero */ switch (ae->ifthen[ae->ii-1].v) { case -1:break; case 0:ae->ifthen[ae->ii-1].v=1;break; case 1:ae->ifthen[ae->ii-1].v=0;break; } ae->ifthen[ae->ii-1].type=E_IFTHEN_TYPE_ELSE; ae->ifthen[ae->ii-1].line=ae->wl[ae->idx].l; ae->ifthen[ae->ii-1].filename=GetCurrentFile(ae); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"ELSE does not need any parameter\n"); } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"ELSE encounter whereas there is no referent IF\n"); } } void __ELSEIF(struct s_assenv *ae) { if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { ae->ifthen[ae->ii-1].type=E_IFTHEN_TYPE_ELSEIF; ae->ifthen[ae->ii-1].line=ae->wl[ae->idx].l; ae->ifthen[ae->ii-1].filename=GetCurrentFile(ae); if (ae->ifthen[ae->ii-1].v) { /* il faut signifier aux suivants qu'on va jusqu'au ENDIF */ ae->ifthen[ae->ii-1].v=-1; } else { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); ae->ifthen[ae->ii-1].v=!!RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,1); } ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"ELSEIF need one expression\n"); } } void __ELSEIF_light(struct s_assenv *ae) { if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { ae->ifthen[ae->ii-1].type=E_IFTHEN_TYPE_ELSEIF; ae->ifthen[ae->ii-1].line=ae->wl[ae->idx].l; ae->ifthen[ae->ii-1].filename=GetCurrentFile(ae); if (ae->ifthen[ae->ii-1].v) { /* il faut signifier aux suivants qu'on va jusqu'au ENDIF */ ae->ifthen[ae->ii-1].v=-1; } else { ae->ifthen[ae->ii-1].v=0; } ae->idx++; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"ELSEIF need one expression\n"); } } void __ENDIF(struct s_assenv *ae) { if (ae->ii) { if (ae->wl[ae->idx].t==1) { ae->ii--; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"ENDIF does not need any parameter\n"); } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"ENDIF encounter whereas there is no referent IF\n"); } } void __internal_PROTECT(struct s_assenv *ae, int memstart, int memend) { struct s_orgzone orgzone={0}; /* add a fake ORG zone */ ObjectArrayAddDynamicValueConcat((void**)&ae->orgzone,&ae->io,&ae->mo,&orgzone,sizeof(orgzone)); /* then switch it with the current ORG */ orgzone=ae->orgzone[ae->io-2]; ae->orgzone[ae->io-2].memstart=memstart; ae->orgzone[ae->io-2].memend=memend; ae->orgzone[ae->io-2].ibank=ae->activebank; ae->orgzone[ae->io-2].protect=1; ae->orgzone[ae->io-1]=orgzone; } void __PROTECT(struct s_assenv *ae) { int memstart,memend; if (!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); ExpressionFastTranslate(ae,&ae->wl[ae->idx+2].w,0); memstart=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,0,0,0); memend=RoundComputeExpression(ae,ae->wl[ae->idx+2].w,0,0,0); __internal_PROTECT(ae,memstart,memend); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"PROTECT need two parameters: startadr,endadr\n"); } } void ___org_close(struct s_assenv *ae) { if (ae->lz>=0) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot ORG inside a LZ section\n"); return; } __internal_UpdateLZBlockIfAny(ae); /* close current ORG */ if (ae->io) { ae->orgzone[ae->io-1].memend=ae->outputadr; } } void ___org_new(struct s_assenv *ae, int nocode) { struct s_orgzone orgzone={0}; int i; /* check current ORG request */ for (i=0;iio;i++) { /* aucun contrôle sur les ORG non écrits ou en NOCODE */ if (ae->orgzone[i].memstart!=ae->orgzone[i].memend && !ae->orgzone[i].nocode) { if (ae->orgzone[i].ibank==ae->activebank) { if (ae->outputadrorgzone[i].memend && ae->outputadr>=ae->orgzone[i].memstart) { if (ae->orgzone[i].protect) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"ORG located a PROTECTED section [#%04X-#%04X-B%d] file [%s] line %d\n",ae->orgzone[i].memstart,ae->orgzone[i].memend,ae->orgzone[i].ibank<32?ae->orgzone[i].ibank:0,ae->filename[ae->orgzone[i].ifile],ae->orgzone[i].iline); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"ORG (output at #%04X) located in a previous ORG section [#%04X-#%04X-B%d] file [%s] line %d\n",ae->outputadr,ae->orgzone[i].memstart,ae->orgzone[i].memend,ae->orgzone[i].ibank<32?ae->orgzone[i].ibank:0,ae->filename[ae->orgzone[i].ifile],ae->orgzone[i].iline); } } } } } OverWriteCheck(ae); /* if there was a crunch block before, now closed */ if (ae->lz>=0) { ae->lz=-1; } orgzone.memstart=ae->outputadr; orgzone.ibank=ae->activebank; orgzone.ifile=ae->wl[ae->idx].ifile; orgzone.iline=ae->wl[ae->idx].l; orgzone.nocode=ae->nocode=nocode; if (nocode) { ___output=___internal_output_nocode; } else { ___output=___internal_output; } ObjectArrayAddDynamicValueConcat((void**)&ae->orgzone,&ae->io,&ae->mo,&orgzone,sizeof(orgzone)); } void __ORG(struct s_assenv *ae) { ___org_close(ae); if (ae->wl[ae->idx+1].t!=2) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); ae->codeadr=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->outputadr,0,0); if (!ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t!=2) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+2].w,0); ae->outputadr=RoundComputeExpression(ae,ae->wl[ae->idx+2].w,ae->outputadr,0,0); ae->idx+=2; } else { ae->outputadr=ae->codeadr; ae->idx++; } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"[%s:%d] ORG code location[,output location]\n"); return; } ___org_new(ae,ae->nocode); } void __NOCODE(struct s_assenv *ae) { if (ae->wl[ae->idx].t==1) { ___org_close(ae); ae->codeadrbackup=ae->codeadr; ae->outputadrbackup=ae->outputadr; ___org_new(ae,1); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"NOCODE directive does not need parameter\n"); } } void __CODE(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { if (strcmp(ae->wl[ae->idx+1].w,"SKIP")==0) { ___org_close(ae); ae->codeadr=ae->codeadrbackup; ae->outputadr=ae->outputadrbackup; ___org_new(ae,1); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"unknown parameter for CODE directive\n"); } ae->idx++; } else if (ae->wl[ae->idx].t==1) { ___org_close(ae); ___org_new(ae,0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CODE directive does not need parameter\n"); } } void __STRUCT(struct s_assenv *ae) { #undef FUNC #define FUNC "__STRUCT" struct s_rasmstructfield rasmstructfield={0}; struct s_rasmstruct rasmstruct={0}; struct s_rasmstruct rasmstructalias={0}; struct s_label curlabel={0}; int crc,i,j,irs; /* filler */ int localsize,cursize; double zeval; if (!ae->wl[ae->idx].t) { if (ae->wl[ae->idx+1].t) { /************************************************** s t r u c t u r e d e c l a r a t i o n **************************************************/ if (!ae->getstruct) { /* cannot be an existing label or EQU (but variable ok) */ crc=GetCRC(ae->wl[ae->idx+1].w); if ((SearchLabel(ae,ae->wl[ae->idx+1].w,crc))!=NULL || (SearchAlias(ae,crc,ae->wl[ae->idx+1].w))!=-1) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"STRUCT name must be different from existing labels ou aliases\n"); } else { ae->backup_filename=GetCurrentFile(ae); ae->backup_line=ae->wl[ae->idx].l; ae->backup_outputadr=ae->outputadr; ae->backup_codeadr=ae->codeadr; ae->getstruct=1; /* STRUCT = NOCODE + ORG 0 */ ___org_close(ae); ae->codeadr=0; ___org_new(ae,1); /* create struct */ rasmstruct.name=TxtStrDup(ae->wl[ae->idx+1].w); rasmstruct.crc=GetCRC(rasmstruct.name); ObjectArrayAddDynamicValueConcat((void **)&ae->rasmstruct,&ae->irasmstruct,&ae->mrasmstruct,&rasmstruct,sizeof(rasmstruct)); ae->idx++; /* wrapper for data capture */ instruction[ICRC_DEFB].makemnemo=_DEFB_struct;instruction[ICRC_DB].makemnemo=_DEFB_struct; instruction[ICRC_DEFW].makemnemo=_DEFW_struct;instruction[ICRC_DW].makemnemo=_DEFW_struct; instruction[ICRC_DEFI].makemnemo=_DEFI_struct; instruction[ICRC_DEFR].makemnemo=_DEFR_struct;instruction[ICRC_DR].makemnemo=_DEFR_struct; instruction[ICRC_DEFS].makemnemo=_DEFS_struct;instruction[ICRC_DS].makemnemo=_DEFS_struct; } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"STRUCT cannot be declared inside previous opened STRUCT [%s] Line %d\n",ae->backup_filename,ae->backup_line); } } else { /************************************************** s t r u c t u r e i n s e r t i o n **************************************************/ int nbelem=1; #if TRACE_STRUCT printf("structure insertion\n"); #endif /* insert struct param1 in memory with name param2 */ crc=GetCRC(ae->wl[ae->idx+1].w); /* look for existing struct */ for (irs=0;irsirasmstruct;irs++) { if (ae->rasmstruct[irs].crc==crc && strcmp(ae->rasmstruct[irs].name,ae->wl[ae->idx+1].w)==0) break; } if (irs==ae->irasmstruct) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Unknown STRUCT %s\n",ae->wl[ae->idx+1].w); } else { /* create alias for sizeof */ if (!ae->getstruct) { if (ae->wl[ae->idx+2].w[0]=='@') { rasmstructalias.name=MakeLocalLabel(ae,ae->wl[ae->idx+2].w,NULL); } else { rasmstructalias.name=TxtStrDup(ae->wl[ae->idx+2].w); } } else { #if TRACE_STRUCT printf("struct [%s] inside struct\n",ae->wl[ae->idx+2].w); #endif /* struct inside struct */ rasmstructalias.name=MemMalloc(strlen(ae->rasmstruct[ae->irasmstruct-1].name)+2+strlen(ae->wl[ae->idx+2].w)); sprintf(rasmstructalias.name,"%s.%s",ae->rasmstruct[ae->irasmstruct-1].name,ae->wl[ae->idx+2].w); } rasmstructalias.crc=GetCRC(rasmstructalias.name); rasmstructalias.size=ae->rasmstruct[irs].size; rasmstructalias.ptr=ae->codeadr; #if TRACE_STRUCT printf("structalias [%s] ptr=%d size=%d\n",rasmstructalias.name,rasmstructalias.ptr,rasmstructalias.size); #endif /* extra parameter to declare an array? */ if (!ae->wl[ae->idx+2].t && !StringIsQuote(ae->wl[ae->idx+3].w)) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+3].w,0); nbelem=RoundComputeExpression(ae,ae->wl[ae->idx+3].w,ae->outputadr,0,0); if (nbelem<1) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Struct array need a positive number of elements!\n"); nbelem=1; } ae->idx++; } rasmstructalias.nbelem=nbelem; #if TRACE_STRUCT printf("EVOL 119 - tableau! %d elem(s)\n",nbelem); #endif ObjectArrayAddDynamicValueConcat((void **)&ae->rasmstructalias,&ae->irasmstructalias,&ae->mrasmstructalias,&rasmstructalias,sizeof(rasmstructalias)); /* create label for global struct ptr */ curlabel.iw=-1; curlabel.ptr=ae->codeadr; if (!ae->getstruct) { if (ae->wl[ae->idx+2].w[0]=='@') curlabel.name=MakeLocalLabel(ae,ae->wl[ae->idx+2].w,NULL); else curlabel.name=TxtStrDup(ae->wl[ae->idx+2].w); curlabel.crc=GetCRC(curlabel.name); PushLabelLight(ae,&curlabel); } else { /* or check for non-local name in struct declaration */ if (ae->wl[ae->idx+2].w[0]=='@') { MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"Meaningless use of local label in a STRUCT definition\n"); } else { curlabel.name=TxtStrDup(rasmstructalias.name); curlabel.crc=GetCRC(curlabel.name); PushLabelLight(ae,&curlabel); } } /* first field is in fact the very beginning of the structure */ if (ae->getstruct) { rasmstructfield.name=TxtStrDup(ae->wl[ae->idx+2].w); rasmstructfield.offset=ae->codeadr; ObjectArrayAddDynamicValueConcat((void **)&ae->rasmstruct[ae->irasmstruct-1].rasmstructfield, &ae->rasmstruct[ae->irasmstruct-1].irasmstructfield,&ae->rasmstruct[ae->irasmstruct-1].mrasmstructfield, &rasmstructfield,sizeof(rasmstructfield)); } /* create subfields */ #if TRACE_STRUCT printf("create subfields\n"); #endif curlabel.iw=-1; curlabel.ptr=ae->codeadr; for (i=0;irasmstruct[irs].irasmstructfield;i++) { curlabel.ptr=ae->codeadr+ae->rasmstruct[irs].rasmstructfield[i].offset; if (!ae->getstruct) { curlabel.name=MemMalloc(strlen(ae->wl[ae->idx+2].w)+strlen(ae->rasmstruct[irs].rasmstructfield[i].name)+2); sprintf(curlabel.name,"%s.%s",ae->wl[ae->idx+2].w,ae->rasmstruct[irs].rasmstructfield[i].name); if (ae->wl[ae->idx+2].w[0]=='@') { char *newlabel; newlabel=MakeLocalLabel(ae,curlabel.name,NULL); MemFree(curlabel.name); curlabel.name=newlabel; } curlabel.crc=GetCRC(curlabel.name); PushLabelLight(ae,&curlabel); /* are we using a struct in a struct definition? */ } else { /* copy structname+label+offset in the structure */ rasmstructfield.name=MemMalloc(strlen(ae->wl[ae->idx+2].w)+strlen(ae->rasmstruct[irs].rasmstructfield[i].name)+2); sprintf(rasmstructfield.name,"%s.%s",ae->wl[ae->idx+2].w,ae->rasmstruct[irs].rasmstructfield[i].name); rasmstructfield.offset=curlabel.ptr; ObjectArrayAddDynamicValueConcat((void **)&ae->rasmstruct[ae->irasmstruct-1].rasmstructfield, &ae->rasmstruct[ae->irasmstruct-1].irasmstructfield,&ae->rasmstruct[ae->irasmstruct-1].mrasmstructfield, &rasmstructfield,sizeof(rasmstructfield)); /* need to push also generic label */ curlabel.name=MemMalloc(strlen(ae->rasmstruct[ae->irasmstruct-1].name)+strlen(rasmstructfield.name)+2); /* overwrite PTR */ sprintf(curlabel.name,"%s.%s",ae->rasmstruct[ae->irasmstruct-1].name,rasmstructfield.name); curlabel.crc=GetCRC(curlabel.name); PushLabelLight(ae,&curlabel); } } /* is there any filler in the declaration? */ localsize=0; /* déterminer si on est en remplissage par défaut ou remplissage surchargé */ #if TRACE_STRUCT printf("struct new behaviour (scan for %d fields)\n",ae->rasmstruct[irs].irasmstructfield); #endif #if 0 for (i=0;irasmstruct[irs].irasmstructfield;i++) { if (!ae->wl[ae->idx+2+i].t || i+1>=ae->rasmstruct[irs].irasmstructfield) { /* si le champ est sur le même offset que le précédent, on le saute */ if (i && ae->rasmstruct[irs].rasmstructfield[i].offset>ae->rasmstruct[irs].rasmstructfield[i-1].offset) continue; #if TRACE_STRUCT printf("get field? (%d)\n",irs); #endif if (!StringIsQuote(ae->wl[ae->idx+i].w)) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+i].w,1); zeval=RoundComputeExpressionCore(ae,ae->wl[ae->idx+i].w,ae->codeadr,0); } else { // push string } localsize+=ae->rasmstruct[irs].rasmstructfield[i].size; /* pour du single shot ? pushbyte(s) at ae->codeadr+ae->rasmstruct[irs].rasmstructfield[i].offset */ //ae->rasmstruct[irs].size; } else { #if TRACE_STRUCT printf("*break*\n"); #endif break; } } #endif /* (LEGACY) filler, on balance des zéros */ #if TRACE_STRUCT printf("struct (almost) legacy filler from %d to %d-1\n",localsize,ae->rasmstruct[irs].size); #endif while (nbelem) { for (i=cursize=0;irasmstruct[irs].irasmstructfield && cursizerasmstruct[irs].rasmstructfield[i].size; } for (;irasmstruct[irs].irasmstructfield;i++) { for (j=0;jrasmstruct[irs].rasmstructfield[i].idata;j++) { ___output(ae,ae->rasmstruct[irs].rasmstructfield[i].data[j]); } } nbelem--; } #if 0 for (i=localsize;irasmstruct[irs].size;i++) ___output(ae,0); #endif ae->idx+=2; // probablement à revoir dans le cas d'une init!!! } } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"STRUCT directive needs one or two parameters\n"); } } void __ENDSTRUCT(struct s_assenv *ae) { #undef FUNC #define FUNC "__ENDSTRUCT" struct s_label curlabel={0}; int i,newlen; #if TRACE_STRUCT printf("endstruct\n"); #endif if (!ae->wl[ae->idx].t) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"ENDSTRUCT directive does not need parameter\n"); } else { if (ae->getstruct) { ae->rasmstruct[ae->irasmstruct-1].size=ae->codeadr; ae->getstruct=0; /* SIZEOF like Vasm with struct name */ curlabel.name=TxtStrDup(ae->rasmstruct[ae->irasmstruct-1].name); curlabel.crc=ae->rasmstruct[ae->irasmstruct-1].crc; curlabel.iw=-1; curlabel.ptr=ae->rasmstruct[ae->irasmstruct-1].size; PushLabelLight(ae,&curlabel); /* compute size for each field */ newlen=strlen(ae->rasmstruct[ae->irasmstruct-1].name)+2; for (i=0;irasmstruct[ae->irasmstruct-1].irasmstructfield-1;i++) { ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].size=ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i+1].offset-ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].offset; ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].fullname=MemMalloc(newlen+strlen(ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].name)); sprintf(ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].fullname,"%s.%s",ae->rasmstruct[ae->irasmstruct-1].name,ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].name); ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].crc=GetCRC(ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].fullname); } ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].size=ae->rasmstruct[ae->irasmstruct-1].size-ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].offset; ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].fullname=MemMalloc(newlen+strlen(ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].name)); sprintf(ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].fullname,"%s.%s",ae->rasmstruct[ae->irasmstruct-1].name,ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].name); ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].crc=GetCRC(ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].fullname); /* unwrap data capture */ if (ae->as80==1) {/* not for UZ80 */ instruction[ICRC_DEFB].makemnemo=_DEFB_as80;instruction[ICRC_DB].makemnemo=_DEFB_as80; instruction[ICRC_DEFW].makemnemo=_DEFW_as80;instruction[ICRC_DW].makemnemo=_DEFW_as80; instruction[ICRC_DEFI].makemnemo=_DEFI_as80; } else { instruction[ICRC_DEFB].makemnemo=_DEFB;instruction[ICRC_DB].makemnemo=_DEFB; instruction[ICRC_DEFW].makemnemo=_DEFW;instruction[ICRC_DW].makemnemo=_DEFW; instruction[ICRC_DEFI].makemnemo=_DEFI; } instruction[ICRC_DEFR].makemnemo=_DEFR;instruction[ICRC_DR].makemnemo=_DEFR; instruction[ICRC_DEFS].makemnemo=_DEFS;instruction[ICRC_DS].makemnemo=_DEFS; /* like there was no byte */ ae->outputadr=ae->backup_outputadr; ae->codeadr=ae->backup_codeadr; ___org_close(ae); ___org_new(ae,0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"ENDSTRUCT encountered outside STRUCT declaration\n"); } } } void __MEMSPACE(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___new_memory_space(ae); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"MEMSPACE directive does not need parameter\n"); } } int (*_internal_getsample)(unsigned char *data, int *idx); #undef FUNC #define FUNC "_internal_AudioGetSampleValue" int __internal_getsample8(unsigned char *data, int *idx) { unsigned char v; v=data[*idx]-128;*idx=*idx+1;return v; } int __internal_getsample16little(unsigned char *data, int *idx) { int cursample; cursample=data[*idx+1]-0x80;*idx=*idx+2; return cursample; } int __internal_getsample24little(unsigned char *data, int *idx) { int cursample; cursample=data[*idx+2-0x80];*idx=*idx+3; return cursample; } /* big-endian */ int __internal_getsample16big(unsigned char *data, int *idx) { int cursample; cursample=data[*idx]-0x80;*idx=*idx+2; return cursample; } int __internal_getsample24big(unsigned char *data, int *idx) { int cursample; cursample=data[*idx]-0x80;*idx=*idx+3; return cursample; } /* float & endian shit */ int _isLittleEndian() /* from lz4.h */ { const union { U32 u; BYTE c[4]; } one = { 1 }; return one.c[0]; } unsigned char * __internal_floatinversion(unsigned char *data) { static unsigned char bswap[4]; bswap[0]=data[3]; bswap[1]=data[2]; bswap[2]=data[1]; bswap[3]=data[0]; return bswap; } int __internal_getsample32bigbig(unsigned char *data, int *idx) { float fsample; int cursample; fsample=*((float*)(data+*idx)); *idx=*idx+4; cursample=(floor)((fsample+1.0)*127.5+0.5); return cursample; } int __internal_getsample32biglittle(unsigned char *data, int *idx) { float fsample; int cursample; fsample=*((float*)(__internal_floatinversion(data+*idx))); *idx=*idx+4; cursample=(floor)((fsample+1.0)*127.5+0.5); return cursample; } #define __internal_getsample32littlelittle __internal_getsample32bigbig #define __internal_getsample32littlebig __internal_getsample32biglittle void _AudioLoadSample(struct s_assenv *ae, unsigned char *data, int filesize, enum e_audio_sample_type sample_type, float normalize) { #undef FUNC #define FUNC "AudioLoadSample" struct s_wav_header *wav_header; int i,j,n,idx,controlsize; int nbchannel,bitspersample,nbsample; int bigendian=0,cursample; double accumulator; unsigned char samplevalue=0, sampleprevious=0; int samplerepeat=0,ipause; unsigned char *subchunk; int subchunksize; if (filesizewl[ae->idx].l,"WAV import - this file is too small to be a valid WAV!\n"); return; } wav_header=(struct s_wav_header *)data; #if TRACE_HEXBIN printf("AudioLoadSample filesize=%d st=%d normalize=%.2lf\n",filesize,sample_type,normalize); #endif if (strncmp(wav_header->ChunkID,"RIFF",4)) { if (strncmp(wav_header->ChunkID,"RIFX",4)) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"WAV import - unsupported audio sample type (chunkid must be 'RIFF' or 'RIFX')\n"); return; } else { bigendian=1; } } if (strncmp(wav_header->Format,"WAVE",4)) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"[%s:%d] WAV import - unsupported audio sample type (format must be 'WAVE')\n"); return; } controlsize=wav_header->SubChunk1Size[0]+wav_header->SubChunk1Size[1]*256+wav_header->SubChunk1Size[2]*65536+wav_header->SubChunk1Size[3]*256*65536; if (controlsize!=16) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"WAV import - invalid wav chunk size (subchunk1 control)\n"); return; } if (strncmp(wav_header->SubChunk1ID,"fmt",3)) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"WAV import - unsupported audio sample type (subchunk1id must be 'fmt')\n"); return; } #if TRACE_HEXBIN printf("AudioLoadSample getsubchunk\n"); #endif subchunk=(unsigned char *)&wav_header->SubChunk2ID; while (strncmp(subchunk,"data",4)) { subchunksize=8+subchunk[4]+subchunk[5]*256+subchunk[6]*65536+subchunk[7]*256*65536; if (subchunksize>=filesize) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"WAV import - data subchunk not found\n"); return; } subchunk+=subchunksize; } subchunksize=subchunk[4]+subchunk[5]*256+subchunk[6]*65536+subchunk[7]*256*65536; controlsize=subchunksize; nbchannel=wav_header->NumChannels[0]+wav_header->NumChannels[1]*256; if (nbchannel<1) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"WAV import - invalid number of audio channel\n"); return; } bitspersample=wav_header->BitsPerSample[0]+wav_header->BitsPerSample[1]*256; #if TRACE_HEXBIN printf("AudioLoadSample bitpersample=%d\n",bitspersample); #endif switch (bitspersample) { case 8:_internal_getsample=__internal_getsample8;break; case 16:if (!bigendian) _internal_getsample=__internal_getsample16little; else _internal_getsample=__internal_getsample16big;break; case 24:if (!bigendian) _internal_getsample=__internal_getsample24little; else _internal_getsample=__internal_getsample24big;break; case 32:if (!bigendian) { if (_isLittleEndian()) { _internal_getsample=__internal_getsample32littlelittle; } else { _internal_getsample=__internal_getsample32littlebig; } } else { if (_isLittleEndian()) { _internal_getsample=__internal_getsample32biglittle; } else { _internal_getsample=__internal_getsample32bigbig; } } break; default: MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"WAV import - unsupported bits per sample (%d)\n",bitspersample); return; } nbsample=controlsize/nbchannel/(bitspersample/8); if (controlsize+sizeof(struct s_wav_header)>filesize) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"WAV import - cannot read %d byte%s of audio whereas the file is %d bytes big!\n",controlsize,controlsize>1?"s":"",filesize); return; } #if TRACE_HEXBIN printf("nbsample=%d (sze=%d,chn=%d,bps=%d) st=%c\n",nbsample,controlsize,nbchannel,bitspersample,sample_type); #endif idx=subchunk-data; switch (sample_type) { default: case AUDIOSAMPLE_SMP: for (i=0;ipsgfine[cursample]; /* output */ ___output(ae,samplevalue); } break; case AUDIOSAMPLE_SM2: /* +1 pour éviter le segfault */ for (i=0;ipsgfine[cursample]); } /* output */ ___output(ae,samplevalue); } break; case AUDIOSAMPLE_SM4: /*** SM4 format has two bits bits -> PSG value 00 -> 0 01 -> 13 10 -> 14 11 -> 15 ***/ /* +3 pour éviter le segfault */ for (i=0;ipsgtab[cursample]>>2); } /* output */ ___output(ae,samplevalue); } break; case AUDIOSAMPLE_DMA: sampleprevious=255; for (i=0;ipsgtab[cursample]; if (samplevalue==sampleprevious) { samplerepeat++; } else { if (!samplerepeat) { /* DMA output */ ___output(ae,sampleprevious); ___output(ae,0x0A); /* volume canal C */ } else { /* DMA pause */ ___output(ae,sampleprevious); ___output(ae,0x0A); /* volume canal C */ while (samplerepeat) { ipause=samplerepeat<4096?samplerepeat:4095; ___output(ae,ipause&0xFF); ___output(ae,0x10 | ((ipause>>8) &0xF)); /* pause */ samplerepeat-=4096; if (samplerepeat<0) samplerepeat=0; } } sampleprevious=samplevalue; } } if (samplerepeat) { /* DMA pause */ ___output(ae,sampleprevious); ___output(ae,0x0A); /* volume canal C */ while (samplerepeat) { ipause=samplerepeat<4096?samplerepeat:4095; ___output(ae,ipause&0xFF); ___output(ae,0x10 | ((ipause>>8) &0xF)); /* pause */ samplerepeat-=4096; if (samplerepeat<0) samplerepeat=0; } } ___output(ae,0); ___output(ae,0x0A); /* volume canal C */ ___output(ae,0x20); ___output(ae,0x40); /* stop or reloop? */ break; } } /* meta fonction qui gère le INCBIN standard plus les variantes SMP et DMA */ void __HEXBIN(struct s_assenv *ae) { int hbinidx,overwritecheck=1,crc; struct s_expr_dico *rvar; unsigned int idx; int size=0,offset=0; float amplification=1.0; int deload=0; int vtiles=0,remap=0,revert=0; int itiles=0,tilex; if (!ae->wl[ae->idx].t) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,1); hbinidx=RoundComputeExpressionCore(ae,ae->wl[ae->idx+1].w,ae->codeadr,0); if (hbinidx>ae->ih) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"internal error with binary file import (index out of bounds)\n"); return; } #if TRACE_HEXBIN printf("Hexbin idx=[%s] filename=[%s]\n",ae->wl[ae->idx+1].w,ae->hexbin[hbinidx].filename); #endif if (!ae->wl[ae->idx+1].t) { if (strcmp("DSK",ae->wl[ae->idx+2].w)==0) { /* import binary from DSK */ } else if (strchr("SD",ae->wl[ae->idx+2].w[0]) && ae->wl[ae->idx+2].w[1]=='M' && strchr("P24A",ae->wl[ae->idx+2].w[2]) && !ae->wl[ae->idx+2].w[3]) { /* SMP,SM2,SM4,DMA */ #if TRACE_HEXBIN printf("Hexbin -> %s\n",ae->wl[ae->idx+2].w); #endif if (!ae->wl[ae->idx+2].t) { amplification=ComputeExpressionCore(ae,ae->wl[ae->idx+3].w,ae->codeadr,0); #if TRACE_HEXBIN printf("sample amplification=%.2lf\n",amplification); #endif } switch (ae->wl[ae->idx+2].w[2]) { case 'P':_AudioLoadSample(ae,ae->hexbin[hbinidx].data,ae->hexbin[hbinidx].datalen, AUDIOSAMPLE_SMP,amplification);break; case '2':_AudioLoadSample(ae,ae->hexbin[hbinidx].data,ae->hexbin[hbinidx].datalen, AUDIOSAMPLE_SM2,amplification);break; case '4':_AudioLoadSample(ae,ae->hexbin[hbinidx].data,ae->hexbin[hbinidx].datalen, AUDIOSAMPLE_SM4,amplification);break; case 'A':_AudioLoadSample(ae,ae->hexbin[hbinidx].data,ae->hexbin[hbinidx].datalen, AUDIOSAMPLE_DMA,amplification);break; default:printf("warning remover\n");break; } ae->idx+=2; return; } else { /* legacy binary file */ #if TRACE_HEXBIN printf("Hexbin legacy datalen=%d\n",ae->hexbin[hbinidx].datalen); #endif if (strcmp("REVERT",ae->wl[ae->idx+2].w)==0) { /* revert data */ if (!ae->wl[ae->idx+2].t) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INCBIN REVERT does not need extra parameters\n"); } #if TRACE_HEXBIN printf(" -> REVERT loading\n"); #endif revert=1; offset=size=0; // full file ae->idx++; } else if (strcmp("REMAP",ae->wl[ae->idx+2].w)==0) { /* reorder tiles data */ if (!ae->wl[ae->idx+2].t) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+3].w,1); remap=RoundComputeExpressionCore(ae,ae->wl[ae->idx+3].w,ae->codeadr,0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INCBIN REMAP need a number of columns for reordering\n"); } #if TRACE_HEXBIN printf(" -> REMAP loading\n"); #endif offset=size=0; // full file ae->idx+=2; } else if (strcmp("ITILES",ae->wl[ae->idx+2].w)==0) { /*** entrelace les tiles, besoin de hauteur et largeur de la tile ***/ if (!ae->wl[ae->idx+2].t) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+3].w,1); tilex=RoundComputeExpressionCore(ae,ae->wl[ae->idx+3].w,ae->codeadr,0); itiles=1; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is INCBIN'file',ITILES,width\n"); } #if TRACE_HEXBIN printf(" -> ITILES loading\n"); #endif offset=size=0; // full file ae->idx+=2; } else if (strcmp("VTILES",ae->wl[ae->idx+2].w)==0) { /* import and reorder tiles */ if (!ae->wl[ae->idx+2].t) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+3].w,1); vtiles=RoundComputeExpressionCore(ae,ae->wl[ae->idx+3].w,ae->codeadr,0); } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INCBIN VTILES need a number of lines for reordering\n"); } #if TRACE_HEXBIN printf(" -> VTILES loading\n"); #endif offset=size=0; // full file ae->idx+=2; } else { char *expwrk; expwrk=TxtStrDup(ae->wl[ae->idx+2].w); ExpressionFastTranslate(ae,&expwrk,1); offset=RoundComputeExpressionCore(ae,expwrk,ae->codeadr,0); MemFree(expwrk); #if TRACE_HEXBIN printf("offset=%d\n",offset); #endif if (!ae->wl[ae->idx+2].t) { if (ae->wl[ae->idx+3].w[0]) { expwrk=TxtStrDup(ae->wl[ae->idx+3].w); ExpressionFastTranslate(ae,&expwrk,1); size=RoundComputeExpressionCore(ae,expwrk,ae->codeadr,0); MemFree(expwrk); } else { size=0; } #if TRACE_HEXBIN printf("size=%d\n",size); #endif if (size<-65535 || size>65536) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INCBIN invalid size\n"); } if (!ae->wl[ae->idx+3].t) { if (ae->wl[ae->idx+4].w[0]) { expwrk=TxtStrDup(ae->wl[ae->idx+4].w); ExpressionFastTranslate(ae,&expwrk,1); offset+=65536*RoundComputeExpressionCore(ae,expwrk,ae->codeadr,0); MemFree(expwrk); } if (!ae->wl[ae->idx+4].t) { if (strcmp(ae->wl[ae->idx+5].w,"OFF")==0) { overwritecheck=0; } else if (strcmp(ae->wl[ae->idx+5].w,"ON")==0) { overwritecheck=1; #if TRACE_HEXBIN printf("mode OVERWRITE\n"); #endif } else if (ae->wl[ae->idx+5].w[0]) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INCBIN invalid overwrite value. Must be 'OFF' or 'ON'\n"); } if (!ae->wl[ae->idx+5].t) { /* copy raw len to a (new) variable */ crc=GetCRC(ae->wl[ae->idx+6].w); if ((rvar=SearchDico(ae,ae->wl[ae->idx+6].w,crc))!=NULL) { rvar->v=ae->hexbin[hbinidx].rawlen; } else { /* mais ne peut être un label ou un alias */ ExpressionSetDicoVar(ae,ae->wl[ae->idx+6].w,ae->hexbin[hbinidx].rawlen); } ae->idx+=6; } else { ae->idx+=5; } } else { ae->idx+=4; } } else { ae->idx+=3; } } else { ae->idx+=2; } } } } else { ae->idx++; } /* preprocessor cannot manage variables so here is the delayed load */ if (ae->hexbin[hbinidx].datalen<0) { struct s_hexbin *curhexbin; char *newfilename; int lm,touched; unsigned char *newdata=NULL; #if TRACE_HEXBIN printf("Hexbin -> as only the assembler know how to deal with var,\n"); printf("we look for tags in the name of a file which were not found\n"); #endif curhexbin=&ae->hexbin[hbinidx]; newfilename=TxtStrDup(curhexbin->filename); /* need to upper case tags */ for (lm=touched=0;newfilename[lm];lm++) { if (newfilename[lm]=='{') touched++; else if (newfilename[lm]=='}') touched--; else if (touched) newfilename[lm]=toupper(newfilename[lm]); } /* on essaie d'interpréter le nom du fichier en dynamique */ newfilename=TranslateTag(ae,newfilename,&touched,1,E_TAGOPTION_REMOVESPACE); /* load */ if (FileExists(newfilename)) { #if TRACE_HEXBIN printf("Hexbin -> surprise! we found the file!\n"); #endif curhexbin->rawlen=curhexbin->datalen=FileGetSize(newfilename); curhexbin->data=MemMalloc(curhexbin->datalen*1.3+10); if (FileReadBinary(newfilename,(char*)curhexbin->data,curhexbin->datalen)!=curhexbin->datalen) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"read error on file [%s]\n",newfilename); return; } FileReadBinaryClose(newfilename); switch (curhexbin->crunch) { #ifndef NO_3RD_PARTIES case 4: newdata=LZ4_crunch(curhexbin->data,curhexbin->datalen,&curhexbin->datalen); MemFree(curhexbin->data); curhexbin->data=newdata; #if TRACE_PREPRO rasm_printf(ae,KVERBOSE"crunched with LZ4 into %d byte(s)\n",curhexbin->datalen); #endif break; case 7: { size_t slzlen; newdata=ZX7_compress(optimize(curhexbin->data, curhexbin->datalen), curhexbin->data, curhexbin->datalen, &slzlen); curhexbin->datalen=slzlen; MemFree(curhexbin->data); curhexbin->data=newdata; #if TRACE_PREPRO rasm_printf(ae,KVERBOSE"crunched with ZX7 into %d byte(s)\n",curhexbin->datalen); #endif } break; case 8: rasm_printf(ae,KWARNING"Exomizer is crunching %.1fkb this may take a while, be patient...\n",curhexbin->datalen/1024.0); newdata=Exomizer_crunch(curhexbin->data,curhexbin->datalen,&curhexbin->datalen); MemFree(curhexbin->data); curhexbin->data=newdata; #if TRACE_PREPRO rasm_printf(ae,KVERBOSE"crunched with Exomizer into %d byte(s)\n",curhexbin->datalen); #endif break; #endif case 48: newdata=LZ48_crunch(curhexbin->data,curhexbin->datalen,&curhexbin->datalen); MemFree(curhexbin->data); curhexbin->data=newdata; #if TRACE_PREPRO rasm_printf(ae,KVERBOSE"crunched with LZ48 into %d byte(s)\n",curhexbin->datalen); #endif break; case 49: newdata=LZ49_crunch(curhexbin->data,curhexbin->datalen,&curhexbin->datalen); MemFree(curhexbin->data); curhexbin->data=newdata; #if TRACE_PREPRO rasm_printf(ae,KVERBOSE"crunched with LZ49 into %d byte(s)\n",curhexbin->datalen); #endif break; default:break; } deload=1; } else { /* still not found */ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"file not found [%s]\n",newfilename); return; } } if (ae->hexbin[hbinidx].datalen>0) { if (hbinidxih && hbinidx>=0) { if (size<0) { #if TRACE_HEXBIN printf("taille négative %d -> conversion en %d\n",size,ae->hexbin[hbinidx].datalen+size); #endif size=ae->hexbin[hbinidx].datalen+size; if (size<1) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INCBIN negative size is greater or equal to filesize\n"); } } /* negative offset conversion */ if (offset<0) { #if TRACE_HEXBIN printf("offset négatif %d -> conversion en %d\n",offset,ae->hexbin[hbinidx].datalen+offset); #endif offset=ae->hexbin[hbinidx].datalen+offset; } if (!size) { if (!offset) { size=ae->hexbin[hbinidx].datalen; } else { size=ae->hexbin[hbinidx].datalen-offset; } #if TRACE_HEXBIN printf("taille nulle et offset=%d -> conversion en %d\n",offset,size); #endif } if (size>ae->hexbin[hbinidx].datalen) { rasm_printf(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INCBIN size is greater than filesize\n"); } else { if (size+offset>ae->hexbin[hbinidx].datalen) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INCBIN size+offset is greater than filesize\n"); } else { if (revert) { int p; p=size-1; while (p>=0) { ___output(ae,ae->hexbin[hbinidx].data[p--]); } } else if (itiles) { /* tiles data reordering */ int tx,ty,it,width; if (size % (tilex*8)) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INCBIN ITILES cannot reorder tiles %d bytewidth with file of size %d\n",tilex,size); } else { it=0; while (ithexbin[hbinidx].data[it+tx+0*tilex]); for (tx=tilex-1;tx>=0;tx--) ___output(ae,ae->hexbin[hbinidx].data[it+tx+1*tilex]); for (tx=0;txhexbin[hbinidx].data[it+tx+3*tilex]); for (tx=tilex-1;tx>=0;tx--) ___output(ae,ae->hexbin[hbinidx].data[it+tx+2*tilex]); for (tx=0;txhexbin[hbinidx].data[it+tx+6*tilex]); for (tx=tilex-1;tx>=0;tx--) ___output(ae,ae->hexbin[hbinidx].data[it+tx+7*tilex]); for (tx=0;txhexbin[hbinidx].data[it+tx+5*tilex]); for (tx=tilex-1;tx>=0;tx--) ___output(ae,ae->hexbin[hbinidx].data[it+tx+4*tilex]); it+=tilex*8; } } } else if (remap) { /* tiles data reordering */ int tx,ty,it,width; width=size/remap; if ((size % remap) || (remap*width>size)) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INCBIN REMAP cannot reorder %d columns%s with file of size %d\n",remap,remap>1?"s":"",size); } else { for (it=0;ithexbin[hbinidx].data[it+tx*remap]); } } } } else if (vtiles) { /* tiles map reordering */ int width,tilex,tiley; width=size/vtiles; if ((size % vtiles) || (vtiles*width>size)) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INCBIN VTILES cannot reorder %d line%s with file of size %d\n",vtiles,vtiles>1?"s":"",size); } else { #if TRACE_HEXBIN printf("Hexbin -> re-tiling MAP! width=%d\n",width); #endif for (idx=tilex=tiley=0;idxhexbin[hbinidx].data[tilex+tiley*width]); tiley++; if (tiley>=vtiles) { tiley=0; tilex++; } } } } else { /* legacy HEXBIN */ if (overwritecheck) { for (idx=offset;idxhexbin[hbinidx].data[idx]); } } else { ___org_close(ae); ___org_new(ae,0); for (idx=offset;idxhexbin[hbinidx].data[idx]); } /* hack to disable overwrite check */ ae->orgzone[ae->io-1].nocode=2; ___org_close(ae); ___org_new(ae,0); } } } } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INTERNAL - HEXBIN refer to unknown structure\n"); FreeAssenv(ae); exit(2); } } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INTERNAL - HEXBIN need one HEX parameter\n"); FreeAssenv(ae); exit(2); } /* generated names must be reloaded! */ if (deload) { ae->hexbin[hbinidx].datalen=-1; MemFree(ae->hexbin[hbinidx].data); } } /* save "nom",start,size -> save binary save "nom",start,size,TAPE -> save tape file save "nom",start,size,AMSDOS -> save binary with Amsdos header save "nom",start,size,DSK,"dskname" -> save binary on DSK data format save "nom",start,size,DSK,"dskname",B -> select face save "nom",start,size,DSK,B -> current DSK, choose face save "nom",start,size,DSK -> current DSK, current face */ void __SAVE(struct s_assenv *ae) { struct s_save cursave={0}; unsigned int offset=0,size=0; int ko=1; if (!ae->wl[ae->idx].t) { /* nom de fichier entre quotes ou bien mot clef DSK */ if (!StringIsQuote(ae->wl[ae->idx+1].w)) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SAVE invalid filename quote\n"); ko=0; } else { if (!ae->wl[ae->idx+1].t) { if (!ae->wl[ae->idx+2].t && ae->wl[ae->idx+3].t!=2) { cursave.ibank=ae->activebank; cursave.ioffset=ae->idx+2; ExpressionFastTranslate(ae,&ae->wl[ae->idx+2].w,1); // si on utilise des variables ça évite la grouille post traitement... cursave.isize=ae->idx+3; ExpressionFastTranslate(ae,&ae->wl[ae->idx+3].w,1); // idem cursave.iw=ae->idx+1; cursave.irun=ae->current_run_idx; if (!ae->wl[ae->idx+3].t) { if (strcmp(ae->wl[ae->idx+4].w,"TAPE")==0) { cursave.tape=1; } else if (strcmp(ae->wl[ae->idx+4].w,"AMSDOS")==0) { cursave.amsdos=1; } else if (strcmp(ae->wl[ae->idx+4].w,"HOBETA")==0) { cursave.hobeta=1; } else if (strcmp(ae->wl[ae->idx+4].w,"DSK")==0) { #if TRACE_EDSK printf("DSK SAVE order [bnk: %d ioff: %d isiz: %d iw=%d [%s] [%s]\n",cursave.ibank,cursave.ioffset,cursave.isize,cursave.iw,ae->wl[ae->idx+2].w,ae->wl[ae->idx+3].w); #endif cursave.dsk=1; if (!ae->wl[ae->idx+4].t) { cursave.iwdskname=ae->idx+5; if (!ae->wl[ae->idx+5].t) { /* face selection - 0 as default */ switch (ae->wl[ae->idx+6].w[0]) { case '1': case 'B': cursave.face=1; break; case '0': case 'A': default: cursave.face=0; break; } } } else { if (ae->nbsave && ae->save[ae->nbsave-1].iwdskname!=-1) { cursave.iwdskname=ae->save[ae->nbsave-1].iwdskname; /* previous DSK */ cursave.face=ae->save[ae->nbsave-1].face; /* previous face */ } else { cursave.iwdskname=-1; MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"cannot autoselect DSK as there was not a previous selection\n"); } } } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SAVE 4th parameter must be empty or AMSDOS or DSK\n"); ko=0; } } ObjectArrayAddDynamicValueConcat((void**)&ae->save,&ae->nbsave,&ae->maxsave,&cursave,sizeof(cursave)); ko=0; } } } } if (ko) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use SAVE 'filename',offset,size[,AMSDOS|DSK[,A|B|'dskname'[,A|B]]]\n"); } while (!ae->wl[ae->idx].t) ae->idx++; } void __MODULE(struct s_assenv *ae) { if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { if (StringIsQuote(ae->wl[ae->idx+1].w)) { if (ae->modulen || ae->module) { MemFree(ae->module); } ae->modulen=strlen(ae->wl[ae->idx+1].w); ae->module=MemMalloc(ae->modulen); /* duplicate and remove quotes */ strcpy(ae->module,ae->wl[ae->idx+1].w+1); ae->module[--ae->modulen]=0; } else { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"MODULE directive need one text parameter\n"); } ae->idx++; } else { if (ae->module) MemFree(ae->module); ae->module=NULL; } } void __TIMESTR(struct s_assenv *ae) { } struct s_asm_keyword instruction[]={ {"LD",0,_LD}, {"DEC",0,_DEC}, {"INC",0,_INC}, {"ADD",0,_ADD}, {"SUB",0,_SUB}, {"OR",0,_OR}, {"AND",0,_AND}, {"XOR",0,_XOR}, {"POP",0,_POP}, {"PUSH",0,_PUSH}, {"DJNZ",0,_DJNZ}, {"JR",0,_JR}, {"JP",0,_JP}, {"CALL",0,_CALL}, {"RET",0,_RET}, {"EX",0,_EX}, {"ADC",0,_ADC}, {"SBC",0,_SBC}, {"EXA",0,_EXA}, {"EXX",0,_EXX}, {"CP",0,_CP}, {"BIT",0,_BIT}, {"RES",0,_RES}, {"SET",0,_SET}, {"IN",0,_IN}, {"OUT",0,_OUT}, {"RLC",0,_RLC}, {"RRC",0,_RRC}, {"RL",0,_RL}, {"RR",0,_RR}, {"SLA",0,_SLA}, {"SRA",0,_SRA}, {"SLL",0,_SLL}, {"SL1",0,_SLL}, {"SRL",0,_SRL}, {"RST",0,_RST}, {"HALT",0,_HALT}, {"DI",0,_DI}, {"EI",0,_EI}, {"NOP",0,_NOP}, {"DEFR",0,_DEFR}, {"DEFB",0,_DEFB}, {"DEFM",0,_DEFB}, {"DR",0,_DEFR}, {"DM",0,_DEFB}, {"DB",0,_DEFB}, {"DEFW",0,_DEFW}, {"DW",0,_DEFW}, {"DEFS",0,_DEFS}, {"DS",0,_DEFS}, {"STR",0,_STR}, {"LDI",0,_LDI}, {"LDIR",0,_LDIR}, {"OUTI",0,_OUTI}, {"INI",0,_INI}, {"RLCA",0,_RLCA}, {"RRCA",0,_RRCA}, {"NEG",0,_NEG}, {"RLA",0,_RLA}, {"RRA",0,_RRA}, {"RLD",0,_RLD}, {"RRD",0,_RRD}, {"DAA",0,_DAA}, {"CPL",0,_CPL}, {"SCF",0,_SCF}, {"LDD",0,_LDD}, {"LDDR",0,_LDDR}, {"CCF",0,_CCF}, {"OUTD",0,_OUTD}, {"IND",0,_IND}, {"RETI",0,_RETI}, {"RETN",0,_RETN}, {"IM",0,_IM}, {"DEFI",0,_DEFI}, {"CPD",0,_CPD}, {"CPI",0,_CPI}, {"CPDR",0,_CPDR}, {"CPIR",0,_CPIR}, {"OTDR",0,_OTDR}, {"OTIR",0,_OTIR}, {"INDR",0,_INDR}, {"INIR",0,_INIR}, {"REPEAT",0,__REPEAT}, {"REND",0,__REND}, {"ENDREPEAT",0,__REND}, {"ENDREP",0,__REND}, {"UNTIL",0,__UNTIL}, {"ORG",0,__ORG}, {"PROTECT",0,__PROTECT}, {"WHILE",0,__WHILE}, {"WEND",0,__WEND}, {"HEXBIN",0,__HEXBIN}, {"ALIGN",0,__ALIGN}, {"ELSEIF",0,__ELSEIF}, {"ELSE",0,__ELSE}, {"IF",0,__IF}, {"ENDIF",0,__ENDIF}, {"IFNOT",0,__IFNOT}, {"IFDEF",0,__IFDEF}, {"IFNDEF",0,__IFNDEF}, {"IFUSED",0,__IFUSED}, {"IFNUSED",0,__IFNUSED}, {"UNDEF",0,__UNDEF}, {"CASE",0,__CASE}, {"BREAK",0,__BREAK}, {"DEFAULT",0,__DEFAULT}, {"SWITCH",0,__SWITCH}, {"ENDSWITCH",0,__ENDSWITCH}, {"WRITE",0,__WRITE}, {"CODE",0,__CODE}, {"NOCODE",0,__NOCODE}, {"MEMSPACE",0,__MEMSPACE}, {"MACRO",0,__MACRO}, {"TICKER",0,__TICKER}, {"LET",0,__LET}, {"ASSERT",0,__ASSERT}, {"CHARSET",0,__CHARSET}, {"RUN",0,__RUN}, {"SAVE",0,__SAVE}, {"BRK",0,__BRK}, {"NOLIST",0,__NOLIST}, {"LIST",0,__LIST}, {"STOP",0,__STOP}, {"PRINT",0,__PRINT}, {"FAIL",0,__FAIL}, {"BREAKPOINT",0,__BREAKPOINT}, {"BANK",0,__BANK}, {"BANKSET",0,__BANKSET}, {"NAMEBANK",0,__NameBANK}, {"LIMIT",0,__LIMIT}, {"LZEXO",0,__LZEXO}, {"LZX7",0,__LZX7}, {"LZ4",0,__LZ4}, {"LZ48",0,__LZ48}, {"LZ49",0,__LZ49}, {"LZCLOSE",0,__LZCLOSE}, {"BUILDZX",0,__BUILDZX}, {"BUILDCPR",0,__BUILDCPR}, {"BUILDSNA",0,__BUILDSNA}, {"BUILDROM",0,__BUILDROM}, {"BUILDTAPE",0,__BUILDTAPE}, {"SETCPC",0,__SETCPC}, {"SETCRTC",0,__SETCRTC}, {"AMSDOS",0,__AMSDOS}, {"OTD",0,_OUTD}, {"OTI",0,_OUTI}, {"SHL",0,_SLA}, {"SHR",0,_SRL}, {"STRUCT",0,__STRUCT}, {"ENDSTRUCT",0,__ENDSTRUCT}, {"ENDS",0,__ENDSTRUCT}, {"NOEXPORT",0,__NOEXPORT}, {"ENOEXPORT",0,__ENOEXPORT}, {"",0,NULL} }; int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout, struct s_rasm_info **debug) { #undef FUNC #define FUNC "Assemble" unsigned char *AmsdosHeader; struct s_expression curexp={0}; struct s_wordlist *wordlist; struct s_expr_dico curdico={0}; struct s_label *curlabel; int icrc,curcrc,i,j,k; unsigned char *lzdata=NULL; int lzlen,lzshift,input_size; size_t slzlen; unsigned char *input_data; struct s_orgzone orgzone={0}; int iorgzone,ibank,offset,endoffset; int il,maxrom; char *TMP_filename=NULL; int minmem=65536,maxmem=0,lzmove; char symbol_line[1024]; int ifast,executed; /* debug */ int curii,inhibe; int ok; rasm_printf(ae,KAYGREEN"Assembling\n"); #if TRACE_ASSEMBLE printf("assembling\n"); #endif #if TRACE_GENERALE printf("*** assembling ***\n"); #endif ae->retdebug=debug; srand((unsigned)time(0)); wordlist=ae->wl; ae->wl=wordlist; /* start outside crunched section */ ae->lz=-1; /* default orgzone */ orgzone.ibank=BANK_MAX_NUMBER; ObjectArrayAddDynamicValueConcat((void**)&ae->orgzone,&ae->io,&ae->mo,&orgzone,sizeof(orgzone)); ___output=___internal_output; /* init des automates */ InitAutomate(ae->AutomateHexa,AutomateHexaDefinition); InitAutomate(ae->AutomateDigit,AutomateDigitDefinition); InitAutomate(ae->AutomateValidLabel,AutomateValidLabelDefinition); InitAutomate(ae->AutomateValidLabelFirst,AutomateValidLabelFirstDefinition); InitAutomate(ae->AutomateExpressionValidCharExtended,AutomateExpressionValidCharExtendedDefinition); InitAutomate(ae->AutomateExpressionValidCharFirst,AutomateExpressionValidCharFirstDefinition); InitAutomate(ae->AutomateExpressionValidChar,AutomateExpressionValidCharDefinition); ae->AutomateExpressionDecision['<']='<'; ae->AutomateExpressionDecision['>']='>'; ae->AutomateExpressionDecision['=']='='; ae->AutomateExpressionDecision['!']='!'; ae->AutomateExpressionDecision[0]='E'; /* gestion d'alias */ ae->AutomateExpressionDecision['~']='~'; /* set operator precedence */ if (!ae->maxam) { for (i=0;i<256;i++) { switch (i) { /* priority 0 */ case '(':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_OPEN;ae->AutomateElement[i].priority=0;break; case ')':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_CLOSE;ae->AutomateElement[i].priority=0;break; /* priority 1 */ case 'b':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_NOT;ae->AutomateElement[i].priority=1;break; /* priority 2 */ case '*':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_MUL;ae->AutomateElement[i].priority=2;break; case '/':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_DIV;ae->AutomateElement[i].priority=2;break; case 'm':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_MOD;ae->AutomateElement[i].priority=2;break; /* priority 3 */ case '+':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_ADD;ae->AutomateElement[i].priority=3;break; case '-':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_SUB;ae->AutomateElement[i].priority=3;break; /* priority 4 */ case '[':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_SHL;ae->AutomateElement[i].priority=4;break; case ']':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_SHR;ae->AutomateElement[i].priority=4;break; /* priority 5 */ case 'l':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_LOWER;ae->AutomateElement[i].priority=5;break; case 'g':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_GREATER;ae->AutomateElement[i].priority=5;break; case 'e':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_EQUAL;ae->AutomateElement[i].priority=5;break; case 'n':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_NOTEQUAL;ae->AutomateElement[i].priority=5;break; case 'k':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_LOWEREQ;ae->AutomateElement[i].priority=5;break; case 'h':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_GREATEREQ;ae->AutomateElement[i].priority=5;break; /* priority 6 */ case '&':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_AND;ae->AutomateElement[i].priority=6;break; /* priority 7 */ case '^':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_XOR;ae->AutomateElement[i].priority=7;break; /* priority 8 */ case '|':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_OR;ae->AutomateElement[i].priority=8;break; /* priority 9 */ case 'a':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_BAND;ae->AutomateElement[i].priority=9;break; /* priority 10 */ case 'o':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_BOR;ae->AutomateElement[i].priority=10;break; default:ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_END; } } } else { for (i=0;i<256;i++) { switch (i) { /* priority 0 */ case '(':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_OPEN;ae->AutomateElement[i].priority=0;break; case ')':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_CLOSE;ae->AutomateElement[i].priority=0;break; /* priority 0.5 */ case 'b':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_NOT;ae->AutomateElement[i].priority=128;break; /* priority 1 */ case '*':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_MUL;ae->AutomateElement[i].priority=464;break; case '/':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_DIV;ae->AutomateElement[i].priority=464;break; case 'm':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_MOD;ae->AutomateElement[i].priority=464;break; case '+':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_ADD;ae->AutomateElement[i].priority=464;break; case '-':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_SUB;ae->AutomateElement[i].priority=464;break; case '[':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_SHL;ae->AutomateElement[i].priority=464;break; case ']':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_SHR;ae->AutomateElement[i].priority=464;break; case '&':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_AND;ae->AutomateElement[i].priority=464;break; case '^':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_XOR;ae->AutomateElement[i].priority=464;break; case '|':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_OR;ae->AutomateElement[i].priority=464;break; /* priority 2 */ case 'l':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_LOWER;ae->AutomateElement[i].priority=664;break; case 'g':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_GREATER;ae->AutomateElement[i].priority=664;break; case 'e':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_EQUAL;ae->AutomateElement[i].priority=664;break; case 'n':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_NOTEQUAL;ae->AutomateElement[i].priority=664;break; case 'k':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_LOWEREQ;ae->AutomateElement[i].priority=664;break; case 'h':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_GREATEREQ;ae->AutomateElement[i].priority=664;break; /* priority 3 */ case 'a':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_BAND;ae->AutomateElement[i].priority=6128;break; case 'o':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_BOR;ae->AutomateElement[i].priority=6128;break; default:ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_END; } } } /* psg conversion */ for (i=j=0;i<100;i++) ae->psgtab[j++]=0; for (i=0;i<49;i++) ae->psgtab[j++]=13; for (i=0;i<35;i++) ae->psgtab[j++]=14; for (i=0;i<72;i++) ae->psgtab[j++]=15; if (j!=256) { rasm_printf(ae,"Internal error with PSG conversion table\n"); exit(-44); } for (i=j=0;i<1;i++) ae->psgfine[j++]=0; for (i=0;i<1;i++) ae->psgfine[j++]=1; for (i=0;i<1;i++) ae->psgfine[j++]=2; for (i=0;i<2;i++) ae->psgfine[j++]=3; for (i=0;i<2;i++) ae->psgfine[j++]=4; for (i=0;i<2;i++) ae->psgfine[j++]=5; for (i=0;i<3;i++) ae->psgfine[j++]=6; for (i=0;i<4;i++) ae->psgfine[j++]=7; for (i=0;i<7;i++) ae->psgfine[j++]=8; for (i=0;i<9;i++) ae->psgfine[j++]=9; for (i=0;i<13;i++) ae->psgfine[j++]=10; for (i=0;i<19;i++) ae->psgfine[j++]=11; for (i=0;i<27;i++) ae->psgfine[j++]=12; for (i=0;i<37;i++) ae->psgfine[j++]=13; for (i=0;i<53;i++) ae->psgfine[j++]=14; for (i=0;i<75;i++) ae->psgfine[j++]=15; if (j!=256) { rasm_printf(ae,"Internal error with PSG conversion table\n"); exit(-44); } /* default var */ ae->autorise_export=1; ExpressionSetDicoVar(ae,"PI",3.1415926545); ExpressionSetDicoVar(ae,"ASSEMBLER_RASM",1); /* add a fictive expression to simplify test when parsing expressions */ ObjectArrayAddDynamicValueConcat((void **)&ae->expression,&ae->ie,&ae->me,&curexp,sizeof(curexp)); /* compute CRC for keywords and directives */ for (icrc=0;instruction[icrc].mnemo[0];icrc++) instruction[icrc].crc=GetCRC(instruction[icrc].mnemo); for (icrc=0;math_keyword[icrc].mnemo[0];icrc++) math_keyword[icrc].crc=GetCRC(math_keyword[icrc].mnemo); if (ae->as80==1) { /* not for UZ80 */ for (icrc=0;instruction[icrc].mnemo[0];icrc++) { if (strcmp(instruction[icrc].mnemo,"DEFB")==0 || strcmp(instruction[icrc].mnemo,"DB")==0) { instruction[icrc].makemnemo=_DEFB_as80; } else if (strcmp(instruction[icrc].mnemo,"DEFW")==0 || strcmp(instruction[icrc].mnemo,"DW")==0) { instruction[icrc].makemnemo=_DEFW_as80; } else if (strcmp(instruction[icrc].mnemo,"DEFI")==0) { instruction[icrc].makemnemo=_DEFI_as80; } } } for (icrc=0;instruction[icrc].mnemo[0];icrc++) { /* get indexes for DEF instructions */ if (strcmp(instruction[icrc].mnemo,"DEFB")==0) { ICRC_DEFB=icrc; } else if (strcmp(instruction[icrc].mnemo,"DB")==0) { ICRC_DB=icrc; } else if (strcmp(instruction[icrc].mnemo,"DEFW")==0) { ICRC_DEFW=icrc; } else if (strcmp(instruction[icrc].mnemo,"DW")==0) { ICRC_DW=icrc; } else if (strcmp(instruction[icrc].mnemo,"DEFR")==0) { ICRC_DEFR=icrc; } else if (strcmp(instruction[icrc].mnemo,"DR")==0) { ICRC_DR=icrc; } else if (strcmp(instruction[icrc].mnemo,"DEFS")==0) { ICRC_DEFS=icrc; } else if (strcmp(instruction[icrc].mnemo,"DS")==0) { ICRC_DS=icrc; } else if (strcmp(instruction[icrc].mnemo,"DEFI")==0) { ICRC_DEFI=icrc; } } /* Execution des mots clefs */ /********************************************************** A S S E M B L I N G M A I N L O O P **********************************************************/ #if TRACE_ASSEMBLE printf("init ok\n"); #endif #if TRACE_GENERALE printf("-loop\n"); #endif ae->idx=1; while (wordlist[ae->idx].t!=2) { curcrc=GetCRC(wordlist[ae->idx].w); /********************* d e b u g i n f o *********************/ #if TRACE_ASSEMBLE { int iiii=0; printf(KVERBOSE"%d [%s] L%d [%s]e=%d ",ae->idx,ae->filename[wordlist[ae->idx].ifile],wordlist[ae->idx].l,wordlist[ae->idx].w,wordlist[ae->idx].e); while (!wordlist[ae->idx+iiii++].t) rasm_printf(ae," [%s]e=%d ",wordlist[ae->idx+iiii].w,wordlist[ae->idx+iiii].e); for (iiii=0;iiiiimacropos;iiii++) { printf("M[%d] s=%d e=%d ",iiii,ae->macropos[iiii].start,ae->macropos[iiii].end); } printf("\n"); } #endif /******************************************************************** c o n d i t i o n n a l a s s e m b l y m a n a g e m e n t ********************************************************************/ if (ae->ii || ae->isw) { /* inhibition of if/endif */ for (inhibe=curii=0;curiiii;curii++) { if (!ae->ifthen[curii].v || ae->ifthen[curii].v==-1) { inhibe=1; break; } } /* when inhibited we are looking only for a IF/IFDEF/IFNOT/IFNDEF/ELSE/ELSEIF/ENDIF or SWITCH/CASE/DEFAULT/ENDSWITCH */ if (inhibe) { /* this section does NOT need to be agressively optimized !!! */ if (curcrc==CRC_ELSEIF && strcmp(wordlist[ae->idx].w,"ELSEIF")==0) { /* true IF needs to be done ONLY on the active level */ if (curii==ae->ii-1) __ELSEIF(ae); else __ELSEIF_light(ae); } else if (curcrc==CRC_ELSE && strcmp(wordlist[ae->idx].w,"ELSE")==0) { __ELSE(ae); } else if (curcrc==CRC_ENDIF && strcmp(wordlist[ae->idx].w,"ENDIF")==0) { __ENDIF(ae); } else if (curcrc==CRC_IF && strcmp(wordlist[ae->idx].w,"IF")==0) { /* as we are inhibited we do not have to truly compute IF */ __IF_light(ae); } else if (curcrc==CRC_IFDEF && strcmp(wordlist[ae->idx].w,"IFDEF")==0) { __IFDEF_light(ae); } else if (curcrc==CRC_IFNOT && strcmp(wordlist[ae->idx].w,"IFNOT")==0) { __IFNOT_light(ae); } else if (curcrc==CRC_IFUSED && strcmp(wordlist[ae->idx].w,"IFUSED")==0) { __IFUSED_light(ae); } else if (curcrc==CRC_IFNUSED && strcmp(wordlist[ae->idx].w,"IFNUSED")==0) { __IFNUSED_light(ae); } else if (curcrc==CRC_IFNDEF && strcmp(wordlist[ae->idx].w,"IFNDEF")==0) { __IFNDEF_light(ae); } else if (curcrc==CRC_SWITCH && strcmp(wordlist[ae->idx].w,"SWITCH")==0) { __SWITCH_light(ae); } else if (curcrc==CRC_CASE && strcmp(wordlist[ae->idx].w,"CASE")==0) { __CASE_light(ae); } else if (curcrc==CRC_ENDSWITCH && strcmp(wordlist[ae->idx].w,"ENDSWITCH")==0) { __ENDSWITCH(ae); } else if (curcrc==CRC_BREAK && strcmp(wordlist[ae->idx].w,"BREAK")==0) { __BREAK_light(ae); } else if (curcrc==CRC_DEFAULT && strcmp(wordlist[ae->idx].w,"DEFAULT")==0) { __DEFAULT_light(ae); } while (wordlist[ae->idx].t==0) ae->idx++; ae->idx++; continue; } else { /* inhibition of switch/case */ for (curii=0;curiiisw;curii++) { if (!ae->switchcase[curii].execute) { inhibe=2; break; } } if (inhibe) { /* this section does NOT need to be agressively optimized !!! */ if (curcrc==CRC_CASE && strcmp(wordlist[ae->idx].w,"CASE")==0) { __CASE(ae); } else if (curcrc==CRC_ENDSWITCH && strcmp(wordlist[ae->idx].w,"ENDSWITCH")==0) { __ENDSWITCH(ae); } else if (curcrc==CRC_IF && strcmp(wordlist[ae->idx].w,"IF")==0) { /* as we are inhibited we do not have to truly compute IF */ __IF_light(ae); } else if (curcrc==CRC_IFDEF && strcmp(wordlist[ae->idx].w,"IFDEF")==0) { __IFDEF(ae); } else if (curcrc==CRC_IFNOT && strcmp(wordlist[ae->idx].w,"IFNOT")==0) { __IFNOT(ae); } else if (curcrc==CRC_ELSE && strcmp(wordlist[ae->idx].w,"ELSE")==0) { __ELSE(ae); } else if (curcrc==CRC_ENDIF && strcmp(wordlist[ae->idx].w,"ENDIF")==0) { __ENDIF(ae); } else if (curcrc==CRC_ELSEIF && strcmp(wordlist[ae->idx].w,"ELSEIF")==0) { __ELSEIF(ae); } else if (curcrc==CRC_IFUSED && strcmp(wordlist[ae->idx].w,"IFUSED")==0) { __IFUSED(ae); } else if (curcrc==CRC_IFNUSED && strcmp(wordlist[ae->idx].w,"IFNUSED")==0) { __IFNUSED(ae); } else if (curcrc==CRC_IFNDEF && strcmp(wordlist[ae->idx].w,"IFNDEF")==0) { __IFNDEF(ae); } else if (curcrc==CRC_SWITCH && strcmp(wordlist[ae->idx].w,"SWITCH")==0) { __SWITCH(ae); } else if (curcrc==CRC_BREAK && strcmp(wordlist[ae->idx].w,"BREAK")==0) { __BREAK(ae); } else if (curcrc==CRC_DEFAULT && strcmp(wordlist[ae->idx].w,"DEFAULT")==0) { __DEFAULT(ae); } while (wordlist[ae->idx].t==0) ae->idx++; ae->idx++; continue; } } } if (ae->imacropos) { /* are we still in a macro? */ if (ae->idx>=ae->macropos[0].end) { /* are we out of all repetition blocks? */ if (!ae->ir && !ae->iw) { ae->imacropos=0; /* quand on sort du local, on récupère le dernier label global */ if (ae->lastsuperglobal!=ae->lastgloballabel && ae->lastsuperglobal) { if (ae->lastglobalalloc) { MemFree(ae->lastgloballabel); ae->lastglobalalloc=0; } ae->lastgloballabel=ae->lastsuperglobal; ae->lastgloballabellen=strlen(ae->lastgloballabel); } } } } /***************************************** e x e c u t e i n s t r u c t i o n *****************************************/ executed=0; if ((ifast=ae->fastmatch[(int)wordlist[ae->idx].w[0]])!=-1) { while (instruction[ifast].mnemo[0]==wordlist[ae->idx].w[0]) { if (instruction[ifast].crc==curcrc && strcmp(instruction[ifast].mnemo,wordlist[ae->idx].w)==0) { #if TRACE_ASSEMBLE printf("-> mnemo\n"); #endif instruction[ifast].makemnemo(ae); executed=1; break; } ifast++; } } /***************************************** e x e c u t e m a c r o *****************************************/ if (!executed) { /* is it a macro? */ if ((ifast=SearchMacro(ae,curcrc,wordlist[ae->idx].w))>=0) { #if TRACE_ASSEMBLE printf("-> macro\n"); #endif wordlist=__MACRO_EXECUTE(ae,ifast); continue; } } /********************************************************************* e x e c u t e e x p r e s s i o n o r p u s h l a b e l *********************************************************************/ if (!ae->stop) { if (!executed) { /* no instruction executed, this is a label or an assignement */ if (wordlist[ae->idx].e) { #if TRACE_ASSEMBLE printf("-> expr\n"); #endif ExpressionFastTranslate(ae,&wordlist[ae->idx].w,0); ComputeExpression(ae,wordlist[ae->idx].w,ae->codeadr,0,0); } else { #if TRACE_ASSEMBLE printf("-> label\n"); #endif PushLabel(ae); } } else { #if TRACE_ASSEMBLE printf("-> ajuste IDX\n"); #endif while (!wordlist[ae->idx].t) { ae->idx++; } } ae->idx++; } else { #if TRACE_ASSEMBLE printf("-> STOP\n"); #endif break; } } #if TRACE_ASSEMBLE rasm_printf(ae,KVERBOSE"%d [%s] L%d [%s] fin de la liste de mots\n",ae->idx,ae->filename[wordlist[ae->idx].ifile],wordlist[ae->idx].l,wordlist[ae->idx].w); printf("check ORG\n"); #endif #if TRACE_GENERALE printf("-check ORG\n"); #endif if (!ae->stop) { /* end of assembly, check there is no opened struct */ if (ae->getstruct) { MakeError(ae,ae->backup_filename,ae->backup_line,"STRUCT declaration was not closed\n"); } /* end of assembly, close the last ORG zone */ if (ae->io) { ae->orgzone[ae->io-1].memend=ae->outputadr; } OverWriteCheck(ae); /* end of assembly, close crunched zone (if any) */ __internal_UpdateLZBlockIfAny(ae); /* end of assembly, check for opened repeat and opened while loop */ for (i=0;iir;i++) { MakeError(ae,ae->filename[wordlist[ae->repeat[i].start].ifile],wordlist[ae->repeat[i].start].l,"REPEAT was not closed\n"); } for (i=0;iiw;i++) { MakeError(ae,ae->filename[wordlist[ae->whilewend[i].start].ifile],wordlist[ae->whilewend[i].start].l,"WHILE was not closed\n"); } /* is there any IF opened? -> need an evolution for a better error message */ for (i=0;iii;i++) { char instr[32]; switch (ae->ifthen[i].type) { case E_IFTHEN_TYPE_IF:strcpy(instr,"IF");break; case E_IFTHEN_TYPE_IFNOT:strcpy(instr,"IFNOT");break; case E_IFTHEN_TYPE_IFDEF:strcpy(instr,"IFDEF");break; case E_IFTHEN_TYPE_IFNDEF:strcpy(instr,"IFNDEF");break; case E_IFTHEN_TYPE_ELSE:strcpy(instr,"ELSE");break; case E_IFTHEN_TYPE_ELSEIF:strcpy(instr,"ELSEIF");break; case E_IFTHEN_TYPE_IFUSED:strcpy(instr,"IFUSED");break; case E_IFTHEN_TYPE_IFNUSED:strcpy(instr,"IFNUSED");break; default:strcpy(instr,""); } MakeError(ae,ae->ifthen[i].filename,ae->ifthen[i].line,"%s conditionnal block was not closed\n",instr); } } #if TRACE_ASSEMBLE printf("crunch if any\n"); #endif /*************************************************** c r u n c h L Z s e c t i o n s ***************************************************/ if (!ae->stop || !ae->nberr) { for (i=0;iilz;i++) { /* compute labels and expression inside crunched blocks */ PopAllExpression(ae,i); ae->curlz=i; iorgzone=ae->lzsection[i].iorgzone; ibank=ae->lzsection[i].ibank; input_data=&ae->mem[ae->lzsection[i].ibank][ae->lzsection[i].memstart]; input_size=ae->lzsection[i].memend-ae->lzsection[i].memstart; //printf("grouik (%d) %s\n",ae->lzsection[i].lzversion,ae->lzsection[i].lzversion==8?"mizou":""); if (!input_size) { rasm_printf(ae,KWARNING"[%s:%d] Warning: crunched section is empty\n",GetCurrentFile(ae),ae->wl[ae->idx].l); } else { switch (ae->lzsection[i].lzversion) { case 7: #ifndef NO_3RD_PARTIES lzdata=ZX7_compress(optimize(input_data, input_size), input_data, input_size, &slzlen); lzlen=slzlen; #endif break; case 4: #ifndef NO_3RD_PARTIES lzdata=LZ4_crunch(input_data,input_size,&lzlen); #endif break; case 8: #ifndef NO_3RD_PARTIES rasm_printf(ae,KWARNING"Exomizer is crunching %.1fkb this may take a while, be patient...\n",input_size/1024.0); lzdata=Exomizer_crunch(input_data,input_size,&lzlen); #endif break; case 48: lzdata=LZ48_crunch(input_data,input_size,&lzlen); break; case 49: lzdata=LZ49_crunch(input_data,input_size,&lzlen); break; default: rasm_printf(ae,"Internal error - unknown crunch method %d\n",ae->lzsection[i].lzversion); exit(-12); } } //rasm_printf(ae,"lzsection[%d] type=%d start=%04X end=%04X crunched size=%d\n",i,ae->lzsection[i].lzversion,ae->lzsection[i].memstart,ae->lzsection[i].memend,lzlen); if (input_sizefilename[ae->wl[ae->lzsection[i].iw].ifile],ae->wl[ae->lzsection[i].iw].l,"As the LZ section cannot crunch data, Rasm may not guarantee assembled file!\n"); } lzshift=lzlen-(ae->lzsection[i].memend-ae->lzsection[i].memstart); if (lzshift>0) { MemMove(ae->mem[ae->lzsection[i].ibank]+ae->lzsection[i].memend+lzshift,ae->mem[ae->lzsection[i].ibank]+ae->lzsection[i].memend,65536-ae->lzsection[i].memend-lzshift); } else if (lzshift<0) { lzmove=ae->orgzone[iorgzone].memend-ae->lzsection[i].memend; if (lzmove) { MemMove(ae->mem[ae->lzsection[i].ibank]+ae->lzsection[i].memend+lzshift,ae->mem[ae->lzsection[i].ibank]+ae->lzsection[i].memend,lzmove); } } memcpy(ae->mem[ae->lzsection[i].ibank]+ae->lzsection[i].memstart,lzdata,lzlen); MemFree(lzdata); /******************************************************************* l a b e l a n d e x p r e s s i o n r e l o c a t i o n *******************************************************************/ /* relocate labels in the same ORG zone AND after the current crunched section */ il=ae->lzsection[i].ilabel; while (ilil && ae->label[il].iorgzone==iorgzone && ae->label[il].ibank==ibank) { curlabel=SearchLabel(ae,ae->label[il].iw!=-1?wordlist[ae->label[il].iw].w:ae->label[il].name,ae->label[il].crc); /* CANNOT be NULL */ curlabel->ptr+=lzshift; //printf("label [%s] shifte de %d valeur #%04X -> #%04X\n",curlabel->iw!=-1?wordlist[curlabel->iw].w:curlabel->name,lzshift,curlabel->ptr-lzshift,curlabel->ptr); il++; } /* relocate expressions in the same ORG zone AND after the current crunched section */ il=ae->lzsection[i].iexpr; while (ilie && ae->expression[il].iorgzone==iorgzone && ae->expression[il].ibank==ibank) { ae->expression[il].wptr+=lzshift; ae->expression[il].ptr+=lzshift; //printf("expression [%s] shiftee ptr=#%04X wptr=#%04X\n", ae->expression[il].reference?ae->expression[il].reference:wordlist[ae->expression[il].iw].w, ae->expression[il].ptr, ae->expression[il].wptr); il++; } /* relocate crunched sections in the same ORG zone AND after the current crunched section */ il=i+1; while (ililz && ae->lzsection[il].iorgzone==iorgzone && ae->lzsection[il].ibank==ibank) { //rasm_printf(ae,"reloger lzsection[%d] O%d B%d\n",il,ae->lzsection[il].iorgzone,ae->lzsection[il].ibank); ae->lzsection[il].memstart+=lzshift; ae->lzsection[il].memend+=lzshift; il++; } /* relocate current ORG zone */ ae->orgzone[iorgzone].memend+=lzshift; } if (ae->ilz) { /* compute expression placed after the last crunched block */ PopAllExpression(ae,ae->ilz); } /* compute expression outside crunched blocks */ PopAllExpression(ae,-1); } /*************************************************************************************************************************************************************************************** **************************************************************************************************************************************************************************************** W R I T E O U T P U T F I L E S **************************************************************************************************************************************************************************************** ***************************************************************************************************************************************************************************************/ TMP_filename=MemMalloc(PATH_MAX); #if 0 for (i=0;iio;i++) { printf("ORG[%02d] start=%04X end=%04X ibank=%d nocode=%d protect=%d\n",i,ae->orgzone[i].memstart,ae->orgzone[i].memend,ae->orgzone[i].ibank,ae->orgzone[i].nocode,ae->orgzone[i].protect); } #endif #if TRACE_ASSEMBLE printf("output files\n"); #endif if (!ae->nberr && !ae->checkmode) { /* enregistrement des fichiers programmes par la commande SAVE */ PopAllSave(ae); if (ae->nbsave==0 || ae->forcecpr || ae->forcesnapshot) { /********************************************* ********************************************** C A R T R I D G E ********************************************** *********************************************/ if (ae->forcecpr) { char ChunkName[32]; int ChunkSize; int do_it=1; unsigned char chunk_endian; if (ae->cartridge_name) { sprintf(TMP_filename,"%s",ae->cartridge_name); } else { sprintf(TMP_filename,"%s.cpr",ae->outputfilename); } FileRemoveIfExists(TMP_filename); rasm_printf(ae,KIO"Write cartridge file %s\n",TMP_filename); for (i=maxrom=0;iio;i++) { if (ae->orgzone[i].ibank<32 && ae->orgzone[i].ibank>maxrom) maxrom=ae->orgzone[i].ibank; } /* construction du CPR */ /* header blablabla */ strcpy(ChunkName,"RIFF"); FileWriteBinary(TMP_filename,ChunkName,4); ChunkSize=(maxrom+1)*(16384+8)+4; chunk_endian=ChunkSize&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1); chunk_endian=(ChunkSize>>8)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1); chunk_endian=(ChunkSize>>16)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1); chunk_endian=(ChunkSize>>24)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1); sprintf(ChunkName,"AMS!"); FileWriteBinary(TMP_filename,ChunkName,4); // for (j=0;jio;j++) { //printf("ORG[%03d]=B%02d/#%04X/#%04X\n",j,ae->orgzone[j].ibank,ae->orgzone[j].memstart,ae->orgzone[j].memend); // } for (i=0;i<=maxrom;i++) { offset=65536; endoffset=0; for (j=0;jio;j++) { if (ae->orgzone[j].protect) continue; /* protected zones exclusion */ /* bank data may start anywhere (typically #0000 or #C000) */ if (ae->orgzone[j].ibank==i && ae->orgzone[j].memstart!=ae->orgzone[j].memend) { if (ae->orgzone[j].memstartorgzone[j].memstart; if (ae->orgzone[j].memend>endoffset) endoffset=ae->orgzone[j].memend; } } if (endoffset>offset) { int lm=0; if (ae->iwnamebank[i]>0) { lm=strlen(ae->wl[ae->iwnamebank[i]].w)-2; } rasm_printf(ae,KVERBOSE"WriteCPR bank %2d of %5d byte%s start at #%04X",i,endoffset-offset,endoffset-offset>1?"s":" ",offset); if (endoffset-offset>16384) { rasm_printf(ae,"\nROM is too big!!!\n"); FileWriteBinaryClose(TMP_filename); FileRemoveIfExists(TMP_filename); FreeAssenv(ae); exit(ABORT_ERROR); } if (lm) { rasm_printf(ae," (%-*.*s)\n",lm,lm,ae->wl[ae->iwnamebank[i]].w+1); } else { rasm_printf(ae,"\n"); } } else { rasm_printf(ae,KVERBOSE"WriteCPR bank %2d (empty)\n",i); } ChunkSize=16384; sprintf(ChunkName,"cb%02d",i); FileWriteBinary(TMP_filename,ChunkName,4); chunk_endian=ChunkSize&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1); chunk_endian=(ChunkSize>>8)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1); chunk_endian=(ChunkSize>>16)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1); chunk_endian=(ChunkSize>>24)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1); if (offset>0xC000) { unsigned char filler[16384]={0}; ChunkSize=65536-offset; if (ChunkSize) FileWriteBinary(TMP_filename,(char*)ae->mem[i]+offset,ChunkSize); /* ADD zeros until the end of the bank */ FileWriteBinary(TMP_filename,(char*)filler,16384-ChunkSize); } else { FileWriteBinary(TMP_filename,(char*)ae->mem[i]+offset,ChunkSize); } } FileWriteBinaryClose(TMP_filename); rasm_printf(ae,"Total %d bank%s (%dK)\n",maxrom+1,maxrom+1>1?"s":"",(maxrom+1)*16); /********************************************* ********************************************** S N A P S H O T ********************************************** *********************************************/ } else if (ae->forcesnapshot) { if (ae->forcezx) { unsigned char zxsnapheader[0x1A]={0}; if (ae->snapshot_name) { sprintf(TMP_filename,"%s",ae->snapshot_name); } else { sprintf(TMP_filename,"%s.sna",ae->outputfilename); } FileRemoveIfExists(TMP_filename); /* do we have a bankset? */ /* zx bootstrap */ zxsnapheader[0x13]=0; /* 0:DI 4:EI */ zxsnapheader[0x17]=ae->zxsnapshot.stack&0xFF; zxsnapheader[0x18]=(ae->zxsnapshot.stack>>8)&0xFF; zxsnapheader[0x19]=1; /* IM 1 */ //ae->zxsnapshot.stack&=0xFFFF; ae->mem[0][ae->zxsnapshot.stack]=ae->zxsnapshot.run&0xFF; ae->mem[0][ae->zxsnapshot.stack+1]=(ae->zxsnapshot.run>>8)&0xFF; rasm_printf(ae,KIO"Write 48K ZX snapshot file %s\n",TMP_filename); /* header */ FileWriteBinary(TMP_filename,(char *)&zxsnapheader,27); /* data */ if (ae->bankset[0]) { FileWriteBinary(TMP_filename,(char *)ae->mem[0]+16384,16384*3); } else { FileWriteBinary(TMP_filename,(char *)ae->mem[5],16384); FileWriteBinary(TMP_filename,(char *)ae->mem[2],16384); FileWriteBinary(TMP_filename,(char *)ae->mem[0],16384); } FileWriteBinaryClose(TMP_filename); } else { unsigned char packed[65536]={0}; unsigned char *rlebank=NULL; char ChunkName[16]; int ChunkSize; int do_it=1; int bankset; int noflood=0; if (ae->snapshot.version==2 && ae->snapshot.CPCType>2) { if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: V2 snapshot cannot select a Plus model (forced to 6128)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); ae->snapshot.CPCType=2; /* 6128 */ } if (ae->snapshot_name) { sprintf(TMP_filename,"%s",ae->snapshot_name); } else { sprintf(TMP_filename,"%s.sna",ae->outputfilename); } FileRemoveIfExists(TMP_filename); maxrom=-1; for (i=0;iio;i++) { if (ae->orgzone[i].ibankorgzone[i].ibank>maxrom && ae->orgzone[i].memstart!=ae->orgzone[i].memend) { maxrom=ae->orgzone[i].ibank; } } //printf("maxrom=%d\n",maxrom); /* construction du SNA */ if (ae->snapshot.version==2) { if (maxrom>=4) { ae->snapshot.dumpsize[0]=128; } else if (maxrom>=0) { ae->snapshot.dumpsize[0]=64; } } if (maxrom==-1) { rasm_printf(ae,KWARNING"Warning: No byte were written in snapshot memory\n"); } else { rasm_printf(ae,KIO"Write snapshot v%d file %s\n",ae->snapshot.version,TMP_filename); /* header */ FileWriteBinary(TMP_filename,(char *)&ae->snapshot,0x100); /* write all memory crunched */ for (i=0;i<=maxrom;i+=4) { bankset=i>>2; if (ae->bankset[bankset]) { memcpy(packed,ae->mem[i],65536); if (i<4 || i+4>maxrom) rasm_printf(ae,KVERBOSE"WriteSNA bank %2d,%d,%d,%d packed\n",i,i+1,i+2,i+3); else if (!noflood) {rasm_printf(ae,KVERBOSE"[...]\n");noflood=1;} } else { memset(packed,0,65536); for (k=0;k<4;k++) { offset=65536; endoffset=0; for (j=0;jio;j++) { if (ae->orgzone[j].protect) continue; /* protected zones exclusion */ /* bank data may start anywhere (typically #0000 or #C000) */ if (ae->orgzone[j].ibank==i+k && ae->orgzone[j].memstart!=ae->orgzone[j].memend) { if (ae->orgzone[j].memstartorgzone[j].memstart; if (ae->orgzone[j].memend>endoffset) endoffset=ae->orgzone[j].memend; } } if (endoffset-offset>16384) { rasm_printf(ae,KERROR"\nBANK is too big!!!\n"); FileWriteBinaryClose(TMP_filename); FileRemoveIfExists(TMP_filename); FreeAssenv(ae); exit(ABORT_ERROR); } /* banks are gathered in the 64K block */ if (offset>0xC000) { ChunkSize=65536-offset; memcpy(packed+k*16384,(char*)ae->mem[i+k]+offset,ChunkSize); } else { memcpy(packed+k*16384,(char*)ae->mem[i+k]+offset,16384); } if (endoffset>offset) { int lm=0; if (ae->iwnamebank[i]>0) { lm=strlen(ae->wl[ae->iwnamebank[i]].w)-2; } if (i<4 || i+4>maxrom) rasm_printf(ae,KVERBOSE"WriteSNA bank %2d of %5d byte%s start at #%04X",i+k,endoffset-offset,endoffset-offset>1?"s":" ",offset); else if (!noflood) {rasm_printf(ae,KVERBOSE"[...]\n");noflood=1;} if (endoffset-offset>16384) { rasm_printf(ae,KERROR"\nRAM block is too big!!!\n"); FileWriteBinaryClose(TMP_filename); FileRemoveIfExists(TMP_filename); FreeAssenv(ae); exit(ABORT_ERROR); } if (lm) { if (i<4 || i+4>maxrom) rasm_printf(ae,KVERBOSE" (%-*.*s)\n",lm,lm,ae->wl[ae->iwnamebank[i+k]].w+1); } else { if (i<4 || i+4>maxrom) rasm_printf(ae,"\n"); } } else { if (i<4 || i+4>maxrom) rasm_printf(ae,KVERBOSE"WriteSNA bank %2d (empty)\n",i+k); else if (!noflood) {rasm_printf(ae,KVERBOSE"[...]\n");noflood=1;} } } } if (ae->snapshot.version==2) { /* snapshot v2 */ FileWriteBinary(TMP_filename,(char*)&packed,65536); if (bankset) { /* v2 snapshot is 128K maximum */ maxrom=7; break; } } else { /* compression par défaut avec snapshot v3 */ rlebank=EncodeSnapshotRLE(packed,&ChunkSize); if (bankset>=0 && bankset<=8) { sprintf(ChunkName,"MEM%d",bankset); } else if (bankset>8 && bankset<=0x40) { /* extended chunk for 4M extension -> MX09 to MX40 (hexa numbered) */ sprintf(ChunkName,"MX%02X",bankset); } else { MakeError(ae,"(core)",0,"internal error during snapshot write, please report (%d)\n",bankset); } FileWriteBinary(TMP_filename,ChunkName,4); if (rlebank!=NULL) { FileWriteBinary(TMP_filename,(char*)&ChunkSize,4); FileWriteBinary(TMP_filename,(char*)rlebank,ChunkSize); MemFree(rlebank); } else { ChunkSize=65536; FileWriteBinary(TMP_filename,(char*)&packed,ChunkSize); } } } /************************************************************** snapshot additional chunks in v3+ only **************************************************************/ if (ae->snapshot.version>=3) { /* export breakpoint */ if (ae->export_snabrk) { /* BRKS chunk for Winape emulator (unofficial) 2 bytes - adress 1 byte - 0=base 64K / 1=extended 2 bytes - condition (zeroed) */ struct s_breakpoint breakpoint={0}; unsigned char *brkschunk=NULL; unsigned int idx=8; /* add labels and local labels to breakpoint pool (if any) */ for (i=0;iil;i++) { if (!ae->label[i].name) { if (strncmp(ae->wl[ae->label[i].iw].w,"BRK",3)==0) { breakpoint.address=ae->label[i].ptr; if (ae->label[i].ibank>3) breakpoint.bank=1; else breakpoint.bank=0; ObjectArrayAddDynamicValueConcat((void **)&ae->breakpoint,&ae->ibreakpoint,&ae->maxbreakpoint,&breakpoint,sizeof(struct s_breakpoint)); } } else { if (strncmp(ae->label[i].name,"@BRK",4)==0 || strstr(ae->label[i].name,".BRK")) { breakpoint.address=ae->label[i].ptr; if (ae->label[i].ibank>3) breakpoint.bank=1; else breakpoint.bank=0; ObjectArrayAddDynamicValueConcat((void **)&ae->breakpoint,&ae->ibreakpoint,&ae->maxbreakpoint,&breakpoint,sizeof(struct s_breakpoint)); } } } brkschunk=MemMalloc(ae->ibreakpoint*5+8); strcpy((char *)brkschunk,"BRKS"); for (i=0;iibreakpoint;i++) { brkschunk[idx++]=ae->breakpoint[i].address&0xFF; brkschunk[idx++]=(ae->breakpoint[i].address&0xFF00)/256; brkschunk[idx++]=ae->breakpoint[i].bank; brkschunk[idx++]=0; brkschunk[idx++]=0; } idx-=8; brkschunk[4]=idx&0xFF; brkschunk[5]=(idx>>8)&0xFF; brkschunk[6]=(idx>>16)&0xFF; brkschunk[7]=(idx>>24)&0xFF; FileWriteBinary(TMP_filename,(char*)brkschunk,idx+8); // 8 bytes for the chunk header MemFree(brkschunk); /* BRKC chunk for ACE emulator minimal integration */ brkschunk=MemMalloc(ae->ibreakpoint*256); strcpy((char *)brkschunk,"BRKC"); idx=8; for (i=0;iibreakpoint;i++) { brkschunk[idx++]=0; /* 0:Execution */ brkschunk[idx++]=0; brkschunk[idx++]=0; brkschunk[idx++]=0; brkschunk[idx++]=ae->breakpoint[i].address&0xFF; brkschunk[idx++]=(ae->breakpoint[i].address&0xFF00)/256; for (j=0;j<2+1+1+2+4+128;j++) { brkschunk[idx++]=0; } sprintf((char *)brkschunk+idx,"breakpoint%d",i); /* breakpoint user name? */ idx+=64+8; } idx-=8; brkschunk[4]=idx&0xFF; brkschunk[5]=(idx>>8)&0xFF; brkschunk[6]=(idx>>16)&0xFF; brkschunk[7]=(idx>>24)&0xFF; FileWriteBinary(TMP_filename,(char *)brkschunk,idx+8); // 8 bytes for the chunk header MemFree(brkschunk); } /* export optionnel des symboles */ if (ae->export_sna) { /* SYMB chunk for ACE emulator 1 byte - name size n bytes - name (without 0 to end the string) 6 bytes - reserved for future use 2 bytes - shitty big endian adress for the symbol */ unsigned char *symbchunk=NULL; unsigned int idx=8; int symbol_len; symbchunk=MemMalloc(8+ae->il*(1+255+6+2)); strcpy((char *)symbchunk,"SYMB"); for (i=0;iil;i++) { if (!ae->label[i].name) { symbol_len=strlen(ae->wl[ae->label[i].iw].w); if (symbol_len>255) symbol_len=255; symbchunk[idx++]=symbol_len; memcpy(symbchunk+idx,ae->wl[ae->label[i].iw].w,symbol_len); idx+=symbol_len; memset(symbchunk+idx,0,6); idx+=6; symbchunk[idx++]=(ae->label[i].ptr&0xFF00)/256; symbchunk[idx++]=ae->label[i].ptr&0xFF; } else { if (ae->export_local || !ae->label[i].local) { symbol_len=strlen(ae->label[i].name); if (symbol_len>255) symbol_len=255; symbchunk[idx++]=symbol_len; memcpy(symbchunk+idx,ae->label[i].name,symbol_len); idx+=symbol_len; memset(symbchunk+idx,0,6); idx+=6; symbchunk[idx++]=(ae->label[i].ptr&0xFF00)/256; symbchunk[idx++]=ae->label[i].ptr&0xFF; } } } if (ae->export_var) { unsigned char *subchunk=NULL; int retidx=0; /* var are part of fast tree search structure */ subchunk=SnapshotDicoTree(ae,&retidx); if (retidx) { symbchunk=MemRealloc(symbchunk,idx+retidx); memcpy(symbchunk+idx,subchunk,retidx); idx+=retidx; SnapshotDicoInsert("FREE",0,&retidx); } } if (ae->export_equ) { symbchunk=MemRealloc(symbchunk,idx+ae->ialias*(1+255+6+2)); for (i=0;iialias;i++) { int tmpptr; symbol_len=strlen(ae->alias[i].alias); if (symbol_len>255) symbol_len=255; symbchunk[idx++]=symbol_len; memcpy(symbchunk+idx,ae->alias[i].alias,symbol_len); idx+=symbol_len; memset(symbchunk+idx,0,6); idx+=6; tmpptr=RoundComputeExpression(ae,ae->alias[i].translation,0,0,0); symbchunk[idx++]=(tmpptr&0xFF00)/256; symbchunk[idx++]=tmpptr&0xFF; } } idx-=8; symbchunk[4]=idx&0xFF; symbchunk[5]=(idx>>8)&0xFF; symbchunk[6]=(idx>>16)&0xFF; symbchunk[7]=(idx>>24)&0xFF; FileWriteBinary(TMP_filename,(char*)symbchunk,idx+8); // 8 bytes for the chunk header } } else { if (ae->export_snabrk) { if (!ae->nowarning) rasm_printf(ae,KWARNING"Warning: breakpoint export is not supported with snapshot version 2\n"); } if (ae->export_sna) { if (!ae->nowarning) rasm_printf(ae,KWARNING"Warning: symbol export is not supported with snapshot version 2\n"); } } FileWriteBinaryClose(TMP_filename); maxrom=(maxrom>>2)*4+4; rasm_printf(ae,KAYGREEN"Total %d bank%s (%dK)\n",maxrom,maxrom>1?"s":"",(maxrom)*16); } } /********************************************* ********************************************** B I N A R Y F I L E ********************************************** *********************************************/ } else { int lastspaceid=-1; if (ae->binary_name) { sprintf(TMP_filename,"%s",ae->binary_name); } else { sprintf(TMP_filename,"%s.bin",ae->outputfilename); } FileRemoveIfExists(TMP_filename); /* en mode binaire classique on va recherche le dernier espace mémoire dans lequel on a travaillé qui n'est pas en 'nocode' */ for (i=0;iio;i++) { /* uniquement si le ORG a ete suivi d'ecriture */ if (ae->orgzone[i].memstart!=ae->orgzone[i].memend && ae->orgzone[i].nocode!=1) { lastspaceid=ae->orgzone[i].ibank; } } if (lastspaceid!=-1) { for (i=0;iio;i++) { if (ae->orgzone[i].protect) continue; /* protected zones exclusion */ /* uniquement si le ORG a ete suivi d'ecriture et n'est pas en 'nocode' */ if (ae->orgzone[i].ibank==lastspaceid && ae->orgzone[i].memstart!=ae->orgzone[i].memend && ae->orgzone[i].nocode!=1) { if (ae->orgzone[i].memstartorgzone[i].memstart; if (ae->orgzone[i].memend>maxmem) maxmem=ae->orgzone[i].memend; } } } if (maxmem-minmem<=0) { if (!ae->stop) { if (!ae->nowarning) rasm_printf(ae,KWARNING"Warning: Not a single byte to output\n"); } if (ae->flux) { *lenout=0; } } else { if (!ae->flux) { rasm_printf(ae,KIO"Write binary file %s (%d byte%s)\n",TMP_filename,maxmem-minmem,maxmem-minmem>1?"s":""); if (ae->amsdos) { AmsdosHeader=MakeAMSDOSHeader(minmem,minmem,maxmem,TMP_filename); //@@TODO FileWriteBinary(TMP_filename,(char *)AmsdosHeader,128); } if (maxmem-minmem>0) { FileWriteBinary(TMP_filename,(char*)ae->mem[lastspaceid]+minmem,maxmem-minmem); FileWriteBinaryClose(TMP_filename); } else { if (ae->amsdos) { FileWriteBinaryClose(TMP_filename); } } } else { *dataout=MemMalloc(maxmem-minmem+1); memcpy(*dataout,ae->mem[lastspaceid]+minmem,maxmem-minmem); *lenout=maxmem-minmem; } } } } /******************************** ********************************* U N U S E D W A R N I N G ********************************* ********************************/ if (ae->warn_unused) { for (i=0;iialias;i++) { if (strcmp(ae->alias[i].alias,"IX") && strcmp(ae->alias[i].alias,"IY")) { if (!ae->alias[i].used) { rasm_printf(ae,KWARNING"[%s:%d] Warning: alias %s declared but not used\n",ae->filename[ae->wl[ae->alias[i].iw].ifile],ae->wl[ae->alias[i].iw].l,ae->alias[i].alias); } } } WarnLabelTree(ae); WarnDicoTree(ae); } /**************************** ***************************** S Y M B O L E X P O R T ***************************** ****************************/ if (ae->export_sym && !ae->export_sna) { char *SymbolFileName; SymbolFileName=MemMalloc(PATH_MAX); #define MAKE_SYMBOL_NAME if (ae->symbol_name) {sprintf(TMP_filename,"%s",ae->symbol_name);} else {sprintf(TMP_filename,"%s.sym",ae->outputfilename);} MAKE_SYMBOL_NAME FileRemoveIfExists(TMP_filename); if (ae->export_multisym) { /* multi-remove before writes */ for (i=0;inbbank;i++) { if (ae->symbol_name) { sprintf(TMP_filename,"%s.bank%d",ae->symbol_name,i); } else { sprintf(TMP_filename,"%s.sym.bank%d",ae->outputfilename,i); } FileRemoveIfExists(TMP_filename); } rasm_printf(ae,KIO"Write symbol files %s.bank*\n",TMP_filename); } else { rasm_printf(ae,KIO"Write symbol file %s\n",TMP_filename); } switch (ae->export_sym) { case 5: /* ZX export */ for (i=0;iil;i++) { if (ae->label[i].autorise_export) { if (ae->export_multisym) { if (ae->symbol_name) { sprintf(TMP_filename,"%s.bank%d",ae->symbol_name,ae->label[i].ibank); } else { sprintf(TMP_filename,"%s.sym.bank%d",ae->outputfilename,ae->label[i].ibank); } } if (!ae->label[i].name) { sprintf(symbol_line,"%d:%04X %s\n",ae->label[i].ibank,ae->label[i].ptr,ae->wl[ae->label[i].iw].w); FileWriteLine(TMP_filename,symbol_line); } else { if (ae->export_local || !ae->label[i].local) { sprintf(symbol_line,"%d:%04X %s\n",ae->label[i].ibank,ae->label[i].ptr,ae->label[i].name); FileWriteLine(TMP_filename,symbol_line); } } } } FileWriteLineClose(TMP_filename); MAKE_SYMBOL_NAME if (ae->export_var) { /* var are part of fast tree search structure */ ExportDicoTree(ae,TMP_filename,"%s %04X"); } if (ae->export_equ) { for (i=0;iialias;i++) { if (strcmp(ae->alias[i].alias,"IX") && strcmp(ae->alias[i].alias,"IY")) { sprintf(symbol_line,"%04X %s\n",RoundComputeExpression(ae,ae->alias[i].translation,0,-ae->alias[i].iw,0),ae->alias[i].alias); FileWriteLine(TMP_filename,symbol_line); } } } break; case 4: /* flexible */ for (i=0;iil;i++) { if (ae->label[i].autorise_export) { if (ae->export_multisym) { if (ae->symbol_name) { sprintf(TMP_filename,"%s.bank%d",ae->symbol_name,ae->label[i].ibank); } else { sprintf(TMP_filename,"%s.sym.bank%d",ae->outputfilename,ae->label[i].ibank); } } if (!ae->label[i].name) { sprintf(symbol_line,ae->flexible_export,ae->wl[ae->label[i].iw].w,ae->label[i].ptr); FileWriteLine(TMP_filename,symbol_line); } else { if (ae->export_local || !ae->label[i].local) { sprintf(symbol_line,ae->flexible_export,ae->label[i].name,ae->label[i].ptr); FileWriteLine(TMP_filename,symbol_line); } } } } MAKE_SYMBOL_NAME if (ae->export_var) { /* var are part of fast tree search structure */ ExportDicoTree(ae,TMP_filename,ae->flexible_export); } if (ae->export_equ) { for (i=0;iialias;i++) { if (strcmp(ae->alias[i].alias,"IX") && strcmp(ae->alias[i].alias,"IY")) { sprintf(symbol_line,ae->flexible_export,ae->alias[i].alias,RoundComputeExpression(ae,ae->alias[i].translation,0,-ae->alias[i].iw,0)); FileWriteLine(TMP_filename,symbol_line); } } } FileWriteLineClose(TMP_filename); break; case 3: /* winape */ for (i=0;iil;i++) { if (ae->label[i].autorise_export) { if (ae->export_multisym) { if (ae->symbol_name) { sprintf(TMP_filename,"%s.bank%d",ae->symbol_name,ae->label[i].ibank); } else { sprintf(TMP_filename,"%s.sym.bank%d",ae->outputfilename,ae->label[i].ibank); } } if (!ae->label[i].name) { sprintf(symbol_line,"%s #%04X\n",ae->wl[ae->label[i].iw].w,ae->label[i].ptr); FileWriteLine(TMP_filename,symbol_line); } else { if (ae->export_local || !ae->label[i].local) { sprintf(symbol_line,"%s #%04X\n",ae->label[i].name,ae->label[i].ptr); FileWriteLine(TMP_filename,symbol_line); } } } } MAKE_SYMBOL_NAME if (ae->export_var) { /* var are part of fast tree search structure */ ExportDicoTree(ae,TMP_filename,"%s #%04X\n"); } if (ae->export_equ) { for (i=0;iialias;i++) { if (strcmp(ae->alias[i].alias,"IX") && strcmp(ae->alias[i].alias,"IY")) { sprintf(symbol_line,"%s #%04X\n",ae->alias[i].alias,RoundComputeExpression(ae,ae->alias[i].translation,0,-ae->alias[i].iw,0)); FileWriteLine(TMP_filename,symbol_line); } } } FileWriteLineClose(TMP_filename); break; case 2: /* pasmo */ for (i=0;iil;i++) { if (ae->label[i].autorise_export) { if (ae->export_multisym) { if (ae->symbol_name) { sprintf(TMP_filename,"%s.bank%d",ae->symbol_name,ae->label[i].ibank); } else { sprintf(TMP_filename,"%s.sym.bank%d",ae->outputfilename,ae->label[i].ibank); } } if (!ae->label[i].name) { sprintf(symbol_line,"%s EQU 0%04XH\n",ae->wl[ae->label[i].iw].w,ae->label[i].ptr); FileWriteLine(TMP_filename,symbol_line); } else { if (ae->export_local || !ae->label[i].local) { sprintf(symbol_line,"%s EQU 0%04XH\n",ae->label[i].name,ae->label[i].ptr); FileWriteLine(TMP_filename,symbol_line); } } } } MAKE_SYMBOL_NAME if (ae->export_var) { /* var are part of fast tree search structure */ ExportDicoTree(ae,TMP_filename,"%s EQU 0%04XH\n"); } if (ae->export_equ) { for (i=0;iialias;i++) { if (strcmp(ae->alias[i].alias,"IX") && strcmp(ae->alias[i].alias,"IY")) { sprintf(symbol_line,"%s EQU 0%04XH\n",ae->alias[i].alias,RoundComputeExpression(ae,ae->alias[i].translation,0,-ae->alias[i].iw,0)); FileWriteLine(TMP_filename,symbol_line); } } } FileWriteLineClose(TMP_filename); break; case 1: /* Rasm */ for (i=0;iil;i++) { if (ae->label[i].autorise_export) { if (ae->export_multisym) { if (ae->symbol_name) { sprintf(TMP_filename,"%s.bank%d",ae->symbol_name,ae->label[i].ibank); } else { sprintf(TMP_filename,"%s.sym.bank%d",ae->outputfilename,ae->label[i].ibank); } } if (!ae->label[i].name) { sprintf(symbol_line,"%s #%X B%d\n",ae->wl[ae->label[i].iw].w,ae->label[i].ptr,ae->label[i].ibank>31?0:ae->label[i].ibank); FileWriteLine(TMP_filename,symbol_line); } else { if (ae->export_local) { sprintf(symbol_line,"%s #%X B%d\n",ae->label[i].name,ae->label[i].ptr,ae->label[i].ibank>31?0:ae->label[i].ibank); FileWriteLine(TMP_filename,symbol_line); } } } } MAKE_SYMBOL_NAME if (ae->export_var) { /* var are part of fast tree search structure */ ExportDicoTree(ae,TMP_filename,"%s #%X B0\n"); } if (ae->export_equ) { for (i=0;iialias;i++) { if (strcmp(ae->alias[i].alias,"IX") && strcmp(ae->alias[i].alias,"IY") && ae->alias[i].autorise_export) { sprintf(symbol_line,"%s #%X B0\n",ae->alias[i].alias,RoundComputeExpression(ae,ae->alias[i].translation,0,-ae->alias[i].iw,0)); FileWriteLine(TMP_filename,symbol_line); } } } FileWriteLineClose(TMP_filename); break; case 0: default:break; } MemFree(SymbolFileName); } /********************************* ********************************** B R E A K P O I N T S ********************************** *********************************/ if (ae->export_brk) { struct s_breakpoint breakpoint={0}; if (ae->breakpoint_name) { sprintf(TMP_filename,"%s",ae->breakpoint_name); } else { sprintf(TMP_filename,"%s.brk",ae->outputfilename); } FileRemoveIfExists(TMP_filename); /* add labels and local labels to breakpoint pool (if any) */ for (i=0;iil;i++) { if (!ae->label[i].name) { if (strncmp(ae->wl[ae->label[i].iw].w,"BRK",3)==0) { breakpoint.address=ae->label[i].ptr; if (ae->label[i].ibank>3) breakpoint.bank=1; else breakpoint.bank=0; ObjectArrayAddDynamicValueConcat((void **)&ae->breakpoint,&ae->ibreakpoint,&ae->maxbreakpoint,&breakpoint,sizeof(struct s_breakpoint)); } } else { if (strncmp(ae->label[i].name,"@BRK",4)==0) { breakpoint.address=ae->label[i].ptr; if (ae->label[i].ibank>3) breakpoint.bank=1; else breakpoint.bank=0; ObjectArrayAddDynamicValueConcat((void **)&ae->breakpoint,&ae->ibreakpoint,&ae->maxbreakpoint,&breakpoint,sizeof(struct s_breakpoint)); } } } if (ae->ibreakpoint) { rasm_printf(ae,KIO"Write breakpoint file %s\n",TMP_filename); for (i=0;iibreakpoint;i++) { sprintf(symbol_line,"#%04X\n",ae->breakpoint[i].address); FileWriteLine(TMP_filename,symbol_line); } FileWriteLineClose(TMP_filename); } else { if (!ae->nowarning) rasm_printf(ae,KWARNING"Warning: no breakpoint to output (previous file [%s] deleted anyway)\n",TMP_filename); } } } else { if (!ae->dependencies) rasm_printf(ae,KERROR"%d error%s\n",ae->nberr,ae->nberr>1?"s":""); } #if TRACE_ASSEMBLE printf("dependencies\n"); #endif /******************************************************************************************* E X P O R T D E P E N D E N C I E S *******************************************************************************************/ if (ae->dependencies) { int trigdep=0; /* depends ALL */ if (ae->outputfilename && strcmp(ae->outputfilename,"rasmoutput")) { trigdep=1; printf("%s",ae->outputfilename); if (ae->dependencies==E_DEPENDENCIES_MAKE) printf(" "); else printf("\n"); } for (i=1;iifile;i++) { trigdep=1; SimplifyPath(ae->filename[i]); printf("%s",ae->filename[i]); if (ae->dependencies==E_DEPENDENCIES_MAKE) printf(" "); else printf("\n"); } for (i=0;iih;i++) { trigdep=1; SimplifyPath(ae->hexbin[i].filename); printf("%s",ae->hexbin[i].filename); if (ae->dependencies==E_DEPENDENCIES_MAKE) printf(" "); else printf("\n"); } if (ae->dependencies==E_DEPENDENCIES_MAKE && trigdep) printf("\n"); } /******************************************************************************************* V E R B O S E S H I T *******************************************************************************************/ #if TRACE_ASSEMBLE rasm_printf(ae,KVERBOSE"------ statistics ------------------\n"); rasm_printf(ae,KVERBOSE"%d file%s\n",ae->ifile,ae->ifile>1?"s":""); rasm_printf(ae,KVERBOSE"%d binary include%s\n",ae->ih,ae->ih>1?"s":""); rasm_printf(ae,KVERBOSE"%d word%s\n",ae->nbword-1,ae->nbword>2?"s":""); rasm_printf(ae,KVERBOSE"%d label%s\n",ae->il,ae->il>1?"s":""); rasm_printf(ae,KVERBOSE"%d struct%s\n",ae->irasmstruct,ae->irasmstruct>1?"s":""); rasm_printf(ae,KVERBOSE"%d var%s\n",ae->idic,ae->idic>1?"s":""); rasm_printf(ae,KVERBOSE"%d expression%s\n",ae->ie,ae->ie>1?"s":""); rasm_printf(ae,KVERBOSE"%d macro%s\n",ae->imacro,ae->imacro>1?"s":""); rasm_printf(ae,KVERBOSE"%d alias%s\n",ae->ialias,ae->ialias>1?"s":""); rasm_printf(ae,KVERBOSE"%d ORG zone%s\n",ae->io-1,ae->io>2?"s":""); rasm_printf(ae,KVERBOSE"%d virtual space%s\n",ae->nbbank,ae->nbbank>1?"s":""); #endif /******************************************************************************************* C L E A N U P *******************************************************************************************/ #if TRACE_ASSEMBLE printf("cleanup\n"); #endif #if TRACE_GENERALE printf("-cleanup\n"); #endif if (TMP_filename) MemFree(TMP_filename); if (ae->nberr) { ok=-1; if (ae->flux && *dataout) { MemFree(*dataout); *dataout=NULL; } if (lenout) *lenout=0; } else { ok=0; } FreeAssenv(ae); #if TRACE_ASSEMBLE printf("end of assembling\n"); #endif #if TRACE_GENERALE printf("-end ok=%d\n",ok); #endif return ok; } void EarlyPrepSrc(struct s_assenv *ae, char **listing, char *filename) { int l,idx,c,quote_type=0; int mlc_start,mlc_idx; /* virer les commentaires en ;, // mais aussi multi-lignes et convertir les decalages, passer les chars en upper case */ l=idx=0; while (listing[l]) { c=listing[l][idx++]; if (!c) { l++; idx=0; continue; } else if (!quote_type) { /* upper case */ if (c>='a' && c<='z') { listing[l][idx-1]=c=c-'a'+'A'; } if (c=='\'' && idx>2 && strncmp(&listing[l][idx-3],"AF'",3)==0) { /* il ne faut rien faire */ } else if (c=='"' || c=='\'') { quote_type=c; } else if (c==';' || (c=='/' && listing[l][idx]=='/')) { idx--; while (listing[l][idx] && listing[l][idx]!=0x0D && listing[l][idx]!=0x0A) listing[l][idx++]=':'; idx--; } else if (c=='>' && listing[l][idx]=='>' && !quote_type) { listing[l][idx-1]=']'; listing[l][idx++]=' '; continue; } else if (c=='<' && listing[l][idx]=='<' && !quote_type) { listing[l][idx-1]='['; listing[l][idx++]=' '; continue; } else if (c=='/' && listing[l][idx]=='*' && !quote_type) { /* multi-line comment */ mlc_start=l; mlc_idx=idx-1; idx++; while (1) { c=listing[l][idx++]; if (!c) { idx=0; l++; if (!listing[l]) { MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"opened comment to the end of the file\n",filename,l+1); return; } } else if (c=='*' && listing[l][idx]=='/') { idx++; break; } } /* merge */ if (mlc_start==l) { /* on the same line */ while (mlc_idx=*ml) { *il=*ml=*il+nbinsert; *reflisting=MemRealloc(*reflisting,sizeof(struct s_listing)*(*ml)); } else { *il=*il+nbinsert; } listing=*reflisting; MemMove(&listing[idx+1+nbinsert],&listing[idx+1],(bil-idx-1)*sizeof(struct s_listing)); for (li=0;zelines[li];li++) { listing[idx+1+li].ifile=ifile; listing[idx+1+li].iline=li+1; listing[idx+1+li].listing=zelines[li]; } } int cmpkeyword(const void * a, const void * b) { struct s_asm_keyword *sa,*sb; sa=(struct s_asm_keyword *)a; sb=(struct s_asm_keyword *)b; return strcmp(sa->mnemo,sb->mnemo); } struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int datalen, struct s_parameter *param) { #undef FUNC #define FUNC "PreProcessing" #define CharWord "@ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.=_($)][+-*/^%#|&'\"\\m}{[]" struct s_assenv *ae=NULL; struct s_wordlist curw={0}; struct s_wordlist *wordlist=NULL; int nbword=0,maxword=0; char **zelines=NULL; char *filename_toread; struct s_macro_fast *MacroFast=NULL; int idxmacrofast=0,maxmacrofast=0; struct s_listing *listing=NULL; struct s_listing curlisting; int ilisting=0,maxlisting=0; char **listing_include=NULL; int i,j,l=0,idx=0,c=0,li,le; char Automate[256]={0}; struct s_hexbin curhexbin; char *newlistingline=NULL; unsigned char *newdata; struct s_label curlabel={0}; char *labelsep1; char **labelines=NULL; /* state machine buffer */ unsigned char *mem=NULL; char *w=NULL,*wtmp=NULL; int lw=0,mw=256; char *bval=NULL; int ival=0,sval=256; char *qval=NULL; int iqval=0,sqval=256; struct s_repeat_index *TABrindex=NULL; struct s_repeat_index *TABwindex=NULL; struct s_repeat_index rindex={0}; struct s_repeat_index windex={0}; int nri=0,mri=0,ri=0; int nwi=0,mwi=0,wi=0; /* state machine trigger */ int waiting_quote=0,lquote; int macro_trigger=0; int escape_code=0; int quote_type=0; int incbin=0,include=0,crunch=0; int rewrite=0,hadcomma=0; int nbinstruction; int ifast,texpr; int ispace=0; #if TRACE_GENERALE printf("*** preprocessing ***\n"); #endif #if TRACE_PREPRO printf("start prepro, alloc assenv\n"); #endif windex.cl=-1; windex.cidx=-1; rindex.cl=-1; rindex.cidx=-1; #if TRACE_PREPRO printf("malloc\n"); #endif ae=MemMalloc(sizeof(struct s_assenv)); #if TRACE_PREPRO printf("memset\n"); #endif memset(ae,0,sizeof(struct s_assenv)); #if TRACE_PREPRO printf("paramz 1\n"); #endif if (param) { ae->export_local=param->export_local; ae->export_sym=param->export_sym; ae->export_var=param->export_var; ae->export_equ=param->export_equ; ae->export_sna=param->export_sna; ae->export_snabrk=param->export_snabrk; if (param->export_sna || param->export_snabrk) { ae->forcesnapshot=1; } ae->export_brk=param->export_brk; ae->warn_unused=param->warn_unused; ae->edskoverwrite=param->edskoverwrite; ae->rough=param->rough; ae->as80=param->as80; ae->dams=param->dams; ae->macrovoid=param->macrovoid; if (param->v2) { ae->forcesnapshot=1; ae->snapshot.version=2; } else { ae->snapshot.version=3; } ae->maxerr=param->maxerr; ae->extended_error=param->extended_error; ae->nowarning=param->nowarning; ae->breakpoint_name=param->breakpoint_name; ae->symbol_name=param->symbol_name; ae->binary_name=param->binary_name; ae->flexible_export=param->flexible_export; ae->cartridge_name=param->cartridge_name; ae->snapshot_name=param->snapshot_name; ae->checkmode=param->checkmode; if (param->rough) ae->maxam=0; else ae->maxam=1; /* additional symbols */ for (i=0;insymb;i++) { char *sep; sep=strchr(param->symboldef[i],'='); if (sep) { *sep=0; ExpressionSetDicoVar(ae,param->symboldef[i],atof(sep+1)); } } if (param->msymb) { MemFree(param->symboldef); param->nsymb=param->msymb=0; } /* include paths */ ae->includepath=param->pathdef; ae->ipath=param->npath; ae->mpath=param->mpath; /* old inline params */ ae->dependencies=param->dependencies; } #if TRACE_PREPRO printf("init 0\n"); #endif #if TRACE_GENERALE printf("-init\n"); #endif /* generic init */ ae->ctx1.maxivar=1; ae->ctx2.maxivar=1; ae->computectx=&ae->ctx1; ae->flux=flux; /* check snapshot structure */ if (sizeof(ae->snapshot)!=0x100 || &ae->snapshot.fdd.motorstate-(unsigned char*)&ae->snapshot!=0x9C || &ae->snapshot.crtcstate.model-(unsigned char*)&ae->snapshot!=0xA4 || &ae->snapshot.romselect-(unsigned char*)&ae->snapshot!=0x55 || &ae->snapshot.interruptrequestflag-(unsigned char*)&ae->snapshot!=0xB4 || &ae->snapshot.CPCType-(unsigned char*)&ae->snapshot!=0x6D) { rasm_printf(ae,"snapshot structure integrity check KO\n"); exit(349); } for (i=0;i<4;i++) { ae->bankgate[i]=0x7FC0; /* video memory has no paging */ ae->setgate[i]=0x7FC0; /* video memory has no paging */ } for (i=0;i<256;i++) { /* 4M expansion support on lower gate array port */ ae->bankgate[i+4]=0x7FC4+(i&3)+((i&31)>>2)*8-0x100*(i>>5); ae->setgate[i+4] =0x7FC2 +((i&31)>>2)*8-0x100*(i>>5); //printf("%04X %04X\n",ae->bankgate[i+4],ae->setgate[i+4]); } memcpy(ae->snapshot.idmark,"MV - SNA",8); ae->snapshot.registers.IM=1; ae->snapshot.gatearray.palette[0]=0x04; ae->snapshot.gatearray.palette[1]=0x0A; ae->snapshot.gatearray.palette[2]=0x15; ae->snapshot.gatearray.palette[3]=0x1C; ae->snapshot.gatearray.palette[4]=0x18; ae->snapshot.gatearray.palette[5]=0x1D; ae->snapshot.gatearray.palette[6]=0x0C; ae->snapshot.gatearray.palette[7]=0x05; ae->snapshot.gatearray.palette[8]=0x0D; ae->snapshot.gatearray.palette[9]=0x16; ae->snapshot.gatearray.palette[10]=0x06; ae->snapshot.gatearray.palette[11]=0x17; ae->snapshot.gatearray.palette[12]=0x1E; ae->snapshot.gatearray.palette[13]=0x00; ae->snapshot.gatearray.palette[14]=0x1F; ae->snapshot.gatearray.palette[15]=0x0E; ae->snapshot.gatearray.palette[16]=0x04; ae->snapshot.gatearray.multiconfiguration=0x8D; // lower/upper ROM off + mode 1 ae->snapshot.CPCType=2; /* 6128 */ ae->snapshot.crtcstate.model=0; /* CRTC 0 */ ae->snapshot.vsyncdelay=2; strcpy((char *)ae->snapshot.unused6+3+0x20+8,RASM_VERSION); /* CRTC default registers */ ae->snapshot.crtc.registervalue[0]=0x3F; ae->snapshot.crtc.registervalue[1]=40; ae->snapshot.crtc.registervalue[2]=46; ae->snapshot.crtc.registervalue[3]=0x8E; ae->snapshot.crtc.registervalue[4]=38; ae->snapshot.crtc.registervalue[6]=25; ae->snapshot.crtc.registervalue[7]=30; ae->snapshot.crtc.registervalue[9]=7; ae->snapshot.crtc.registervalue[12]=0x30; ae->snapshot.psg.registervalue[7]=0x3F; /* audio mix all channels OFF */ /* PPI Init */ ae->snapshot.ppi.control=0x82; /* standard stack */ ae->snapshot.registers.HSP=0xC0; /* winape sprintf(symbol_line,"%s #%4X\n",ae->label[i].name,ae->label[i].ptr); pasmo sprintf(symbol_line,"%s EQU 0%4XH\n",ae->label[i].name,ae->label[i].ptr); rasm sprintf(symbol_line,"%s #%X B%d\n",ae->wl[ae->label[i].iw].w,ae->label[i].ptr,ae->label[i].ibank>31?0:ae->label[i].ibank); */ #if TRACE_PREPRO printf("paramz\n"); #endif if (param && param->labelfilename) { for (j=0;param->labelfilename[j] && param->labelfilename[j][0];j++) { rasm_printf(ae,"Label import from [%s]\n",param->labelfilename[j]); ae->label_filename=param->labelfilename[j]; ae->label_line=1; labelines=FileReadLines(param->labelfilename[j]); i=0; while (labelines[i]) { /* upper case */ for (j=0;labelines[i][j];j++) labelines[i][j]=toupper(labelines[i][j]); if ((labelsep1=strstr(labelines[i],": EQU 0"))!=NULL) { /* sjasm */ *labelsep1=0; curlabel.name=labelines[i]; curlabel.iw=-1; curlabel.crc=GetCRC(curlabel.name); curlabel.ptr=strtol(labelsep1+6,NULL,16); PushLabelLight(ae,&curlabel); } else if ((labelsep1=strstr(labelines[i]," EQU 0"))!=NULL) { /* pasmo */ *labelsep1=0; curlabel.name=labelines[i]; curlabel.iw=-1; curlabel.crc=GetCRC(curlabel.name); curlabel.ptr=strtol(labelsep1+6,NULL,16); //ObjectArrayAddDynamicValueConcat((void **)&ae->label,&ae->il,&ae->ml,&curlabel,sizeof(curlabel)); PushLabelLight(ae,&curlabel); } else if ((labelsep1=strstr(labelines[i]," "))!=NULL) { /* winape / rasm */ if (*(labelsep1+1)=='#') { *labelsep1=0; curlabel.name=labelines[i]; curlabel.iw=-1; curlabel.crc=GetCRC(curlabel.name); curlabel.ptr=strtol(labelsep1+2,NULL,16); //ObjectArrayAddDynamicValueConcat((void **)&ae->label,&ae->il,&ae->ml,&curlabel,sizeof(curlabel)); PushLabelLight(ae,&curlabel); } } i++; ae->label_line++; } MemFree(labelines); } ae->label_filename=NULL; ae->label_line=0; } #if TRACE_PREPRO printf("init 3\n"); #endif /* 32 CPR default roms but 260+ max snapshot RAM pages + one workspace */ for (i=0;imem,&ae->nbbank,&ae->maxbank,&mem,sizeof(mem)); } #if TRACE_PREPRO printf("nbbank=%d initialised\n",ae->nbbank); #endif ae->activebank=BANK_MAX_NUMBER; ae->maxptr=65536; for (i=0;i<256;i++) { ae->charset[i]=(unsigned char)i; } if (param && param->outputfilename) { ae->outputfilename=TxtStrDup(param->outputfilename); } else if (param && param->automatic_radix && param->filename) { int rilook; rilook=strlen(param->filename); ae->outputfilename=TxtStrDup(param->filename); /* look for extension */ while (rilook && ae->outputfilename[rilook]!='.') { /* end of scan with directory reference or nothing found */ if (ae->outputfilename[rilook]=='/' || ae->outputfilename[rilook]=='\\') rilook=0; else rilook--; } if (ae->outputfilename[rilook]=='.') { ae->outputfilename[rilook]=0; } } else { ae->outputfilename=TxtStrDup("rasmoutput"); } /* si on est en ligne de commande ET que le fichier n'est pas trouvé */ if (param && param->filename && !FileExists(param->filename)) { char *LTryExtension[]={".asm",".z80",".o",".dam",".mxm",".txt", ".ASM",".Z80",".O",".DAM",".MXM",".TXT",NULL}; int iguess=1; l=strlen(param->filename); filename=MemRealloc(param->filename,l+6); /* si le nom du fichier termine par un . on n'ajoute que l'extension, sinon on l'ajoute avec le . */ if (param->filename[l-1]=='.') strcat(param->filename,"asm"); else strcat(param->filename,".asm"); while (!FileExists(param->filename) && LTryExtension[iguess]!=NULL) { TxtReplace(param->filename,LTryExtension[iguess-1],LTryExtension[iguess],0); /* no realloc with this */ if (!FileExists(param->filename)) { param->filename[l]=0; } iguess++; } } if (param && param->filename && !FileExists(param->filename)) { rasm_printf(ae,"Cannot find file [%s]\n",param->filename); exit(-1802); } if (param) rasm_printf(ae,KAYGREEN"Pre-processing [%s]\n",param->filename); for (nbinstruction=0;instruction[nbinstruction].mnemo[0];nbinstruction++); qsort(instruction,nbinstruction,sizeof(struct s_asm_keyword),cmpkeyword); for (i=0;i<256;i++) { ae->fastmatch[i]=-1; } for (i=0;ifastmatch[(int)instruction[i].mnemo[0]]==-1) ae->fastmatch[(int)instruction[i].mnemo[0]]=i; } for (i=0;CharWord[i];i++) {Automate[((int)CharWord[i])&0xFF]=1;} /* separators */ Automate[' ']=2; Automate[',']=2; Automate['\t']=2; /* end of line */ Automate[':']=3; /* les 0x0A et 0x0D seront deja  remplaces en ':' */ /* expression */ Automate['=']=4; /* on stocke l'emplacement de l'egalite */ Automate['<']=4; /* ou des operateurs */ Automate['>']=4; /* d'evaluation */ Automate['!']=4; StateMachineResizeBuffer(&w,256,&mw); StateMachineResizeBuffer(&bval,256,&sval); StateMachineResizeBuffer(&qval,256,&sqval); w[0]=0; bval[0]=0; qval[0]=0; #if TRACE_PREPRO printf("read file/flux\n"); #endif #if TRACE_GENERALE printf("-read/flux\n"); #endif if (!ae->flux) { zelines=FileReadLines(filename); FieldArrayAddDynamicValueConcat(&ae->filename,&ae->ifile,&ae->maxfile,filename); } else { int flux_nblines=0; int flux_curpos; /* copie des données */ for (i=0;iflux_curpos) { zelines[flux_nblines]=MemMalloc(i-flux_curpos+1); memcpy(zelines[flux_nblines],datain+flux_curpos,i-flux_curpos); zelines[flux_nblines][i-flux_curpos]=0; flux_nblines++; } /* terminator */ zelines[flux_nblines]=NULL; /* en mode flux on prend le repertoire courant en reference */ FieldArrayAddDynamicValueConcat(&ae->filename,&ae->ifile,&ae->maxfile,CURRENT_DIR); } #if TRACE_PREPRO printf("remove comz, do includes\n"); #endif #if TRACE_GENERALE printf("-comz/include\n"); #endif EarlyPrepSrc(ae,zelines,ae->filename[ae->ifile-1]); for (i=0;zelines[i];i++) { curlisting.ifile=0; curlisting.iline=i+1; curlisting.listing=zelines[i]; ObjectArrayAddDynamicValueConcat((void**)&listing,&ilisting,&maxlisting,&curlisting,sizeof(curlisting)); } MemFree(zelines); /* on s'assure que la derniere instruction est prise en compte a peu de frais */ if (ilisting) { datalen=strlen(listing[ilisting-1].listing); listing[ilisting-1].listing=MemRealloc(listing[ilisting-1].listing,datalen+2); listing[ilisting-1].listing[datalen]=':'; listing[ilisting-1].listing[datalen+1]=0; } waiting_quote=quote_type=0; l=idx=0; while (l2 && strncmp(&listing[l].listing[idx-3],"AF'",3)==0) { /* rien */ } else if (c=='"' || c=='\'') { if (!quote_type) { quote_type=c; lquote=l; } else { if (c==quote_type) { quote_type=0; } } } if (waiting_quote) { /* expecting quote and nothing else */ switch (waiting_quote) { case 1: if (c==quote_type) waiting_quote=2; break; case 2: if (!quote_type) { waiting_quote=3; qval[iqval]=0; } else { qval[iqval++]=c; StateMachineResizeBuffer(&qval,iqval,&sqval); qval[iqval]=0; } } if (waiting_quote==3) { if (incbin) { int fileok=0,ilookfile; /* qval contient le nom du fichier a lire */ filename_toread=MergePath(ae,ae->filename[listing[l].ifile],qval); if (FileExists(filename_toread)) { fileok=1; } else { for (ilookfile=0;ilookfileipath && !fileok;ilookfile++) { filename_toread=MergePath(ae,ae->includepath[ilookfile],qval); if (FileExists(filename_toread)) { fileok=1; } } } curhexbin.filename=TxtStrDup(filename_toread); curhexbin.crunch=crunch; if (fileok) { /* lecture */ curhexbin.rawlen=curhexbin.datalen=FileGetSize(filename_toread); curhexbin.data=MemMalloc(curhexbin.datalen*1.3+10); #if TRACE_PREPRO switch (crunch) { case 0:rasm_printf(ae,KBLUE"incbin [%s] size=%d\n",filename_toread,curhexbin.datalen);break; case 4:rasm_printf(ae,KBLUE"inclz4 [%s] size=%d\n",filename_toread,curhexbin.datalen);break; case 7:rasm_printf(ae,KBLUE"incsx7 [%s] size=%d\n",filename_toread,curhexbin.datalen);break; case 8:rasm_printf(ae,KBLUE"incexo [%s] size=%d\n",filename_toread,curhexbin.datalen);break; case 88:rasm_printf(ae,KBLUE"incexb [%s] size=%d\n",filename_toread,curhexbin.datalen);break; case 48:rasm_printf(ae,KBLUE"incl48 [%s] size=%d\n",filename_toread,curhexbin.datalen);break; case 49:rasm_printf(ae,KBLUE"incl49 [%s] size=%d\n",filename_toread,curhexbin.datalen);break; default:rasm_printf(ae,KBLUE"invalid crunch state!\n");exit(-42); } #endif if (FileReadBinary(filename_toread,(char*)curhexbin.data,curhexbin.datalen)!=curhexbin.datalen) { rasm_printf(ae,"read error on %s",filename_toread); exit(2); } FileReadBinaryClose(filename_toread); switch (crunch) { #ifndef NO_3RD_PARTIES case 4: newdata=LZ4_crunch(curhexbin.data,curhexbin.datalen,&curhexbin.datalen); MemFree(curhexbin.data); curhexbin.data=newdata; #if TRACE_PREPRO rasm_printf(ae,KVERBOSE"crunched with LZ4 into %d byte(s)\n",curhexbin.datalen); #endif break; case 7: { size_t slzlen; newdata=ZX7_compress(optimize(curhexbin.data, curhexbin.datalen), curhexbin.data, curhexbin.datalen, &slzlen); curhexbin.datalen=slzlen; MemFree(curhexbin.data); curhexbin.data=newdata; #if TRACE_PREPRO rasm_printf(ae,KVERBOSE"crunched with ZX7 into %d byte(s)\n",curhexbin.datalen); #endif } break; case 8: rasm_printf(ae,KWARNING"Exomizer is crunching %.1fkb this may take a while, be patient...\n",curhexbin.datalen/1024.0); newdata=Exomizer_crunch(curhexbin.data,curhexbin.datalen,&curhexbin.datalen); MemFree(curhexbin.data); curhexbin.data=newdata; #if TRACE_PREPRO rasm_printf(ae,KVERBOSE"crunched with Exomizer into %d byte(s)\n",curhexbin.datalen); #endif break; #endif case 48: newdata=LZ48_crunch(curhexbin.data,curhexbin.datalen,&curhexbin.datalen); MemFree(curhexbin.data); curhexbin.data=newdata; #if TRACE_PREPRO rasm_printf(ae,KVERBOSE"crunched with LZ48 into %d byte(s)\n",curhexbin.datalen); #endif break; case 49: newdata=LZ49_crunch(curhexbin.data,curhexbin.datalen,&curhexbin.datalen); MemFree(curhexbin.data); curhexbin.data=newdata; #if TRACE_PREPRO rasm_printf(ae,KVERBOSE"crunched into with LZ49 %d byte(s)\n",curhexbin.datalen); #endif break; default:break; } } else { /* TAG + info */ curhexbin.datalen=-1; curhexbin.data=MemMalloc(2); /* not yet an error, we will know later when executing the code */ } ObjectArrayAddDynamicValueConcat((void**)&ae->hexbin,&ae->ih,&ae->mh,&curhexbin,sizeof(curhexbin)); /* insertion */ le=strlen(listing[l].listing); newlistingline=MemMalloc(le+32); memcpy(newlistingline,listing[l].listing,rewrite); rewrite+=sprintf(newlistingline+rewrite,"HEXBIN #%X",ae->ih-1); strcat(newlistingline+rewrite,listing[l].listing+idx); idx=rewrite; MemFree(listing[l].listing); listing[l].listing=newlistingline; incbin=0; } else if (include) { /* qval contient le nom du fichier a lire */ int fileok=0,ilookfile; /* qval contient le nom du fichier a lire */ filename_toread=MergePath(ae,ae->filename[listing[l].ifile],qval); if (FileExists(filename_toread)) { fileok=1; } else { for (ilookfile=0;ilookfileipath && !fileok;ilookfile++) { filename_toread=MergePath(ae,ae->includepath[ilookfile],qval); if (FileExists(filename_toread)) { fileok=1; } } } if (fileok) { int newi,newj; #if TRACE_PREPRO rasm_printf(ae,KBLUE"include [%s]\n",filename_toread); #endif /* lecture */ listing_include=FileReadLines(filename_toread); FieldArrayAddDynamicValueConcat(&ae->filename,&ae->ifile,&ae->maxfile,filename_toread); /* virer les commentaires + pré-traitement */ EarlyPrepSrc(ae,listing_include,ae->filename[ae->ifile-1]); /* split de la ligne en cours + suppression de l'instruction include */ PreProcessingSplitListing(&listing,&ilisting,&maxlisting,l,rewrite,idx); /* insertion des nouvelles lignes + reference fichier + numeros de ligne */ PreProcessingInsertListing(&listing,&ilisting,&maxlisting,l,listing_include,ae->ifile-1); MemFree(listing_include); /* free le tableau mais pas les lignes */ listing_include=NULL; idx=0; /* on reste sur la meme ligne mais on se prepare a relire du caractere 0! */ } else { /* TAG + info */ curhexbin.filename=TxtStrDup(filename_toread); curhexbin.datalen=-2; curhexbin.data=MemMalloc(2); /* not yet an error, we will know later when executing the code */ ObjectArrayAddDynamicValueConcat((void**)&ae->hexbin,&ae->ih,&ae->mh,&curhexbin,sizeof(curhexbin)); /* insertion */ le=strlen(listing[l].listing); newlistingline=MemMalloc(le+32); memcpy(newlistingline,listing[l].listing,rewrite); rewrite+=sprintf(newlistingline+rewrite,"HEXBIN #%X",ae->ih-1); strcat(newlistingline+rewrite,listing[l].listing+idx); idx=rewrite; MemFree(listing[l].listing); listing[l].listing=newlistingline; } include=0; } waiting_quote=0; qval[0]=0; iqval=0; } } else { /* classic behaviour */ /* looking for include/incbin */ if (((c>='A' && c<='Z') || (c>='0' && c<='9') || c=='@' || c=='_')&& !quote_type) { bval[ival++]=c; StateMachineResizeBuffer(&bval,ival,&sval); bval[ival]=0; } else { if (strcmp(bval,"INCLUDE")==0) { include=1; waiting_quote=1; rewrite=idx-7-1; /* quote right after keyword */ if (c==quote_type) { waiting_quote=2; } } else if (strcmp(bval,"READ")==0) { include=1; waiting_quote=1; rewrite=idx-4-1; /* quote right after keyword */ if (c==quote_type) { waiting_quote=2; } } else if (strcmp(bval,"INCLZ4")==0) { incbin=1; crunch=4; waiting_quote=1; rewrite=idx-6-1; /* quote right after keyword */ if (c==quote_type) { waiting_quote=2; } } else if (strcmp(bval,"INCEXB")==0) { incbin=1; crunch=88; waiting_quote=1; rewrite=idx-6-1; /* quote right after keyword */ if (c==quote_type) { waiting_quote=2; } } else if (strcmp(bval,"INCEXO")==0) { incbin=1; crunch=8; waiting_quote=1; rewrite=idx-6-1; /* quote right after keyword */ if (c==quote_type) { waiting_quote=2; } } else if (strcmp(bval,"INCZX7")==0) { incbin=1; crunch=7; waiting_quote=1; rewrite=idx-6-1; /* quote right after keyword */ if (c==quote_type) { waiting_quote=2; } } else if (strcmp(bval,"INCL48")==0) { incbin=1; crunch=48; waiting_quote=1; rewrite=idx-6-1; /* quote right after keyword */ if (c==quote_type) { waiting_quote=2; } } else if (strcmp(bval,"INCL49")==0) { incbin=1; crunch=49; waiting_quote=1; rewrite=idx-6-1; /* quote right after keyword */ if (c==quote_type) { waiting_quote=2; } } else if (strcmp(bval,"INCBIN")==0) { incbin=1; crunch=0; waiting_quote=1; rewrite=idx-6-1; /* quote right after keyword */ if (c==quote_type) { waiting_quote=2; } } else if (strcmp(bval,"INCWAV")==0) { incbin=1; crunch=0; waiting_quote=1; rewrite=idx-6-1; /* quote right after keyword */ if (c==quote_type) { waiting_quote=2; } } else if (strcmp(bval,"WHILE")==0) { /* remplir la structure repeat_index */ windex.ol=listing[l].iline; windex.oidx=idx; windex.ifile=ae->ifile-1; ObjectArrayAddDynamicValueConcat((void**)&TABwindex,&nwi,&mwi,&windex,sizeof(windex)); } else if (strcmp(bval,"REPEAT")==0) { /* remplir la structure repeat_index */ rindex.ol=listing[l].iline; rindex.oidx=idx; rindex.ifile=ae->ifile-1; ObjectArrayAddDynamicValueConcat((void**)&TABrindex,&nri,&mri,&rindex,sizeof(rindex)); } else if (strcmp(bval,"WEND")==0) { /* retrouver la structure repeat_index correspondant a l'ouverture */ for (wi=nwi-1;wi>=0;wi--) { if (TABwindex[wi].cl==-1) { TABwindex[wi].cl=c; TABwindex[wi].cidx=idx; break; } } if (wi==-1) { MakeError(ae,ae->filename[listing[l].ifile],listing[l].iline,"WEND refers to unknown WHILE\n"); //exit(1); } } else if (strcmp(bval,"REND")==0 || strcmp(bval,"UNTIL")==0) { /* retrouver la structure repeat_index correspondant a l'ouverture */ for (ri=nri-1;ri>=0;ri--) { if (TABrindex[ri].cl==-1) { TABrindex[ri].cl=c; TABrindex[ri].cidx=idx; break; } } if (ri==-1) { MakeError(ae,ae->filename[listing[l].ifile],listing[l].iline,"%s refers to unknown REPEAT\n",bval); //exit(1); } } bval[0]=0; ival=0; } } } #if TRACE_PREPRO printf("check quotes and repeats\n"); #endif if (quote_type) { MakeError(ae,ae->filename[listing[lquote].ifile],listing[lquote].iline,"quote opened was not closed\n"); //exit(1); } /* repeat expansion check */ for (ri=0;rifilename[TABrindex[ri].ifile],TABrindex[ri].ol,"REPEAT was not closed\n"); } } /* creer une liste de mots */ curw.w=TxtStrDup("BEGIN"); curw.l=0; curw.ifile=0; curw.t=1; curw.e=0; ObjectArrayAddDynamicValueConcat((void**)&wordlist,&nbword,&maxword,&curw,sizeof(curw)); /* pour les calculs d'adresses avec IX et IY on enregistre deux variables bidons du meme nom */ curw.e=2; curw.w=TxtStrDup("IX~0"); ObjectArrayAddDynamicValueConcat((void**)&wordlist,&nbword,&maxword,&curw,sizeof(curw)); curw.w=TxtStrDup("IY~0"); ObjectArrayAddDynamicValueConcat((void**)&wordlist,&nbword,&maxword,&curw,sizeof(curw)); curw.e=0; #if TRACE_PREPRO l=0; while (l31?c:'.',Automate[((int)c)&0xFF]); #endif switch (Automate[((int)c)&0xFF]) { case 0: MakeError(ae,ae->filename[listing[l].ifile],listing[l].iline,"invalid char '%c' (%d) char %d\n",c,c,idx); #if TRACE_PREPRO printf("c='%c' automate[c]=%d\n",c>31?c:'.',Automate[((int)c)&0xFF]); #endif exit(0); break; case 1: if (c=='\'' && idx>2 && strncmp(&listing[l].listing[idx-3],"AF'",3)==0) { w[lw++]=c; StateMachineResizeBuffer(&w,lw,&mw); w[lw]=0; break; } else if (c=='\'' || c=='"') { quote_type=c; /* debut d'une quote, on finalise le mot -> POURQUOI DONC? */ //idx--; #if TRACE_PREPRO printf("quote\n"); #endif /* on finalise le mot si on est en début d'une nouvelle instruction ET que c'est un SAVE */ if (strcmp(w,"SAVE")==0) { idx--; } else { w[lw++]=c; StateMachineResizeBuffer(&w,lw,&mw); w[lw]=0; break; } } else { if (c!=' ' && c!='\t') { w[lw++]=c; StateMachineResizeBuffer(&w,lw,&mw); w[lw]=0; } else { /* Winape/Maxam operator compatibility on expressions */ #if TRACE_PREPRO printf("1/2 winape maxam operator test for [%s]\n",w+ispace); #endif if (texpr) { if (strcmp(w+ispace,"AND")==0) { w[ispace]='&'; lw=ispace+1; } else if (strcmp(w+ispace,"OR")==0) { #if TRACE_PREPRO printf("conversion OR vers |\n"); #endif w[ispace]='|'; lw=ispace+1; } else if (strcmp(w+ispace,"MOD")==0) { w[ispace]='m'; lw=ispace+1; } else if (strcmp(w+ispace,"XOR")==0) { w[ispace]='^'; lw=ispace+1; } else if (strcmp(w+ispace,"%")==0) { w[ispace]='m'; lw=ispace+1; } } ispace=lw; } break; } case 2: /* separator (space, tab, comma) */ #if TRACE_PREPRO printf("*** separator='%c'\n",c); #endif /* patch argument suit une expression d'évaluation (ASSERT) */ if (c==',') hadcomma=1; if (lw) { w[lw]=0; if (texpr && !wordlist[nbword-1].t && wordlist[nbword-1].e && !hadcomma) { /* pour compatibilite winape avec AND,OR,XOR */ #if TRACE_PREPRO printf("2/2 winape maxam operator test for expression [%s]\n",w+ispace); #endif if (strcmp(w,"AND")==0) { wtmp=TxtStrDup("&"); } else if (strcmp(w,"OR")==0) { wtmp=TxtStrDup("|"); } else if (strcmp(w,"XOR")==0) { wtmp=TxtStrDup("^"); } else if (strcmp(w,"%")==0) { wtmp=TxtStrDup("m"); } else { wtmp=TxtStrDup(w); } /* on concatène le nouveau mot à l'expression */ nbword--; lw=0; for (li=0;wordlist[nbword].w[li];li++) { w[lw++]=wordlist[nbword].w[li]; StateMachineResizeBuffer(&w,lw,&mw); } w[lw]=0; MemFree(wordlist[nbword].w); for (li=0;wtmp[li];li++) { w[lw++]=wtmp[li]; StateMachineResizeBuffer(&w,lw,&mw); } w[lw]=0; MemFree(wtmp); /* et on modifie l'automate pour la suite! */ Automate[' ']=1; Automate['\t']=1; ispace=lw; } else if (strcmp(w,"EQU")==0) { /* il y avait un mot avant alors on va reorganiser la ligne */ nbword--; lw=0; for (li=0;wordlist[nbword].w[li];li++) { w[lw++]=wordlist[nbword].w[li]; StateMachineResizeBuffer(&w,lw,&mw); } MemFree(wordlist[nbword].w); curw.e=lw+1; /* on ajoute l'egalite d'alias*/ w[lw++]='~'; StateMachineResizeBuffer(&w,lw,&mw); w[lw]=0; Automate[' ']=1; Automate['\t']=1; ispace=lw; texpr=1; } else { curw.w=TxtStrDup(w); curw.l=listing[l].iline; curw.ifile=listing[l].ifile; curw.t=0; #if TRACE_PREPRO if (curw.w[0]=='=') { printf("(1) bug prout\n"); exit(1); } printf("ajout du mot [%s]\n",curw.w); #endif ObjectArrayAddDynamicValueConcat((void**)&wordlist,&nbword,&maxword,&curw,sizeof(curw)); //texpr=0; /* reset expr */ curw.e=0; lw=0; w[lw]=0; /* match keyword? then next spaces will be ignored*/ if (macro_trigger) { struct s_macro_fast curmacrofast; Automate[' ']=1; Automate['\t']=1; ispace=0; texpr=1; #if TRACE_PREPRO printf("macro trigger w=[%s]\n",curw.w); #endif /* add macro name to instruction pool for preprocessor but not struct or write */ if (macro_trigger=='M') { curmacrofast.mnemo=curw.w; curmacrofast.crc=GetCRC(curw.w); ObjectArrayAddDynamicValueConcat((void**)&MacroFast,&idxmacrofast,&maxmacrofast,&curmacrofast,sizeof(struct s_macro_fast)); } macro_trigger=0; } else { int keymatched=0; if ((ifast=ae->fastmatch[(int)curw.w[0]])!=-1) { while (instruction[ifast].mnemo[0]==curw.w[0]) { if (strcmp(instruction[ifast].mnemo,curw.w)==0) { keymatched=1; if (strcmp(curw.w,"MACRO")==0 || strcmp(curw.w,"STRUCT")==0 || strcmp(curw.w,"WRITE")==0) { /* @@TODO AS80 compatibility patch!!! */ macro_trigger=curw.w[0]; } else { Automate[' ']=1; Automate['\t']=1; ispace=0; /* instruction en cours, le reste est a interpreter comme une expression */ #if TRACE_PREPRO printf("instruction en cours\n"); #endif texpr=1; } break; } ifast++; } } if (!keymatched) { int macrocrc; macrocrc=GetCRC(curw.w); for (keymatched=0;keymatchedfilename[listing[l].ifile],listing[l].iline,"empty parameter\n"); } } break; case 3: /* fin de ligne, on remet l'automate comme il faut */ #if TRACE_PREPRO printf("EOL\n"); #endif macro_trigger=0; Automate[' ']=2; Automate['\t']=2; ispace=0; texpr=0; /* si le mot lu a plus d'un caractère */ if (lw) { if (!wordlist[nbword-1].t && (wordlist[nbword-1].e || w[0]=='=') && !hadcomma) { /* cas particulier d'ecriture libre */ /* bugfix inhibition 19.06.2018 */ /* ajout du terminateur? */ w[lw]=0; #if TRACE_PREPRO printf("nbword=%d w=[%s] ->",nbword,w);fflush(stdout); #endif nbword--; wordlist[nbword].w=MemRealloc(wordlist[nbword].w,strlen(wordlist[nbword].w)+lw+1); strcat(wordlist[nbword].w,w); #if TRACE_PREPRO printf("%s\n",wordlist[nbword].w); #endif /* on change de type! */ wordlist[nbword].t=1; //ObjectArrayAddDynamicValueConcat((void**)&wordlist,&nbword,&maxword,&curw,sizeof(curw)); curw.e=0; lw=0; w[lw]=0; } else if (nbword && strcmp(w,"EQU")==0) { /* il y avait un mot avant alors on va reorganiser la ligne */ nbword--; lw=0; for (li=0;wordlist[nbword].w[li];li++) { w[lw++]=wordlist[nbword].w[li]; StateMachineResizeBuffer(&w,lw,&mw); w[lw]=0; } MemFree(wordlist[nbword].w); /* on ajoute l'egalite ou comparaison! */ curw.e=lw+1; w[lw++]='='; StateMachineResizeBuffer(&w,lw,&mw); w[lw]=0; Automate[' ']=1; Automate['\t']=1; } else { /* mot de fin de ligne, à priori pas une expression */ curw.w=TxtStrDup(w); curw.l=listing[l].iline; curw.ifile=listing[l].ifile; curw.t=1; #if TRACE_PREPRO printf("mot de fin de ligne = [%s]\n",curw.w); if (curw.w[0]=='=') { printf("(3) bug prout\n"); exit(1); } #endif ObjectArrayAddDynamicValueConcat((void**)&wordlist,&nbword,&maxword,&curw,sizeof(curw)); curw.e=0; lw=0; w[lw]=0; hadcomma=0; } } else { /* sinon c'est le précédent qui était terminateur d'instruction */ wordlist[nbword-1].t=1; w[lw]=0; } hadcomma=0; break; case 4: #if TRACE_PREPRO printf("expr operator=%c\n",c); #endif /* expression/condition */ texpr=1; if (lw) { Automate[' ']=1; Automate['\t']=1; if (!curw.e) { curw.e=lw+1; w[lw++]=c; StateMachineResizeBuffer(&w,lw,&mw); w[lw]=0; } else { w[lw++]=c; StateMachineResizeBuffer(&w,lw,&mw); w[lw]=0; } } else { /* 2018.06.06 évolution sur le ! (not) */ #if TRACE_PREPRO printf("*** operateur commence le mot\n"); printf("mot precedent=[%s] t=%d\n",wordlist[nbword-1].w,wordlist[nbword-1].t); #endif if (hadcomma && c=='!') { /* on peut commencer un argument par un NOT */ w[lw++]=c; StateMachineResizeBuffer(&w,lw,&mw); w[lw]=0; /* automate déjà modifié rien de plus */ } else if (!wordlist[nbword-1].t) { /* il y avait un mot avant alors on va reorganiser la ligne */ /* patch NOT -> SAUF si c'est une directive */ int keymatched=0; if ((ifast=ae->fastmatch[(int)wordlist[nbword-1].w[0]])!=-1) { while (instruction[ifast].mnemo[0]==wordlist[nbword-1].w[0]) { if (strcmp(instruction[ifast].mnemo,wordlist[nbword-1].w)==0) { keymatched=1; break; } ifast++; } } if (!keymatched) { int macrocrc; macrocrc=GetCRC(wordlist[nbword-1].w); for (i=0;ifilename[listing[l].ifile],listing[l].iline,"cannot start expression with '=','!','<','>'\n"); } } break; default: rasm_printf(ae,KERROR"Internal error (Automate wrong value=%d)\n",Automate[c]); exit(-1); } } else { /* lecture inconditionnelle de la quote */ #if TRACE_PREPRO printf("quote[%d]=%c\n",lw,c); #endif w[lw++]=c; StateMachineResizeBuffer(&w,lw,&mw); w[lw]=0; if (!escape_code) { if (c=='\\') escape_code=1; if (lw>1 && c==quote_type) { quote_type=0; } } else { escape_code=0; } } } #if TRACE_PREPRO printf("END\n"); #endif curw.w="END"; curw.l=0; curw.t=2; curw.ifile=0; ObjectArrayAddDynamicValueConcat((void**)&wordlist,&nbword,&maxword,&curw,sizeof(curw)); #if TRACE_PREPRO rasm_printf(ae,KVERBOSE"wordlist contains %d element%s\n",nbword,nbword>1?"s":""); #endif ae->nbword=nbword; /* switch words for macro declaration with AS80 & UZ80 */ if (param && param->as80) { for (l=0;lwl=wordlist; if (param) { MemFree(param->filename); } if (MacroFast) MemFree(MacroFast); if (TABwindex) MemFree(TABwindex); if (TABrindex) MemFree(TABrindex); #if TRACE_PREPRO printf("return ae\n"); #endif return ae; } int Rasm(struct s_parameter *param) { #undef FUNC #define FUNC "Rasm" struct s_assenv *ae=NULL; /* read and preprocess source */ ae=PreProcessing(param->filename,0,NULL,0,param); /* assemble */ return Assemble(ae,NULL,NULL,NULL); } /* fonction d'export */ int RasmAssemble(const char *datain, int lenin, unsigned char **dataout, int *lenout) { struct s_assenv *ae=NULL; if (lenout) *lenout=0; ae=PreProcessing(NULL,1,datain,lenin,NULL); return Assemble(ae,dataout,lenout,NULL); } int RasmAssembleInfo(const char *datain, int lenin, unsigned char **dataout, int *lenout, struct s_rasm_info **debug) { struct s_assenv *ae=NULL; int ret; ae=PreProcessing(NULL,1,datain,lenin,NULL); ret=Assemble(ae,dataout,lenout,debug); return ret; } #define AUTOTEST_PAGELABELGEN "buildsna: bank: cpt=5: ld bc,{page}miam{cpt}: bank cpt: nop: miam{cpt} nop: assert {page}miam{cpt}==0x7FC5 " #define AUTOTEST_NOINCLUDE "truc equ 0:if truc:include'bite':endif:nop" #define AUTOTEST_SETINSIDE "ld hl,0=0xC9FB" #define AUTOTEST_OPERATOR_CONVERSION "ld hl,10 OR 20:ld a,40 and 10:ld bc,5 MOD 2:ld a,(ix+45 xor 45)" #define AUTOTEST_OPERATOR_MODULO "revar=46: devar=5 : var=46%5 : assert var==1: var=46 % 5 : assert var==1: var=46 mod 5 : assert var==1:" \ "var=revar%5 : assert var==1: var=revar%devar : assert var==1: var=46%devar : assert var==1: var=revar % 5 : assert var==1:" \ "var=revar % devar : assert var==1: var=46 % devar : assert var==1: var=revar % %101 : assert var==1: var=revar%%101 : assert var==1: nop" #define AUTOTEST_UNDEF "mavar=10: ifdef mavar: undef mavar: endif: ifdef mavar: fail 'undef did not work': endif:nop " #define AUTOTEST_INSTRMUSTFAILED "ld a,b,c:ldi a: ldir bc:exx hl,de:exx de:ex bc,hl:ex hl,bc:ex af,af:ex hl,hl:ex hl:exx hl: "\ "neg b:push b:push:pop:pop c:sub ix:add ix:add:sub:di 2:ei 3:ld i,c:ld r,e:rl:rr:rlca a:sla:sll:"\ "ldd e:lddr hl:adc ix:adc b,a:xor 12,13:xor b,1:xor:or 12,13:or b,1:or:and 12,13:and b,1:and:inc:dec" #define AUTOTEST_VIRGULE "defb 5,5,,5" #define AUTOTEST_VIRGULE2 "print '5,,5':nop" #define AUTOTEST_OVERLOADMACPRM "macro test,idx: defb idx:endm:macro test2,idx:defb {idx}:endm:repeat 2,idx:test idx-1:test2 idx-1:rend" #define AUTOTEST_IFDEFMACRO "macro test:nop:endm:ifndef test:error:else:test:endif:ifdef test:test:else:error:endif:nop" #define AUTOTEST_PRINTVAR "label1: macro test, param: print 'param {param}', {hex}{param}: endm:: test label1: nop" #define AUTOTEST_PRINTSPACE "idx=5: print 'grouik { idx + 3 } ':nop" #define AUTOTEST_NOT "myvar=10:myvar=10+myvar:if 5!=3:else:print glop:endif:ifnot 5:print glop:else:endif:" \ "ifnot 0:else:print glop:endif:if !(5):print glop:endif:if !(0):else:print glop:endif:" \ "ya=!0:if ya==1:else:print glop:endif:if !5:print glop:endif:ya = 0:ya =! 0:if ya == 1:" \ "else:print glop:endif:if ! 5:print glop:endif:if 1-!( !0 && !0):else:print glop:endif:nop" #define AUTOTEST_MACRO "macro glop:@glop:ld hl,@next:djnz @glop:@next:mend:macro glop2:@glop:glop:ld hl,@next:djnz @glop:glop:" \ "@next:mend:cpti=0:repeat:glop:cpt=0:glop:repeat:glop2:repeat 1:@glop:dec a:ld hl,@next:glop2:glop2:" \ "jr nz,@glop:@next:rend:cpt=cpt+1:glop2:until cpt<3:cpti=cpti+1:glop2:until cpti<3" #define AUTOTEST_MACRO_ADV "idx=10:macro mac2 param1,param2:ld hl,{param1}{idx+10}{param2}:{param1}{idx+10}{param2}:djnz {param1}{idx+10}{param2}:mend: " \ "mac2 label,45:mac2 glop,10:djnz glop2010:jp label2045" #define AUTOTEST_MACROPAR "macro unemac, param1, param2:defb '{param1}':defb {param2}:mend:unemac grouik,'grouik'" #define AUTOTEST_OPCODES "nop::ld bc,#1234::ld (bc),a::inc bc:inc b:dec b:ld b,#12:rlca:ex af,af':add hl,bc:ld a,(bc):dec bc:" \ "inc c:dec c:ld c,#12:rrca::djnz $:ld de,#1234:ld (de),a:inc de:inc d:dec d:ld d,#12:rla:jr $:" \ "add hl,de:ld a,(de):dec de:inc e:dec e:ld e,#12:rra::jr nz,$:ld hl,#1234:ld (#1234),hl:inc hl:inc h:" \ "dec h:ld h,#12:daa:jr z,$:add hl,hl:ld hl,(#1234):dec hl:inc l:dec l:ld l,#12:cpl::jr nc,$:" \ "ld sp,#1234:ld (#1234),a:inc sp:inc (hl):dec (hl):ld (hl),#12:scf:jr c,$:add hl,sp:ld a,(#1234):" \ "dec sp:inc a:dec a:ld a,#12:ccf::ld b,b:ld b,c:ld b,d:ld b,e:ld b,h:ld b,l:ld b,(hl):ld b,a:ld c,b:" \ "ld c,c:ld c,d:ld c,e:ld c,h:ld c,l:ld c,(hl):ld c,a::ld d,b:ld d,c:ld d,d:ld d,e:ld d,h:ld d,l:" \ "ld d,(hl):ld d,a:ld e,b:ld e,c:ld e,d:ld e,e:ld e,h:ld e,l:ld e,(hl):ld e,a::ld h,b:ld h,c:ld h,d:" \ "ld h,e:ld h,h:ld h,l:ld h,(hl):ld h,a:ld l,b:ld l,c:ld l,d:ld l,e:ld l,h:ld l,l:ld l,(hl):ld l,a::" \ "ld (hl),b:ld (hl),c:ld (hl),d:ld (hl),e:ld (hl),h:ld (hl),l:halt:ld (hl),a:ld a,b:ld a,c:ld a,d:" \ "ld a,e:ld a,h:ld a,l:ld a,(hl):ld a,a::add b:add c:add d:add e:add h:add l:add (hl):add a:adc b:" \ "adc c:adc d:adc e:adc h:adc l:adc (hl):adc a::sub b:sub c:sub d:sub e:sub h:sub l:sub (hl):sub a:" \ "sbc b:sbc c:sbc d:sbc e:sbc h:sbc l:sbc (hl):sbc a::and b:and c:and d:and e:and h:and l:and (hl):" \ "and a:xor b:xor c:xor d:xor e:xor h:xor l:xor (hl):xor a::or b:or c:or d:or e:or h:or l:or (hl):" \ "or a:cp b:cp c:cp d:cp e:cp h:cp l:cp (hl):cp a::ret nz:pop bc:jp nz,#1234:jp #1234:call nz,#1234:" \ "push bc:add #12:rst 0:ret z:ret:jp z,#1234:nop:call z,#1234:call #1234:adc #12:rst 8::ret nc:pop de:" \ "jp nc,#1234:out (#12),a:call nc,#1234:push de:sub #12:rst #10:ret c:exx:jp c,#1234:in a,(#12):" \ "call c,#1234:nop:sbc #12:rst #18::ret po:pop hl:jp po,#1234:ex (sp),hl:call po,#1234:push hl:" \ "and #12:rst #20:ret pe:jp (hl):jp pe,#1234:ex de,hl:call pe,#1234:nop:xor #12:rst #28::ret p:pop af:" \ "jp p,#1234:di:call p,#1234:push af:or #12:rst #30:ret m:ld sp,hl:jp m,#1234:ei:call m,#1234:nop:" \ "cp #12:rst #38:in b,(c):out (c),b:sbc hl,bc:ld (#1234),bc:neg:retn:im 0:ld i,a:in c,(c):out (c),c:" \ "adc hl,bc:ld bc,(#1234):reti:ld r,a::in d,(c):out (c),d:sbc hl,de:ld (#1234),de:retn:im 1:ld a,i:" \ "in e,(c):out (c),e:adc hl,de:ld de,(#1234):im 2:ld a,r::in h,(c):out (c),h:sbc hl,hl:rrd:in l,(c):" \ "out (c),l:adc hl,hl:rld::in 0,(c):out (c),0:sbc hl,sp:ld (#1234),sp:in a,(c):out (c),a:adc hl,sp:" \ "ld sp,(#1234)::ldi:cpi:ini:outi:ldd:cpd:ind:outd::ldir:cpir:inir:otir:lddr:cpdr:indr:otdr::rlc b:" \ "rlc c:rlc d:rlc e:rlc h:rlc l:rlc (hl):rlc a:rrc b:rrc c:rrc d:rrc e:rrc h:rrc l:rrc (hl):rrc a::" \ "rl b:rl c:rl d:rl e:rl h:rl l:rl (hl):rl a:rr b:rr c:rr d:rr e:rr h:rr l:rr (hl):rr a:sla b:sla c:" \ "sla d:sla e:sla h:sla l:sla (hl):sla a:sra b:sra c:sra d:sra e:sra h:sra l:sra (hl):sra a::sll b:" \ "sll c:sll d:sll e:sll h:sll l:sll (hl):sll a:srl b:srl c:srl d:srl e:srl h:srl l:srl (hl):srl a::" \ "bit 0,b:bit 0,c:bit 0,d:bit 0,e:bit 0,h:bit 0,l:bit 0,(hl):bit 0,a::bit 1,b:bit 1,c:bit 1,d:bit 1,e:" \ "bit 1,h:bit 1,l:bit 1,(hl):bit 1,a::bit 2,b:bit 2,c:bit 2,d:bit 2,e:bit 2,h:bit 2,l:bit 2,(hl):" \ "bit 2,a::bit 3,b:bit 3,c:bit 3,d:bit 3,e:bit 3,h:bit 3,l:bit 3,(hl):bit 3,a::bit 4,b:bit 4,c:" \ "bit 4,d:bit 4,e:bit 4,h:bit 4,l:bit 4,(hl):bit 4,a::bit 5,b:bit 5,c:bit 5,d:bit 5,e:bit 5,h:bit 5,l:" \ "bit 5,(hl):bit 5,a::bit 6,b:bit 6,c:bit 6,d:bit 6,e:bit 6,h:bit 6,l:bit 6,(hl):bit 6,a::bit 7,b:" \ "bit 7,c:bit 7,d:bit 7,e:bit 7,h:bit 7,l:bit 7,(hl):bit 7,a::res 0,b:res 0,c:res 0,d:res 0,e:res 0,h:" \ "res 0,l:res 0,(hl):res 0,a::res 1,b:res 1,c:res 1,d:res 1,e:res 1,h:res 1,l:res 1,(hl):res 1,a::" \ "res 2,b:res 2,c:res 2,d:res 2,e:res 2,h:res 2,l:res 2,(hl):res 2,a::res 3,b:res 3,c:res 3,d:res 3,e:" \ "res 3,h:res 3,l:res 3,(hl):res 3,a::res 4,b:res 4,c:res 4,d:res 4,e:res 4,h:res 4,l:res 4,(hl):" \ "res 4,a::res 5,b:res 5,c:res 5,d:res 5,e:res 5,h:res 5,l:res 5,(hl):res 5,a::res 6,b:res 6,c:" \ "res 6,d:res 6,e:res 6,h:res 6,l:res 6,(hl):res 6,a::res 7,b:res 7,c:res 7,d:res 7,e:res 7,h:res 7,l:" \ "res 7,(hl):res 7,a::set 0,b:set 0,c:set 0,d:set 0,e:set 0,h:set 0,l:set 0,(hl):set 0,a::set 1,b:" \ "set 1,c:set 1,d:set 1,e:set 1,h:set 1,l:set 1,(hl):set 1,a::set 2,b:set 2,c:set 2,d:set 2,e:set 2,h:" \ "set 2,l:set 2,(hl):set 2,a::set 3,b:set 3,c:set 3,d:set 3,e:set 3,h:set 3,l:set 3,(hl):set 3,a::" \ "set 4,b:set 4,c:set 4,d:set 4,e:set 4,h:set 4,l:set 4,(hl):set 4,a::set 5,b:set 5,c:set 5,d:set 5,e:" \ "set 5,h:set 5,l:set 5,(hl):set 5,a::set 6,b:set 6,c:set 6,d:set 6,e:set 6,h:set 6,l:set 6,(hl):" \ "set 6,a::set 7,b:set 7,c:set 7,d:set 7,e:set 7,h:set 7,l:set 7,(hl):set 7,a::add ix,bc::add ix,de::" \ "ld ix,#1234:ld (#1234),ix:inc ix:inc xh:dec xh:ld xh,#12:add ix,ix:ld ix,(#1234):dec ix:inc xl:" \ "dec xl:ld xl,#12::inc (ix+#12):dec (ix+#12):ld (ix+#12),#34:add ix,sp::ld b,xh:ld b,xl:" \ "ld b,(ix+#12):ld c,xh:ld c,xl:ld c,(ix+#12):::ld d,xh:ld d,xl:ld d,(ix+#12):ld e,xh:ld e,xl:" \ "ld e,(ix+#12)::ld xh,b:ld xh,c:ld xh,d:ld xh,e:ld xh,xh:ld xh,xl:ld h,(ix+#12):ld xh,a:ld xl,b:" \ "ld xl,c:ld xl,d:ld xl,e:ld xl,xh:ld xl,xl:ld l,(ix+#12):ld xl,a::ld (ix+#12),b:ld (ix+#12),c:" \ "ld (ix+#12),d:ld (ix+#12),e:ld (ix+#12),h:ld (ix+#12),l:ld (ix+#12),a:ld a,xh:ld a,xl:" \ "ld a,(ix+#12)::add xh:add xl:add (ix+#12):adc xh:adc xl:adc (ix+#12)::sub xh:sub xl:sub (ix+#12):" \ "sbc xh:sbc xl:sbc (ix+#12)::and xh:and xl:and (ix+#12):xor xh:xor xl:xor (ix+#12)::or xh:or xl:" \ "or (ix+#12):cp xh:cp xl:cp (ix+#12)::pop ix:ex (sp),ix:push ix:jp (ix)::ld sp,ix:::rlc (ix+#12),b:" \ "rlc (ix+#12),c:rlc (ix+#12),d:rlc (ix+#12),e:rlc (ix+#12),h:rlc (ix+#12),l:rlc (ix+#12):" \ "rlc (ix+#12),a:rrc (ix+#12),b:rrc (ix+#12),c:rrc (ix+#12),d:rrc (ix+#12),e:rrc (ix+#12),h:" \ "rrc (ix+#12),l:rrc (ix+#12):rrc (ix+#12),a::rl (ix+#12),b:rl (ix+#12),c:rl (ix+#12),d:rl (ix+#12),e:" \ "rl (ix+#12),h:rl (ix+#12),l:rl (ix+#12):rl (ix+#12),a:rr (ix+#12),b:rr (ix+#12),c:rr (ix+#12),d:" \ "rr (ix+#12),e:rr (ix+#12),h:rr (ix+#12),l:rr (ix+#12):rr (ix+#12),a::sla (ix+#12),b:sla (ix+#12),c:" \ "sla (ix+#12),d:sla (ix+#12),e:sla (ix+#12),h:sla (ix+#12),l:sla (ix+#12):sla (ix+#12),a:" \ "sra (ix+#12),b:sra (ix+#12),c:sra (ix+#12),d:sra (ix+#12),e:sra (ix+#12),h:sra (ix+#12),l:" \ "sra (ix+#12):sra (ix+#12),a::sll (ix+#12),b:sll (ix+#12),c:sll (ix+#12),d:sll (ix+#12),e:" \ "sll (ix+#12),h:sll (ix+#12),l:sll (ix+#12):sll (ix+#12),a:srl (ix+#12),b:srl (ix+#12),c:" \ "srl (ix+#12),d:srl (ix+#12),e:srl (ix+#12),h:srl (ix+#12),l:srl (ix+#12):srl (ix+#12),a::" \ "bit 0,(ix+#12):bit 1,(ix+#12):bit 2,(ix+#12):bit 3,(ix+#12):bit 4,(ix+#12):bit 5,(ix+#12):" \ "bit 6,(ix+#12):bit 7,(ix+#12):bit 0,(ix+#12),d:bit 1,(ix+#12),b:bit 2,(ix+#12),c:bit 3,(ix+#12),d:" \ "bit 4,(ix+#12),e:bit 5,(ix+#12),h:bit 6,(ix+#12),l:bit 7,(ix+#12),a:::res 0,(ix+#12),b:" \ "res 0,(ix+#12),c:res 0,(ix+#12),d:res 0,(ix+#12),e:res 0,(ix+#12),h:res 0,(ix+#12),l:res 0,(ix+#12):" \ "res 0,(ix+#12),a::res 1,(ix+#12),b:res 1,(ix+#12),c:res 1,(ix+#12),d:res 1,(ix+#12),e:" \ "res 1,(ix+#12),h:res 1,(ix+#12),l:res 1,(ix+#12):res 1,(ix+#12),a::res 2,(ix+#12),b:" \ "res 2,(ix+#12),c:res 2,(ix+#12),d:res 2,(ix+#12),e:res 2,(ix+#12),h:res 2,(ix+#12),l:res 2,(ix+#12):" \ "res 2,(ix+#12),a::res 3,(ix+#12),b:res 3,(ix+#12),c:res 3,(ix+#12),d:res 3,(ix+#12),e:" \ "res 3,(ix+#12),h:res 3,(ix+#12),l:res 3,(ix+#12):res 3,(ix+#12),a::res 4,(ix+#12),b:" \ "res 4,(ix+#12),c:res 4,(ix+#12),d:res 4,(ix+#12),e:res 4,(ix+#12),h:res 4,(ix+#12),l:" \ "res 4,(ix+#12):res 4,(ix+#12),a::res 5,(ix+#12),b:res 5,(ix+#12),c:res 5,(ix+#12),d:" \ "res 5,(ix+#12),e:res 5,(ix+#12),h:res 5,(ix+#12),l:res 5,(ix+#12):res 5,(ix+#12),a::" \ "res 6,(ix+#12),b:res 6,(ix+#12),c:res 6,(ix+#12),d:res 6,(ix+#12),e:res 6,(ix+#12),h:" \ "res 6,(ix+#12),l:res 6,(ix+#12):res 6,(ix+#12),a::res 7,(ix+#12),b:res 7,(ix+#12),c:" \ "res 7,(ix+#12),d:res 7,(ix+#12),e:res 7,(ix+#12),h:res 7,(ix+#12),l:res 7,(ix+#12):" \ "res 7,(ix+#12),a::set 0,(ix+#12),b:set 0,(ix+#12),c:set 0,(ix+#12),d:set 0,(ix+#12),e:" \ "set 0,(ix+#12),h:set 0,(ix+#12),l:set 0,(ix+#12):set 0,(ix+#12),a::set 1,(ix+#12),b:" \ "set 1,(ix+#12),c:set 1,(ix+#12),d:set 1,(ix+#12),e:set 1,(ix+#12),h:set 1,(ix+#12),l:" \ "set 1,(ix+#12):set 1,(ix+#12),a::set 2,(ix+#12),b:set 2,(ix+#12),c:set 2,(ix+#12),d:" \ "set 2,(ix+#12),e:set 2,(ix+#12),h:set 2,(ix+#12),l:set 2,(ix+#12):set 2,(ix+#12),a::" \ "set 3,(ix+#12),b:set 3,(ix+#12),c:set 3,(ix+#12),d:set 3,(ix+#12),e:set 3,(ix+#12),h:" \ "set 3,(ix+#12),l:set 3,(ix+#12):set 3,(ix+#12),a::set 4,(ix+#12),b:set 4,(ix+#12),c:" \ "set 4,(ix+#12),d:set 4,(ix+#12),e:set 4,(ix+#12),h:set 4,(ix+#12),l:set 4,(ix+#12):" \ "set 4,(ix+#12),a::set 5,(ix+#12),b:set 5,(ix+#12),c:set 5,(ix+#12),d:set 5,(ix+#12),e:" \ "set 5,(ix+#12),h:set 5,(ix+#12),l:set 5,(ix+#12):set 5,(ix+#12),a::set 6,(ix+#12),b:" \ "set 6,(ix+#12),c:set 6,(ix+#12),d:set 6,(ix+#12),e:set 6,(ix+#12),h:set 6,(ix+#12),l:" \ "set 6,(ix+#12):set 6,(ix+#12),a::set 7,(ix+#12),b:set 7,(ix+#12),c:set 7,(ix+#12),d:" \ "set 7,(ix+#12),e:set 7,(ix+#12),h:set 7,(ix+#12),l:set 7,(ix+#12):set 7,(ix+#12),a::add iy,bc::" \ "add iy,de::ld iy,#1234:ld (#1234),iy:inc iy:inc yh:dec yh:ld yh,#12:add iy,iy:ld iy,(#1234):dec iy:" \ "inc yl:dec yl:ld yl,#12::inc (iy+#12):dec (iy+#12):ld (iy+#12),#34:add iy,sp::ld b,yh:ld b,yl:" \ "ld b,(iy+#12):ld c,yh:ld c,yl:ld c,(iy+#12):::ld d,yh:ld d,yl:ld d,(iy+#12):ld e,yh:ld e,yl:" \ "ld e,(iy+#12)::ld yh,b:ld yh,c:ld yh,d:ld yh,e:ld yh,yh:ld yh,yl:ld h,(iy+#12):ld yh,a:ld yl,b:" \ "ld yl,c:ld yl,d:ld yl,e:ld yl,yh:ld yl,yl:ld l,(iy+#12):ld yl,a::ld (iy+#12),b:ld (iy+#12),c:" \ "ld (iy+#12),d:ld (iy+#12),e:ld (iy+#12),h:ld (iy+#12),l:ld (iy+#12),a:ld a,yh:ld a,yl:" \ "ld a,(iy+#12)::add yh:add yl:add (iy+#12):adc yh:adc yl:adc (iy+#12)::sub yh:sub yl:" \ "sub (iy+#12):sbc yh:sbc yl:sbc (iy+#12)::and yh:and yl:and (iy+#12):xor yh:xor yl:xor (iy+#12)::" \ "or yh:or yl:or (iy+#12):cp yh:cp yl:cp (iy+#12)::pop iy:ex (sp),iy:push iy:jp (iy)::ld sp,iy::" \ "rlc (iy+#12),b:rlc (iy+#12),c:rlc (iy+#12),d:rlc (iy+#12),e:rlc (iy+#12),h:rlc (iy+#12),l:" \ "rlc (iy+#12):rlc (iy+#12),a:rrc (iy+#12),b:rrc (iy+#12),c:rrc (iy+#12),d:rrc (iy+#12),e:" \ "rrc (iy+#12),h:rrc (iy+#12),l:rrc (iy+#12):rrc (iy+#12),a::rl (iy+#12),b:rl (iy+#12),c:" \ "rl (iy+#12),d:rl (iy+#12),e:rl (iy+#12),h:rl (iy+#12),l:rl (iy+#12):rl (iy+#12),a:rr (iy+#12),b:" \ "rr (iy+#12),c:rr (iy+#12),d:rr (iy+#12),e:rr (iy+#12),h:rr (iy+#12),l:rr (iy+#12):rr (iy+#12),a::" \ "sla (iy+#12),b:sla (iy+#12),c:sla (iy+#12),d:sla (iy+#12),e:sla (iy+#12),h:sla (iy+#12),l:" \ "sla (iy+#12):sla (iy+#12),a:sra (iy+#12),b:sra (iy+#12),c:sra (iy+#12),d:sra (iy+#12),e:" \ "sra (iy+#12),h:sra (iy+#12),l:sra (iy+#12):sra (iy+#12),a::sll (iy+#12),b:sll (iy+#12),c:" \ "sll (iy+#12),d:sll (iy+#12),e:sll (iy+#12),h:sll (iy+#12),l:sll (iy+#12):sll (iy+#12),a:" \ "srl (iy+#12),b:srl (iy+#12),c:srl (iy+#12),d:srl (iy+#12),e:srl (iy+#12),h:srl (iy+#12),l:" \ "srl (iy+#12):srl (iy+#12),a::bit 0,(iy+#12):bit 1,(iy+#12):bit 2,(iy+#12):bit 3,(iy+#12):" \ "bit 4,(iy+#12):bit 5,(iy+#12):bit 6,(iy+#12):bit 7,(iy+#12)::res 0,(iy+#12),b:res 0,(iy+#12),c:" \ "res 0,(iy+#12),d:res 0,(iy+#12),e:res 0,(iy+#12),h:res 0,(iy+#12),l:res 0,(iy+#12):" \ "res 0,(iy+#12),a::res 1,(iy+#12),b:res 1,(iy+#12),c:res 1,(iy+#12),d:res 1,(iy+#12),e:" \ "res 1,(iy+#12),h:res 1,(iy+#12),l:res 1,(iy+#12):res 1,(iy+#12),a::res 2,(iy+#12),b:" \ "res 2,(iy+#12),c:res 2,(iy+#12),d:res 2,(iy+#12),e:res 2,(iy+#12),h:res 2,(iy+#12),l:" \ "res 2,(iy+#12):res 2,(iy+#12),a::res 3,(iy+#12),b:res 3,(iy+#12),c:res 3,(iy+#12),d:" \ "res 3,(iy+#12),e:res 3,(iy+#12),h:res 3,(iy+#12),l:res 3,(iy+#12):res 3,(iy+#12),a::" \ "res 4,(iy+#12),b:res 4,(iy+#12),c:res 4,(iy+#12),d:res 4,(iy+#12),e:res 4,(iy+#12),h:" \ "res 4,(iy+#12),l:res 4,(iy+#12):res 4,(iy+#12),a::res 5,(iy+#12),b:res 5,(iy+#12),c:" \ "res 5,(iy+#12),d:res 5,(iy+#12),e:res 5,(iy+#12),h:res 5,(iy+#12),l:res 5,(iy+#12):" \ "res 5,(iy+#12),a::res 6,(iy+#12),b:res 6,(iy+#12),c:res 6,(iy+#12),d:res 6,(iy+#12),e:" \ "res 6,(iy+#12),h:res 6,(iy+#12),l:res 6,(iy+#12):res 6,(iy+#12),a::res 7,(iy+#12),b:" \ "res 7,(iy+#12),c:res 7,(iy+#12),d:res 7,(iy+#12),e:res 7,(iy+#12),h:res 7,(iy+#12),l:" \ "res 7,(iy+#12):res 7,(iy+#12),a::set 0,(iy+#12),b:set 0,(iy+#12),c:set 0,(iy+#12),d:" \ "set 0,(iy+#12),e:set 0,(iy+#12),h:set 0,(iy+#12),l:set 0,(iy+#12):set 0,(iy+#12),a::" \ "set 1,(iy+#12),b:set 1,(iy+#12),c:set 1,(iy+#12),d:set 1,(iy+#12),e:set 1,(iy+#12),h:" \ "set 1,(iy+#12),l:set 1,(iy+#12):set 1,(iy+#12),a::set 2,(iy+#12),b:set 2,(iy+#12),c:" \ "set 2,(iy+#12),d:set 2,(iy+#12),e:set 2,(iy+#12),h:set 2,(iy+#12),l:set 2,(iy+#12):" \ "set 2,(iy+#12),a::set 3,(iy+#12),b:set 3,(iy+#12),c:set 3,(iy+#12),d:set 3,(iy+#12),e:" \ "set 3,(iy+#12),h:set 3,(iy+#12),l:set 3,(iy+#12):set 3,(iy+#12),a::set 4,(iy+#12),b:" \ "set 4,(iy+#12),c:set 4,(iy+#12),d:set 4,(iy+#12),e:set 4,(iy+#12),h:set 4,(iy+#12),l:" \ "set 4,(iy+#12):set 4,(iy+#12),a::set 5,(iy+#12),b:set 5,(iy+#12),c:set 5,(iy+#12),d:" \ "set 5,(iy+#12),e:set 5,(iy+#12),h:set 5,(iy+#12),l:set 5,(iy+#12):set 5,(iy+#12),a::" \ "set 6,(iy+#12),b:set 6,(iy+#12),c:set 6,(iy+#12),d:set 6,(iy+#12),e:set 6,(iy+#12),h:" \ "set 6,(iy+#12),l:set 6,(iy+#12):set 6,(iy+#12),a::set 7,(iy+#12),b:set 7,(iy+#12),c:" \ "set 7,(iy+#12),d:set 7,(iy+#12),e:set 7,(iy+#12),h:set 7,(iy+#12),l:set 7,(iy+#12):" \ "set 7,(iy+#12),a:" #define AUTOTEST_LABNUM "mavar=67:label{mavar}truc:ld hl,7+2*label{mavar}truc:mnt=1234567:lab2{mavar}{mnt}:" \ "ld de,lab2{mavar}{mnt}:lab3{mavar}{mnt}h:ld de,lab3{mavar}{mnt}h" #define AUTOTEST_EQUNUM "mavar = 9:monlabel{mavar+5}truc:unalias{mavar+5}heu equ 50:autrelabel{unalias14heu}:ld hl,autrelabel50" #define AUTOTEST_DELAYNUM "macro test label: dw {label}: endm: repeat 3, idx:idx2 = idx-1:" \ " test label_{idx2}: rend:repeat 3, idx:label_{idx-1}:nop:rend" #define AUTOTEST_STRUCT "org #1000:label1 :struct male:age defb 0:height defb 0:endstruct:struct female:" \ "age defb 0:height defb 0:endstruct:struct couple:struct male husband:" \ "struct female wife:endstruct:if $-label1!=0:stop:endif:ld a,(ix+couple.wife.age):" \ "ld bc,couple:ld bc,{sizeof}couple:struct couple mycouple:" \ "if mycouple.husband != mycouple.husband.age:stop:endif:ld hl,mycouple:" \ "ld hl,mycouple.wife.age:ld bc,{sizeof}mycouple:macro cmplastheight p1:" \ "ld hl,@mymale.height:ld a,{p1}:cp (hl):ld bc,{sizeof}@mymale:ld hl,@mymale:ret:" \ "struct male @mymale:mend:cmplastheight 5:cmplastheight 3:nop" #define AUTOTEST_STRUCT2 "struct bite: preums defb 0: deuze defw 1: troize defs 10: endstruct:" \ " if {sizeof}bite.preums!=1 || {sizeof}bite.deuze!=2 || {sizeof}bite.troize!=10: stop: endif: nop " #define AUTOTEST_REPEAT "ce=100:repeat 2,ce:repeat 5,cx:repeat 5,cy:defb cx*cy:rend:rend:rend:assert cx==6 && cy==6 && ce==3:" \ "cpt=0:repeat:cpt=cpt+1:until cpt>4:assert cpt==5" #define AUTOTEST_REPEATKO "repeat 5:nop" #define AUTOTEST_WHILEKO "while 5:nop" #define AUTOTEST_TICKER "repeat 2: ticker start, mc:out (0),a:out (c),a:out (c),h:out (c),0:ticker stop, mc:if mc!=15:ld hl,bite:else:nop:endif:rend" #define AUTOTEST_ORG "ORG #8000,#1000:defw $:ORG $:defw $" #define AUTOTEST_BANKORG "bank 0:nop:org #5:nop:bank 1:unevar=10:bank 0:assert $==6:ret:bank 1:assert $==0:bank 0:assert $==7" #define AUTOTEST_VAREQU "label1 equ #C000:label2 equ (label1*2)/16:label3 equ label1-label2:label4 equ 15:var1=50*3+2:var2=12*label1:var3=label4-8:var4=label2:nop" #define AUTOTEST_FORMAT "hexa=#12A+$23B+45Ch+0x56D:deci=123.45+-78.54*2-(7-7)*2:bina=0b101010+1010b-%1111:assert hexa==3374 && deci==-33.63 && bina==37:nop" #define AUTOTEST_CHARSET "charset 'abcde',0:defb 'abcde':defb 'a','b','c','d','e':defb 'a',1*'b','c'*1,1*'d','e'*1:charset:" \ "defb 'abcde':defb 'a','b','c','d','e':defb 'a',1*'b','c'*1,1*'d','e'*1" #define AUTOTEST_CHARSET2 "charset 97,97+26,0:defb 'roua':charset:charset 97,10:defb 'roua':charset 'o',5:defb 'roua':charset 'ou',6:defb 'roua'" #define AUTOTEST_NOCODE "let monorg=$:NoCode:Org 0:Element1 db 0:Element2 dw 3:Element3 ds 50:Element4 defb 'rdd':Org 0:pouet defb 'nop':" \ "Code:Org monorg:cpt=$+element2+element3+element4:defs cpt,0" #define AUTOTEST_LZSEGMENT "org #100:debut:jr nz,zend:lz48:repeat 128:nop:rend:lzclose:jp zend:lz48:repeat 2:dec a:jr nz,@next:ld a,5:@next:jp debut:rend:" \ "lzclose:zend" #define AUTOTEST_PAGETAG "bankset 0:org #5000:label1:bankset 1:org #9000:label2:bankset 2:" \ "assert {page}label1==0x7FC0:assert {page}label2==0x7FC6:assert {pageset}label1==#7FC0:assert {pageset}label2==#7FC2:nop" #define AUTOTEST_PAGETAG2 "bankset 0:call maroutine:bank 4:org #C000:autreroutine:nop:" \ "ret:bank 5:org #8000:maroutine:ldir:ret:bankset 2:org #9000:troize:nop:" \ "assert {page}maroutine==#7FC5:assert {pageset}maroutine==#7FC2:assert {page}autreroutine==#7FC4:" \ "assert {pageset}autreroutine==#7FC2:assert {page}troize==#7FCE:assert {pageset}troize==#7FCA" #define AUTOTEST_PAGETAG3 "buildsna:bank 2:assert {bank}$==2:assert {page}$==0x7FC0:assert {pageset}$==#7FC0:" \ "bankset 1:org #4000:assert {bank}$==5:assert {page}$==0x7FC5:assert {pageset}$==#7FC2" #define AUTOTEST_SWITCH "mavar=4:switch mavar:case 1:nop:case 4:defb 4:case 3:defb 3:break:case 2:nop:case 4:defb 4:endswitch" #define AUTOTEST_PREPRO0 "\n\n\n\n;bitch\n\nnop\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nxor a\n\n\n\n\n\n\n\n\n\n\n\n" #define AUTOTEST_PREPRO1 " macro DEBUG_INK0, coul: out (c), a: endm: ifndef NDEBUG:DEBUG_BORDER_NOPS = 0: endif" #define AUTOTEST_PREPRO2 " nop : mycode other tartine ldir : defw tartine,other, mycode : assert tartine==other && other==mycode && mycode==1 && $==9" #define AUTOTEST_PREPRO3 "nop\n \n /* test ' ici */\n nop /* retest */ 5\n /* bonjour\n prout\n caca\n pipi */" \ " nop\n nop /* nop */ : nop\n ; grouik /*\n \n /* ; pouet */ ld hl,#2121\n " #define AUTOTEST_PREPRO4 "glop=0\n nop ; glop=1\n assert glop==0\n nop\n glop=0\n nop // glop=1\n assert glop==0\n nop\n glop=0 : /* glop=1 */ nop\n" \ "assert glop==0\n nop\n \n glop=0 : /* glop=1 // */ nop\n assert glop==0\n nop\n glop=0 : /* glop=1 ; */ nop\n" \ "assert glop==0\n nop\n glop=0 ; /* glop=1\n nop // glop=2 /*\n assert glop==0\n nop\n" #define AUTOTEST_PROXIM "routine:.step1:jp .step2:.step2:jp .step1:deuze:nop:.step1:djnzn .step1:djnz routine.step2" #define AUTOTEST_TAGPRINT "unevar=12:print 'trucmuche{unevar}':print '{unevar}':print '{unevar}encore','pouet{unevar}{unevar}':ret" #define AUTOTEST_TAGFOLLOW "ret:uv=1234567890:unlabel_commeca_{uv} equ pouetpouetpouettroulala:pouetpouetpouettroulala:assert unlabel_commeca_{uv}>0" #define AUTOTEST_TAGREALLOC "zoomscroller_scroller_height equ 10: another_super_long_equ equ 256: pinouille_super_long_useless_equ equ 0: " \ "zz equ 1111111111: org #100: repeat zoomscroller_scroller_height,idx: " \ "zoomscroller_buffer_line_{idx-1}_{pinouille_super_long_useless_equ} nop: zoomscroller_buffer_line_{idx-1}_{zz} nop: " \ "rend: align 256: repeat zoomscroller_scroller_height,idx: zoomscroller_buffer_line_{idx-1}_{pinouille_super_long_useless_equ}_duplicate nop: " \ "zoomscroller_buffer_line_{idx-1}_{zz}_duplicate nop: rend: repeat zoomscroller_scroller_height, line: idx = line - 1: " \ "assert zoomscroller_buffer_line_{idx}_{pinouille_super_long_useless_equ} + another_super_long_equ == "\ "zoomscroller_buffer_line_{idx}_{pinouille_super_long_useless_equ}_duplicate: " \ "assert zoomscroller_buffer_line_{idx}_{zz} + another_super_long_equ == zoomscroller_buffer_line_{idx}_{zz}_duplicate: rend" #define AUTOTEST_DEFUSED "ld hl,labelused :ifdef labelused:fail 'labelexiste':endif:ifndef labelused:else:fail 'labelexiste':endif:" \ "ifnused labelused:fail 'labelused':endif:ifused labelused:else:fail 'labelused':endif:labelused" #define AUTOTEST_SAVEINVALID1 "nop : save'gruik',20,-100" #define AUTOTEST_SAVEINVALID2 "nop : save'gruik',-20,100" #define AUTOTEST_SAVEINVALID3 "nop : save'gruik',40000,30000" #define AUTOTEST_MACROPROX " macro unemacro: nop: endm: global_label: ld hl, .table: .table" #define AUTOTEST_PROXBACK " macro grouik: @truc djnz @truc: .unprox djnz .unprox: mend:" \ "ld b,2: unglobal nop: djnz unglobal: ld b,2: .unprox nop: djnz .unprox: beforelocal=$ :" \ "repeat 2: @unlocal: ld b,2: .unprox nop: djnz .unprox: grouik : djnz .unprox : rend: assert .unprox < beforelocal : nop" #define AUTOTEST_LOCAPROX "repeat 1: @label nop: .prox nop: @label2 nop: djnz @label.prox: rend" #define AUTOTEST_QUOTES "defb 'rdd':str 'rdd':charset 'rd',0:defb '\\r\\d':str '\\r\\d'" #define AUTOTEST_NEGATIVE "ld a,-5: ld bc,-0x3918:ld de,0+-#3918:ld de,-#3918:var1=-5+6:var2=-#3918+#3919:assert var1+var2==2" #define AUTOTEST_FORMULA1 "a=5:b=2:assert int(a/b)==3:assert !a+!b==0:a=a*100:b=b*100:assert a*b==100000:ld hl,a*b-65536:a=123+-5*(-6/2)-50*2<<1" #define AUTOTEST_FORMULA2 "vala= (0.5+(4*0.5))*6:valb= int((0.5+(4*0.5))*6):nop:if vala!=valb:push erreur:endif" #define AUTOTEST_SHIFTMAX "a=45: a=a>>256: assert a==0:nop" #define AUTOTEST_FRAC "mavar=frac(5.5):assert mavar==0.5:assert frac(6.6)==0.6:assert frac(1.1)==0.1:assert frac(1)==0:assert frac(100000)==0:nop" /* test override control between bank and bankset in snapshot mode + temp workspace */ #define AUTOTEST_BANKSET "buildsna:bank 0:nop:bank 1:nop:bank:nop:bank 2:nop:bank 3:nop:bankset 1:nop:bank 8:nop:bank 9:nop:bank 10:nop:bank 11:nop" #define AUTOTEST_LIMITOK "org #100:limit #102:nop:limit #103:ld a,0:protect #105,#107:limit #108:xor a:org $+3:inc a" #define AUTOTEST_LIMITKO "limit #100:org #100:add ix,ix" #define AUTOTEST_DEFS "defs 256,0" #define AUTOTEST_LIMIT03 "limit -1 : nop" #define AUTOTEST_LIMIT04 "limit #10000 : nop" #define AUTOTEST_LIMIT05 "org #FFFF : ldir" #define AUTOTEST_LIMIT06 "org #FFFF : nop" #define AUTOTEST_LIMIT07 "org #ffff : Start: equ $ : di : ld hl,#c9fb : ld (#38),hl" #define AUTOTEST_DELAYED_RUN "run _start:nop:_start nop" #define AUTOTEST_INHIBITION "if 0:ifused truc:ifnused glop:ifdef bidule:ifndef machin:ifnot 1:nop:endif:nop:else:nop:endif:endif:endif:endif:endif" #define AUTOTEST_LZ4 "lz4:repeat 10:nop:rend:defb 'roudoudoudouoneatxkjhgfdskljhsdfglkhnopnopnopnop':lzclose" #define AUTOTEST_MAXERROR "repeat 20:aglapi:rend:nop" #define AUTOTEST_ENHANCED_LD "ld h,(ix+11): ld l,(ix+10): ld h,(iy+21): ld l,(iy+20): ld b,(ix+11): ld c,(ix+10):" \ "ld b,(iy+21): ld c,(iy+20): ld d,(ix+11): ld e,(ix+10): ld d,(iy+21): ld e,(iy+20): ld hl,(ix+10): " \ "ld hl,(iy+20):ld bc,(ix+10):ld bc,(iy+20): ld de,(ix+10):ld de,(iy+20)" #define AUTOTEST_ENHANCED_PUSHPOP "push bc,de,hl,ix,iy,af:pop hl,bc,de,iy,ix,af:nop 2:" \ "push bc:push de:push hl:push ix:push iy:push af:"\ "pop hl:pop bc:pop de:pop iy:pop ix:pop af:nop:nop" #define AUTOTEST_ENHANCED_LD2 "ld (ix+0),hl: ld (ix+0),de: ld (ix+0),bc: ld (iy+0),hl: ld (iy+0),de: ld (iy+0),bc:"\ "ld (ix+1),h: ld (ix+0),l: ld (ix+1),d: ld (ix+0),e: ld (ix+1),b: ld (ix+0),c: ld (iy+1),h: ld (iy+0),l: ld (iy+1),d: ld (iy+0),e: ld (iy+1),b: ld (iy+0),c" #define AUTOTEST_INHIBITION2 "ifdef roudoudou:macro glop bank,page,param:ld a,{bank}:ld hl,{param}{bank}:if {bank}:nop:else:exx:" \ "endif::switch {param}:nop:case 4:nop:case {param}:nop:default:nop:break:endswitch:endif:defb 'coucou'" #define AUTOTEST_INHIBITIONMAX "roudoudou:ifndef roudoudou:if pouet:macro glop bank,page,param:ifdef nanamouskouri:ld hl,{param}{bank}:"\ "elseif aglapi:exx:endif:if {bank}:nop:elseif {grouik}:exx:endif:switch {bite}:nop:case {nichon}:nop:default:nop:break:endswitch:else:"\ "ifnot {jojo}:exx:endif:endif:else:defb 'coucou':endif" #define AUTOTEST_NOEXPORT "unlabel nop:.unlocal nop:unevar=5:unequ equ 10:noexport unlabel, .unlocal, "\ "unlabel.unlocal, unevar, unequ:enoexport unlabel, .unlocal, unlabel.unlocal, unevar, unequ" #define AUTOTEST_UNDERVAR "coucou nop:_coucou nop:_mavar=5:jr _coucou+_mavar:print _mavar" #define AUTOTEST_CODESKIP "org #100: nop: old_dollar=$: nocode: defs 10: assert $==old_dollar+10: code: "\ "assert $==old_dollar+10: org #200: nop: old_dollar=$: nocode: defs 10: assert $==old_dollar+10: code skip: assert $==old_dollar" #define AUTOTEST_EMBEDDED_ERRORS "nop : rien : rien : rien : glop nop : glapi nop" #define AUTOTEST_EMBEDDED_LABELS " disarkCounter = 0:MACRO dkps:PLY_AKG_DisarkPointerRegionStart_{disarkCounter}:ENDM" \ ":MACRO dkpe\nPLY_AKG_DisarkPointerRegionEnd_{disarkCounter}:\ndisarkCounter = disarkCounter + 1:ENDM:\ndkps\ndkpe\ndkps" #define AUTOTEST_TAGLOOP "tab1 = #100:tab2 = #200:tab3 = #300:macro genreg channel,psg:label{channel} EQU tab{psg} + channeloffset:"\ "endm:channel=1:while channel <= 9:psg=floor(((channel-1)/3)+1):channeloffset=((channel-1) % 3)*2:"\ "genreg {channel},{psg}:channel=channel+1:wend:assert LABEL5==#0202:assert LABEL6==#0204:assert LABEL7==#0300:"\ "assert LABEL8==#0302:nop" #define AUTOTEST_PLUSCOLOR " myval=0x123 : assert getr(myval)==2 : assert getb(myval)==3 : assert getg(myval)==1 : assert getv(myval)==1" \ " : assert setr(2)+setv(1)+setb(3)==0x123 : assert setv(-2)==setv(0) && setb(220)==setb(15) : nop " #define AUTOTEST_ASSERT " macro zem,nom,adr: overflow equ $-{adr}: assert $<{adr},{nom}: nop: mend: zem 'bidule',#2FFF :" \ " macro zem2,nom,adr: overflow2 equ $-{adr}: assert $<{adr},{nom},{adr},overflow2: nop: mend: zem2 'bidule',#2FFF :" \ " macro zem3,nom,adr: overflow3 equ $-{adr}: assert $<{adr},{nom},{hex}{adr},overflow3: nop: mend: zem3 'bidule',#2FFF " #define AUTOTEST_OPERATORASSIGN "a=5 : a*=3 : assert a==15 : a/=5 : assert a==3 : a&=2 : assert a==2 : a+=10 : assert a==12 : "\ "a-=3 : assert a==9 : a%=5 : assert a==4 : a|=1 : assert a==5 : a<<=3 : assert a==40 : "\ "a>>=1 : assert a==20 : nop" #define AUTOTEST_OPERATORASSIGN2 "a=1 : a+=2 : assert a==3 : repeat 2 : a+=10 : rend : assert a==23: a=1 : a-=2 : assert a==-1 : repeat 2 : a-=10 : rend : assert a==-21: " \ "a=3 : a*=2 : assert a==6 : repeat 2 : a*=10 : rend : assert a==600: a=600 : a/=2 : assert a==300 : repeat 2 : a/=10 : rend : assert a==3 : nop" struct s_autotest_keyword { char *keywordtest; int result; }; struct s_autotest_keyword autotest_keyword[]={ {"ld ly,h",1}, {"ld lx,h",1}, {"ld ly,l",1}, {"ld lx,l",1}, {"ld hy,h",1}, {"ld hx,h",1}, {"ld hy,l",1}, {"ld hx,l",1}, {"nop",0},{"nop 2",0},{"nop a",1},{"nop (hl)",1},{"nop nop",1},{"nop grouik",1}, {"ldir",0},{"ldir 5",1},{"ldir ldir",1},{"ldir (hl)",1},{"ldir a",1},{"ldir grouik",1}, {"ldi",0},{"ldi 5",1},{"ldi ldi",1},{"ldi (hl)",1},{"ldi a",1},{"ldi grouik",1}, {"lddr",0},{"lddr 5",1},{"lddr lddr",1},{"lddr (hl)",1},{"lddr a",1},{"lddr groudk",1}, {"ldd",0},{"ldd 5",1},{"ldd ldd",1},{"ldd (hl)",1},{"ldd a",1},{"ldd groudk",1}, {"jr $",0},{"jr 0",0},{"jr jr",1},{"jr (hl)",1},{"jr a",1}, {"jr c,$",0},{"jr c,0",0},{"jr c,jr",1},{"jr c,(hl)",1},{"jr c,a",1}, {"jr nc,$",0},{"jr nc,0",0},{"jr nc,jr",1},{"jr nc,(hl)",1},{"jr nc,a",1}, {"jr z,$",0},{"jr 0",0},{"jr jr",1},{"jr (hl)",1},{"jr a",1}, {"jr nz,$",0},{"jr 0",0},{"jr jr",1},{"jr (hl)",1},{"jr a",1}, {"jp $",0},{"jp 0",0},{"jp jp",1},{"jp (hl)",0},{"jp (ix)",0},{"jp (iy)",0},{"jp (de)",1},{"jp a",1}, {"jp c,$",0},{"jp c,0",0},{"jp c,jp",1}, {"jp c,(hl)",1}, {"jp c,(ix)",1}, {"jp c,(iy)",1},{"jp c,(de)",1},{"jp c,a",1}, {"jp nc,$",0},{"jp nc,0",0},{"jp nc,jp",1},{"jp nc,(hl)",1},{"jp nc,(ix)",1},{"jp nc,(iy)",1},{"jp nc,(de)",1},{"jp nc,a",1}, {"jp z,$",0},{"jp z,0",0},{"jp z,jp",1}, {"jp z,(hl)",1}, {"jp z,(ix)",1}, {"jp z,(iy)",1},{"jp z,(de)",1},{"jp z,a",1}, {"jp nz,$",0},{"jp nz,0",0},{"jp nz,jp",1},{"jp nz,(hl)",1},{"jp nz,(ix)",1},{"jp nz,(iy)",1},{"jp nz,(de)",1},{"jp nz,a",1}, {"jp pe,$",0},{"jp pe,0",0},{"jp pe,jp",1},{"jp pe,(hl)",1},{"jp pe,(ix)",1},{"jp pe,(iy)",1},{"jp pe,(de)",1},{"jp pe,a",1}, {"jp po,$",0},{"jp po,0",0},{"jp po,jp",1},{"jp po,(hl)",1},{"jp po,(ix)",1},{"jp po,(iy)",1},{"jp po,(de)",1},{"jp po,a",1}, {"jp p,$",0},{"jp p,0",0},{"jp p,jp",1}, {"jp p,(hl)",1}, {"jp p,(ix)",1}, {"jp p,(iy)",1},{"jp p,(de)",1},{"jp p,a",1}, {"jp m,$",0},{"jp m,0",0},{"jp m,jp",1}, {"jp m,(hl)",1}, {"jp m,(ix)",1}, {"jp m,(iy)",1},{"jp m,(de)",1},{"jp m,a",1}, {"ret",0},{"ret c",0},{"ret nc",0},{"ret pe",0},{"ret po",0},{"ret m",0},{"ret p",0},{"reti",0},{"ret ret",1},{"ret 5",1},{"ret (hl)",1},{"ret a",1}, {"xor a",0},{"xor a,b",1},{"xor",1},{"xor (de)",1},{"xor (hl)",0},{"xor (bc)",1},{"xor (ix+0)",0},{"xor (iy+0)",},{"xor xor",1}, {"and a",0},{"and a,b",1},{"xor",1},{"and (de)",1},{"and (hl)",0},{"and (bc)",1},{"and (ix+0)",0},{"and (iy+0)",},{"and xor",1}, {"or a",0},{"or a,b",1},{"xor",1},{"or (de)",1},{"or (hl)",0},{"or (bc)",1},{"or (ix+0)",0},{"or (iy+0)",},{"or xor",1}, {"add",1},{"add a",0},{"add a,a",0},{"add add",1},{"add (hl)",0},{"add (de)",1},{"add xh",0},{"add grouik",1}, {"add hl,ix",1},{"add hl,iy",1},{"add ix,iy",1},{"add iy,ix",1},{"add hl,0",1},{"add hl,grouik",1},{"add ix,hl",1},{"add iy,hl",1}, {"adc",1},{"adc a",0},{"adc a,a",0},{"adc adc",1},{"adc (hl)",0},{"adc (de)",1},{"adc xh",0},{"adc grouik",1}, {"adc hl,ix",1},{"adc hl,iy",1},{"adc ix,iy",1},{"adc iy,ix",1},{"adc hl,0",1},{"adc hl,grouik",1},{"adc ix,hl",1},{"adc iy,hl",1}, {"sub",1},{"sub a",0},{"sub a,a",0},{"sub sub",1},{"sub (hl)",0},{"sub (de)",1},{"sub xh",0},{"sub grouik",1}, {"sub hl,ix",1},{"sub hl,iy",1},{"sub ix,iy",1},{"sub iy,ix",1},{"sub hl,0",1},{"sub hl,grouik",1},{"sub ix,hl",1},{"sub iy,hl",1}, {"sbc",1},{"sbc a",0},{"sbc a,a",0},{"sbc sbc",1},{"sbc (hl)",0},{"sbc (de)",1},{"sbc xh",0},{"sbc grouik",1}, {"sbc hl,ix",1},{"sbc hl,iy",1},{"sbc ix,iy",1},{"sbc iy,ix",1},{"sbc hl,0",1},{"sbc hl,grouik",1},{"sbc ix,hl",1},{"sbc iy,hl",1}, {"exx",0},{"exx hl",1},{"exx hl,de",1},{"exx af,af'",1},{"exx exx",1},{"exx 5",1}, {"ex",1},{"ex af,af'",0},{"ex hl,de",0},{"ex hl,bc",1},{"ex hl,hl",1},{"ex hl,ix",1}, {"cp",1},{"cp cp ",1},{"cp 5",0},{"cp c",0},{"cp a,5",0},{"cp a,c",0},{"cp hl",1},{"cp (hl)",0},{"cp a,(hl)",0},{"cp (de)",1},{"cp de",1}, {"cpi",0},{"cpi (hl)",1},{"cpi a",1},{"cpi 5",1}, {"cpd",0},{"cpd (hl)",1},{"cpd a",1},{"cpd 5",1}, {"cpir",0},{"cpir (hl)",1},{"cpir a",1},{"cpir 5",1}, {"cpdr",0},{"cpdr (hl)",1},{"cpdr a",1},{"cpdr 5",1}, {"call #1234",0},{"call call",1},{"call (hl)",1},{"call (ix)",1},{"call (iy)",1},{"call (de)",1},{"call hl",1},{"call bc",1},{"call a",1},{"call 5,5",1}, {"rst 5",1},{"rst",1},{"rst 0",0},{"rst rst",1},{"rst (hl)",1},{"rst (ix)",1},{"rst (iy)",1},{"rst z",1},{"rst z,0",1}, {"djnz",1},{"djnz $",0},{"djnz $,0",1},{"djnz djnz",1},{"djnz (hl)",1}, {"djnz (ix)",1},{"djnz (iy)",1},{"djnz (bc)",1},{"djnz bc",1},{"djnz ix",1},{"djnz iy",1},{"djnz hl",1}, {"push",1},{"push push",1},{"push pop",1},{"push af'",1},{"push (ix)",1},{"push (hl)",1},{"push (#1234)",1},{"push #1234",1}, {"pop",1},{"pop pop",1},{"pop push",1},{"pop af'",1},{"pop (ix)",1},{"pop (hl)",1},{"pop (#1234)",1},{"pop #1234",1}, {"set -1,a",1},{"set 9,a",1},{"set 0,xh",1},{"set 0,ix",1},{"set 0",1},{"set",1},{"set set",1},{"set 0,a,a",1},{"set 0,(ix+0),xh",1}, {"bit -1,a",1},{"bit 9,a",1},{"bit 0,xh",1},{"bit 0,ix",1},{"bit 0",1},{"bit",1},{"bit bit",1},{"bit 0,a,a",1},{"bit 0,(ix+0),xh",1}, {"res -1,a",1},{"res 9,a",1},{"res 0,xh",1},{"res 0,ix",1},{"res 0",1},{"res",1},{"res res",1},{"res 0,a,a",1},{"res 0,(ix+0),xh",1}, {"srl",1},{"srl srl",1},{"srl hl",0}, /* srl hl is a kind of macro */ {"rld a",1},{"rld (hl)",1},{"rld rld",1},{"rld 5",1},{"rld (ix)",1}, {"rrd a",1},{"rrd (hl)",1},{"rrd rrd",1},{"rrd 5",1},{"rrd (ix)",1}, {"cpl a",1},{"cpl (hl)",1},{"cpl cpl",1},{"cpl 0",1}, {"daa daa daa",1},{"daa 0",1},{"daa (hl)",1}, {"scf scf",1},{"scf 0",1},{"scf (hl)",1}, {"ccf ccf",1},{"ccf 0",1},{"ccf (hl)",1}, {"out",1},{"out out",1},{"out (c)",1},{"out (c),xh",1},{"out 0",1}, {"out (c),hl",1},{"out (hl),c",1},{"out (c),(ix+0)",1},{"out (c),a,b",1}, {"outi 0",1},{"outi (hl)",1}, {"otir 0",1},{"otir (hl)",1}, {"otdr 0",1},{"otdr (hl)",1}, {"outd 0",1},{"outd (hl)",1}, {"in",1},{"in in",1},{"in (c)",1},{"in xh,(c)",1},{"in 0",1}, {"in hl,(c)",1},{"in c,(hl)",1},{"in (c),(ix+0)",1},{"in a,(c),b",1}, {"ini 0",1},{"ini (hl)",1}, {"inir 0",1},{"inir (hl)",1}, {"indr 0",1},{"indr (hl)",1}, {"ind 0",1},{"ind (hl)",1}, {"di 5",1},{"di di",1},{"di hl",1},{"di a",1}, {"ei 5",1},{"ei ei",1},{"ei hl",1},{"ei a",1}, {"im",1},{"im 3",1},{"im -1",1},{"im (hl)",1}, {"halt 5",1},{"reti 5",1},{"retn 5",1},{"ld i,b",1},{"ld b,i",1}, {"repeat 5:nop:rend",0},{"repeat 100000:a=5:rend",1},{"repeat -5:nop:rend",1},{"repeat repeat:nop:rend",1}, {"macro bidule:nop:mend:bidule",0},{"macro bidule:nop:macro glop:nop:mend:mend:bidule",1}, {"macro bidule:nop",1},{"macro bidule:nop:mend:macro glop:nop:bidule",1}, /* {"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",}, {"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",}, {"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",}, */ {NULL,0} }; void MiniDump(unsigned char *opcode, int opcodelen) { #undef FUNC #define FUNC "MiniDump" int i; printf("%d byte%s to dump\n",opcodelen,opcodelen>1?"s":""); for (i=0;i [%s]\n",cpt,tmpsplit[i]);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL; } MemFree(tmpstr3);FreeFields(tmpsplit); cpt++; printf("testing various opcode tests OK\n"); idx=0; while (autotest_keyword[idx].keywordtest) { ret=RasmAssemble(autotest_keyword[idx].keywordtest,strlen(autotest_keyword[idx].keywordtest),&opcode,&opcodelen); if (!ret && !autotest_keyword[idx].result) { } else if (ret && autotest_keyword[idx].result) { } else { printf("Autotest %03d ERROR ([%s] test) is %s instead of %s\n",cpt,autotest_keyword[idx].keywordtest,!ret?"ok":"ko",ret?"ok":"ko"); } if (opcode) MemFree(opcode);opcode=NULL; idx++; } cpt++; printf("testing moar various opcode tests OK\n"); ret=RasmAssemble(AUTOTEST_ORG,strlen(AUTOTEST_ORG),&opcode,&opcodelen); if (!ret && opcodelen==4 && opcode[1]==0x80 && opcode[2]==2 && opcode[3]==0x10) {} else {printf("Autotest %03d ERROR (ORG relocation)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing ORG relocation OK\n"); ret=RasmAssemble(AUTOTEST_MAXERROR,strlen(AUTOTEST_MAXERROR),&opcode,&opcodelen); if (ret) {} else {printf("Autotest %03d ERROR (must return an error code!)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing error code OK\n"); ret=RasmAssemble(AUTOTEST_BANKORG,strlen(AUTOTEST_BANKORG),&opcode,&opcodelen); if (!ret) {} else {printf("Autotest %03d ERROR (BANK org adr)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing BANK/ORG OK\n"); ret=RasmAssemble(AUTOTEST_LIMITOK,strlen(AUTOTEST_LIMITOK),&opcode,&opcodelen); if (!ret) {} else {printf("Autotest %03d ERROR (limit ok)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing LIMIT 1 OK\n"); ret=RasmAssemble(AUTOTEST_LIMITKO,strlen(AUTOTEST_LIMITKO),&opcode,&opcodelen); if (ret) {} else {printf("Autotest %03d ERROR (out of limit)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing LIMIT 2 OK\n"); ret=RasmAssemble(AUTOTEST_LIMIT03,strlen(AUTOTEST_LIMIT03),&opcode,&opcodelen); if (ret) {} else {printf("Autotest %03d ERROR (limit: negative limit)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing inegative LIMIT OK\n"); ret=RasmAssemble(AUTOTEST_LIMIT04,strlen(AUTOTEST_LIMIT04),&opcode,&opcodelen); if (ret) {} else {printf("Autotest %03d ERROR (limit: max limit test)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing max LIMIT OK\n"); ret=RasmAssemble(AUTOTEST_LIMIT05,strlen(AUTOTEST_LIMIT05),&opcode,&opcodelen); if (ret) {} else {printf("Autotest %03d ERROR (limit: ldir in #FFFF)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing 16 bits opcode overriding LIMIT OK\n"); ret=RasmAssemble(AUTOTEST_LIMIT06,strlen(AUTOTEST_LIMIT06),&opcode,&opcodelen); if (!ret) {} else {printf("Autotest %03d ERROR (limit: nop in #FFFF)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing opcode overriding LIMIT OK\n"); ret=RasmAssemble(AUTOTEST_LIMIT07,strlen(AUTOTEST_LIMIT07),&opcode,&opcodelen); if (ret) {} else {printf("Autotest %03d ERROR (limit: ld hl,#1234 in #FFFF)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing opcode with variable overriding LIMIT OK\n"); ret=RasmAssemble(AUTOTEST_DELAYED_RUN,strlen(AUTOTEST_DELAYED_RUN),&opcode,&opcodelen); if (!ret) {} else {printf("Autotest %03d ERROR (delayed RUN set)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing delayed RUN OK\n"); ret=RasmAssemble(AUTOTEST_LZSEGMENT,strlen(AUTOTEST_LZSEGMENT),&opcode,&opcodelen); if (!ret && opcodelen==23 && opcode[1]==21 && opcode[9]==23) {} else {printf("Autotest %03d ERROR (LZ segment relocation)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing LZ segment relocation OK\n"); ret=RasmAssemble(AUTOTEST_LZ4,strlen(AUTOTEST_LZ4),&opcode,&opcodelen); if (!ret && opcodelen==49 && opcode[0]==0x15 && opcode[4]==0x44 && opcode[0xB]==0xF0) {} else {printf("Autotest %03d ERROR (LZ4 segment)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing LZ4 segment OK\n"); ret=RasmAssemble(AUTOTEST_DEFS,strlen(AUTOTEST_DEFS),&opcode,&opcodelen); if (!ret && opcodelen==256 && opcode[0]==0) {} else {printf("Autotest %03d ERROR (defs)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing DEFS OK\n"); ret=RasmAssemble(AUTOTEST_BANKSET,strlen(AUTOTEST_BANKSET),&opcode,&opcodelen); if (!ret) {} else {printf("Autotest %03d ERROR (bank/bankset)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing BANK/BANKSET OK\n"); ret=RasmAssemble(AUTOTEST_PAGETAG,strlen(AUTOTEST_PAGETAG),&opcode,&opcodelen); if (!ret) {} else {printf("Autotest %03d ERROR (page/pageset)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing prefix PAGE/PAGESET 1 OK\n"); ret=RasmAssemble(AUTOTEST_PAGETAG2,strlen(AUTOTEST_PAGETAG2),&opcode,&opcodelen); if (!ret) {} else {printf("Autotest %03d ERROR (page/pageset 2)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing prefix PAGE/PAGESET 2 OK\n"); ret=RasmAssemble(AUTOTEST_PAGETAG3,strlen(AUTOTEST_PAGETAG3),&opcode,&opcodelen); if (!ret) {} else {printf("Autotest %03d ERROR (page/pageset 3)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing prefix PAGE/PAGESET 3 OK\n"); ret=RasmAssemble(AUTOTEST_UNDEF,strlen(AUTOTEST_UNDEF),&opcode,&opcodelen); if (!ret) {} else {printf("Autotest %03d ERROR (simple undef)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing UNDEF OK\n"); ret=RasmAssemble(AUTOTEST_TAGPRINT,strlen(AUTOTEST_TAGPRINT),&opcode,&opcodelen); if (!ret && opcodelen==1 && opcode[0]==0xC9) {} else {printf("Autotest %03d ERROR (tag inside printed string)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing tags inside printed string OK\n"); ret=RasmAssemble(AUTOTEST_TAGFOLLOW,strlen(AUTOTEST_TAGFOLLOW),&opcode,&opcodelen); if (!ret && opcodelen==1 && opcode[0]==0xC9) {} else {printf("Autotest %03d ERROR (tag+alias fast translating)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing tag+alias in fast translate OK\n"); ret=RasmAssemble(AUTOTEST_TAGREALLOC,strlen(AUTOTEST_TAGREALLOC),&opcode,&opcodelen); if (!ret && opcodelen==276) {} else {printf("Autotest %03d ERROR (tag realloc with fast translate)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing tag realloc with fast translate OK\n"); ret=RasmAssemble(AUTOTEST_TAGLOOP,strlen(AUTOTEST_TAGLOOP),&opcode,&opcodelen); if (!ret) {} else {printf("Autotest %03d ERROR (generated alias inside loop with generated var names )\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing generated alias inside loop with generated var names OK\n"); ret=RasmAssemble(AUTOTEST_PRINTVAR,strlen(AUTOTEST_PRINTVAR),&opcode,&opcodelen); if (!ret) {} else {printf("Autotest %03d ERROR (param inside printed string)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing param inside printed string OK\n"); ret=RasmAssemble(AUTOTEST_PRINTSPACE,strlen(AUTOTEST_PRINTSPACE),&opcode,&opcodelen); if (!ret) {} else {printf("Autotest %03d ERROR (space inside tag string for PRINT directive)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing space inside tag string for PRINT directive OK\n"); ret=RasmAssemble(AUTOTEST_INHIBITION,strlen(AUTOTEST_INHIBITION),&opcode,&opcodelen); if (!ret) {} else {printf("Autotest %03d ERROR (conditionnal inhibition)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing conditionnal inhibition OK\n"); ret=RasmAssemble(AUTOTEST_SWITCH,strlen(AUTOTEST_SWITCH),&opcode,&opcodelen); if (!ret && opcodelen==3 && opcode[0]==4 && opcode[1]==3 && opcode[2]==4) {} else {printf("Autotest %03d ERROR (switch case)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing SWITCH/CASE OK\n"); ret=RasmAssemble(AUTOTEST_NOCODE,strlen(AUTOTEST_NOCODE),&opcode,&opcodelen); if (!ret && opcodelen==57) {} else {printf("Autotest %03d ERROR (code/nocode)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing code/nocode OK\n"); ret=RasmAssemble(AUTOTEST_VAREQU,strlen(AUTOTEST_VAREQU),&opcode,&opcodelen); if (!ret) {} else {printf("Autotest %03d ERROR (var & equ)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing var & equ OK\n"); ret=RasmAssemble(AUTOTEST_CHARSET,strlen(AUTOTEST_CHARSET),&opcode,&opcodelen); if (!ret) {} else {printf("Autotest %03d ERROR (simple charset)\n",cpt);exit(-1);} if (opcodelen!=30 || memcmp(opcode,opcode+5,5) || memcmp(opcode+10,opcode+5,5)) {printf("Autotest %03d ERROR (simple charset)\n",cpt);exit(-1);} if (memcmp(opcode+15,opcode+20,5) || memcmp(opcode+15,opcode+25,5)) {printf("Autotest %03d ERROR (simple charset)\n",cpt);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing simple charset OK\n"); ret=RasmAssemble(AUTOTEST_CHARSET2,strlen(AUTOTEST_CHARSET2),&opcode,&opcodelen); if (!ret) {} else {printf("Autotest %03d ERROR (extended charset)\n",cpt);exit(-1);} for (i=chk=0;inberror==2 && debug->nbsymbol==3) { /* printf("\n"); for (i=0;inberror;i++) { printf("%d -> %s\n",i,debug->error[i].msg); } for (i=0;inbsymbol;i++) { printf("%d -> %s=%d\n",i,debug->symbol[i].name,debug->symbol[i].v); } RasmFreeInfoStruct(debug); */ } else {printf("Autotest %03d ERROR (embedded error struct) err=%d nberr=%d (2) nbsymb=%d (3)\n",cpt,ret,debug->nberror,debug->nbsymbol);MiniDump(opcode,opcodelen);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing internal error struct OK\n"); ret=RasmAssembleInfo(AUTOTEST_EMBEDDED_LABELS,strlen(AUTOTEST_EMBEDDED_LABELS),&opcode,&opcodelen,&debug); if (!ret && debug->nbsymbol==3) { /* printf("\nnbsymbol=%d\n",debug->nbsymbol); for (i=0;inbsymbol;i++) { printf("%d -> %s=%d\n",i,debug->symbol[i].name,debug->symbol[i].v); }*/ RasmFreeInfoStruct(debug); } else {printf("Autotest %03d ERROR (embedded test)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; printf("testing internal label struct OK\n"); #ifdef RDD printf("\n%d bytes\n",_static_library_memory_used); tmpstr3=FileReadContent("./test/PlayerAky.asm",&filelen); printf(".");fflush(stdout);ret=RasmAssembleInfo(tmpstr3,filelen,&opcode,&opcodelen,&debug); if (!ret) {} else {printf("Autotest %03d ERROR (PlayerAky)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);} if (opcode) MemFree(opcode);opcode=NULL;cpt++; RasmFreeInfoStruct(debug); MemFree(tmpstr3); printf("\n%d bytes\n",_static_library_memory_used); #endif FileRemoveIfExists("rasmoutput.cpr"); printf("All internal tests OK\n"); #ifdef RDD /* private dev lib tools */ printf("checking memory\n"); CloseLibrary(); #endif exit(0); } /****************************************************** LZ48 v005 / LZ49 v002 ******************************************************/ int LZ48_encode_extended_length(unsigned char *odata, int length) { int ioutput=0; while (length>=255) { odata[ioutput++]=0xFF; length-=255; } /* if the last value is 255 we must encode 0 to end extended length */ /*if (length==0) rasm_printf(ae,"bugfixed!\n");*/ odata[ioutput++]=(unsigned char)length; return ioutput; } int LZ48_encode_block(unsigned char *odata,unsigned char *data, int literaloffset,int literalcpt,int offset,int maxlength) { int ioutput=1; int token=0; int i; if (offset<0 || offset>255) { fprintf(stderr,"internal offset error!\n"); exit(-2); } if (literalcpt<15) { token=literalcpt<<4; } else { token=0xF0; ioutput+=LZ48_encode_extended_length(odata+ioutput,literalcpt-15); } for (i=0;i2) { token|=(maxlength-3); } else { /* endoffset has no length */ } } else { token|=0xF; ioutput+=LZ48_encode_extended_length(odata+ioutput,maxlength-18); } odata[ioutput++]=(unsigned char)offset-1; odata[0]=(unsigned char)token; return ioutput; } unsigned char *LZ48_encode_legacy(unsigned char *data, int length, int *retlength) { int i,startscan,current=1,token,ioutput=1,curscan; int maxoffset=0,maxlength,matchlength,literal=0,literaloffset=1; unsigned char *odata=NULL; odata=MemMalloc((size_t)length*1.5+10); if (!odata) { fprintf(stderr,"malloc(%.0lf) - memory full\n",(size_t)length*1.5+10); exit(-1); } /* first byte always literal */ odata[0]=data[0]; /* force short data encoding */ if (length<5) { token=(length-1)<<4; odata[ioutput++]=(unsigned char)token; for (i=1;i=3 && matchlength>maxlength) { maxoffset=startscan; maxlength=matchlength; } startscan++; } if (maxlength) { ioutput+=LZ48_encode_block(odata+ioutput,data,literaloffset,literal,current-maxoffset,maxlength); current+=maxlength; literaloffset=current; literal=0; } else { literal++; current++; } } ioutput+=LZ48_encode_block(odata+ioutput,data,literaloffset,literal,0,0); *retlength=ioutput; return odata; } int LZ49_encode_extended_length(unsigned char *odata, int length) { int ioutput=0; while (length>=255) { odata[ioutput++]=0xFF; length-=255; } /* if the last value is 255 we must encode 0 to end extended length */ /*if (length==0) rasm_printf(ae,"bugfixed!\n");*/ odata[ioutput++]=(unsigned char)length; return ioutput; } int LZ49_encode_block(unsigned char *odata,unsigned char *data, int literaloffset,int literalcpt,int offset,int maxlength) { int ioutput=1; int token=0; int i; if (offset<0 || offset>511) { fprintf(stderr,"internal offset error!\n"); exit(-2); } if (literalcpt<7) { token=literalcpt<<4; } else { token=0x70; ioutput+=LZ49_encode_extended_length(odata+ioutput,literalcpt-7); } for (i=0;i2) { token|=(maxlength-3); } else { /* endoffset has no length */ } } else { token|=0xF; ioutput+=LZ49_encode_extended_length(odata+ioutput,maxlength-18); } if (offset>255) { token|=0x80; offset-=256; } odata[ioutput++]=(unsigned char)offset-1; odata[0]=(unsigned char)token; return ioutput; } unsigned char *LZ49_encode_legacy(unsigned char *data, int length, int *retlength) { int i,startscan,current=1,token,ioutput=1,curscan; int maxoffset=0,maxlength,matchlength,literal=0,literaloffset=1; unsigned char *odata=NULL; odata=MemMalloc((size_t)(length*1.5+10)); if (!odata) { fprintf(stderr,"malloc(%.0lf) - memory full\n",(size_t)length*1.5+10); exit(-1); } /* first byte always literal */ odata[0]=data[0]; /* force short data encoding */ if (length<5) { token=(length-1)<<4; odata[ioutput++]=(unsigned char)token; for (i=1;i=3 && matchlength>maxlength) { maxoffset=startscan; maxlength=matchlength; } startscan++; } if (maxlength) { ioutput+=LZ49_encode_block(odata+ioutput,data,literaloffset,literal,current-maxoffset,maxlength); current+=maxlength; literaloffset=current; literal=0; } else { literal++; current++; } } ioutput+=LZ49_encode_block(odata+ioutput,data,literaloffset,literal,0,0); *retlength=ioutput; return odata; } /*************************************** semi-generic body of program ***************************************/ #ifndef INTEGRATED_ASSEMBLY /* Usage display the mandatory parameters */ void Usage(int help) { #undef FUNC #define FUNC "Usage" printf("%s (c) 2017 Edouard BERGE (use -n option to display all licenses)\n",RASM_VERSION); #ifndef NO_3RD_PARTIES printf("LZ4 (c) Yann Collet / ZX7 (c) Einar Saukas / Exomizer 2 (c) Magnus Lind\n"); #endif printf("\n"); printf("SYNTAX: rasm [options]\n"); printf("\n"); if (help) { printf("FILENAMES:\n"); printf("-oa automatic radix from input filename\n"); printf("-o choose a common radix for all files\n"); printf("-ob choose a full filename for binary output\n"); printf("-oc choose a full filename for cartridge output\n"); printf("-oi choose a full filename for snapshot output\n"); printf("-os choose a full filename for symbol output\n"); printf("-ot choose a full filename for tape output\n"); printf("-ok choose a full filename for breakpoint output\n"); printf("-I set a path for files to read\n"); printf("-no disable all file output\n"); printf("DEPENDENCIES EXPORT:\n"); printf("-depend=make output dependencies on a single line\n"); printf("-depend=list output dependencies as a list\n"); printf("if 'binary filename' is set then it will be outputed first\n"); printf("SYMBOLS EXPORT:\n"); printf("-s export symbols %%s #%%X B%%d (label,adr,cprbank)\n"); printf("-sz export symbols with ZX emulator convention\n"); printf("-sp export symbols with Pasmo convention\n"); printf("-sw export symbols with Winape convention\n"); printf("-ss export symbols in the snapshot (SYMB chunk for ACE)\n"); printf("-sc export symbols with source code convention\n"); printf("-sm export symbol in multiple files (one per bank)\n"); printf("-l import symbol file (winape,pasmo,rasm)\n"); printf("-eb export breakpoints\n"); printf("-wu warn for unused symbols (alias, var or label)\n"); printf("SYMBOLS ADDITIONAL OPTIONS:\n"); printf("-sl export also local symbol\n"); printf("-sv export also variables symbol\n"); printf("-sq export also EQU symbol\n"); printf("-sa export all symbols (like -sl -sv -sq option)\n"); printf("-Dvariable=value import value for variable\n"); printf("COMPATIBILITY:\n"); printf("-m Maxam style calculations\n"); printf("-dams Dams 'dot' label convention\n"); printf("-ass AS80 behaviour mimic\n"); printf("-uz UZ80 behaviour mimic\n"); printf("EDSK generation/update:\n"); printf("-eo overwrite files on disk if it already exists\n"); printf("SNAPSHOT:\n"); printf("-sb export breakpoints in snapshot (BRKS & BRKC chunks)\n"); printf("-ss export symbols in the snapshot (SYMB chunk for ACE)\n"); printf("-v2 export snapshot version 2 instead of version 3\n"); printf("PARSING:\n"); printf("-me set maximum number of error (0 means no limit)\n"); printf("-xr extended error display\n"); printf("-w disable warnings\n"); printf("-void force void usage with macro without parameter\n"); printf("\n"); } else { printf("use option -h for help\n"); printf("\n"); } exit(ABORT_ERROR); } void Licenses() { #undef FUNC #define FUNC "Licenses" printf(" ____ \n"); printf(" | _ \\ __ _ ___ _ __ ___ \n"); printf(" | |_) / _` / __| '_ ` _ \\ \n"); printf(" | _ < (_| \\__ \\ | | | | |\n"); printf(" |_| \\_\\__,_|___/_| |_| |_|\n"); printf("\n"); printf(" is using MIT 'expat' license\n"); printf("\" Copyright (c) BERGE Edouard (roudoudou)\n\n"); printf("Permission is hereby granted, free of charge,\n"); printf("to any person obtaining a copy of this software\n"); printf("and associated documentation/source files of\n"); printf("RASM, to deal in the Software without restriction,\n"); printf("including without limitation the rights to use,\n"); printf("copy, modify, merge, publish, distribute,\n"); printf("sublicense, and/or sell copies of the Software,\n"); printf("and to permit persons to whom the Software is\n"); printf("furnished to do so, subject to the following\n"); printf("conditions:\n"); printf("The above copyright notice and this permission\n"); printf("notice shall be included in all copies or\n"); printf("substantial portions of the Software.\n"); printf("The Software is provided 'as is', without\n"); printf("warranty of any kind, express or implied,\n"); printf("including but not limited to the warranties of\n"); printf("merchantability, fitness for a particular\n"); printf("purpose and noninfringement. In no event shall\n"); printf("the authors or copyright holders be liable for\n"); printf("any claim, damages or other liability, whether\n"); printf("in an action of contract, tort or otherwise,\n"); printf("arising from, out of or in connection with the\n"); printf("software or the use or other dealings in the\n"); printf("Software. \"\n"); #ifndef NO_3RD_PARTIES printf("\n\n\n\n"); printf("******* license of LZ4 cruncher / sources were modified ***********\n\n\n\n"); printf("BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n"); printf("Redistribution and use in source and binary forms, with or without\n"); printf("modification, are permitted provided that the following conditions are\n"); printf("met:\n\n"); printf(" * Redistributions of source code must retain the above copyright\n"); printf("notice, this list of conditions and the following disclaimer.\n"); printf(" * Redistributions in binary form must reproduce the above\n"); printf("copyright notice, this list of conditions and the following disclaimer\n"); printf("in the documentation and/or other materials provided with the\n"); printf("distribution.\n\n"); printf("THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"); printf("'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"); printf("LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"); printf("A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"); printf("OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"); printf("SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"); printf("LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"); printf("DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"); printf("THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"); printf("(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"); printf("OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n"); printf("You can contact the author at :\n"); printf(" - LZ4 homepage : http://www.lz4.org\n"); printf(" - LZ4 source repository : https://github.com/lz4/lz4\n"); printf("\n\n\n\n"); printf("******* license of ZX7 cruncher / sources were modified ***********\n\n\n\n"); printf(" * (c) Copyright 2012 by Einar Saukas. All rights reserved.\n"); printf(" *\n"); printf(" * Redistribution and use in source and binary forms, with or without\n"); printf(" * modification, are permitted provided that the following conditions are met:\n"); printf(" * * Redistributions of source code must retain the above copyright\n"); printf(" * notice, this list of conditions and the following disclaimer.\n"); printf(" * * Redistributions in binary form must reproduce the above copyright\n"); printf(" * notice, this list of conditions and the following disclaimer in the\n"); printf(" * documentation and/or other materials provided with the distribution.\n"); printf(" * * The name of its author may not be used to endorse or promote products\n"); printf(" * derived from this software without specific prior written permission.\n"); printf(" *\n"); printf(" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND\n"); printf(" * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n"); printf(" * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n"); printf(" * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY\n"); printf(" * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n"); printf(" * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n"); printf(" * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n"); printf(" * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"); printf(" * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n"); printf(" * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"); printf("\n\n\n\n"); printf("******* license of exomizer cruncher / sources were modified ***********\n\n\n\n"); printf(" * Copyright (c) 2005 Magnus Lind.\n"); printf(" *\n"); printf(" * This software is provided 'as-is', without any express or implied warranty.\n"); printf(" * In no event will the authors be held liable for any damages arising from\n"); printf(" * the use of this software.\n"); printf(" *\n"); printf(" * Permission is granted to anyone to use this software, alter it and re-\n"); printf(" * distribute it freely for any non-commercial, non-profit purpose subject to\n"); printf(" * the following restrictions:\n"); printf(" *\n"); printf(" * 1. The origin of this software must not be misrepresented; you must not\n"); printf(" * claim that you wrote the original software. If you use this software in a\n"); printf(" * product, an acknowledgment in the product documentation would be\n"); printf(" * appreciated but is not required.\n"); printf(" *\n"); printf(" * 2. Altered source versions must be plainly marked as such, and must not\n"); printf(" * be misrepresented as being the original software.\n"); printf(" *\n"); printf(" * 3. This notice may not be removed or altered from any distribution.\n"); printf(" *\n"); printf(" * 4. The names of this software and/or it's copyright holders may not be\n"); printf(" * used to endorse or promote products derived from this software without\n"); printf(" * specific prior written permission.\n"); #endif printf("\n\n"); exit(0); } int _internal_check_flexible(char *fxp) { #undef FUNC #define FUNC "_internal_check_flexible" char *posval,*posvar; int cpt=0,i; posvar=strstr(fxp,"%s"); posval=strstr(fxp,"%"); if (!posval || !posvar) { printf("invalid flexible export string, need 2 formated fields, example: \"%%s %%d\"\n"); exit(1); } if (posval2) { printf("invalid flexible export string, must be only two formated fields, example: \"%%s %%d\"\n"); exit(1); } return 1; } /* ParseOptions used to parse command line and configuration file */ int ParseOptions(char **argv,int argc, struct s_parameter *param) { #undef FUNC #define FUNC "ParseOptions" char *sep; int i=0; if (strcmp(argv[i],"-autotest")==0) { RasmAutotest(); } else if (strcmp(argv[i],"-uz")==0) { param->as80=2; } else if (strcmp(argv[i],"-ass")==0) { param->as80=1; } else if (strcmp(argv[i],"-eb")==0) { param->export_brk=1; } else if (strcmp(argv[i],"-wu")==0) { param->warn_unused=1; } else if (strcmp(argv[i],"-dams")==0) { } else if (strcmp(argv[i],"-void")==0) { param->macrovoid=1; } else if (strcmp(argv[i],"-xr")==0) { param->extended_error=1; } else if (strcmp(argv[i],"-eo")==0) { param->edskoverwrite=1; } else if (strcmp(argv[i],"-depend=make")==0) { param->dependencies=E_DEPENDENCIES_MAKE; param->checkmode=1; } else if (strcmp(argv[i],"-depend=list")==0) { param->dependencies=E_DEPENDENCIES_LIST; param->checkmode=1; } else if (strcmp(argv[i],"-no")==0) { param->checkmode=1; } else if (strcmp(argv[i],"-w")==0) { param->nowarning=1; } else if (argv[i][0]=='-') { switch(argv[i][1]) { case 'I': if (argv[i][2]) { char *curpath; int l; l=strlen(argv[i]); curpath=MemMalloc(l); /* strlen(path)+2 */ strcpy(curpath,argv[i]+2); #ifdef OS_WIN if (argv[i][l-1]!='/' && argv[i][l-1]!='\\') strcat(curpath,"\\"); #else if (argv[i][l-1]!='/' && argv[i][l-1]!='\\') strcat(curpath,"/"); #endif FieldArrayAddDynamicValueConcat(¶m->pathdef,¶m->npath,¶m->mpath,curpath); MemFree(curpath); } else { Usage(1); } break; case 'D': if ((sep=strchr(argv[i],'='))!=NULL) { if (sep!=argv[i]+2) { FieldArrayAddDynamicValueConcat(¶m->symboldef,¶m->nsymb,¶m->msymb,argv[i]+2); } else { Usage(1); } } else { Usage(1); } break; case 'm': switch (argv[i][2]) { case 0: param->rough=0.0; return i; case 'e': if (argv[i][3]) Usage(1); if (i+1maxerr=atoi(argv[++i]); return i; } default:Usage(1); } Usage(1); break; case 's': if (argv[i][2] && argv[i][3]) Usage(1); switch (argv[i][2]) { case 0:param->export_sym=1;return 0; case 'z': param->export_sym=5;return 0; case 'm': param->export_multisym=1;return 0; case 'b': param->export_snabrk=1;return 0; case 'p': param->export_sym=2;return 0; case 'w': param->export_sym=3;return 0; case 'c': if (i+1export_sym=4; param->flexible_export=TxtStrDup(argv[++i]); param->flexible_export=MemRealloc(param->flexible_export,strlen(param->flexible_export)+3); strcat(param->flexible_export,"\n"); /* check export string */ if (_internal_check_flexible(param->flexible_export)) return i; else Usage(1); } Usage(1); case 'l': param->export_local=1;return 0; case 'v': param->export_var=1;return 0; case 'q': param->export_equ=1;return 0; case 'a': param->export_local=1; param->export_var=1; param->export_equ=1; return 0; case 's': param->export_local=1; param->export_sym=1; param->export_sna=1;return 0; default: break; } Usage(1); case 'l': if (argv[i][2]) Usage(1); if (i+1labelfilename,argv[++i]); break; } Usage(1); case 'i': printf("@@@\n@@@ --> deprecated option, there is no need to use -i option to set input file <--\n@@@\n"); Usage(0); case 'o': if (argv[i][2] && argv[i][3]) Usage(1); switch (argv[i][2]) { case 0: if (i+1outputfilename==NULL) { param->outputfilename=argv[++i]; break; } Usage(1); case 'a': param->automatic_radix=1; break; case 't': if (i+1tape_name==NULL) { param->tape_name=argv[++i]; break; } Usage(1); case 'i': if (i+1snapshot_name==NULL) { param->snapshot_name=argv[++i]; break; } Usage(1); case 'b': if (i+1binary_name==NULL) { param->binary_name=argv[++i]; break; } Usage(1); case 'c': if (i+1cartridge_name==NULL) { param->cartridge_name=argv[++i]; break; } Usage(1); case 'k': if (i+1breakpoint_name==NULL) { param->breakpoint_name=argv[++i]; break; } Usage(1); case 's': if (i+1symbol_name==NULL) { param->symbol_name=argv[++i]; break; } Usage(1); default: Usage(1); } break; case 'd':if (!argv[i][2]) printf("deprecated option -d\n"); else Usage(1); break; case 'a':if (!argv[i][2]) printf("deprecated option -a\n"); else Usage(1); break; case 'c':if (!argv[i][2]) printf("deprecated option -c\n"); else Usage(1); break; case 'v': if (!argv[i][2]) { printf("deprecated option -v\n"); } else if (argv[i][2]=='2') { param->v2=1; } break; case 'n':if (!argv[i][2]) Licenses(); else Usage(1); case 'h':Usage(1); default: Usage(1); } } else { if (param->filename==NULL) { param->filename=TxtStrDup(argv[i]); } else if (param->outputfilename==NULL) { param->outputfilename=argv[i]; } else Usage(1); } return i; } /* GetParametersFromCommandLine retrieve parameters from command line and fill pointers to file names */ void GetParametersFromCommandLine(int argc, char **argv, struct s_parameter *param) { #undef FUNC #define FUNC "GetParametersFromCommandLine" int i; for (i=1;ifilename) Usage(0); if (param->export_local && !param->export_sym) Usage(1); // à revoir? } /* main check parameters execute the main processing */ int main(int argc, char **argv) { #undef FUNC #define FUNC "main" struct s_parameter param={0}; int ret; param.maxerr=20; param.rough=0.5; GetParametersFromCommandLine(argc,argv,¶m); ret=Rasm(¶m); #ifdef RDD /* private dev lib tools */ printf("checking memory\n"); CloseLibrary(); #endif exit(ret); return 0; // Open WATCOM Warns without this... } #endif