From 01e01039f6adeaf03eee0a7762432f448b70f7c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89douard=20BERG=C3=89?= Date: Thu, 16 Aug 2018 16:38:19 +0300 Subject: [PATCH] Update to v0.99 --- docs/RASM_manual_EN.pdf | Bin 198143 -> 0 bytes docs/RASM_manual_FR.pdf | Bin 168710 -> 0 bytes docs/rasm_en.html | 1390 +++++++++++ docs/rasm_fr.html | 1404 +++++++++++ minilib.h | 96 +- rasm.c | 5235 +++++++++++++++++++++++++++++---------- updates.txt | 92 +- 7 files changed, 6872 insertions(+), 1345 deletions(-) delete mode 100644 docs/RASM_manual_EN.pdf delete mode 100644 docs/RASM_manual_FR.pdf create mode 100644 docs/rasm_en.html create mode 100644 docs/rasm_fr.html diff --git a/docs/RASM_manual_EN.pdf b/docs/RASM_manual_EN.pdf deleted file mode 100644 index 535602eb650d76d2d21d70061d76c19a08b54e3f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 198143 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

|Da{pCplg=Dn+`$WggM2DVHp9Gek# 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�HhRkS|6%MMg9A;UH{2u>+qP}n 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

    }`VEO?uF>9y-Xl{ep?*lr8D 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 + + +

    Contents

    +
    Introduction
    + Features
    + Installation
    + Compilation
    +    - Linux Compilation
    +    - Windows Compilation
    +    - DOS Compilation
    +    - Morphos Compilation
    + + Behaviour
    + command line
    +    - File options
    +    - EDSK file export
    +    - Snapshot file export
    +    - Symbol options
    +    - Dependencies options
    +    - Compatibility options
    +    - Dev options (internal use)
    + + Format
    +    - General
    +    - Comments
    +    - Literal values
    +    - Allowed characters
    +    - Files
    +    - Labels
    +    - Proximity labels
    +    - Local labels
    +    - Tags specific to labels or structures
    +       {BANK}
    +       {PAGE}
    +       {PAGESET}
    +       {SIZEOF}
    +    - Syntax coloring in VIM
    + + Expressions
    +    - Calculation operators
    +    - Operators priorities
    + + Variables
    +    - Statics
    +    - Dynamics
    + + Memory directives
    +    - ALIGN
    +    - BANK
    +    - BANKSET
    +    - LIMIT
    +    - ORG
    +    - PROTECT
    +    - WRITE DIRECT
    + + Data directives
    +    - CHARSET
    +    - DEFB
    +    - DEFW
    +    - DEFI
    +    - DEFR
    +    - DEFS
    +    - EQU
    +    - STR
    +    - STRUCT
    + + Import and compression directives
    +    - INCLUDE
    +    - INCBIN
    +    - INCL48, INCL49, INCLZ4, INCZX7, INCEXO
    +    - LZ48, LZ49, LZ4, LZX7, LZEXO
    +    - LZCLOSE
    + + Conditionnal code directives
    +    - ASSERT
    +    - IF IFNOT THEN ELSEIF ELSE ENDIF
    +    - IFDEF, IFNDEF
    +    - IFUSED, IFNUSED
    +    - MACRO
    +    - PRINT
    +    - FAIL
    +    - REPEAT, REND, UNTIL
    +    - SWITCH, CASE, DEFAULT, BREAK, ENDSWITCH
    +    - STOP
    +    - WHILE, WEND
    + + File output directives
    +    - AMSDOS
    +    - BREAKPOINT
    +    - BUILDCPR
    +    - BUILDSNA
    +    - RUN
    +    - SAVE
    +    - SETCPC
    +    - SETCRTC
    + + Useless directives
    +    - LIST, NOLIST, LET
    + + Instruction set
    + Limitations
    + +
    + + + +
    Introduction
    + During the making of my first big demo CRTC³, available assemblers were too slow and too limited. The demo has 250'000 words (out of comments), 35'000 labels and 60'000 expressions. I needed a damn fast assembler with cartridge management, banking facilities and integrated crunched sections (to avoid import/export and multi-pass).

    + + 18 years ago i wrote a small assembler. I didn't use it back in the days cause it was very limited. Nevertheless, i took up the mono-pass concept of it.

    + + Rasm uses proven concepts (merkel trees, many caches, grouped allocs) and a linear conception because recursivity slow down anything. The performances in real conditions are really fast, especially with huge projects.

    + + Nowadays Rasm is used on big projects:
    +  - Ghost'n Goblins by Golem13
    +  - Arkos Tracker II by Targhan (embedded in the software)
    +
    +
    + Rasm is under MIT licence. +
    +
    Fonctionnalities
    +
      +
    • ultra-fast compilation
    • +
    • common compressors included
    • +
    • binary, snapshot, floppy, cartridge export
    • +
    • symbols import/export
    • +
    • overwriting control
    • +
    • unlimited memory spaces where labels are shared
    • +
    • dedicated directives for memory/ROM management
    • +
    • all instructions supported
    • +
    • macros, conditionnal code, unlimited loops, local labels, switch/case
    • +
    • double precision calculation with correct rounding
    • +
    • optionnal compatibility with Maxam or AS80
    • +
    +
    +
    Installation
    + Rasm is a standalone executable, there is no installation. +
    +
    Compilation
    +
    Linux compilation
    + + cc rasm_v096.c -O2 -lm -lrt -march=native
    + mv a.out rasm
    + strip rasm +
    +
    +
    Windows compilation
    + + cl.exe rasm_v096.c -O2 + +
    +
    Compilation DOS or Windows 32 bits with Watcom
    + + # do not use -s or -ox option, this will cause a fatal stack issue + wcl386.exe rasm_v096.c -6r -6s -fp6 -d0 -k4000000 -obmiler + +
    +
    MorphOS compilation
    + + ppc-morphos-gcc-5 -O2 -c -o rasm rasm_v096.c
    + strip rasm +
    +
    +
    +
    Rasm behaviour
    + The goal of Rasm is to be easy to use. He will make default filenames, autoselect a cartridge or snapshot file when dedicated ROM directives are used.

    + + Rasm allow any ORG in the same memory space but it will trigger an error if two ORG zones overlap. For each new ORG, Rasm will do the check.

    + + If you need to assemble two programs in the same adressing range you may use the second parameter of ORG to relocate the code elsewhere or create a new memory space with directive BANK

    + + Rasm has many error messages to help fixing wrong syntax.

    + + Rasm pre-processor remove useless spaces and comments. A first check is perform on valid characters and quotes. Some Maxam operators are translated to their C equivalent.

    + + When using relative file reference, the root directory to the relative path is that of the current file.

    +
    +
    Command line
    + Usage: rasm.exe <file to assemble> [options]

    + + Example: rasm.exe myfile.asm +
    Filenames options
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    -o <file radix>set a common name for each output file, disregarding his type (.bin, .cpr, .sym). The default value is “rasmoutputâ€
    + Example:
    + + rasm.exe test -o grouik -s
    + Pre-processing [test.asm]
    + Assembling
    + Write binary file grouik.bin (25 bytes)
    + Write symbol file grouik.sym (10 bytes)
    +
    +
    -ob <binary filename>set the full filename for automatic binary output.
    -oc <cartridge filename>set the full filename for cartridge output.
    -oi <snapshot filename>set the full filename for snapshot output.
    -os <symbol filename>set the full filename for symbol output.
    -ok <breakpoint filename>set the full filename for breakpoint export.
    -I<include directory>set the include directory. Multiple -I options is possible.
    -nodisable file output.
    +
    +
    EDSK file option
    + + + + + + +
    -eo   overwrite file in the EDSK if it exists.
    +
    +
    Snapshot file option
    + + + + + + + + + + + + + +
    -v2Export a snapshot version 2 (default is version 3) +
    -sbExport breakpoints in snapshot file (Winape and ACE emulator format), only with snapshot version 3+
    -ssExport symbols in snapshot file (Winape and ACE emulator format), only with snapshot version 3+
    +
    +
    Symbol options
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    -sexport symbols in Rasm format
    + Example of outputed file:
    + + LABEL1 #0 B0
    + LABEL2 #1 B0
    + LABEL3 #2 B0
    + LABEL4 #4 B0
    +
    +
    -spexport symbols in Pasmo format
    + Example of outputed file:
    + + LABEL1 EQU 00000H
    + LABEL2 EQU 00001H
    + LABEL3 EQU 00002H
    + LABEL4 EQU 00004H
    +
    +
    -swexport symbols in Winape format
    + Example of outputed file:
    + + LABEL1 #0
    + LABEL2 #1
    + LABEL3 #2
    + LABEL4 #4
    +
    +
    -sladditionnal option to export also local labels.
    -svadditionnal option to export also variables.
    -sqadditionnal option to export also EQU aliases.
    -sameta option meaning -sl -sv -sq
    -ssexport symbols in snapshot
    -ebexport breakpoints
    -l <label file>import symbols in Rasm, Pasmo or Winape format
    + Note: You may import as many symbol file as you want using multiple times -l option
    + + rasm.exe test -l import1.sym -l import2.sym -l import3.sym
    +
    +
    + + Note 1: Arnold emulator is Rasm and Pasmo compliant for labels.
    + Note 2: Winape emulator cannot handle long labels.
    +
    +
    Dependencies options
    + -depend=make
    +Export all dependencies in a single line (for makefile usage)

    + -depend=list
    +Export all dependencies, one per line (for other usage)

    + If there is a binary output filename set (-ob option), it will be outputed in first position. +
    +
    Compatibility options
    + + + + + + + + + + + + + + + + + + + + + +
               
    -mMaxam compatibility
      +
    • 16 bits unsigned integer calculations with wrong rounding
    • +
    • comparisons using single = sign
    • +
    • simplified operator priorities (see charts)
    • +
    -assAS80 compatibility
      +
    • 32 bits integer calculations with wrong rounding
    • +
    • DEFB,DEFW,DEFI or DEFR directives with more than one parameter use first outputed byte as reference adress. Not the current outputed byte. That's why AS80 does not generate the same thing when using two DEFB instead of one with two parameters when using $ reference in it.
    • +
    • macro parameters are not protected by {}
    • +
    • MACRO directive must be used after the name of the macro
    • +
    -uzUZ80 compatibility
      +
    • 32 bits integer calculations with wrong rounding
    • +
    • macro parameters are not protected by {}
    • +
    • MACRO directive must be used after the name of the macro
    • +
    +
    +
    Dev options
    + + + + + + + + + + + + + + + + + +
    -vverbose mode, display stats
    -dverbose detailed pre-processing
    -averbose detailed assembling
    -ndisplay third parties licences
    +
    +
    +
    Source code format
    +
    Generalities
    + Assembler is not COBOL, it's useless to use identation with Rasm, except to be pretty. A ":" separator is not required between labels and instructions. As a direct consequence you cannot use a reserved word (directive, register, Z80 instruction) as a label.

    + + As you may declare two labels without separator, i encourage you to use the optionnal "(void)" parameter with macros declared without parameter (see macro chapter)

    + + Windows and Unix files are both supported.

    + + Rasm is not case sensitive. Don't be surprise to see your code in upper case in error messages.

    + + A label is NOT an alias, and NOT a variable. Rasm knows the difference!

    + + - a label refer to a memory adress (an adress and sometimes a memory page if the workspace is in cartridge/snapshot space)
    + - an alias (EQU) is a text, which encountered, is replaced by another one. Known variables are translated during first declaration
    + - a variable is global to the whole source, his value must be initialised and may be modified anytime
    +
    +
    Comments
    + Rasm uses the semicolon to start a comment. Every appending chars will be ignored until carriage return.

    + + Note: There is no multi-lines comments. +
    +
    Literal values
    + Rasm accepts the following values:
    +
      +
    • Decimal if the value begins with a digit.
    • +
    • Binary if the value begins with %, 0b or ends with b.
    • +
    • Octal if the value begins with @.
    • +
    • Hexadecimal if the value begins with #, $, 0x or ends with h.
    • +
    • ASCII value with a single char between quotes.
    • +
    • Value of a label or a variable if it begins with a letter or @ followed by a letter.
    • +
    • $ symbol used alone means current instruction adress. When using DEFB, DEFW, DEFI, DEFR ou DEFS, the current adress is that of the current instruction. DEF* directives will output the very same data if you use multiple DEF or one DEF with multiple arguments.
    • +
    + + All Rasm calculations are done with double precision floating point accumulator. A correct rounding is done in the end for integer needs.

    + + Beware of the & char, reserved for AND operator. +
    +
    Allowed chars
    + Between quotes, all characters are allowed, at your own risks for special conversions. Outside quotes, you can use letters, digits, the dot, arobas, parenthesis, dollar, operators, pipe, power, percent, sharp, paragraphs, chevrons and also both quotes types.

    + Quoted strings may contains escaped chars:
    +
  • \t

  • +
  • \n

  • +
  • \r

  • +
  • \f

  • +
  • \v

  • +
  • \b

  • +
  • \0
  • -> except with PRINT directive
    + +
    +
    Files
    + RASM is using UNIX model for file management. Windows path are converted on the fly. If you use only relative paths and filenames Windows can handle, you may use your sources with Rasm either with Linux or Windows without modification.

    + + Relative path rule is simple: Every relative path take root of the file where it was read. +
    +
    Labels
    + Inside a loop (REPEAT/WHILE/UNTIL) or inside a macro, you may use local labels the same way as Winape assembler does, prefixing labels with '@'.

    + + You may use a label value with a directive (ORG for example) only if the label declaration is before the directive.

    + + Every label beginning with BRK or @BRK will generate a BREAKPOINT.

    + + In DAMS mode, you may prefix labels with a dot but the call to this label will be done without the dot. DAMS mode will disable proximity labels.

    +
    +
    Local labels
    + Local labels must be declared inside a loop or a repeat. Those labels are invisibles out of the loop scope.

    + + Local labels are declared with prefix '@'.

    + + Usage of local label in a loop:
    + + repeat 16
    + add hl,bc
    + jr nc,@no_overflow
    + dec hl
    + @no_overflow
    + rend
    +
    +
    +
    Proximity label
    + Proximity labels may be used anywhere. The prefix is the dot '.'

    + + Proximity label sample code:
    + + routine1
    + add hl,bc
    + jr nc,.no_overflow
    + dec hl
    + .no_overflow
    +
    + routine2
    + add hl,bc
    + jr nc,.no_overflow
    + dec hl
    + .no_overflow
    +
    + routine3
    + xor a
    + ld hl,routine1.no_overflow ; retrieve proximity label of routine1
    + ld de,routine2.no_overflow ; of routine2
    + sbc hl,de
    +
    +
    +
    Specifics tags for labels or structures
    +
    {BANK}
    + Using {BANK} prefix before a label (example: {BANK}mylabel ) get the BANK number where is located the label, instead of his absolute adress.

    + + Example:
    + + Bank 0
    + ld a,{bank}mysub ; will be assembled LD A,1
    + call connect_bank
    + jp mysub
    + bank 1
    + defb 'coucou'
    + mysub
    + jr $
    +
    + +
    {PAGE}
    + Using {PAGE} prefix before a label (example: {PAGE}mylabel ) get a Gate array style of the BANK number where is located the label, instead of the label adress.

    + If you are using BANKSET directive to select 4 banks in a 64K set, then the gate array value is composed of the set number and the 2 most significant bits of the label adress.

    + + Example:
    + + Bank 0
    + ld a,{page}mysub ; will be assembled LD A,#C5
    + ld b,#7F
    + out (c),a
    + jp mysub
    + bank 5
    + defb 'coucou'
    + mysub
    + jr $
    +
    +
    {PAGESET}
    + Using {PAGESET} prefix before a label (example: {PAGESET}mylabel ) get a Gate array style of the BANKSET number where is located the label, instead of the label adress.

    + + Example:
    + + bank 0
    + ld a,{pageset}mysub ; will be assembled LD A,#C2
    + ld b,#7F
    + out (c),a ; as all the RAM is switching the code is supposed to be in ROM, or in a proper place
    + jp mysub
    + bank 5
    + defb 'coucou'
    + mysub
    + jr $
    +
    +
    {SIZEOF}
    + Using {SIZEOF} prefix before a structure name get the size of it.

    + + See structure chapter here. +
    +
    Syntax color with VIM
    +
      +
    • If you already own a syntax color file, just add the following lines to the file .vim/syntax/z80.vim
    • +
    • Or you may download the whole file here
    • +
    +
    + + " rasm/winape directives
    + syn keyword z80PreProc charset bank write save include incbin incl48 incl49
    + syn keyword z80PreProc macro mend switch case break while wend repeat until
    + syn keyword z80PreProc buildcpr amsdos lz48 lz49 lzclose protect
    + syn keyword z80PreProc direct brk let print stop nolist str
    + syn keyword z80PreProc defr dr defi bankset page pageset sizeof endm struct endstruct ends
    + syn keyword z80PreProc incexo lzexo lzx7 inczx7 buildsna setcrtc setcpc assert print
    + syn keyword z80Reg lix liy hix hiy
    +
    + +
    +
    +
    Expressions
    +
    Calculation operators
    + Rasm is using a simplified calculation engine with multiple priorities (like C language). Here is the list of supported operations:
    +
      +
    • * multiply
    • +
    • / divide
    • +
    • + addition
    • +
    • - soustraction
    • +
    • & or AND for logical and
    • +
    • | or OR for logical or
    • +
    • ^ or XOR for logical xor
    • +
    • % or MOD for modulo
    • +
    • && for boolean and
    • +
    • || for boolean or
    • +
    • << multiply by a power of two
    • +
    • >> divide by a power of two
    • +
    • hi() get upper 8 bits of a word
    • +
    • lo() get lower 8 bits of a word
    • +
    • sin() sinus
    • +
    • cos() cosinus
    • +
    • asin() d'arc-sinus
    • +
    • acos() d'arc-cosinus
    • +
    • atan() d'arc-tangente
    • +
    • int() float to integer conversion
    • +
    • floor() convert a float to the closest lower integer value
    • +
    • abs() absolute value
    • +
    • ln() logarithme népérien
    • +
    • log10() logarithme base 10
    • +
    • exp() exponentielle
    • +
    • sqrt() square root
    • +
    • == égalité (ou un seul = en mode Maxam)
    • +
    • != ou <> différent de
    • +
    • <= less or equal
    • +
    • >= greater or equal
    • +
    • < lower
    • +
    • > greater
    • +
    +
    +
    Operators priorities
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Lower is the prevalence, higher is the execution priority.
    OperatorsRasm PrevalenceMaxam Prevalence
    (   )00
    !  1464
    *   /   %2464
    +   -3464
    <<   >>4464
    <   <=   ==   =>   >   !=5664
    &   AND6464
    |   OR7464
    ^   XOR8464
    &&96128
    ||106128
    +
    +
    + +
    Variables
    +
    Static variables or alias
    + You may create an unlimited number of alias with directive EQU. Alias cannot be modified (use variables if you need to). +
    +
    Dynamic variables
    + Rasm is able to handle an unlimited number of variables.

    + + Syntax:
    + + myvar=5
    + LET myvar=5 ; Winape compatible +
    + + Variables are used for numeric values only.

    + + Examples:
    + + dep=0
    + repeat 16
    + ld (ix+dep),a
    + dep=dep+8
    + rend
    + + ang=0
    + repeat 256
    + defb 127*sin(ang)
    + ang=ang+360/256
    + rend
    +
    +
    +
    + + + + A directive is not a functiob. That is a keyword which must be (séparé) with at least one space char.

    + + Correct syntax: ASSERT (4*myvar)
    + Wrong syntax: ASSERT(4*myvar)
    + +
    Directives mémoires
    +
    ALIGN <boundary>[,fill]
    + If you want to enforce that the current code adress is aligned to a value. Si l'adresse d'écriture du code en cours n'est pas un multiple de la valeur d'alignement, on augmente cette dernière afin que ça soit le cas. Cette instruction ne produit pas d'octet sur la sortie. Cependant, si un ALIGN est réalisé entre deux portions de code, ce sont des zéros qui seront en mémoire car les espaces de travail sont initialisés avec la valeur zéro.

    + Exemple:
    + + ALIGN 2 ; align code on even adress
    + ALIGN 256 ; align code on high byte
    +
    +
    +
    BANK [ROM page number, RAM page number]
    + Select a ROM number (cartridge) or a RAM slot (snapshot). When using BANK, cartridge is selected if there is no previous BUILDSNA directive.

    + + Values range from 0 to 31. In snapshot mode the values range from 0 to 35 (64K base memory + 512K extended memory).

    + + Used without parameter, the BANK directive open a new memory workspace. +
    +
    BANKSET <64K bloc number>
    + BANKSET directive select a set of 4 pages in a row. With snapshot v3, there is 9 memory sets, indexed from 0 to 8.

    + + You may use BANK and BANKSET in a source but you cannot select the same memory space. A check will trigger an error if you try to.

    + + Using this directive enables snapshot output (like BUILDSNA does). +
    +
    LIMIT <adress boundary>
    + Enforce a lower limit when assembling. Default limit is 65536 but you may need to change this value.

    + + If you want to protect a zone, take a look at the directive PROTECT. +
    +
    ORG <logical adress>[,physical adress]
    + Change assembling adress. You may write the code to another adress than the logical adress with the second parameter.

    + + Assembling to an absolute adress:
    + + ORG #8000
    + defw $
    + ; bytecode output
    + #8000: #00,#80
    +
    + +
    + Assembling to another adress than where the code will be written:
    + + ORG #8000,#1000
    + defw $
    + ; bytecode output
    + #1000: #00,#80
    +
    + +
    + Get back physical adress after changing logical adress:
    + + ORG #8000,#1000
    + defw $ ; This instruction is logically in #8000 but will be written in #1000
    + ORG $ ; ORG do not care of logical adress, we are in #1002 after the previous DEFW
    + defw $ ; current adress is #1002
    + ; bytecode output
    + #1000: #00,#80,#02,#10
    +
    + +
    +
    PROTECT <starting adress>,<ending adress>
    + Protect the memory zone from writes. +
    +
    WRITE DIRECT <lower rom>[,<higher rom>[,<RAM gate array>]]
    + The purpose of this directive is the Winape compatibility. Prefer usage of BANK or BANKSET directives.

    + + Using lower ROM (from 0 et 7) or higher ROM (from 0 et 31) is like BANK usage.

    + + Using only RAM gate array (disabling ROM with -1 like Winape does) a new memory workspace is created, like using BANK directive without parameter. +
    +
    + +
    Data declaration directives
    +
    CHARSET 'string',<value> | <code>,<value> | <start>,<end>,<value>
    + The directive allow quoted char values to be changed. There is 4 usages for this directive:
    +
      +
    • 'string',<value> → First char of the string will get the value <value>. Then the next char <value>+1 and so on until the end of the string.
    • +
    • <code>,<value> → Set to the ASCII char <code> the value <value>.
    • +
    • <start>,<end>,<value> → Set to the ASCII char from <start> to <end> an incremental value starting from <value>.
    • +
    • Without parameter → Reset all ASCII char to default.
    • +
    + This directive is Winape compatible.

    + +
    + Redefine char:
    + + CHARSET 'T','t' ; 'T' chars will be outputed as 't'
    + defb 'tT'
    + ; bytecode output
    + #0000: #74 #74
    +
    + +
    + Redefine non consecutives chars:
    + + CHARSET 'turndiskheo ',0
    + defb 'there is no turndisk'
    + ; bytecode output
    + #0000: #00,#08,#09,#02,#0B,#05,#06,#0B,#03,#0A,#0B,#00,#01,#02,#03,#04,#05,#06,#07
    +
    + +
    + Redefine consecutives chars:
    + + CHARSET 'A','Z','a' ; Change all uppercases to their respective lowercases
    + defb 'abcdeABCDE'
    + ; bytecode output
    + #0000: #61,#62,#63,#64,#65,#61,#62,#63,#64,#65
    +
    +
    +
    DB, DEFB, DM, DEFM <value>[,<value>,...]
    + This directive handle one or more parameters and output bytes regarding of thoses parameters. The value may be a literal value, a formula (the result will be rounded), or a string where each char will output a byte. If CHARSET directive were used, the outputed bytes respect the CHARSET redefinition.

    + + Example:
    + + defb 'r'-'a'+'A',oudoudou',#FF,lo($)
    +
    + The current adress ($) is the one from outputed byte (this is not the case in AS80 mode, see compatibility options). +
    +
    DEFW, DW <value>[,<value>,...]
    + This directive handle one or more parameters and output words (two bytes) regarding thoses parameters. Values may be literal value, formula, single char but not a string!

    + + Example:
    + + defw mylabel1,mylabel2,'a'+#100

    +
    +
    + +
    DEFI <value>[,<value>,...]
    + This directive handle one or more parameters and output integers (four bytes) regarding thoses parameters. Values may be literal value, formula, single char but not a string!

    +
    +
    DEFR, DR <real number>[,<real number>,...]
    + This directive handle one or more parameters and output AMSTRAD firmware compatible real numbers (5 bytes)

    + Example:
    + + defr 5/12,7/3
    +
    +
    +
    DEFS, DS <repetition>[,<value>,[<repetition>,...]
    + This directive outputs a byte and repeat <repetition> times. If the byte to output is not set, then the directive will output zeroes. If the repetition value is zero then no byte will be outputed. You may declare multiples repetition sequences with only one DEFS.

    + + Examples:
    + + defs 5,8,4,1 ; output=#08,#08,#08,#08,#08,#01,#01,#01,#01
    + defs 5,8,4 ; output=#08,#08,#08,#08,#08,#00,#00,#00,#00
    + defs 5 ; output=#00,#00,#00,#00,#00
    +
    +
    +
    <alias> EQU <replacement string>
    + Create an alias. When assembling, each alias will be replaced by the replacement string previously defined. There is an infinite recursivity check done for each alias declaration.

    + + Example:
    + + tab1 EQU #8000
    + tab2 EQU tab1+#100
    +
    + ld hl,tab2
    +
    +
    +
    STR 'string1'[,'string2'...]
    + Almost same directive as DEFB, except the very last outputed char will have his 7th bit forced to 1.

    + + Both lines will output the same bytes:
    + + defb 'roudoudo','u'+128
    + str 'roudoudou'
    +
    +
    +
    STRUCT <prototype name>[,<variable name>]
    + Z80 processor is able to manage structures thanks to his indexed instructions (with IX and IY registers). Structures may be used anywhere.

    + + Example of structure creation
    + + struct st1
    + ch1 defw 0
    + ch2 defb 0
    + endstruct
    + ; structure st1 created with two fields ch1 and ch2. No byte outputed.
    + ; Imbricated structures
    + struct metast1
    + struct st1 pr1
    + struct st1 pr2
    + endstruct
    + ; structure metast1 created with 2 sub-structures st1 called pr1 et pr2
    +
    +
    + Recommended usage to get a structure size is to use the prefix {SIZEOF}. Like Vasm, you can get the structure size using his prototype name but it is not a recommended usage.
    + + LD HL,{SIZEOF}metast1
    + LD HL,metast1
    +
    +
    + STRUCT directive called with 2 parameters will create a structure in memory, based on prototype. In the example below, it will create a metast1 structure type, called mymeta.

    + + struct metast1 mymeta
    +
    +
    + Example of retrieving fields offsets using prototype name:
    + + LD A,(IX+metast1.pr2.ch1) ; offset because prototype used
    +
    +
    + Example of retrieving fields absolute adress using declared structure name:
    + + LD HL,mymeta.pr2.ch1
    + LD A,(HL)
    +
    +
    +
    +
    Crunch and import directives
    +
    INCLUDE, READ 'file to read'
    + Read a textfile in place of the directive. The root of the relative path is the location of the file containing the include directive. An absolute path discard the relative path.

    + + There is no recursivity limit, be aware of what you are doing. +
    +
    INCBIN 'file to read'[,offset[,size[,extended offset[,OFF]]]]
    + Read a binary file. Binary data will go straight to memory space. Additional parameters are Winape INCBIN compatibles. The first offset had no limitation (like Winape) so for a pure Rasm usage, do not bother with extended offset.

    + + You may use a negative offset, relative to the end of the file.

    + + You may use a negative size, relative to the fullsize of the file, minus the offset. A size of -10 will read all the file except 10 latest byets.

    + + A zero size will read all the file.

    + + 'OFF' parameter: You may want to read binary data in order to initialise a memory space, then assemble code on it. The 'OFF' parameter will disable overwrite check for this file.

    + + Example:
    + + org #4000
    + incbin'makeraw.bin',0,0,0,OFF ; read in #4000 without overwrite check
    + org #4001
    + defb #BB ; overwrite 2nd byte without error
    +
    +
    +
    INCL48, INCL49, INCLZ4, INCZX7, INCEXO 'file to read'
    + Read a binary file, crunch it in LZ48, LZ49, LZ4, Exomizer or ZX7 on the fly. +
    +
    LZ48, LZ49, LZ4, LZX7, LZEXO
    + Open a crunched section in LZ48,LZ49, LZ4, ZX7 or Exomizer. Outputed code will be crunched after assembling. The code placed after the zone will be relocated (labels, ...).

    + + You cannot call a label located after a crunched zone from the crunched zone because we cannot know where it will be located after crunching. This will trigger an error.

    + + Limitations:
    +
      +
    • Code or data of a crunched zone cannot exceed 64K.
    • +
    • You cannot imbricate crunched sections.
    • +
    +
    + Example:
    + + org #1000
    + ld hl,zecrunch
    + ld de,#8000
    + call decrunch
    + call #8000
    + jp next ; label next after crunched zone will be relocated
    +
    + zecrunch
    + lz48 ; this section will be crunched
    + org #8000,$
    + nop
    + nop
    + nop
    + ret
    + lzclose
    +
    + next
    + ret
    +
    + +
    +
    LZCLOSE
    + Close an LZ section. +
    +
    + +
    Conditionnal code directives
    +
    ASSERT <condition>[,text,text,text...]
    + Check condition and stop assembling when result is false.

    + Example:
    + + assert mygenend-mygenstart<#100
    + assert mygenend-mygenstart<#100,'code is too big'
    +
    +
    +
    IF <condition>, IFNOT <condition>, ELSE, ELSEIF <condition>, ENDIF
    + Directive in order to test and enable block of code.

    + + Example:
    + + CODE_PRODUCTION=1
    + [...]
    + if CODE_PRODUCTION
    + or #80
    + else
    + print 'test version'
    + endif
    +
    + +
    +
    IFDEF, IFNDEF <variable or label>
    + Both directives test variable or label existence. +
    +
    IFUSED, IFNUSED <variable or label>
    + Both directives test variable or label usage, BEFORE the test. +
    +
    MACRO
    + Rasm supports macro with curly brackets (Winape compatible). You may use conditionnal assembling with macros cause a macro is barely a copy/paste with args replacement.

    + + Example of a long distance indexing (except B or C register):
    + + macro LDIXREG register,dep
    + if {dep}<-128 || {dep}>127
    + push bc
    + ld bc,{dep}
    + add ix,bc
    + ld (ix+0),{register}
    + pop bc
    + else
    + ld (ix+{dep}),{register}
    + endif
    + mend
    +
    + + Note: End of macro is directive MEND or ENDM


    + + + Macros without paramètre
    + Beware that any misspeled macro call will be turn into label declaration! Recommanded usage is to use a fake (VOID) parameter each call. Then a misspeled macro with (VOID) parameter will trigger an error.

    + + macro withoutparam
    + nop
    + mend
    +
    + withoutparam (void) ; secured call of macro
    +
    + +

    Macro calls with static or dynamic args
    + You can send args to macro, either as text replacement, or as formula that will be evaluated before replacement.

    + + macro test myarg
    + defb {myarg}
    + mend
    +
    + repeat 2
    + test repeat_counter
    + rend
    + repeat 2
    + test {eval}repeat_counter
    + rend
    +
    + + In the first loop, a 'defb repeat_counter' will be repeated.
    + In the second loop, a 'defb 1' will be repeated as the counter is previously evaluated.
    +
    +
    PRINT 'string',<variable>,<expression>
    + Write some text, variables or expression during assembly. The default output for numerical values is a floating point value but you may use prefix to change display format.

    +
    {hex}
    Display as hexadecimal value. If the value is less than #FF then display will be forced to 2 digits. Less than #FFFF the display will be forced to 4 digits. There won't be extra zeros for upper values. + +
    {hex2}, {hex4}, {hex8}
    Force hex display to 2, 4 or 8 digits. + +
    {bin}
    Display a binary value. If the value is less than #FF display will be forced to 8 bits. Less than #FFFF the display will be forced to 16 bits. Any negative 32 bits value with all 16 upper bits to 1 will be displayed as 16 bits value. + +
    {bin8},{bin16},{bin32}
    Force binary display to 8, 16 ou 32 bits. + +
    {int}
    Display value as integer. + +
    +
    FAIL 'string',<variable>,<expression>
    + Directive inherited from PRINT, but trigger an error and STOP assembling. +
    +
    REPEAT <repetition number>, REND / REPEAT, UNTIL <condition>
    + REPEAT directive makes a loop of a block of instructions. You may fix a number of repetition or use conditionnal mode with end block directive UNTIL. You may get the internal loop counter anytime with internal value REPEAT_COUNTER.

    + + Example:
    + + repeat 10
    + ldi
    + print repeat_counter
    + rend
    +
    + cpt=10
    + repeat
    + ldi
    + cpt=cpt-1
    + until cpt>0
    +
    + Example with exported counter:
    + + repeat 10,hello
    + ldi
    + print hello
    + rend
    +
    +
    + Note: The 'hello' variable may exist or not. If not it will be created when starting the REPEAT loop. +
    +
    STOP
    + STOP assembly, there will be no outputed files. +
    +
    SWITCH, CASE, BREAK, DEFAULT, ENDSWITCH
    + SWITCH/CASE syntax mimics the C syntax. You may use multiple cases with the very same value. This allow you to write more complex cases.

    + + Below, the macro call with '5' will output all defb with 'oui' or 'encore oui':
    + + macro ouioui mavar
    + switch {mavar}
    + nop ; outside case, won't be outputed
    + case 3
    + defb 'non'
    + case 5
    + defb 'oui'
    + case 7
    + defb 'encore oui'
    + break
    + case 8
    + defb 'non'
    + case 5
    + defb 'encore oui'
    + break
    + default
    + defb 'non'
    + endswitch
    + mend
    +
    +
    +
    WHILE, WEND
    + Repeat a block as long as the condition is checked and true. You may use anytime a WHILE_COUNTER variable to get the internal counter.

    + + Example:
    + + cpt=10
    + while cpt>0
    + ldi
    + cpt=cpt-1
    + print 'cpt=',cpt,' while_counter=',while_counter
    + wend
    +
    + Loop will run 10 times with the following output:
    + + Pre-processing [while.asm]
    + Assembling
    + cpt= 9.00 while_counter= 1.00
    + cpt= 8.00 while_counter= 2.00
    + cpt= 7.00 while_counter= 3.00
    + cpt= 6.00 while_counter= 4.00
    + cpt= 5.00 while_counter= 5.00
    + cpt= 4.00 while_counter= 6.00
    + cpt= 3.00 while_counter= 7.00
    + cpt= 2.00 while_counter= 8.00
    + cpt= 1.00 while_counter= 9.00
    + cpt= 0.00 while_counter= 10.00
    + Write binary file rasmoutput.bin (20 bytes)
    +
    +
    +
    + +
    Output file directives
    +
    AMSDOS
    + This directive add an AMSDOS header to the automatic binary output file of Rasm. Header won't be add to binaries produced by SAVE directives (except if you explicitly set it). +
    +
    BREAKPOINT [<adress>]
    + Add a breakpoint (this won't be assembled) to the current adress or to the adress of the parameter. Breakpoints may be exported to a raw file or in snapshots (Winape and ACE compatible).

    + + Note: Any label starting with BRK or @BRK will generate a breakpoint.

    +
    +
    BUILDCPR
    + This deprecated directive was supposed to force cartridge output when using multiple kind of binaries. +
    +
    BUILDSNA [V2]
    + This directive force Rasm to output a snapshot instead of a cartridge when using BANK(s).

    + + The default settings of snapshot is a CPC 6128 with CRTC 0 but you may use SETCRTC and SETCPC directives to change those settings.

    + + The snapshot will include a classic CPC screen (like AMSDOS basic) with all non blinking colors (like AMSDOS basic). Audio channels are disabled, ROMS are disabled and interrupt mode is 1.

    + + Example:
    + + buildsna ; recommanded usage when using snapshot is to set it first
    +
    + bankset 0 ; assembling in first 64K
    + org #1000
    + run #1000 ; snapshot will run at #1000
    +
    + ld b,#7F
    + ld a,{page}mydata ; get gate array value for paging memory
    + out (c),c
    + ld a,(mydata)
    + jr $
    +
    + bank 6 ; choose 3th bank of 2nd 64K set
    + nop
    + mydata defb #DD
    +
    + bank ; without parameter, this is a temporary memory space
    + ; that won't be save in the snapshot
    +
    + pouet
    + repeat 10
    + cpi
    + rend
    + camion
    + save"another",pouet,camion-pouet
    +
    +
    + Compatibility option for snapshot version 2: Some emulators or hardware board do not support snapshot v3. Just add arg 'v2' to SNAPSHOT directive. (New limitations are 128K max):
    + + buildsna v2
    +
    +
    +
    RUN <adress>[,<gate array configuration>}
    + Select the memory location where to start a snapshot. Optional parameter to set the gate array configuration. +
    +
    SAVE 'filename',<adress>,<size>[,AMSDOS|DSK[,'dsk filename'[,<side>]]]
    + Record a binary file from the adress until adress+taille of the current memory space. All SAVE directives are delayed until the end of assembling. If there is no error then files will be written. You cannot SAVE intermediate assembling state.

    + + When recording file on a floppy image (DSK), the filename will be forced to upper case and truncated if it does not respect AMSDOS limitations

    + + Examples:
    + + SAVE 'myfile.bin',start,size ; Save a raw binary file
    + SAVE 'myfile.bin',start,size,AMSDOS ; Save a binary file with AMSDOS header
    + SAVE 'myfile.bin',start,size,DSK,'fichierdsk.dsk' ; Save a binary file (AMDOS header mandatory) on a DSK file
    +
    + + +
    +
    SETCPC <model>
    + Select CPC model when recording snapshot v3:
    +
      +
    • 0 : CPC 464
    • +
    • 1 : CPC 664
    • +
    • 2 : CPC 6128
    • +
    • 4 : 464 Plus
    • +
    • 5 : 6128 Plus
    • +
    • 6 : GX-4000
    • +
    +
    +
    SETCRTC <CRTC model>
    + Select CRTC model when writing snapshot v3 file. Range value for CRTC model is from 0 to 4. CPC Plus and GX-4000 share CRTC 3. +
    +
    + +
    Compatibility directives
    +
    LIST, NOLIST, LET
    + Those directives are ignored. Usage for Maxam/Winape compatibility only. +
    +
    + + +
    Instruction set
    + Rasm support all documented and undocumented instructions, even complex instructions like bitops+load.

    + + 8 bits register storage of IX and IY is doing indifferently with LX, IXL or XL, and so on.

    + + Complex instructions syntax:
    + + res 0,(ix+0),a
    + bit 0,(ix+0),a
    + sll 0,(ix+0),a
    + rl 0,(ix+0),a
    + rr 0,(ix+0),a
    +
    +
    + Undocumented opcodes syntax:
    + + out (#12),a ; #12 is any 8 bits value
    + in a,(#12)
    + in 0,(c) ou in f,(c)
    + sll <register> or sl1 <register>
    +
    +
    + Multi-arg syntax available for PUSH, POP and NOP:
    + - PUSH multi-args
    + + push bc,de,hl ; → push bc : push de : push hl
    +
    + - NOP repetition
    + + nop 4 ; → nop : nop : nop : nop
    +
    + - complex LD
    + + LD BC,BC ; → LD B,B : LD C,C
    + LD BC,DE ; → LD B,D : LD C,E
    + LD BC,HL ; → LD B,H : LD C,L
    + LD DE,BC ; → LD D,B : LD E,C
    + LD DE,DE ; → LD D,D : LD E,E
    + LD DE,HL ; → LD D,H : LD E,L
    + LD HL,BC ; → LD H,B : LD L,C
    + LD HL,DE ; → LD H,D : LD L,E
    + LD HL,HL ; → LD H,H : LD L,L
    +
    + LD HL,(IX+n) ; → LD H,(IX+n+1) : LD L,(IX+n)
    + LD HL,(IY+n) ; → LD H,(IY+n+1) : LD L,(IY+n)
    + LD DE,(IX+n) ; → LD D,(IX+n+1) : LD E,(IX+n)
    + LD DE,(IY+n) ; → LD D,(IY+n+1) : LD E,(IY+n)
    + LD BC,(IX+n) ; → LD B,(IX+n+1) : LD C,(IX+n)
    + LD BC,(IY+n) ; → LD B,(IY+n+1) : LD C,(IY+n)
    +
    + LD (IX+n),HL ; → LD (IX+n+1),H : LD (IX+n),L
    + LD (IY+n),HL ; → LD (IY+n+1),H : LD (IY+n),L
    + LD (IX+n),DE ; → LD (IX+n+1),D : LD (IX+n),E
    + LD (IY+n),DE ; → LD (IY+n+1),D : LD (IY+n),E
    + LD (IX+n),BC ; → LD (IX+n+1),B : LD (IX+n),C
    + LD (IY+n),BC ; → LD (IY+n+1),B : LD (IY+n),C
    +
    +
    + +
    Limitations
    +
      +
    • You cannot use a Z80 instruction or register as label,alias or variable.
    • +
    • You cannot use the same name for alias, label or variable.
    • +
    • Rasm is not case sensitive.
    • +
    • Crunched sections cannot exceed 64K before compression.
    • +
    +
    + +
    + Rasm is using licence MIT "expat"

    + + « Copyright © BERGÉ Édouard (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. » +
    + + + + diff --git a/docs/rasm_fr.html b/docs/rasm_fr.html new file mode 100644 index 0000000..1aafc6f --- /dev/null +++ b/docs/rasm_fr.html @@ -0,0 +1,1404 @@ + + + + + Rasm assembler v0.96 documentation + + + + + + + + + +
    +

    RASM v0.96


    roudoudou Z80 assembler

    + + + +

    Table des matières

    + Introduction
    + Fonctionnalités
    + Installation
    + Compilation
    +    - Compilation Linux
    +    - Compilation Windows
    +    - Compilation MorphOS
    + + Comportement
    + Ligne de commande
    +    - Options de noms de fichiers
    +    - Options d'export sur fichier EDSK
    +    - Options d'export sur fichier snapshot
    +    - Options de symboles
    +    - Options de dépendances
    +    - Options de compatibilité
    +    - Options de développeur (usage interne)
    + + Format du code source
    +    - Généralité
    +    - Commentaires
    +    - Valeurs litérales
    +    - Caractères autorisés
    +    - Fichiers
    +    - Labels
    +    - Labels de proximité
    +    - Labels locaux
    +    - Tags spécifiques aux labels ou structures
    +       {BANK}
    +       {PAGE}
    +       {PAGESET}
    +       {SIZEOF}
    +    - Coloration syntaxique dans VIM
    + + Expressions
    +    - Opérateurs de calcul
    +    - Priorité d’exécution des opérateurs
    + + Variables
    +    - Statiques
    +    - Dynamiques
    + + Directives mémoires
    +    - ALIGN
    +    - BANK
    +    - BANKSET
    +    - LIMIT
    +    - ORG
    +    - PROTECT
    +    - WRITE DIRECT
    + + Directives de définition de données
    +    - CHARSET
    +    - DEFB
    +    - DEFW
    +    - DEFI
    +    - DEFR
    +    - DEFS
    +    - EQU
    +    - STR
    +    - STRUCT
    + + Directives d'import et de compression
    +    - INCLUDE
    +    - INCBIN
    +    - INCL48, INCL49, INCLZ4, INCZX7, INCEXO
    +    - LZ48, LZ49, LZ4, LZX7, LZEXO
    +    - LZCLOSE
    + + Directives de code conditionnel
    +    - ASSERT
    +    - IF IFNOT THEN ELSEIF ELSE ENDIF
    +    - IFDEF, IFNDEF
    +    - IFUSED, IFNUSED
    +    - MACRO
    +    - PRINT
    +    - FAIL
    +    - REPEAT, REND, UNTIL
    +    - SWITCH, CASE, DEFAULT, BREAK, ENDSWITCH
    +    - STOP
    +    - WHILE, WEND
    + + Directives de sortie fichier
    +    - AMSDOS
    +    - BREAKPOINT
    +    - BUILDCPR
    +    - BUILDSNA
    +    - RUN
    +    - SAVE
    +    - SETCPC
    +    - SETCRTC
    + + Directives de compatibilité
    +    - LIST, NOLIST, LET
    + + Jeu d'instruction
    + Limitations
    + +
    + + + +
    Introduction
    + Lors de la création de ma démo CRTC³, les assembleurs existants ont tous rapidement montré leurs limites, que ce soit en termes de rapidité d'assemblage ou de fonctionnalités offertes. En effet, le projet final analyse plus de 250'000 mots (hors commentaires), 35'000 labels et 60'000 expressions. Il fallait donc en priorité un assembleur qui soit rapide et lui ajouter au minimum des fonctionnalités que n'ont pas les autres: support natif des cartouches, disquettes ou snapshot Amstrad, espaces mémoires multiples, calculs flottants, compressions les plus courantes intégrées (afin de s'éviter par exemple de fastidieux export/imports de symboles), etc.

    + + Il y a 18 ans, j'avais programmé un petit assembleur. Je ne m'en étais pas servi à l'époque car il était limité. J'en ai néanmoins repris le principe d'assemblage mono-passe.

    + + Rasm utilise des concepts éprouvés (arbres de Merkel, nombreux caches, allocations groupées) et surtout une conception linéaire (la récursivité tue les performances). Les performances d'assemblage sont extrêmement rapides en conditions réelles sur de gros projets, si bien que certaines optimisations n'ont même pas été faites.

    + + Aujourd'hui Rasm est utilisé sur plusieurs gros projets:
    +  - Ghost'n Goblins par Golem13
    +  - Arkos Tracker II par Targhan de façon intégrée au logiciel
    +
    +
    + Rasm est diffusé sous licence MIT. +
    +
    Fonctionnalités
    +
      +
    • compilation ultra-rapide
    • +
    • intégration des compresseurs les plus courants
    • +
    • export au format binaire, cartouche, disquettes, snapshot...
    • +
    • export/import des symboles
    • +
    • contrôle automatique des zones mémoires contre l'écrasement
    • +
    • espaces mémoires illimités où les labels/variables sont partagées
    • +
    • gestion dédiée des ROM et extensions mémoires
    • +
    • absolument toutes les instructions sont supportées
    • +
    • macros, code conditionnel, boucles illimités, labels locaux, switch/case
    • +
    • calculs internes en double précision et arrondi correct
    • +
    • compatibilité optionnelle avec Maxam ou AS80
    • +
    +
    +
    Installation
    + Rasm est un exécutable indépendant, il s'utilise tel que, sans installation aucune. +
    +
    Compilation
    +
    Compilation Linux avec GCC ou Clang
    + + cc rasm_v096.c -O2 -lm -lrt -march=native
    + mv a.out rasm
    + strip rasm +
    +
    +
    Compilation Windows avec Visual Studio
    + + cl.exe rasm_v096.c -O2 + +
    +
    Compilation DOS ou Windows 32 bits avec Watcom
    + + # do not use -s or -ox option, this will cause a fatal stack issue + wcl386.exe rasm_v096.c -6r -6s -fp6 -d0 -k4000000 -obmiler + +
    +
    Compilation MorphOS (ixemul)
    + + ppc-morphos-gcc-5 -O2 -c -o rasm rasm_v096.c
    + strip rasm +
    +
    +
    +
    Comportement de Rasm (généralités)
    + Rasm essaie d'être simple d'utilisation. En ce sens il va produire des noms de fichier par défaut, déterminer la quantité de mémoire à enregistrer ou même créer un fichier cartouche si les banques ROM ont été sélectionnées lors de l'assemblage.

    + + Rasm permet l'utilisation de plusieurs ORG au sein d'un même espace mémoire. Par contre il n'autorise pas de ré-écrire sur les mêmes adresses mémoire. À chaque nouveau ORG, Rasm contrôle qu'aucune zone de code écrite ne se chevauche.

    + + Si vous avez besoin de générer plusieurs morceaux de code à la même adresse, vous avez deux possibilités. Soit vous utilisez le deuxième paramètre de la directive ORG pour écrire ce code ailleurs, soit vous pouvez créer à tout moment un nouvel espace mémoire avec la directive BANK

    + + Dans la mesure du possible, Rasm essaie d'afficher des messages d'erreurs afin de vous orienter vers la solution syntaxique convenable.

    + + Rasm va d'abord pré-traiter le fichier à assembler pour enlever les espaces superflus, les commentaires, vérifier les quotes, que les caractères utilisés soient conformes et enfin transformer certaines instructions en d'autres pour convenance interne. Par exemple les opérateurs Maxam XOR, AND, OR et MOD seront convertis en un seul caractère approchant la syntaxe du C.

    + + Lorsqu'une directive de lecture ne fait pas référence à un chemin absolu, le répertoire racine au chemin relatif est celui du fichier en cours.

    +
    +
    Ligne de commande
    + La syntaxe de base est: rasm.exe <fichier à assembler> [options]

    + + Exemple: rasm.exe monfichier.asm +
    Options relatives aux noms de fichiers
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    -o <radix de fichier>définir un nom commun pour chaque type de fichier en sortie, quel que soit son type (.bin, .cpr, .sym). La valeur par défaut est “rasmoutputâ€
    + Exemple:
    + + rasm.exe test -o grouik -s
    + Pre-processing [test.asm]
    + Assembling
    + Write binary file grouik.bin (25 bytes)
    + Write symbol file grouik.sym (10 bytes)
    +
    +
    -ob <nom de fichier binaire>définir le nom complet pour le fichier de sortie binaire.
    -oc <nom de fichier cartouche>définir le nom complet pour le fichier de sortie cartouche.
    -oi <nom de fichier snapshot>définir le nom complet pour le fichier de sortie snapshot.
    -os <nom de fichier symbole>définir le nom complet pour le fichier de sortie des symboles.
    -ok <nom de fichier breakpoint>définir le nom complet pour le fichier de sortie des points d'arrêt.
    -I<répertoire dans lequel chercher les fichiers à inclure>définir le répertoire d'inclusion des fichiers, plusieurs options -I cumulables.
    -nodésactiver toute écriture de fichier
    +
    +
    Options d'export sur fichier EDSK
    + + + + + + +
    -eo   écraser les fichiers sur l'image disque si il y a conflit de nom.
    +
    +
    Options d'export sur fichier snapshot
    + + + + + + + + + + + + +
    -v2Créé un snapshot version 2 (export par défaut en version 3) +
    -sbExporte les points d'arrêt (breakpoints) dans le fichier snapshot (compatible avec les formats Winape et ACE), uniquement avec la version 3+
    -ssExporte les symboles dans le fichier snapshot (compatible avec les formats Winape et ACE), uniquement avec la version 3+
    +
    +
    Options relatives aux symboles
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    -sexporter les symboles au format Rasm
    + Exemple de fichier produit:
    + + LABEL1 #0 B0
    + LABEL2 #1 B0
    + LABEL3 #2 B0
    + LABEL4 #4 B0
    +
    +
    -spexporter les symboles au format Pasmo
    + Exemple de fichier produit:
    + + LABEL1 EQU 00000H
    + LABEL2 EQU 00001H
    + LABEL3 EQU 00002H
    + LABEL4 EQU 00004H
    +
    +
    -swexporter les symboles au format Winape
    + Exemple de fichier produit:
    + + LABEL1 #0
    + LABEL2 #1
    + LABEL3 #2
    + LABEL4 #4
    +
    +
    -sloption additionnelle aux trois précédentes qui permet d'exporter aussi les symboles locaux aux macros ou boucles de répétition.
    -svoption additionnelle aux trois précédentes qui permet d'exporter aussi les variables.
    -sqoption additionnelle aux trois précédentes qui permet d'exporter aussi les alias EQU.
    -saoption équivalente à -sl -sv -sq
    -ssexporter les symboles dans un snapshot
    -ebexporter les points d'arrêt
    -l <fichier label>importer un fichier de labels pour l'assemblage au format Rasm, Sjasm, Pasmo ou Winape. La détection du format est automatique.
    -D<var>=<valeur>option pour définir une variable depuis la ligne de commande. Exemple: rasm.exe -DTRUC=1 va définir la variable TRUC à 1.
    +

    + Note 1: Il est possible de cumuler plusieurs fichiers de symboles en cumulant les options -l
    + + rasm.exe test -l import1.sym -l import2.sym -l import3.sym
    +
    + Note 2: L'émulateur Arnold est compatible avec Rasm et Pasmo.
    + Note 3: L'émulateur Winape n'est pas capable de prendre en charge des labels trop longs! +
    + +
    +
    Options de compatibilité
    + -depend=make
    +Exporte toutes les dépendances du programme sur une seule ligne (pour une utilisation en makefile).

    + -depend=list
    +Exporte toutes les dépendances du programme, une par ligne.

    + Si un nom de fichier binaire est spécifié (option -ob) alors il sera ajouté en première position. +
    +
    Options de compatibilité
    + + + + + + + + + + + + + + + + + + + + + +
               
    -mcompatibilité Maxam
      +
    • calculs réalisés en entiers 16 bits non signés avec un mauvais arrondi
    • +
    • les comparaisons se font avec l'opérateur = simple
    • +
    • la priorité des opérateurs est simplifiée (voir tableau)
    • +
    -asscompatibilité AS80
      +
    • calculs réalisés en entiers 32 bits avec un mauvais arrondi
    • +
    • les déclarations de type DEFB,DEFW,DEFI ou DEFR multiples ont pour référence d'adresse l'adresse du premier octet produit et non l'adresse de l'octet courant. Cette spécificité d'AS80 fait que deux DEFB ne produisent pas la même chose qu'un seul DEFB avec deux valeurs (quand la référence $ est utilisée).
    • +
    • les paramètres des macros ne sont plus protégés par les chevrons {}
    • +
    • la directive MACRO s'utilise après le nom de la macro et non avant
    • +
    -uzcompatibilité UZ80
      +
    • calculs réalisés en entiers 32 bits avec un mauvais arrondi
    • +
    • les paramètres des macros ne sont plus protégés par les chevrons {}
    • +
    • la directive MACRO s'utilise après le nom de la macro et non avant
    • +
    +
    +
    Options de développement
    + + + + + + + + + + + + + + + + + +
    -vmode verbeux, affiche des informations et statistiques sur l'assemblage
    -dproduit des informations lors du pré-processing
    -aproduit des informations lors de l'assemblage
    -naffiche les licences tierces
    +
    +
    +
    Format du code source
    +
    Généralité
    + L'assembleur n'est pas du COBOL, il est inutile d'indenter vos sources avec Rasm, autrement que pour faire joli. Il n'est pas nécessaire de séparer un label d'une instruction ou d'un autre label par le caractère deux points, bien qu'il soit possible de le faire. La conséquence directe de cette écriture libre implique une différence avec les assembleurs de conception obsolète. Il n'est pas possible (et heureusement) de créer un label qui ait le même nom qu'une directive ou instruction Z80.

    + + Le défaut de cette liberté est que l'assembleur ne peut pas savoir si vous voulez déclarer un label quand vous vous trompez dans l'écriture du nom d'une macro sans paramètre. Pour palier à ce défaut, vous pouvez ajouter un paramètre fictif “(void)†qui déclenchera une erreur si le nom de macro n'est pas connu.

    + + Les fichiers peuvent être lus au format windows ou unix, une conversion interne et transparente sera réalisée en interne.

    + + Rasm n'est pas sensible à la casse, toutes les lettres sont converties en majuscules en interne. Ne soyez pas surpris de ne voir que des majuscules dans les messages d'erreur.

    + + Un label n'est PAS un alias et n'est PAS une variable, Rasm fait la différence!

    + + - un label fait référence à un emplacement mémoire (une adresse et éventuellement une page mémoire si l'espace de travail correspond à une cartouche ou un snapshot)
    + - un alias (EQU) est un texte qui, une fois rencontré, est remplacé par un autre, certaines informations étant figées à la définition du texte.
    + - une variable est globale à l'ensemble du source, sa valeur doit être initialisée et peut-être modifiée à tout moment.
    +
    +
    Commentaires
    + La saisie de commentaire sous Rasm est classique et précédée du caractère point-virgule. Tous les caractères suivants sont ignorés jusqu'au prochain retour chariot.

    + + Note: Il n'y a pas de commentaire multi-lignes +
    +
    Valeurs littérales
    + Rasm interprète les valeurs numériques suivantes:
    +
      +
    • En décimal si la valeur commence par un chiffre.
    • +
    • En binaire si la valeur commence par un % ou 0b.
    • +
    • En octal si la valeur commence par un @.
    • +
    • En hexadécimal si la valeur commence par un #, un $, 0x ou se termine par un h.
    • +
    • En valeur ascii si un caractère unique est entre quotes.
    • +
    • En valeur associée à une variable ou un label, si la littérale commence par une lettre ou un '@' pour les labels locaux.
    • +
    • Le symbole $ utilisé seul indique l'adresse de début de l'instruction en cours. Lors d'un define type DEFB, DEFW, DEFI, DEFR ou DEFS, l'adresse courante est celle de l'élément en cours. Un DEF* produira les mêmes données que vous utilisiez plusieurs arguments à la suite ou bien plusieurs DEF*.
    • +
    + + Rasm fait tous ses calculs internes en nombre flottant double précision. Un arrondi correct est réalisé en fin de chaine de calcul pour les besoins en nombres entiers.

    + + Attention, le caractère & est réservé pour l'opérateur AND. +
    +
    Caractères autorisés
    + Entre quotes, tous les caractères sont autorisés, à vos risques et périls concernant la conversion ASCII vers l'Amstrad. En dehors des quotes, vous pourrez utiliser toutes les lettres, tous les chiffres, le point, l'arobas, les parenthèses, le dollar, les opérateurs plus, moins, multiplié, divisé, le pipe, circonflexe, le pourcent, le dièse, le paragraphe, les chevrons et les deux types de quotes.

    + Les chaines de caractères entre quotes peuvent contenir des caractères échappés:
    +
  • \t

  • +
  • \n

  • +
  • \r

  • +
  • \f

  • +
  • \v

  • +
  • \b

  • +
  • \0
  • -> sauf avec le PRINT
    +
    +
    Fichiers
    + RASM utilise en interne le modèle de fichiers UNIX qu'il converti automatiquement au besoin. En utilisant uniquement des chemins relatifs (et des noms de fichiers que Windows peut comprendre), on peut tout à fait avoir un code qui compile à la fois sous UNIX et Windows sans faire de modification.

    + + La règle de gestion des chemins relatifs est simple. Tout chemin relatif a pour origine le répertoire du fichier dans lequel il a été lu. +
    +
    Labels
    + À l'intérieur d'une boucle (REPEAT/WHILE/UNTIL) ou dans une macro, il est possible d'utiliser des labels locaux de la même façon qu'avec l'assembleur intégré de Winape en préfixant le label par le caractère '@'.

    + + À chaque itération de boucle et ce, pour chaque imbrication de boucle, un suffixe est ajouté au label local contenant la valeur hexadécimale du compteur interne de répétition. Il est ainsi possible d'appeler un label local à une répétition en dehors de la boucle, mais cet usage n'est pas conseillé.

    + + Il est possible d'utiliser la valeur d'un label dans une commande (ORG par exemple) si et seulement si le label précède la directive.

    + + Tout label qui commence par le préfixe BRK ou @BRK génère aussi un point d'arrêt.

    + + En mode DAMS, il est possible d'utiliser la déclaration désuète d'un label en le préfixant d'un point. L'appel à ce label se fera sans le point du début. L'usage des labels de proximité est alors désactivé.

    +
    +
    Labels locaux non exportables
    + On peut déclarer un label local à l'intérieur d'une macro ou d'une boucle. Ce label sera invisible hors de son contexte (hors de la macro, ou à chaque répétition de boucle).

    + + Les labels locaux sont préfixés par le caractère '@'.

    + + Exemple d'utilisation d'un label local dans une boucle:
    + + repeat 16
    + add hl,bc
    + jr nc,@no_overflow
    + dec hl
    + @no_overflow
    + rend
    +
    +
    +
    Labels de proximité
    + Hors d'une macro ou d'une boucle, les labels locaux héritent du label global qui précède.

    + + Exemple d'utilisation d'un label de proximité:
    + + routine1
    + add hl,bc
    + jr nc,.no_overflow
    + dec hl
    + .no_overflow
    +
    + routine2
    + add hl,bc
    + jr nc,.no_overflow
    + dec hl
    + .no_overflow
    +
    + routine3
    + xor a
    + ld hl,routine1.no_overflow ; récupération du label local à routine1
    + ld de,routine2.no_overflow ; idem routine2
    + sbc hl,de
    +
    +
    +
    Tags spécifiques aux labels ou structures
    +
    {BANK}
    + Le préfixe {BANK} devant un label (exemple: {BANK}monlabel ) permet de récupérer la valeur de la BANK dans laquelle est déclaré le label, plutôt que l'adresse du label.

    + + Exemple d'utilisation du tag:
    + + bank 0
    + ld a,{bank}maroutine ; sera assemblé LD A,1
    + call connect_bank
    + jp maroutine
    + bank 1
    + defb 'coucou'
    + maroutine
    + jr $
    +
    + +
    {PAGE}
    + Le préfixe {PAGE} devant un label (exemple: {PAGE}monlabel ) permet de récupérer la valeur type Gate array de la BANK dans laquelle est déclaré le label, plutôt que l'adresse du label. Par exemple pour un label situé dans la BANK 5 la valeur retournée sera #C5

    + Si vous utilisez l'adressage mémoire par 64K avec la directive BANKSET, alors la valeur gate array sera déduite du set de 64K ainsi que de l'adresse du label (2 bits de poids fort)

    + + Exemple d'utilisation du tag:
    + + buildsna ; force mode snapshot
    + Bank 0
    + ld a,{page}maroutine ; sera assemblé LD A,#C5
    + ld b,#7F
    + out (c),a
    + jp maroutine
    + bank 5
    + defb 'coucou'
    + maroutine
    + jr $
    +
    +
    {PAGESET}
    + Le préfixe {PAGESET} devant un label (exemple: {PAGESET}monlabel ) permet de récupérer la valeur type Gate array du BANKSET dans lequel est déclaré le label, plutôt que l'adresse du label. Par exemple pour un label situé dans la BANK 5 la valeur retournée sera #C2

    + + Exemple d'utilisation du tag:
    + + bank 0
    + ld a,{pageset}maroutine ; sera assemblé LD A,#C2
    + ld b,#7F
    + out (c),a ; vu qu'on commute toute la RAM le code est supposé être exécuté depuis la ROM dans la majorité des cas
    + jp maroutine
    + bank 5
    + defb 'coucou'
    + maroutine
    + jr $
    +
    +
    {SIZEOF}
    + Le préfixe {SIZEOF} devant un nom de structure ou de sous-structure permet de récupérer la taille de cette dernière.

    + + Voir la définition des structures ici. +
    +
    Coloration syntaxique dans VIM
    +
      +
    • Si vous avez déjà le fichier de coloration syntaxique Z80 il suffit d'ajouter les lignes suivantes au fichier .vim/syntax/z80.vim
    • +
    • Ou vous pouvez télécharger le fichier complet de syntaxe ici
    • +
    +
    + + " rasm/winape directives
    + syn keyword z80PreProc charset bank write save include incbin incl48 incl49
    + syn keyword z80PreProc macro mend switch case break while wend repeat until
    + syn keyword z80PreProc buildcpr amsdos lz48 lz49 lzclose protect
    + syn keyword z80PreProc direct brk let print stop nolist str
    + syn keyword z80PreProc defr dr defi bankset page pageset sizeof endm struct endstruct ends
    + syn keyword z80PreProc incexo lzexo lzx7 inczx7 buildsna setcrtc setcpc assert print
    + syn keyword z80Reg lix liy hix hiy
    +
    + +
    +
    +
    Expressions
    +
    Opérateurs de calcul
    + Rasm utilise un moteur d'expression simplifié à priorités multiples (comme le C). Il supporte les opérateurs et fonctions suivant(e)s:
    +
      +
    • * multiplication
    • +
    • / division
    • +
    • + addition
    • +
    • - soustraction
    • +
    • & ou AND opérateur logique ET
    • +
    • | ou OR opérateur logique OU
    • +
    • ^ ou XOR opérateur logique OU exclusif
    • +
    • % ou MOD pour faire le modulo
    • +
    • && opérateur booléen ET
    • +
    • || opérateur booléen OU
    • +
    • << multiplication par la puissance n de deux
    • +
    • >> division par la puissance n de deux
    • +
    • hi() poids fort de l'entier 16 bits
    • +
    • lo() poids faible de l'entier 16 bits
    • +
    • sin() calcul de sinus
    • +
    • cos() calcul de cosinus
    • +
    • asin() calcul d'arc-sinus
    • +
    • acos() calcul d'arc-cosinus
    • +
    • atan() calcul d'arc-tangente
    • +
    • int() conversion en nombre entier
    • +
    • floor() conversion au nombre entier directement inférieur
    • +
    • abs() valeur absolue
    • +
    • ln() logarithme népérien
    • +
    • log10() logarithme base 10
    • +
    • exp() exponentielle
    • +
    • sqrt() racine carrée
    • +
    • == égalité (ou un seul = en mode Maxam)
    • +
    • != ou <> différent de
    • +
    • <= inférieur ou égal
    • +
    • >= supérieur ou égal
    • +
    • < inférieur
    • +
    • > supérieur
    • +
    +
    +
    Priorité d’exécution des opérateurs
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Plus la prévalence est faible, plus l'opération est prioritaire.
    OpérateursPrévalence RasmPrévalence Maxam
    (   )00
    !  1464
    *   /   %2464
    +   -3464
    <<   >>4464
    <   <=   ==   =>   >   !=5664
    &   AND6464
    |   OR7464
    ^   XOR8464
    &&96128
    ||106128
    +
    +
    + +
    Variables
    +
    Variables statiques ou alias
    + Il est possible de créer un nombre illimité d’alias avec la directive EQU. Ces alias ne peuvent pas être modifiés une fois qu'ils sont définis. +
    +
    Variables dynamiques
    + Rasm autorise un nombre illimité de variables pour des calculs internes.

    + + Syntaxe:
    + + mavariable=5
    + LET mavariable=5 ; syntaxe compatible Winape +
    + + Ces variables peuvent être utilisées comme offset lors d'une boucle de répétition ou comme opérateurs de calcul pour créer des tables de données.

    + + Exemples:
    + + dep=0
    + repeat 16
    + ld (ix+dep),a
    + dep=dep+8
    + rend
    + + ang=0
    + repeat 256
    + defb 127*sin(ang)
    + ang=ang+360/256
    + rend
    +
    +
    +
    + + + + Une directive n'est pas une fonction, c'est un mot clef qui doit être séparé de ses paramètres par au moins un espace.

    + + Syntaxe correcte: ASSERT (4*mavar)
    + Syntaxe incorrecte: ASSERT(4*mavar)
    + +
    Directives mémoires
    +
    ALIGN <valeur d'alignement>[,valeur de remplissage]
    + Si l'adresse d'écriture du code en cours n'est pas un multiple de la valeur d'alignement, on augmente cette dernière afin que ça soit le cas. Utilisée avec un seul paramètre, cette instruction ne produit pas d'octet sur la sortie. Ainsi, par défaut ce sont des zéros qui seront en mémoire si on réalise un ALIGN entre deux portions de code.

    + Utilisée avec le paramètre de remplissage, des octets seront produits (même si la valeur est zéro) et ces données seront comptées dans le calcul d'enregistrement automatique de binaire ainsi que dans le contrôle d'écrasement mémoire.

    + Exemple:
    + + ALIGN 2 ; aligner le code sur une adresse paire
    + ALIGN 256 ; aligner le code sur le poids fort de l'adresse
    +
    +
    +
    BANK [numéro de page ROM, numéro de page RAM]
    + Sélectionner un emplacement ROM (cartouche) ou RAM (snapshot). L'usage de cette instruction active par défaut l'écriture de la cartouche en fin d'assemblage.

    + + Les valeurs possibles vont de 0 à 31. En mode snapshot on peut aussi utiliser cette directive, cette fois avec des valeurs de 0 à 35 (64K de base + 512K d'extension mémoire).

    + + Sans paramètre, la directive ouvre un nouvel espace mémoire de travail +
    +
    BANKSET <numéro de bloc de 64K>
    + Sélectionner un emplacement mémoire pour les snapshots, en groupant les pages 4 à 4. Le format snapshot v3 supportant au maximum une extension de 512K, il y a 9 sets mémoire indexés de 0 à 8.

    + + Il est possible d'utiliser BANK et BANKSET en même temps mais il est impératif de ne pas sélectionner la même page à la fois avec BANK et BANKSET. Un contrôle déclenchera une erreur si vous tentez de le faire.

    + + L'appel de cette directive force automatiquement la génération de snapshot. +
    +
    LIMIT <adresse limite>
    + Imposer une limite plus basse à l'écriture de l'assemblage. Par défaut, la limite est de 65536 mais on peut avoir besoin de ne pas dépasser une certaine valeur.

    + + Pour protéger une zone définie, il vaut mieux utiliser la fonction PROTECT. +
    +
    ORG <adresse logique>[,adresse d'écriture du code]
    + Assembler le code à une adresse spécifique. On peut optionnellement choisir d'assembler le code à une adresse, mais l'écrire à un autre endroit avec le deuxième paramètre.

    + + Assembler le code à une adresse absolue:
    + + ORG #8000
    + defw $
    + ; bytecode produit
    + #8000: #00,#80
    +
    + +
    + Assembler le code à une adresse autre que celle du code:
    + + ORG #8000,#1000
    + defw $
    + ; bytecode produit
    + #1000: #00,#80
    +
    + +
    + Retrouver l'adresse physique après l'avoir modifiée:
    + + ORG #8000,#1000
    + defw $ ; cette instruction est logiquement en #8000 mais physiquement écrite en #1000
    + ORG $ ; le ORG s'affranchit de l'adresse logique, on est physiquement en #1002 après le defw
    + defw $ ; adresse courante est #1002
    + ; bytecode produit
    + #1000: #00,#80,#02,#10
    +
    + +
    +
    PROTECT <adresse de début>,<adresse de fin>
    + Empêcher l'écriture de données dans la zone début/fin de l'espace mémoire courant. +
    +
    WRITE DIRECT <rom basse>[,<rom haute>[,<RAM>]]
    + Cette directive est présente pour compatibilité avec Winape, son usage est déconseillé. Utilisez de préférence les directives BANK ou BANKSET.

    + + En spécifiant une rom basse (entre 0 et 7) ou une rom haute (entre 0 et 31), cette directive a le même effet que la directive BANK.

    + + En spécifiant uniquement l'adresse RAM (n'importe quelle valeur) et en désactivant les numéros de rom avec la valeur -1, on créé à chaque appel un nouvel espace mémoire. On peut ainsi assembler plusieurs code au même emplacement mémoire, mais dans un espace différent. Cet usage est équivalent à la directive BANK sans paramètre. +
    +
    + +
    Directives de définition de données
    +
    CHARSET 'chaine',<valeur> | <code>,<valeur> | <début>,<fin>,<valeur>
    + La directive permet de redéfinir des valeurs aux caractères assemblés entre quotes selon quatre formats:
    +
      +
    • 'chaine',<valeur> → Le premier caractère de la chaine aura pour nouvelle valeur la <valeur>. Le caractère suivant <valeur>+1 et ainsi de suite pour tous les caractères de la chaine.
    • +
    • <code>,<valeur> → Attribuer au caractère de valeur ASCII <code> la valeur <valeur>.
    • +
    • <début>,<fin>,<valeur> → Attribuer aux caractères de valeur ASCII <début> à <fin> une valeur incrémentale en partant de <valeur>.
    • +
    • aucun paramètre → réassigne à tous les caractères leur valeur ASCII par défaut.
    • +
    + Cette fonction est compatible Winape.

    + +
    + Redéfinir un caractère:
    + + CHARSET 'T','t' ; les T majuscules seront écrits t minuscules
    + defb 'tT'
    + ; bytecode produit
    + #0000: #74 #74
    +
    + +
    + Redéfinir quelques caractères non consécutifs:
    + + CHARSET 'turndiskheo ',0
    + defb 'there is no turndisk'
    + ; bytecode produit
    + #0000: #00,#08,#09,#02,#0B,#05,#06,#0B,#03,#0A,#0B,#00,#01,#02,#03,#04,#05,#06,#07
    +
    + +
    + Redéfinir des caractères consécutifs:
    + + CHARSET 'A','Z','a' ; transformer toutes les majuscules en minuscules
    + defb 'abcdeABCDE'
    + ; bytecode produit
    + #0000: #61,#62,#63,#64,#65,#61,#62,#63,#64,#65
    +
    +
    +
    DB, DEFB, DM, DEFM <valeur>[,<valeur>,...]
    + Cette directive prend un ou plusieurs paramètres et génère une suite d'octets représentative des paramètres en entrée. La valeur peut être une valeur litérale, une formule dont le résultat sera éventuellement arrondi et tronqué ou même une chaine de caractères dont chaque caractère produira un octet en sortie égale à sa valeur ASCII, sauf si la directive CHARSET a été utilisée pour redéfinir ces valeurs.

    + + Exemple:
    + + defb 'r'-'a'+'A',oudoudou',#FF,lo($)
    +
    + La référence d'adresse courante est celle de l'octet en cours par défaut. +
    +
    DEFW, DW <valeur>[,<valeur>,...]
    + Cette directive prend un ou plusieurs paramètres et génère une suite de mots (deux octets) représentative des paramètres en entrée. Les valeurs peuvent être une valeur littérale, une formule dont le résultat sera éventuellement arrondi et tronqué. Cette directive ne supporte pas une chaine de plusieurs caractères comme valeur.

    + + Exemple:
    + + defw mylabel1,mylabel2,'a'+#100

    +
    +
    + +
    DEFI
    + Cette direction prend un ou plusieurs paramètres et génère une suite de double-mots (4 octets) représentative des paramètres en entrée. Les valeurs peuvent être une valeur littérale, une formule dont le résultat sera éventuellement arrondi et tronqué. Cette directive ne supporte pas une chaine de plusieurs caractères comme valeur.
    +
    +
    DEFR, DR <nombre réel>[,<nombre réel>,...]
    + Cette directive prend un ou plusieurs paramètres et génère une suite de nombre réels (5 octets chaque) compatibles avec le firmware des Amstrad CPC.

    + Exemple:
    + + defr 5/12,7/3
    +
    +
    +
    DEFS, DS <répétition>[,<valeur>,[<répétition>,...]
    + Cette directive génère une suite d'octets répétitive. Si la valeur de remplissage est omise alors zéro sera pris par défaut. Si la valeur de répétition est nulle alors aucun octet ne sera produit. Il est possible de déclarer plusieurs suites de répétition avec le même DEFS mais les premières répétitions sera toujours interprétées comme ayant une valeur à répéter.

    + + Exemple:
    + + defs 5,8,4,1 ; output=#08,#08,#08,#08,#08,#01,#01,#01,#01
    + defs 5,8,4 ; output=#08,#08,#08,#08,#08,#00,#00,#00,#00
    + defs 5 ; output=#00,#00,#00,#00,#00
    +
    +
    +
    <alias> EQU <chaine de remplacement>
    + Création d'un alias. Quand l'assembleur rencontrera l'alias dans une expression, le texte sera remplacé par celui défini lors du EQU. Un test de récursivité infini est réalisé à la création de l'alias.

    + Exemple:
    + + tab1 EQU #8000
    + tab2 EQU tab1+#100
    +
    + ld hl,tab2
    +
    +
    +
    STR 'chaine1'[,'chaine2'...]
    + Directive similaire à DEFB, sauf que le dernier caractère de chaque chaine aura son bit 7 forcé à 1 (opération OR #80 sur le dernier octet).

    + + Les deux lignes suivantes produiront les mêmes octets:
    + + defb 'roudoudo','u'+128
    + str 'roudoudou'
    +
    +
    +
    STRUCT <nom de prototype>[,<nom de variable>]
    + Le Z80 est particulièrement apte à traiter des structures de données grâce aux instructions indexées (registres IX et IY) mais on peut simplement vouloir déclarer des structures par convenance personnelle.

    + + Exemple de création d’une structure
    + + struct st1
    + ch1 defw 0
    + ch2 defb 0
    + endstruct
    + La structure st1 est créée avec deux champs ch1 et ch2. Aucun octet n’est produit en mémoire.
    + Imbriquer les structures
    + struct metast1
    + struct st1 pr1
    + struct st1 pr2
    + endstruct
    + La structure metast1 est créée avec deux sous-structures de type st1 appellées pr1 et pr2
    +
    +
    + Pour récupérer la taille d’une structure, il est recommandé d’utiliser le préfixe {SIZEOF}. La taille d’une structure peut être récupérée avec le nom de son prototype comme Vasm mais cette pratique est fortement déconseillée et n’existe qu’à des fins de compatibilité.
    + + LD HL,{SIZEOF}metast1
    + LD HL,metast1
    +
    +
    + La directive STRUCT appelée avec deux paramètres va créer en mémoire une structure sur la base d’un prototype existant, qu’il faudra nommer. Par exemple ci-dessous, on va créer une structure mymeta de type metast1.

    + + struct metast1 mymeta
    +
    +
    + On peut récupérer les offsets des champs d’une structure en utilisant les informations du prototype:
    + + LD A,(IX+metast1.pr2.ch1) ; offset car prototype utilisé
    +
    +
    + Si on utilise le nom d’une structure statique alors c’est l’adresse absolue qui est renvoyée:
    + + LD HL,mymeta.pr2.ch1
    + LD A,(HL)
    +
    +
    +
    +
    Directives d'import et de compression
    +
    INCLUDE, READ 'fichier à lire'
    + Lire un fichier texte et l'intégrer au code source à l'emplacement de l'instruction de lecture. Le chemin relatif de lecture a pour racine l'emplacement du fichier dans lequel est l'instruction de lecture. Un chemin absolu s'affranchit de ce répertoire racine.

    + + Il n'y a pas de limite de récursivité en lecture. Attention à ce que vous faites. +
    +
    INCBIN 'fichier à lire'[,offset[,size[,offset étendu[,OFF]]]] ou INCBIN 'fichier wav',SMP|SM2|SM4|DMA
    + Lire un fichier binaire. Les données lues seront directement injectées. Les paramètres optionnels sont compatibles avec la fonction INCBIN de Winape. L'offset n'est pas limité à 64Ko comme Winape. L'offset étendu est là pour compatibilité. Son usage est à éviter pour rester lisible.

    + + Il est possible de donner un offset négatif, relatif à la fin du fichier.

    + + Il est possible de donner une taille de fichier négative. La taille lue sera égale à la taille totale du fichier ajoutée à cette valeur négative. Pour tout lire sauf les 10 derniers octets, on précisera une taille de -10 dans la commande.

    + + Une taille de zéro chargera tout le fichier.

    + + Paramètre OFF: Si on souhaite charger un fichier pour initialiser de la “mémoire†et qu'on souhaite assembler du code par dessus, on peut désactiver pour la lecture de ce fichier le contrôle d'écrasement.

    + + Exemple:
    + + org #4000
    + incbin'makeraw.bin',0,0,0,OFF ; lecture en #4000 avec contrôle d'écrasement désactivé
    + org #4001
    + defb #BB ; écrasement du deuxième octet sans erreur
    +
    + Exemple de lecture de fichier audio:
    + + org #4000
    + incbin'sound.wav',DMA
    +
    + Les fichiers WAV sont à priori tous supportés quel que soit leur format, mono-canal ou multi-canal. Une fusion des voix sera réalisée en cas de fichier multi-canal. La fréquence d'échantillonage n'est pas prise en compte. Chaque échantillon sera converti en une valeur PSG. Vos fichiers audio pour liste DMA devront au préalable avoir été converti à 15600Hz. Pour les samples classiques, à votre vitesse de relecture. Il existe deux formats additionnels pour les samples classiques nommés SM2 et SM4.

    + Le format SM2 contient deux valeurs sur un seul octet, premier échantillon dans les bits de poids fort.

    + Le format SM4 contient quatre valeurs sur un seul octet, premier échantillon dans les bits de poids fort. Le système retenu est le suivant. Les valeurs codées sont les valeurs 0,13,14,15. Ainsi on peut coder sur seulement 2 bits avec toute l'amplitude 4 bits du PSG. Il suffit de copier les deux bits en position 2 et 3. Le zéro reste zéro de facto.

    +
    +
    INCL48, INCL49, INCLZ4, INCZX7, INCEXO 'fichier à lire'
    + Lire un fichier binaire, le compresser en LZ48, LZ49, LZ4, Exomizer ou ZX7 et l'injecter directement dans le code. +
    +
    LZ48, LZ49, LZ4, LZX7, LZEXO
    + Ouvrir un segment de code compressé en LZ48,LZ49, LZ4, ZX7 ou Exomizer. Le code produit sera compressé après assemblage et l'ensemble du code situé après la zone sera relogé.

    + + Il n'est pas possible d'appeler un label situé après un segment compressé depuis le code compressé pour des raisons évidentes dûes aux aléas de la compression. Une erreur s'affichera expliquant pourquoi.

    + + Limitations:
    +
      +
    • Le code ou les données d'une zone LZ ne peut excéder l'espace d'adressage de 64Ko.
    • +
    • Il n'est pas possible d'imbriquer les segments compressés.
    • +
    +
    + Exemple:
    + + org #1000
    + ld hl,zecrunch
    + ld de,#8000
    + call decrunch
    + call #8000
    + jp next ; label next after crunched zone will be relocated
    +
    + zecrunch
    + lz48 ; this section will be crunched
    + org #8000,$
    + nop
    + nop
    + nop
    + ret
    + lzclose
    +
    + next
    + ret
    +
    + +
    +
    LZCLOSE
    + Fermer une zone LZ. +
    +
    + +
    Directives de code conditionnel
    +
    ASSERT <condition>[,texte,texte,texte,...]
    + Vérifier une condition et arrêter l'assemblage si la condition est fausse.

    + Exemple:
    + + assert mygenend-mygenstart<#100
    + assert mygenend-mygenstart<#100,'code trop gros'
    +
    +
    +
    IF <condition>, IFNOT <condition>, ELSE, ELSEIF <condition>, ENDIF
    + Directive de test et définition de blocs pour le code conditionnel.

    + + Exemple:
    + + CODE_PRODUCTION=1
    + [...]
    + if CODE_PRODUCTION
    + or #80
    + else
    + print 'version de test'
    + endif
    +
    + +
    +
    IFDEF, IFNDEF <variable ou label>
    + Ces deux directives permettent de tester l'existence ou la non existence d'une variable ou d'un label, AVANT la directive. +
    +
    IFUSED, IFNUSED <variable ou label>
    + Ces deux directives permettent de tester l'utilisation ou la non utilisation d'une variable ou d'un label, AVANT la directive. +
    +
    MACRO
    + Rasm supporte les macros avec chevrons (compatible avec Winape). Il est possible de faire de l'assemblage conditionnel avec les macros car à chaque appel de macro, le code d'origine est inséré, les paramètres substitués et enfin le code est interprété de façon classique.

    + + Exemple pour une écriture longue distance générique (sauf pour B ou C):
    + + macro LDIXREG registre,dep ; chaque paramètre séparé par une virgule
    + if {dep}<-128 || {dep}>127
    + push bc
    + ld bc,{dep}
    + add ix,bc
    + ld (ix+0),{registre}
    + pop bc
    + else
    + ld (ix+{dep}),{registre}
    + endif
    + mend
    +
    + + Note: Le marqueur de fin de macro peut être indifférement MEND ou ENDM


    + + + Macros sans paramètre
    + En cas de faute de frappe, pour éviter que la macro mal orthographiée soit remplacée par un label, il est conseillé d'utiliser le paramètre (VOID) à chaque appel. Ainsi, si la macro est mal orthographiée, la présence du (VOID) déclenchera une erreur.

    + + macro sansparam
    + nop
    + mend
    +
    + sansparam (void) ; appel sécurisé de la macro
    +
    + +

    Appel de macro en paramètre statique ou dynamique
    + Les macros de Rasm sont (en logique interne) du code qui est remplacé au vol lors de l'assemblage. Il y a deux possibilités de remplacement pour les paramètres. Soit le paramètre est copié tel que, soit il peut être calculé et c'est sa valeur calculée qui sera injecté dans la macro.

    + + macro test myarg
    + defb {myarg}
    + mend
    +
    + repeat 2
    + test repeat_counter
    + rend
    + repeat 2
    + test {eval}repeat_counter
    + rend
    +
    + + Dans la première boucle, c'est la ligne defb repeat_counter qui sera développée tandis que le second appel, avec le paramètre précédé du tag {eval}, c'est la première valeur de repeat_counter qui sera développée, entrainant deux defb identiques. +
    +
    PRINT 'chaine',<variable>,<expression>
    + Écrire du texte, variables ou expressions lors de l'assemblage. Concernant les valeurs numériques l'affichage par défaut est un nombre flottant mais il est possible de formater les variables en préfixant la variable par des tags:

    +
    {hex}
    afficher la variable en hexadécimal. Si la variable vaut moins de #FF alors l'affichage sera forcé sur deux chiffres. Si la variable vaut moins de #FFFF alors l'affichage sera forcé sur quatre chiffres. Au dessus il n'y aura pas d'extra-zéros. + +
    {hex2}, {hex4}, {hex8}
    pour forcer l'affichage quel que soit la valeur, sur 2, 4 ou 8 chiffres. + +
    {bin}
    afficher la variable en binaire. Si la variabke vaut moins de #FF alors l'affichage sera forcé sur 8 bits. Si la variable vaut moins de #FFFF alors l'affichage sera forcé sur 16 bits. Un pré-traitement enlève les 16 bits supérieurs de la valeur 32 bits au cas où tous les bits sont à 1 (nombre négatif). + +
    {bin8},{bin16},{bin32}
    pour forcer l'affichage quel que soit la valeur, sur 8, 16 ou 32 bits. + +
    {int}
    afficher en décimal, nombre entier. + +
    +
    FAIL 'chaine',<variable>,<expression>
    + Directive dérivée de PRINT, qui sort de Rasm en erreur. +
    +
    REPEAT <nombre de répétition>[,variable], REND / REPEAT, UNTIL <condition>
    + Répète un bloc d'instructions. On peut soit fixer un nombre de répétitions, soit utiliser le mode conditionnel avec la directive de fin de bloc UNTIL. Il est possible à tout moment de consulter le numéro d'itération du repeat courant avec la variable REPEAT_COUNTER. Pour le cas de répétition non conditionnel, on peut donner un nom de variable (qui existe déjà ou non) pour que le compteur y soit recopié à chaque itération.

    + + Exemple:
    + + repeat 10
    + ldi
    + print repeat_counter
    + rend
    +
    + cpt=10
    + repeat
    + ldi
    + cpt=cpt-1
    + until cpt>0
    +
    + + Exemple avec compteur exporté:
    + + repeat 10,hello
    + ldi
    + print hello
    + rend
    +
    +
    + Note: La variable 'hello' peut exister ou non. Si elle n'existe pas au début du REPEAT, elle sera crée. +
    +
    STOP
    + Arrêter l'assemblage. Aucun fichier ne sera écrit. +
    +
    SWITCH, CASE, BREAK, DEFAULT, ENDSWITCH
    + La syntaxe est une mimic du case en C, avec la particularité de pouvoir écrire plusieurs CASE qui ont la même valeur, ce qui donne plus de souplesse au code conditionnel.

    + + Dans cet exemple, l'appel de la macro avec 5 assemblera toutes les chaines de defb avec 'oui' ou 'encore oui':
    + + macro ouioui mavar
    + switch {mavar}
    + nop ; pas assemblé car hors case
    + case 3
    + defb 'non'
    + case 5
    + defb 'oui'
    + case 7
    + defb 'encore oui'
    + break
    + case 8
    + defb 'non'
    + case 5
    + defb 'encore oui'
    + break
    + default
    + defb 'non'
    + endswitch
    + mend
    +
    +
    +
    WHILE, WEND
    + Répète un bloc d'instructions tant que la condition est vérifiée. Il est possible de consulter à tout moment la variable WHILE_COUNTER pour déclencher des évènements en fonction du numéro d'itération.

    + + Exemple:
    + + cpt=10
    + while cpt>0
    + ldi
    + cpt=cpt-1
    + print 'cpt=',cpt,' while_counter=',while_counter
    + wend
    +
    + La boucle sera exécutée 10 fois de suite produisant la sortie texte suivante:
    + + Pre-processing [while.asm]
    + Assembling
    + cpt= 9.00 while_counter= 1.00
    + cpt= 8.00 while_counter= 2.00
    + cpt= 7.00 while_counter= 3.00
    + cpt= 6.00 while_counter= 4.00
    + cpt= 5.00 while_counter= 5.00
    + cpt= 4.00 while_counter= 6.00
    + cpt= 3.00 while_counter= 7.00
    + cpt= 2.00 while_counter= 8.00
    + cpt= 1.00 while_counter= 9.00
    + cpt= 0.00 while_counter= 10.00
    + Write binary file rasmoutput.bin (20 bytes)
    +
    +
    +
    + +
    Directives de sortie fichier
    +
    AMSDOS
    + Ajoute un entête Amsdos au fichier binaire produit automatiquement par Rasm. Cet entête n'est pas ajouté lors d'un SAVE. La fonction SAVE dispose elle aussi d’une option pour ajouter cet entête à la demande. +
    +
    BREAKPOINT [<adresse>]
    + Ajoute un point d'arrêt (ce n'est pas une instruction qui est assemblée) avec pour adresse de break l'adresse de l'instruction suivante ou celle du paramètre optionnel. Les points d'arrêt peuvent être exportés sous forme de fichier brut ou dans les snapshots (compatible avec les émulateurs ACE et Winape).

    + + Note: Tout label qui commence par le préfixe BRK ou @BRK génère à la fois un label et un point d'arrêt.

    +
    +
    BUILDCPR
    + La directive n'a plus d'utilité. Elle était supposée forcer l'écriture d'une cartouche lorsqu'on cumulait les différents types de sauvegarde. +
    +
    BUILDSNA [V2]
    + L'usage de la directive BUILDSNA indique à Rasm qu'on veut générer un snapshot et non une cartouche (dans le doute c'est une cartouche qui est générée).

    + + Par défaut le snapshot est initialisé avec un 6128 CRTC 0 mais il est possible avec les directives SETCRTC et SETCPC de choisir un autre type de CPC et de CRTC.

    + + Le snapshot généré par Rasm inclu un écran de taille classique (le même que sous Basic), les encres sont aux valeurs par défaut du Basic (non clignottantes). Les 3 voies audio sont désactivées, les roms désactivées et le mode d'interruption est 1.

    + + Exemple:
    + + buildsna ; il est conseillé de commencer par déclarer le SNA pour
    + ; éviter d'avoir un problème de limite à 512K
    +
    + bankset 0 ; assembler dans les premiers 64K de la machine
    + org #1000
    + run #1000 ; le snapshot s'exécutera en #1000
    +
    + ld b,#7F
    + ld a,{page}mydata ; récupère l'ordre gate array de pagination mémoire
    + out (c),c
    + ld a,(mydata)
    + jr $
    +
    + bank 6 ; choisir la troisième bank du deuxième jeu de 64K
    + nop
    + mydata defb #DD
    +
    + bank ; sans paramètre, créer un espace mémoire indépendant qui ne
    + ; sera pas enregistré dans le snapshot
    +
    + pouet
    + repeat 10
    + cpi
    + rend
    + camion
    + save"autrechose",pouet,camion-pouet
    +
    +
    + Option de compatibilité pour la création de snapshot version 2: Certains émulateurs ou cartes hardware ne gèrent pas encore le format v3. Pour rétrograder les snapshots en format v2 (128K maximum, non compressés), il suffit d'ajouter le paramètre V2 après la directive comme suit:
    + + buildsna v2
    +
    +
    +
    RUN <adresse>[,<gate array configuration>]
    + Cette directive n'est prise en compte que si on génère un snapshot. Alors l'adresse de démarrage du code sera injectée dans le snapshot. En option on peut spécifier la configuration du gate array, typiquement pour exécuter un programme depuis les 64K de mémoire étendue. +
    +
    SAVE 'nom de fichier',<adresse>,<taille>[,AMSDOS|DSK[,'fichier dsk'[,<face>]]]
    + Enregistre un fichier binaire à partir de la mémoire adresse jusqu'à adresse+taille de l'espace mémoire en cours. Bien que l'instruction SAVE puisse être déclarée à n'importe quel moment, les enregistrements de fichier sont toujours réalisés en fin d'assemblage si et seulement si il n'y a pas eu d'erreur. Il n'est donc pas possible d'enregistrer des états intermédiaires d'assemblage.

    + + Lorsqu'on enregistre sur une image de disquette (DSK), le nom du fichier binaire est automatiquement tronqué et mis en majuscule si il n'est pas conforme aux limitations de l'AMSDOS.

    + + Exemples:
    + + SAVE 'monfichier.bin',debut,taille ; Enregistrer un fichier binaire brut
    + SAVE 'monfichier.bin',debut,taille,AMSDOS ; Enregistrer un fichier binaire avec entête AMSDOS
    + SAVE 'monfic.bin',debut,taille,DSK,'fichierdsk.dsk' ; Enregistrer un fichier binaire sur une image de disquette
    +
    + + +
    +
    SETCPC <modèle>
    + Choisir le modèle de CPC quand on enregistre un snapshot. Les valeurs autorisées sont:
    +
      +
    • 0 : CPC 464
    • +
    • 1 : CPC 664
    • +
    • 2 : CPC 6128
    • +
    • 4 : 464 Plus
    • +
    • 5 : 6128 Plus
    • +
    • 6 : GX-4000
    • +
    +
    +
    SETCRTC <modèle>
    + Choisir le modèle de CRTC quand on enregistre un snapshot. Les valeurs autorisées vont de 0 à 4. Pour rappel, les CPC ont des CRTC 0,1,2 ou 4 et les Plus ou GX-4000 ont tous le CRTC 3. +
    +
    + +
    Directives de compatibilité
    +
    LIST, NOLIST, LET
    + Directives ignorées, pour compatibilité avec Winape. +
    +
    + + +
    Jeu d'instruction
    + Toutes les instructions documentées et non documentées sont supportées.

    + + L'adressage 8 bits des registres d'index IX et IY se fait indifféremment avec LX, IXL ou XL, etc.

    + + Les instructions complexes s'écrivent de la façon suivante:
    + + res 0,(ix+0),a
    + bit 0,(ix+0),a
    + sll 0,(ix+0),a
    + rl 0,(ix+0),a
    + rr 0,(ix+0),a
    +
    +
    + Syntaxes des instructions non documentées:
    + + out (#12),a ; #12 peut être n'importe quelle valeur 8 bits
    + in a,(#12)
    + in 0,(c) ou in f,(c)
    + sll <registre> ou sl1 <registre>
    +
    +
    + Syntaxes spéciales autorisées:
    + - PUSH multi-arguments
    + + push bc,de,hl ; → push bc : push de : push hl
    +
    + - NOP répétitif
    + + nop 4 ; → nop : nop : nop : nop
    +
    + - complex LD
    + + LD BC,BC ; → LD B,B : LD C,C
    + LD BC,DE ; → LD B,D : LD C,E
    + LD BC,HL ; → LD B,H : LD C,L
    + LD DE,BC ; → LD D,B : LD E,C
    + LD DE,DE ; → LD D,D : LD E,E
    + LD DE,HL ; → LD D,H : LD E,L
    + LD HL,BC ; → LD H,B : LD L,C
    + LD HL,DE ; → LD H,D : LD L,E
    + LD HL,HL ; → LD H,H : LD L,L
    +
    + LD HL,(IX+n) ; → LD H,(IX+n+1) : LD L,(IX+n)
    + LD HL,(IY+n) ; → LD H,(IY+n+1) : LD L,(IY+n)
    + LD DE,(IX+n) ; → LD D,(IX+n+1) : LD E,(IX+n)
    + LD DE,(IY+n) ; → LD D,(IY+n+1) : LD E,(IY+n)
    + LD BC,(IX+n) ; → LD B,(IX+n+1) : LD C,(IX+n)
    + LD BC,(IY+n) ; → LD B,(IY+n+1) : LD C,(IY+n)
    +
    + LD (IX+n),HL ; → LD (IX+n+1),H : LD (IX+n),L
    + LD (IY+n),HL ; → LD (IY+n+1),H : LD (IY+n),L
    + LD (IX+n),DE ; → LD (IX+n+1),D : LD (IX+n),E
    + LD (IY+n),DE ; → LD (IY+n+1),D : LD (IY+n),E
    + LD (IX+n),BC ; → LD (IX+n+1),B : LD (IX+n),C
    + LD (IY+n),BC ; → LD (IY+n+1),B : LD (IY+n),C
    +
    +
    + +
    Limitations
    +
      +
    • Il n'est pas possible d'utiliser la mnémonique d'une instruction Z80 comme un label.
    • +
    • Il n'est pas possible d'utiliser le même nom pour un label, une variable ou un alias.
    • +
    • Rasm n'est pas sensible à la casse.
    • +
    • Les blocs de code à compresser dynamiquement ne peuvent excéder 64K.
    • +
    +
    + +
    + Ce logiciel et sa documentation utilisent la licence MIT "expat"

    + + « Copyright © BERGÉ Édouard (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. » +
    + +
    + + diff --git a/minilib.h b/minilib.h index 72f8422..c0c4a22 100644 --- a/minilib.h +++ b/minilib.h @@ -171,6 +171,33 @@ int CSVGetFieldArrayNumber(char **myfield) return n; } +/*** + * TxtSplit + * + * split the parameter string into an array of strings + */ +char **TxtSplitWithChar(char *in_str, char split_char) +{ + #undef FUNC + #define FUNC "TxtSplitWithChar" + + char **tab=NULL; + char *match_str; + int redo=1; + int idx,idmax; + + match_str=in_str; + + while (redo && *in_str) { + while (*match_str && *match_str!=split_char) match_str++; + redo=*match_str; + *match_str=0; + FieldArrayAddDynamicValueConcat(&tab,&idx,&idmax,in_str); + in_str=++match_str; + } + + return tab; +} /*** Add a value to a list of strings @@ -957,75 +984,6 @@ long long FileGetSize(char *filename) return nn; } -/* - * 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) -{ - #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 FileReadContent(filename,filesize) _internal_readbinaryfile(filename,filesize) - /*** * append a string * return the number of char appened diff --git a/rasm.c b/rasm.c index bc3c1a9..6ecb066 100644 --- a/rasm.c +++ b/rasm.c @@ -1,10 +1,12 @@ #define PROGRAM_NAME "RASM" -#define PROGRAM_VERSION "0.86" -#define PROGRAM_DATE "xx/04/2018" -#define PROGRAM_COPYRIGHT "© 2017 BERGE Edouard (roudoudou) " +#define PROGRAM_VERSION "0.99" +#define PROGRAM_DATE "xx/07/2018" +#define PROGRAM_COPYRIGHT "© 2017 BERGE Edouard / roudoudou from Resistance" #define RASM_VERSION PROGRAM_NAME" v"PROGRAM_VERSION +#define DEBUG_PREPRO 0 + /*** Rasm (roudoudou assembler) Z80 assembler @@ -32,16 +34,18 @@ any claim, damages or other liability, whether in an action of contract, arising from, out of or in connection with the software or the use or other dealings in the Software. » ----------------------------------------------------------------------------------------------------- -GCC compilation: -cc rasm_v084.c -O2 -lm -lrt -march=native -strip a.out -mv a.out rasm +Linux compilation with GCC or Clang: +cc rasm_v099.c -O2 -lm -lrt -march=native -o rasm +strip rasm -Visual studio compilation: -cl.exe rasm_v084.c -O2 +Windows compilation with Visual studio: +cl.exe rasm_v099.c -O2 + +DOS (windows compatible) 32 bits compilation with Watcom: +wcl386 rasm_v099.c -6r -6s -fp6 -d0 -k4000000 -ox /bt=DOS /l=dos4g MorphOS compilation (ixemul): -ppc-morphos-gcc-5 -O2 -c -o rasm rasm_v084.c +ppc-morphos-gcc-5 -O2 -c -o rasm rasm_v099.c strip rasm */ @@ -63,6 +67,7 @@ strip rasm #else /* private dev lib wont be published */ #include"../tools/library.h" + #define TxtSplitWithChar _internal_TxtSplitWithChar #endif #ifndef NO_3RD_PARTIES @@ -81,48 +86,93 @@ const char __attribute__((section(".text"))) ver_version[]={ "\0$VER: "PROGRAM_N #undef __FILENAME__ #define __FILENAME__ "rasm.c" +/******************************************************************* + 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 export_local; + int export_var; + int export_equ; + int export_sym; + int export_sna; + int export_snabrk; + int export_brk; + int verbose; + int nowarning; + int checkmode; + int dependencies; + int maxerr; + int extended_error; + int edskoverwrite; + float rough; + int as80,dams; + int v2; + char *symbol_name; + char *binary_name; + char *cartridge_name; + char *snapshot_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, -E_COMPUTE_OPERATION_CLOSE, -E_COMPUTE_OPERATION_ADD, -E_COMPUTE_OPERATION_SUB, -E_COMPUTE_OPERATION_DIV, -E_COMPUTE_OPERATION_MUL, -E_COMPUTE_OPERATION_AND, -E_COMPUTE_OPERATION_OR, -E_COMPUTE_OPERATION_MOD, -E_COMPUTE_OPERATION_XOR, -E_COMPUTE_OPERATION_SHL, -E_COMPUTE_OPERATION_SHR, -E_COMPUTE_OPERATION_BAND, -E_COMPUTE_OPERATION_BOR, -E_COMPUTE_OPERATION_LOWER, -E_COMPUTE_OPERATION_GREATER, -E_COMPUTE_OPERATION_EQUAL, -E_COMPUTE_OPERATION_NOTEQUAL, -E_COMPUTE_OPERATION_LOWEREQ, -E_COMPUTE_OPERATION_GREATEREQ, +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, -E_COMPUTE_OPERATION_COS, -E_COMPUTE_OPERATION_INT, -E_COMPUTE_OPERATION_FLOOR, -E_COMPUTE_OPERATION_ABS, -E_COMPUTE_OPERATION_LN, -E_COMPUTE_OPERATION_LOG10, -E_COMPUTE_OPERATION_SQRT, -E_COMPUTE_OPERATION_ASIN, -E_COMPUTE_OPERATION_ACOS, -E_COMPUTE_OPERATION_ATAN, -E_COMPUTE_OPERATION_EXP, -E_COMPUTE_OPERATION_LOW, -E_COMPUTE_OPERATION_HIGH, -E_COMPUTE_OPERATION_END +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_END=37 }; struct s_compute_element { @@ -131,6 +181,42 @@ 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 @@ -144,6 +230,7 @@ enum e_expression { 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 */ @@ -176,6 +263,9 @@ struct s_label { 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 */ + /* errmsg */ + int fileidx; + int fileline; }; struct s_alias { @@ -198,12 +288,18 @@ struct s_crcdico_tree { struct s_expr_dico *dico; int ndico,mdico; }; -struct s_crcalias_tree { - struct s_crcalias_tree *radix[256]; - struct s_alias *alias; - int nalias,malias; +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 *************************************************/ @@ -230,7 +326,7 @@ struct s_orgzone { **************************************************/ struct s_hexbin { unsigned char *data; - int datalen; + int datalen,rawlen; char *filename; }; @@ -310,6 +406,8 @@ struct s_repeat { int value; int maxim; int repeat_counter; + char *repeatvar; + int repeatcrc; }; struct s_whilewend { @@ -333,6 +431,24 @@ struct s_repeat_index { }; +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 **************************************************/ @@ -384,7 +500,10 @@ struct s_listing { int iline; }; - +enum e_tagtranslateoption { +E_TAGOPTION_NONE=0, +E_TAGOPTION_REMOVESPACE +}; #ifdef RASM_THREAD struct s_rasm_thread { @@ -425,7 +544,7 @@ struct s_snapshot { unsigned char H; }general; unsigned char R; - unsigned char I; + unsigned char regI; /* I incompatible with tgmath.h */ unsigned char IFF0; unsigned char IFF1; unsigned char LX; @@ -543,8 +662,8 @@ struct s_assenv { int nbbank,maxbank; int forcecpr,bankmode,activebank,amsdos,forcesnapshot,packedbank; struct s_snapshot snapshot; - int bankset[9]; - int bankused[35]; + int bankset[9]; /* 64K selected flag */ + int bankused[35]; /* 16K selected flag */ int bankgate[36]; /* parsing */ struct s_wordlist *wl; @@ -557,7 +676,7 @@ struct s_assenv { int nberr,flux,verbose; int fastmatch[256]; unsigned char charset[256]; - int maxerr; + int maxerr,extended_error,nowarning; /* ORG tracking */ int codeadr,outputadr,nocode; int minadr,maxadr; @@ -575,8 +694,10 @@ struct s_assenv { /* expressions */ struct s_expression *expression; int ie,me; - int maxam,as80; + 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; @@ -584,6 +705,8 @@ struct s_assenv { char *module; struct s_breakpoint *breakpoint; int ibreakpoint,maxbreakpoint; + char *lastgloballabel; + int lastgloballabellen; /* repeat */ struct s_repeat *repeat; int ir,mr; @@ -591,7 +714,8 @@ struct s_assenv { struct s_whilewend *whilewend; int iw,mw; /* if/then/else */ - int *ifthen; + //int *ifthen; + struct s_ifthen *ifthen; int ii,mi; /* switch/case */ struct s_switchcase *switchcase; @@ -600,6 +724,7 @@ struct s_assenv { struct s_expr_dico *dico; int idic,mdic; struct s_crcdico_tree dicotree; /* fast dico access */ + struct s_crcused_tree usedtree; /* fast used access */ /* crunch section flag */ struct s_lz_section *lzsection; int ilz,mlz; @@ -614,13 +739,15 @@ struct s_assenv { /* alias */ struct s_alias *alias; int ialias,malias; - struct s_crcalias_tree aliastree; /* fast alias access */ /* 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]; @@ -629,6 +756,8 @@ struct s_assenv { 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; @@ -645,7 +774,7 @@ struct s_assenv { struct s_edsk_wrapper *edsk_wrapper; int nbedskwrapper,maxedskwrapper; int edskoverwrite; - int checkmode; + int checkmode,dependencies; int stop; }; @@ -670,6 +799,7 @@ struct s_math_keyword math_keyword[]={ {"EXP",0,E_COMPUTE_OPERATION_EXP}, {"LO",0,E_COMPUTE_OPERATION_LOW}, {"HI",0,E_COMPUTE_OPERATION_HIGH}, +{"PSGVALUE",0,E_COMPUTE_OPERATION_PSG}, {"",0,-1} }; @@ -684,6 +814,7 @@ struct s_math_keyword math_keyword[]={ #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 @@ -691,6 +822,8 @@ struct s_math_keyword math_keyword[]={ #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 @@ -770,10 +903,11 @@ 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 AutomateExpressionValidCharDefinition "0123456789.ABCDEFGHIJKLMNOPQRSTUVWXYZ_{}@$" #define AutomateValidLabelFirstDefinition ".ABCDEFGHIJKLMNOPQRSTUVWXYZ_@" -#define AutomateValidLabelDefinition "0123456789.ABCDEFGHIJKLMNOPQRSTUVWXYZ_@" +#define AutomateValidLabelDefinition "0123456789.ABCDEFGHIJKLMNOPQRSTUVWXYZ_@{}" #define AutomateDigitDefinition ".0123456789" #define AutomateHexaDefinition "0123456789ABCDEF" @@ -791,6 +925,77 @@ unsigned char *LZ49_encode_legacy(unsigned char *data, int length, int *retlengt #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 @@ -1021,14 +1226,89 @@ void rasm_printf(struct s_assenv *ae, ...) { char *format; va_list argptr; - if (!ae->flux) { + if (!ae->flux && !ae->dependencies) { va_start(argptr,ae); format=va_arg(argptr,char *); vfprintf(stdout,format,argptr); va_end(argptr); } } +/*** + 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" + + char *pos,*repos; + int i,len; + +#ifdef OS_WIN + while ((pos=strstr(filename,"\\..\\"))!=NULL) { + repos=pos-1; + while (repos>=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;iradix[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 @@ -1270,49 +1594,43 @@ char *StringLooksLike(struct s_assenv *ae, char *str) #undef FUNC #define FUNC "StringLooksLike" - char *ret=NULL; - int i,curs,score=3; + char *ret=NULL,*tmpret; + int i,curs,score=4; /* search in variables */ - //ExportDicoTree(ae,TMP_filename,"%s #%04X\n"); + ret=StringLooksLikeDico(ae,&score,str); /* search in labels */ for (i=0;iil;i++) { - if (!ae->label[i].name) { + 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; } } - //sprintf(symbol_line,"%s #%04X\n",ae->label[i].name,ae->label[i].ptr); pas de test sur les locaux } /* search in alias */ for (i=0;iialias;i++) { - curs=_internal_LevenshteinDistance(ae->alias[i].alias,str); - if (cursalias[i].alias; + if (strlen(ae->alias[i].alias)>4) { + curs=_internal_LevenshteinDistance(ae->alias[i].alias,str); + if (cursalias[i].alias; + } } } -// char *StringLooksLikeMacro(char *str, int *retscore); - return ret; -} - -void MaxError(struct s_assenv *ae) -{ - #undef FUNC - #define FUNC "MaxError" - - ae->nberr++; - if (ae->nberr==ae->maxerr) { - rasm_printf(ae,"Too many errors!\n"); - exit(1); + tmpret=StringLooksLikeMacro(ae,str,&curs); + if (cursnbbank;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++) { + //printf("structalias[%d]=%s (%d)\n",i,ae->rasmstructalias[i].name,ae->rasmstructalias[i].size); + 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].name); + } + if (ae->rasmstruct[i].mrasmstructfield) MemFree(ae->rasmstruct[i].rasmstructfield); + } + 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); + 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++) { +//printf("alias[%d][%s]=[%s]\n",i,ae->alias[i].alias,ae->alias[i].translation); + 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); + } + + 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,"-> %s",source_lines[zeline]); + } else { + rasm_printf(ae,"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,"Too many errors!\n"); + FreeAssenv(ae); + exit(1); + } +} + void (*___output)(struct s_assenv *ae, unsigned char v); void ___internal_output(struct s_assenv *ae,unsigned char v) @@ -1361,7 +1835,8 @@ void ___internal_output(struct s_assenv *ae,unsigned char v) ae->mem[ae->activebank][ae->outputadr++]=v; ae->codeadr++; } else { - rasm_printf(ae,"[%s] Error line %d - output exceed limit %d\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->maxptr); + rasm_printf(ae,"[%s:%d] output exceed limit %d\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->maxptr); + FreeAssenv(ae); exit(3); } } @@ -1374,7 +1849,8 @@ void ___internal_output_nocode(struct s_assenv *ae,unsigned char v) ae->outputadr++; ae->codeadr++; } else { - rasm_printf(ae,"[%s] Error line %d - NOCODE output exceed limit %d\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->maxptr); + rasm_printf(ae,"[%s:%d] NOCODE output exceed limit %d\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->maxptr); + FreeAssenv(ae); exit(3); } } @@ -1391,11 +1867,11 @@ void ___output_set_limit(struct s_assenv *ae,int zelimit) /* apply limit */ limit=zelimit; } else { - rasm_printf(ae,"[%s] Error line %d - limit exceed hardware limitation!\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] limit exceed hardware limitation!\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } if (ae->outputadr>=0 && ae->outputadr>limit) { - rasm_printf(ae,"[%s] Error line %d - limit too high for current output!\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] limit too high for current output!\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ae->maxptr=limit; @@ -1549,10 +2025,11 @@ void CheckAndSortAliases(struct s_assenv *ae) struct s_alias tmpalias; int i,dw,dm,du,crc; for (i=0;iialias-1;i++) { - /* est-ce qu'on retrouve des anciens alias dans le nouveau ? */ + /* is there previous aliases in the new alias? */ if (strstr(ae->alias[ae->ialias-1].translation,ae->alias[i].alias)) { - /* peut-être, on s'en assure */ + /* 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; } @@ -1590,7 +2067,7 @@ void CheckAndSortAliases(struct s_assenv *ae) ae->alias[dm]=tmpalias; } } else { - /* pas de tri pour un seul élément */ + /* one alias need no sort */ } } @@ -1789,22 +2266,244 @@ struct s_expr_dico *SearchDico(struct s_assenv *ae, char *dico, int crc) } return NULL; } -/* -struct s_crclabel_tree { - struct s_crclabel_tree *radix[256]; - struct s_label *label; - int nlabel,mlabel; -}; -*/ -void FreeLabelTreeRecurse(struct s_crclabel_tree *lt) +int DelDico(struct s_assenv *ae, char *dico, int crc) { #undef FUNC - #define FUNC "FreeLabelTreeRecurse" + #define FUNC "DelDico" - int i; + struct s_crcdico_tree *curdicotree; + struct s_expr_dico *retdico=NULL; + int i,radix,dek=32; - for (i=0;i<256;i++) { - if (lt->radix[i]) { + 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) { + 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]); } } @@ -1836,7 +2535,6 @@ struct s_label *SearchLabel(struct s_assenv *ae, char *label, int crc) int i,radix,dek=32; curlabeltree=&ae->labeltree; - while (dek) { dek=dek-8; radix=(crc>>dek)&0xFF; @@ -1870,6 +2568,23 @@ char *MakeLocalLabel(struct s_assenv *ae,char *varbuffer, int *retdek) //if (strncmp(varbuffer,"@FAST",5)==0) debug=1; else debug=0; //if (debug) printf("[%s]\n",varbuffer); 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+1); + if (retdek) *retdek=0; +//printf("manage proximity label [%s]\n",locallabel); + return locallabel; + } else { + rasm_printf(ae,"[%s:%d] cannot create proximity label or alias [%s] as there is no previous global label\n",GetExpFile(ae,0),ae->wl[ae->idx].l,varbuffer); + MaxError(ae); + return varbuffer; + } + } + if (!retdek) { locallabel=MemMalloc(lenbuf+(ae->ir+ae->iw+3)*8+8); strcpy(locallabel,varbuffer); @@ -1936,33 +2651,121 @@ char *TradExpression(char *zexp) 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; +} + +int RoundComputeExpressionCore(struct s_assenv *ae,char *zeexpression,int ptr,int didx); + +/* + 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 removespace) { + /******************************************************* + 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}; + + *touched=0; + while ((starttag=strchr(varbuffer,'{'))!=NULL) { + if ((endtag=strchr(starttag,'}'))==NULL) { + rasm_printf(ae,"[%s:%d] invalid tag in string [%s]\n",GetExpFile(ae,0),GetExpLine(ae,0),varbuffer); + MaxError(ae); + return NULL; + } + /* allow inception */ + tagcount=1; + tagcheck=starttag+1; + while (*tagcheck && tagcount) { + if (*tagcheck=='}') tagcount--; else if (*tagcheck=='{') tagcount++; + tagcheck++; + } + if (tagcount) { + rasm_printf(ae,"[%s:%d] invalid brackets combination in string [%s]\n",GetExpFile(ae,0),GetExpLine(ae,0),varbuffer); + MaxError(ae); + 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 (removespace) expr=TxtReplace(expr," ","",0); + if (enablefast) ExpressionFastTranslate(ae,&expr,0); + validx=(int)RoundComputeExpressionCore(ae,expr,ae->codeadr,0); + if (validx<0) { + strcpy(curvalstr,""); + rasm_printf(ae,"[%s:%d] indexed tag must NOT be a negative value [%s]\n",GetExpFile(ae,0),GetExpLine(ae,0),varbuffer); + MaxError(ae); + 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" - /* evaluator v2 */ - static struct s_compute_element *tokenstack=NULL; - static int maxtokenstack=0; - int nbtokenstack=0; - + /* static execution buffers */ + static double *accu=NULL; + static int maccu=0; static struct s_compute_element *computestack=NULL; static int maxcomputestack=0; + int i,paccu=0; + int nbtokenstack=0; int nbcomputestack=0; - - static struct s_compute_element *operatorstack=NULL; - static int maxoperatorstack=0; int nboperatorstack=0; struct s_compute_element stackelement; int o2,okclose,itoken; - /* parser legacy */ - static char *varbuffer=NULL; - static int maxivar=1; int idx=0,crc,icheck,is_binary,ivar=0; - char c,asciivalue[11]; + char asciivalue[11]; + unsigned char c; /* backup alias replace */ char *zeexpression,*expr; int original=1; @@ -1976,39 +2779,45 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int double curval; /* negative value */ int allow_minus_as_sign=0; - /* execution */ - static double *accu=NULL; - static int maccu=0; - int i,paccu=0; + /* extended replace in labels */ + int curly=0,curlyflag=0; + char *Automate; /* 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 (maxcomputestack) MemFree(computestack); if (maxoperatorstack) MemFree(operatorstack); - maccu=maxtokenstack=maxcomputestack=maxoperatorstack=0; + maxtokenstack=maxoperatorstack=0; maxivar=1; - accu=NULL; varbuffer=NULL; tokenstack=NULL; - computestack=NULL; operatorstack=NULL; +#endif return 0.0; } + /* be sure to have at least some bytes allocated */ - StateMachineResizeBuffer(&varbuffer,128,&maxivar); + StateMachineResizeBuffer(&ae->computectx->varbuffer,128,&ae->computectx->maxivar); zeexpression=original_zeexpression; if (!zeexpression[0]) { return 0; } - - /* hack if the first value is negative */ +//printf("compute[%s]\n",zeexpression); + /* double hack if the first value is negative */ if (zeexpression[0]=='-') { - memset(&stackelement,0,sizeof(stackelement)); - ObjectArrayAddDynamicValueConcat((void **)&tokenstack,&nbtokenstack,&maxtokenstack,&stackelement,sizeof(stackelement)); + 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) { @@ -2020,7 +2829,7 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int memcpy(zeexpression+idx,asciivalue,4); idx+=3; } else { - rasm_printf(ae,"[%s] Error line %d - Only single escaped char may be quoted [%s]\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression)); + rasm_printf(ae,"[%s:%d] Only single escaped char may be quoted [%s]\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression)); MaxError(ae); zeexpression[0]=0; return 0; @@ -2030,7 +2839,7 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int memcpy(zeexpression+idx,asciivalue,3); idx+=2; } else { - rasm_printf(ae,"[%s] Error line %d - Only single char may be quoted [%s]\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression)); + rasm_printf(ae,"[%s:%d] Only single char may be quoted [%s]\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression)); MaxError(ae); zeexpression[0]=0; return 0; @@ -2103,8 +2912,9 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int idx++; c='n'; // boolean NOTEQUAL } else { - rasm_printf(ae,"[%s] Error line %d - ! sign must be followed by = [%s]\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression)); - MaxError(ae); + //rasm_printf(ae,"[%s:%d] ! sign must be followed by = [%s]\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression)); + //MaxError(ae); + c='b'; } break; case '=': @@ -2123,18 +2933,18 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int if (allow_minus_as_sign) { /* previous char was an opening parenthesis or an operator */ ivar=0; - varbuffer[ivar++]='-'; - StateMachineResizeBuffer(&varbuffer,ivar,&maxivar); + ae->computectx->varbuffer[ivar++]='-'; + StateMachineResizeBuffer(&ae->computectx->varbuffer,ivar,&ae->computectx->maxivar); c=zeexpression[++idx]; while (ae->AutomateExpressionValidChar[(int)c&0xFF]) { - varbuffer[ivar++]=c; - StateMachineResizeBuffer(&varbuffer,ivar,&maxivar); + ae->computectx->varbuffer[ivar++]=c; + StateMachineResizeBuffer(&ae->computectx->varbuffer,ivar,&ae->computectx->maxivar); idx++; c=zeexpression[idx]; } - varbuffer[ivar]=0; + ae->computectx->varbuffer[ivar]=0; if (ivar<2) { - rasm_printf(ae,"[%s] Error line %d - expression [%s] invalid minus sign\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression)); + rasm_printf(ae,"[%s:%d] expression [%s] invalid minus sign\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression)); MaxError(ae); if (!original) { MemFree(zeexpression); @@ -2197,20 +3007,47 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int ivar=0; /* first char does not allow same chars as next chars */ if (ae->AutomateExpressionValidCharFirst[((int)c)&0xFF]) { - varbuffer[ivar++]=c; - StateMachineResizeBuffer(&varbuffer,ivar,&maxivar); +//printf("getword %c",c);fflush(stdout); + 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]; - while (ae->AutomateExpressionValidChar[((int)c)&0xFF]) { - varbuffer[ivar++]=c; - StateMachineResizeBuffer(&varbuffer,ivar,&maxivar); + Automate=ae->AutomateExpressionValidChar; +//printf("%c",c);fflush(stdout); + while (Automate[((int)c)&0xFF]) { + if (c=='{') { + curly++; + curlyflag=1; +//printf(" curly "); + 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]; +//printf("%c",c);fflush(stdout); } } - varbuffer[ivar]=0; + ae->computectx->varbuffer[ivar]=0; +//printf(" -> [%s]\n",ae->computectx->varbuffer); if (!ivar) { - rasm_printf(ae,"[%s] Error line %d - invalid char (%d=%c) expression [%s]\n",GetExpFile(ae,didx),GetExpLine(ae,didx),c,c>31?c:' ',TradExpression(zeexpression)); + rasm_printf(ae,"[%s:%d] invalid char (%d=%c) expression [%s]\n",GetExpFile(ae,didx),GetExpLine(ae,didx),c,c>31?c:' ',TradExpression(zeexpression)); + MaxError(ae); + if (!original) { + MemFree(zeexpression); + } + return 0; + } else if (curly) { + rasm_printf(ae,"[%s:%d] wrong curly brackets in expression [%s]\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression)); MaxError(ae); if (!original) { MemFree(zeexpression); @@ -2230,7 +3067,7 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int ************************************/ stackelement=ae->AutomateElement[c]; if (stackelement.operator>E_COMPUTE_OPERATION_GREATEREQ) { - rasm_printf(ae,"[%s] Error line %d - expression [%s] - unknown operator %c (%d)\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),c>31?c:'.',c); + rasm_printf(ae,"[%s:%d] expression [%s] has unknown operator %c (%d)\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),c>31?c:'.',c); MaxError(ae); } /* stackelement.value isn't used */ @@ -2238,31 +3075,42 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int /************************************ V A L U E ************************************/ -//printf("varbuffer=[%s] c=%c\n",varbuffer,c); - if (varbuffer[0]=='-') minusptr=1; else minusptr=0; +//printf("value varbuffer=[%s] c=%c\n",ae->computectx->varbuffer,c); + if (ae->computectx->varbuffer[0]=='-') minusptr=1; else minusptr=0; /* constantes ou variables/labels */ - switch (varbuffer[minusptr]) { + switch (ae->computectx->varbuffer[minusptr]) { case '0': /* 0x hexa value hack */ - if (varbuffer[minusptr+1]=='X' && ae->AutomateHexa[varbuffer[minusptr+2]]) { - for (icheck=minusptr+3;varbuffer[icheck];icheck++) { - if (ae->AutomateHexa[varbuffer[icheck]]) continue; - rasm_printf(ae,"[%s] Error line %d - expression [%s] - %s is not a valid hex number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),varbuffer); + 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; + rasm_printf(ae,"[%s:%d] expression [%s] - %s is not a valid hex number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),ae->computectx->varbuffer); MaxError(ae); break; } - curval=strtol(varbuffer+minusptr+2,NULL,16); + curval=strtol(ae->computectx->varbuffer+minusptr+2,NULL,16); break; } else /* 0b binary value hack */ - if (varbuffer[minusptr+1]=='B' && (varbuffer[minusptr+2]>='0' && varbuffer[minusptr+2]<='1')) { - for (icheck=minusptr+3;varbuffer[icheck];icheck++) { - if (varbuffer[icheck]>='0' && varbuffer[icheck]<='1') continue; - rasm_printf(ae,"[%s] Error line %d - expression [%s] - %s is not a valid binary number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),varbuffer); + 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; + rasm_printf(ae,"[%s:%d] expression [%s] - %s is not a valid binary number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),ae->computectx->varbuffer); + MaxError(ae); + 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; + rasm_printf(ae,"[%s:%d] expression [%s] - %s is not a valid octal number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),ae->computectx->varbuffer); MaxError(ae); break; } - curval=strtol(varbuffer+minusptr+2,NULL,2); + curval=strtol(ae->computectx->varbuffer+minusptr+2,NULL,2); break; } case '1': @@ -2275,103 +3123,131 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int case '8': case '9': /* check number */ - for (icheck=minusptr;varbuffer[icheck];icheck++) { - if (ae->AutomateDigit[varbuffer[icheck]]) continue; + for (icheck=minusptr;ae->computectx->varbuffer[icheck];icheck++) { + if (ae->AutomateDigit[ae->computectx->varbuffer[icheck]]) continue; /* Intel hexa & binary style */ - switch (varbuffer[strlen(varbuffer)-1]) { + switch (ae->computectx->varbuffer[strlen(ae->computectx->varbuffer)-1]) { case 'H': - for (icheck=minusptr;varbuffer[icheck+1];icheck++) { - if (ae->AutomateHexa[varbuffer[icheck]]) continue; - rasm_printf(ae,"[%s] Error line %d - expression [%s] - %s is not a valid hex number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),varbuffer); + for (icheck=minusptr;ae->computectx->varbuffer[icheck+1];icheck++) { + if (ae->AutomateHexa[ae->computectx->varbuffer[icheck]]) continue; + rasm_printf(ae,"[%s:%d] expression [%s] - %s is not a valid hex number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),ae->computectx->varbuffer); MaxError(ae); } - curval=strtol(varbuffer+minusptr,NULL,16); + curval=strtol(ae->computectx->varbuffer+minusptr,NULL,16); break; case 'B': - for (icheck=minusptr;varbuffer[icheck+1];icheck++) { - if (varbuffer[icheck]=='0' || varbuffer[icheck]=='1') continue; - rasm_printf(ae,"[%s] Error line %d - expression [%s] - %s is not a valid binary number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),varbuffer); + for (icheck=minusptr;ae->computectx->varbuffer[icheck+1];icheck++) { + if (ae->computectx->varbuffer[icheck]=='0' || ae->computectx->varbuffer[icheck]=='1') continue; + rasm_printf(ae,"[%s:%d] expression [%s] - %s is not a valid binary number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),ae->computectx->varbuffer); MaxError(ae); } - curval=strtol(varbuffer+minusptr,NULL,2); + curval=strtol(ae->computectx->varbuffer+minusptr,NULL,2); break; default: - rasm_printf(ae,"[%s] Error line %d - expression [%s] - %s is not a valid number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),varbuffer); + rasm_printf(ae,"[%s:%d] expression [%s] - %s is not a valid number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),ae->computectx->varbuffer); MaxError(ae); } icheck=0; break; } - if (!varbuffer[icheck]) curval=atof(varbuffer+minusptr); + if (!ae->computectx->varbuffer[icheck]) curval=atof(ae->computectx->varbuffer+minusptr); break; case '%': /* check number */ - if (!varbuffer[minusptr+1]) { - rasm_printf(ae,"[%s] Error line %d - expression [%s] - %s is an empty binary number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),varbuffer); + if (!ae->computectx->varbuffer[minusptr+1]) { + rasm_printf(ae,"[%s:%d] expression [%s] - %s is an empty binary number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),ae->computectx->varbuffer); MaxError(ae); } - for (icheck=minusptr+1;varbuffer[icheck];icheck++) { - if (varbuffer[icheck]=='0' || varbuffer[icheck]=='1') continue; - rasm_printf(ae,"[%s] Error line %d - expression [%s] - %s is not a valid binary number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),varbuffer); + for (icheck=minusptr+1;ae->computectx->varbuffer[icheck];icheck++) { + if (ae->computectx->varbuffer[icheck]=='0' || ae->computectx->varbuffer[icheck]=='1') continue; + rasm_printf(ae,"[%s:%d] expression [%s] - %s is not a valid binary number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),ae->computectx->varbuffer); MaxError(ae); break; } - curval=strtol(varbuffer+minusptr+1,NULL,2); + curval=strtol(ae->computectx->varbuffer+minusptr+1,NULL,2); break; case '#': /* check number */ - if (!varbuffer[minusptr+1]) { - rasm_printf(ae,"[%s] Error line %d - expression [%s] - %s is an empty hex number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),varbuffer); + if (!ae->computectx->varbuffer[minusptr+1]) { + rasm_printf(ae,"[%s:%d] expression [%s] - %s is an empty hex number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),ae->computectx->varbuffer); MaxError(ae); } - for (icheck=minusptr+1;varbuffer[icheck];icheck++) { - if (ae->AutomateHexa[varbuffer[icheck]]) continue; - rasm_printf(ae,"[%s] Error line %d - expression [%s] - %s is not a valid hex number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),varbuffer); + for (icheck=minusptr+1;ae->computectx->varbuffer[icheck];icheck++) { + if (ae->AutomateHexa[ae->computectx->varbuffer[icheck]]) continue; + rasm_printf(ae,"[%s:%d] expression [%s] - %s is not a valid hex number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),ae->computectx->varbuffer); MaxError(ae); break; } - curval=strtol(varbuffer+minusptr+1,NULL,16); + curval=strtol(ae->computectx->varbuffer+minusptr+1,NULL,16); break; default: - /* $ hex value hack */ - if (varbuffer[minusptr+0]=='$' && ae->AutomateHexa[varbuffer[minusptr+1]]) { - for (icheck=minusptr+2;varbuffer[icheck];icheck++) { - if (ae->AutomateHexa[varbuffer[icheck]]) continue; - rasm_printf(ae,"[%s] Error line %d - expression [%s] - %s is not a valid hex number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),varbuffer); - MaxError(ae); +//printf("default curlyflag=%d\n",curlyflag); + 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; + rasm_printf(ae,"[%s:%d] expression [%s] - %s is not a valid hex number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),ae->computectx->varbuffer); + MaxError(ae); + break; + } + curval=strtol(ae->computectx->varbuffer+minusptr+1,NULL,16); break; } - curval=strtol(varbuffer+minusptr+1,NULL,16); - break; - } - /* @ octal value hack */ - if (varbuffer[minusptr+0]=='@' && ((varbuffer[minusptr+1]>='0' && varbuffer[minusptr+1]<='7'))) { - for (icheck=minusptr+2;varbuffer[icheck];icheck++) { - if (varbuffer[icheck]>='0' && varbuffer[icheck]<='7') continue; - rasm_printf(ae,"[%s] Error line %d - expression [%s] - %s is not a valid octal number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),varbuffer); - MaxError(ae); + /* @ 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; + rasm_printf(ae,"[%s:%d] expression [%s] - %s is not a valid octal number\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),ae->computectx->varbuffer); + MaxError(ae); + break; + } + curval=strtol(ae->computectx->varbuffer+minusptr+1,NULL,8); break; } - curval=strtol(varbuffer+minusptr+1,NULL,8); - break; - } - /* Intel hexa value hack */ - if (ae->AutomateHexa[varbuffer[minusptr+0]]) { - if (varbuffer[strlen(varbuffer)-1]=='H') { - for (icheck=minusptr;varbuffer[icheck+1];icheck++) { - if (!ae->AutomateHexa[varbuffer[icheck]]) break; - } - if (!varbuffer[icheck+1]) { - curval=strtol(varbuffer+minusptr,NULL,16); - 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; + } } } } - crc=GetCRC(varbuffer+minusptr); - + + if (curlyflag) { + char *minivarbuffer; + int touched; + +//printf("in: zexpr->[%s] varbuffer=[%s]\n",zeexpression,ae->computectx->varbuffer); + /* besoin d'un sous-contexte */ + minivarbuffer=TxtStrDup(ae->computectx->varbuffer+minusptr); + ae->computectx=&ae->ctx2; + minivarbuffer=TranslateTag(ae,minivarbuffer, &touched,0,E_TAGOPTION_NONE); + 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; +//printf("out:zexpr->[%s] varbuffer=[%s]\n",zeexpression,ae->computectx->varbuffer); + } + +//printf("getcrc [%s]\n",ae->computectx->varbuffer); + 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(varbuffer+minusptr,math_keyword[imkey].mnemo)==0) { + 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; @@ -2379,57 +3255,58 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int /************************************************ C R E A T E E X T R A T O K E N ************************************************/ - ObjectArrayAddDynamicValueConcat((void **)&tokenstack,&nbtokenstack,&maxtokenstack,&stackelement,sizeof(stackelement)); + ObjectArrayAddDynamicValueConcat((void **)&ae->computectx->tokenstack,&nbtokenstack,&ae->computectx->maxtokenstack,&stackelement,sizeof(stackelement)); stackelement.operator=E_COMPUTE_OPERATION_OPEN; - ObjectArrayAddDynamicValueConcat((void **)&tokenstack,&nbtokenstack,&maxtokenstack,&stackelement,sizeof(stackelement)); + ObjectArrayAddDynamicValueConcat((void **)&ae->computectx->tokenstack,&nbtokenstack,&ae->computectx->maxtokenstack,&stackelement,sizeof(stackelement)); allow_minus_as_sign=1; idx++; } else { - rasm_printf(ae,"[%s] Error line %d - expression [%s] - %s is a reserved keyword!\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),math_keyword[imkey].mnemo); + rasm_printf(ae,"[%s:%d] expression [%s] - %s is a reserved keyword!\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),math_keyword[imkey].mnemo); MaxError(ae); curval=0; idx++; } + ivar=0; break; } } if (math_keyword[imkey].mnemo[0]) continue; - if (varbuffer[minusptr+0]=='$' && varbuffer[minusptr+1]==0) { + if (ae->computectx->varbuffer[minusptr+0]=='$' && ae->computectx->varbuffer[minusptr+1]==0) { curval=ptr; } else { - curdic=SearchDico(ae,varbuffer+minusptr,crc); + curdic=SearchDico(ae,ae->computectx->varbuffer+minusptr,crc); if (curdic) { curval=curdic->v; break; } else { /* getbank hack */ - if (varbuffer[minusptr]!='{') { + if (ae->computectx->varbuffer[minusptr]!='{') { bank=0; page=0; - } else if (strncmp(varbuffer+minusptr,"{BANK}",6)==0) { + } else if (strncmp(ae->computectx->varbuffer+minusptr,"{BANK}",6)==0) { bank=6; page=0; /* obligé de recalculer le CRC */ - crc=GetCRC(varbuffer+minusptr+bank); - } else if (strncmp(varbuffer+minusptr,"{PAGE}",6)==0) { + 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(varbuffer+minusptr+bank); - } else if (strncmp(varbuffer+minusptr,"{PAGESET}",9)==0) { + 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(varbuffer+minusptr+bank); - } else if (strncmp(varbuffer+minusptr,"{SIZEOF}",8)==0) { + 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(varbuffer+minusptr+bank); + crc=GetCRC(ae->computectx->varbuffer+minusptr+bank); /* search in structures prototypes */ for (i=0;iirasmstruct;i++) { - if (ae->rasmstruct[i].crc==crc && strcmp(ae->rasmstruct[i].name,varbuffer+minusptr+bank)==0) { + if (ae->rasmstruct[i].crc==crc && strcmp(ae->rasmstruct[i].name,ae->computectx->varbuffer+minusptr+bank)==0) { curval=ae->rasmstruct[i].size; break; } @@ -2437,19 +3314,19 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int if (i==ae->irasmstruct) { /* search in structures aliases */ for (i=0;iirasmstructalias;i++) { - if (ae->rasmstructalias[i].crc==crc && strcmp(ae->rasmstructalias[i].name,varbuffer+minusptr+bank)==0) { + if (ae->rasmstructalias[i].crc==crc && strcmp(ae->rasmstructalias[i].name,ae->computectx->varbuffer+minusptr+bank)==0) { curval=ae->rasmstructalias[i].size; break; } } if (i==ae->irasmstructalias) { - rasm_printf(ae,"[%s] Error line %d - cannot SIZEOF unknown structure [%s]!\n",GetExpFile(ae,didx),GetExpLine(ae,didx),varbuffer+minusptr+bank); + rasm_printf(ae,"[%s:%d] cannot SIZEOF unknown structure [%s]!\n",GetExpFile(ae,didx),GetExpLine(ae,didx),ae->computectx->varbuffer+minusptr+bank); MaxError(ae); curval=0; } } } else { - rasm_printf(ae,"[%s] Error line %d - expression [%s] - %s is an unknown prefix!\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),varbuffer); + rasm_printf(ae,"[%s:%d] expression [%s] - %s is an unknown prefix!\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),ae->computectx->varbuffer); MaxError(ae); } /* limited label translation while processing crunched blocks @@ -2459,34 +3336,39 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int expression->crunch_block=2 -> non car sera relogée */ if (page!=3) { - curlabel=SearchLabel(ae,varbuffer+minusptr+bank,crc); + 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 { +//printf("page=%d | ptr=%X ibank=%d\n",page,curlabel->ptr,curlabel->ibank); switch (page) { - case 2: + case 2: /* PAGESET */ if (curlabel->ibank<36) { - curval=(curlabel->ibank>>2)*8+2+0xC0; + if (curlabel->ibank>3) curval=((curlabel->ibank>>2)-1)*8+0xC2; else curval=0xC0; } else { - rasm_printf(ae,"[%s] Error line %d - expression [%s] cannot use PAGESET - label [%s] is in a temporary space!\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),varbuffer); + rasm_printf(ae,"[%s:%d] expression [%s] cannot use PAGESET - label [%s] is in a temporary space!\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),ae->computectx->varbuffer); MaxError(ae); curval=curlabel->ibank; } break; - case 1: + case 1:/* PAGE */ if (curlabel->ibank<36) { - curval=ae->bankgate[curlabel->ibank]; + if (ae->bankset[curlabel->ibank>>2]) { + curval=ae->bankgate[(curlabel->ibank&0xFC)+(curlabel->ptr>>14)]; + } else { + curval=ae->bankgate[curlabel->ibank]; + } } else { - rasm_printf(ae,"[%s] Error line %d - expression [%s] cannot use PAGE - label [%s] is in a temporary space!\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),varbuffer); + rasm_printf(ae,"[%s:%d] expression [%s] cannot use PAGE - label [%s] is in a temporary space!\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),ae->computectx->varbuffer); MaxError(ae); curval=curlabel->ibank; } break; case 0:curval=curlabel->ibank;break; - default:rasm_printf(ae,"[%s] INTERNAL ERROR Error line %d\n",GetExpFile(ae,didx),GetExpLine(ae,didx));exit(-664); + default:rasm_printf(ae,"[%s:%d] INTERNAL ERROR (unknown paging)\n",GetExpFile(ae,didx),GetExpLine(ae,didx));FreeAssenv(ae);exit(-664); } } } else { @@ -2501,27 +3383,31 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int if (curlabel->ibank<36) { curval=(curlabel->ibank>>2)*8+2+0xC0; } else { - rasm_printf(ae,"[%s] Error line %d - expression [%s] cannot use PAGESET - label [%s] is in a temporary space!\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),varbuffer); + rasm_printf(ae,"[%s:%d] expression [%s] cannot use PAGESET - label [%s] is in a temporary space!\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),ae->computectx->varbuffer); MaxError(ae); curval=curlabel->ibank; } break; case 1: if (curlabel->ibank<36) { + if (ae->bankset[curlabel->ibank>>2]) { + curval=ae->bankgate[(curlabel->ibank&0xFC)+(curlabel->ptr>>14)]; + } else { curval=ae->bankgate[curlabel->ibank]; + } } else { - rasm_printf(ae,"[%s] Error line %d - expression [%s] cannot use PAGE - label [%s] is in a temporary space!\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),varbuffer); + rasm_printf(ae,"[%s:%d] expression [%s] cannot use PAGE - label [%s] is in a temporary space!\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),ae->computectx->varbuffer); MaxError(ae); curval=curlabel->ibank; } break; case 0:curval=curlabel->ibank;break; - default:rasm_printf(ae,"[%s] INTERNAL ERROR Error line %d\n",GetExpFile(ae,didx),GetExpLine(ae,didx));exit(-664); + default:rasm_printf(ae,"[%s:%d] INTERNAL ERROR (unknown paging)\n",GetExpFile(ae,didx),GetExpLine(ae,didx));FreeAssenv(ae);exit(-664); } } } } else { - rasm_printf(ae,"[%s] Error line %d - Label [%s](%d) cannot be computed because it is located after the crunched zone %d\n",GetExpFile(ae,didx),GetExpLine(ae,didx),varbuffer,curlabel->lz,ae->expression[didx].lz); + rasm_printf(ae,"[%s:%d] Label [%s](%d) cannot be computed because it is located after the crunched zone %d\n",GetExpFile(ae,didx),GetExpLine(ae,didx),ae->computectx->varbuffer,curlabel->lz,ae->expression[didx].lz); MaxError(ae); curval=0; } @@ -2537,7 +3423,7 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int /*********** to allow aliases declared after use ***********/ - if ((ialias=SearchAlias(ae,crc,varbuffer+minusptr))>=0) { + if ((ialias=SearchAlias(ae,crc,ae->computectx->varbuffer+minusptr))>=0) { newlen=ae->alias[ialias].len; lenw=strlen(zeexpression); if (newlen>ivar) { @@ -2561,28 +3447,35 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int continue; } else { /* last chance to get a keyword */ - if (strcmp(varbuffer+minusptr,"REPEAT_COUNTER")==0) { + if (strcmp(ae->computectx->varbuffer+minusptr,"REPEAT_COUNTER")==0) { if (ae->ir) { curval=ae->repeat[ae->ir-1].repeat_counter; } else { - rasm_printf(ae,"[%s] Error line %d - cannot use REPEAT_COUNTER keyword outside a repeat loop\n",GetExpFile(ae,didx),GetExpLine(ae,didx)); + rasm_printf(ae,"[%s:%d] cannot use REPEAT_COUNTER keyword outside a repeat loop\n",GetExpFile(ae,didx),GetExpLine(ae,didx)); MaxError(ae); curval=0; } - } else if (strcmp(varbuffer+minusptr,"WHILE_COUNTER")==0) { + } else if (strcmp(ae->computectx->varbuffer+minusptr,"WHILE_COUNTER")==0) { if (ae->iw) { curval=ae->whilewend[ae->iw-1].while_counter; } else { - rasm_printf(ae,"[%s] Error line %d - cannot use WHILE_COUNTER keyword outside a while loop\n",GetExpFile(ae,didx),GetExpLine(ae,didx)); + rasm_printf(ae,"[%s:%d] cannot use WHILE_COUNTER keyword outside a while loop\n",GetExpFile(ae,didx),GetExpLine(ae,didx)); MaxError(ae); curval=0; } } else { /* in case the expression is a register */ - if (IsRegister(varbuffer+minusptr)) { - rasm_printf(ae,"[%s] Error line %d - cannot use register %s in this context\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression)); + if (IsRegister(ae->computectx->varbuffer+minusptr)) { + rasm_printf(ae,"[%s:%d] cannot use register %s in this context\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression)); } else { - rasm_printf(ae,"[%s] Error line %d - expression [%s] keyword [%s] not found in variables,labels or aliases\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),varbuffer+minusptr); + rasm_printf(ae,"[%s:%d] expression [%s] keyword [%s] not found in variables, labels or aliases\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression),ae->computectx->varbuffer+minusptr); + if (ae->extended_error) { + char *lookstr; + lookstr=StringLooksLike(ae,ae->computectx->varbuffer+minusptr); + if (lookstr) { + rasm_printf(ae," did you mean [%s] ?\n",lookstr); + } + } } MaxError(ae); curval=0; @@ -2604,29 +3497,93 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int /************************************ C R E A T E T O K E N ************************************/ - ObjectArrayAddDynamicValueConcat((void **)&tokenstack,&nbtokenstack,&maxtokenstack,&stackelement,sizeof(stackelement)); + 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; + default:printf("bug\n");break; + } + + } + printf("\n"); +#endif + for (itoken=0;itokencomputectx->tokenstack[itoken].operator) { case E_COMPUTE_OPERATION_PUSH_DATASTC: - ObjectArrayAddDynamicValueConcat((void **)&computestack,&nbcomputestack,&maxcomputestack,&tokenstack[itoken],sizeof(stackelement)); +#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 **)&operatorstack,&nboperatorstack,&maxoperatorstack,&tokenstack[itoken],sizeof(stackelement)); + 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 (operatorstack[o2].operator!=E_COMPUTE_OPERATION_OPEN) { - ObjectArrayAddDynamicValueConcat((void **)&computestack,&nbcomputestack,&maxcomputestack,&operatorstack[o2],sizeof(stackelement)); + 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--; @@ -2634,16 +3591,20 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int } } if (!okclose) { - rasm_printf(ae,"[%s] Error line %d - missing parenthesis [%s]\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression)); + rasm_printf(ae,"[%s:%d] missing parenthesis [%s]\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression)); MaxError(ae); if (!original) { MemFree(zeexpression); } return 0; } - if (o2>=0 && operatorstack[o2].operator>=E_COMPUTE_OPERATION_SIN) { - ObjectArrayAddDynamicValueConcat((void **)&computestack,&nbcomputestack,&maxcomputestack,&operatorstack[o2],sizeof(stackelement)); + /* 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: @@ -2654,6 +3615,7 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int 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: @@ -2664,17 +3626,20 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int 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 && operatorstack[o2].operator!=E_COMPUTE_OPERATION_OPEN) { - if (tokenstack[itoken].priority>=operatorstack[o2].priority || operatorstack[o2].operator>=E_COMPUTE_OPERATION_SIN) { - ObjectArrayAddDynamicValueConcat((void **)&computestack,&nbcomputestack,&maxcomputestack,&operatorstack[o2],sizeof(stackelement)); + 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 **)&operatorstack,&nboperatorstack,&maxoperatorstack,&tokenstack[itoken],sizeof(stackelement)); + 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: @@ -2690,14 +3655,18 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int case E_COMPUTE_OPERATION_EXP: case E_COMPUTE_OPERATION_LOW: case E_COMPUTE_OPERATION_HIGH: - ObjectArrayAddDynamicValueConcat((void **)&operatorstack,&nboperatorstack,&maxoperatorstack,&tokenstack[itoken],sizeof(stackelement)); + case E_COMPUTE_OPERATION_PSG: +#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,&operatorstack[--nboperatorstack],sizeof(stackelement)); + ObjectArrayAddDynamicValueConcat((void **)&computestack,&nbcomputestack,&maxcomputestack,&ae->computectx->operatorstack[--nboperatorstack],sizeof(stackelement)); } /******************************************** @@ -2754,35 +3723,40 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int 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; - default:rasm_printf(ae,"invalid computing state! (%d)\n",computestack[i].operator); + case E_COMPUTE_OPERATION_PSG:if (paccu>0) accu[paccu-1]=ae->psgfine[((int)accu[paccu-1])&0xFF];break; + default:rasm_printf(ae,"[%s:%d] invalid computing state! (%d)\n",GetExpFile(ae,didx),GetExpLine(ae,didx),computestack[i].operator);paccu=0; } if (!paccu) { - rasm_printf(ae,"[%s] Error line %d - Missing operande for calculation [%s]\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression)); - exit(INTERNAL_ERROR); + rasm_printf(ae,"[%s:%d] Missing operande for calculation [%s]\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression)); + MaxError(ae); + 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_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); + printf("pacc=%d operation %s p=%d\n",paccu,computestack[i].operator==E_COMPUTE_OPERATION_MUL?"*": + computestack[i].operator==E_COMPUTE_OPERATION_ADD?"+": + computestack[i].operator==E_COMPUTE_OPERATION_DIV?"/": + computestack[i].operator==E_COMPUTE_OPERATION_SUB?"-": + computestack[i].operator==E_COMPUTE_OPERATION_BAND?"&&": + computestack[i].operator==E_COMPUTE_OPERATION_BOR?"||": + computestack[i].operator==E_COMPUTE_OPERATION_SHL?"<<": + computestack[i].operator==E_COMPUTE_OPERATION_SHR?">>": + 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) { @@ -2794,7 +3768,7 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int accu[paccu]=computestack[i].value;paccu++; break; case E_COMPUTE_OPERATION_OPEN: - case E_COMPUTE_OPERATION_CLOSE:/* cannot happend */ break; + 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; @@ -2802,6 +3776,7 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int 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));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));paccu--;break; @@ -2810,7 +3785,7 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int /* 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]=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; @@ -2829,11 +3804,13 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int 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; - default:rasm_printf(ae,"invalid computing state! (%d)\n",computestack[i].operator); + case E_COMPUTE_OPERATION_PSG:if (paccu>0) accu[paccu-1]=ae->psgfine[((int)floor(accu[paccu-1]+0.5))&0xFF];break; + default:rasm_printf(ae,"[%s:%d] invalid computing state! (%d)\n",GetExpFile(ae,didx),GetExpLine(ae,didx),computestack[i].operator);paccu=0; } if (!paccu) { - rasm_printf(ae,"[%s] Error line %d - Missing operande for calculation [%s]\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression)); - exit(INTERNAL_ERROR); + rasm_printf(ae,"[%s:%d] Missing operande for calculation [%s]\n",GetExpFile(ae,didx),GetExpLine(ae,didx),TradExpression(zeexpression)); + MaxError(ae); + break; } } } @@ -2844,10 +3821,10 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int return accu[0]; } else { if (paccu) { - rasm_printf(ae,"[%s] Error line %d - Missing operator\n",GetExpFile(ae,didx),GetExpLine(ae,didx)); + rasm_printf(ae,"[%s:%d] Missing operator\n",GetExpFile(ae,didx),GetExpLine(ae,didx)); MaxError(ae); } else { - rasm_printf(ae,"[%s] Error line %d - Missing operande for calculation\n",GetExpFile(ae,didx),GetExpLine(ae,didx)); + rasm_printf(ae,"[%s:%d] Missing operande for calculation\n",GetExpFile(ae,didx),GetExpLine(ae,didx)); MaxError(ae); } return accu[paccu-1]; @@ -2860,7 +3837,7 @@ int RoundComputeExpressionCore(struct s_assenv *ae,char *zeexpression,int ptr,in void ExpressionSetDicoVar(struct s_assenv *ae,char *name, double v) { #undef FUNC - #define FUNC "ComputeExpression Core" + #define FUNC "ExpressionSetDicoVar" struct s_expr_dico curdic; curdic.name=TxtStrDup(name); @@ -2868,7 +3845,7 @@ void ExpressionSetDicoVar(struct s_assenv *ae,char *name, double v) curdic.v=v; //ObjectArrayAddDynamicValueConcat((void**)&ae->dico,&ae->idic,&ae->mdic,&curdic,sizeof(curdic)); if (SearchLabel(ae,curdic.name,curdic.crc)) { - rasm_printf(ae,"[%s] Error line %d - cannot create variable [%s] as there is already a label with the same name\n",GetExpFile(ae,0),GetExpLine(ae,0),name); + rasm_printf(ae,"[%s:%d] cannot create variable [%s] as there is already a label with the same name\n",GetExpFile(ae,0),GetExpLine(ae,0),name); MaxError(ae); MemFree(curdic.name); return; @@ -2881,10 +3858,11 @@ double ComputeExpression(struct s_assenv *ae,char *expr, int ptr, int didx, int #define FUNC "ComputeExpression" char *ptr_exp,*ptr_exp2,backupeval; - int crc,idic,idx=0,ialias; + int crc,idic,idx=0,ialias,touched; double v,vl; struct s_alias curalias; struct s_expr_dico *curdic; + char *minibuffer; while (!ae->AutomateExpressionDecision[((int)expr[idx])&0xFF]) idx++; @@ -2898,15 +3876,24 @@ double ComputeExpression(struct s_assenv *ae,char *expr, int ptr, int didx, int *ptr_exp=0; ptr_exp2=expr+idx+1; - /* alias locaux */ - if (expr[0]=='@') { + /* alias locaux ou de proximité */ + if (strchr("@.",expr[0])) { + /* local label creation handle formula in tags */ curalias.alias=MakeLocalLabel(ae,expr,NULL); + } else if (strchr(expr,'{')) { + /* alias name contains formula */ + curalias.alias=TranslateTag(ae,TxtStrDup(expr),&touched,0,E_TAGOPTION_NONE); +//printf("alias name contains formula [%s] -> [%s]\n",expr,curalias.alias); } else { curalias.alias=TxtStrDup(expr); } curalias.crc=GetCRC(curalias.alias); if ((ialias=SearchAlias(ae,curalias.crc,curalias.alias))>=0) { - rasm_printf(ae,"[%s] Error line %d - Duplicate alias [%s]\n",GetExpFile(ae,0),GetExpLine(ae,0),expr); + rasm_printf(ae,"[%s:%d] Duplicate alias [%s]\n",GetExpFile(ae,0),GetExpLine(ae,0),expr); + MaxError(ae); + MemFree(curalias.alias); + } else if (SearchDico(ae,curalias.alias,curalias.crc)) { + rasm_printf(ae,"[%s:%d] Alias cannot override existing variable [%s]\n",GetExpFile(ae,0),GetExpLine(ae,0),expr); MaxError(ae); MemFree(curalias.alias); } else { @@ -2923,19 +3910,20 @@ double ComputeExpression(struct s_assenv *ae,char *expr, int ptr, int didx, int S E T V A R *****************************************/ case '=': - if (ae->AutomateExpressionDecision[((int)expr[idx+1])&0xFF]==0) { + /* patch NOT */ + 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 { - rasm_printf(ae,"[%s] Error line %d - meaningless use of an expression [%s]\n",GetExpFile(ae,0),GetExpLine(ae,0),expr); + rasm_printf(ae,"[%s:%d] meaningless use of an expression [%s]\n",GetExpFile(ae,0),GetExpLine(ae,0),expr); MaxError(ae); return 0; } } else { /* affectation */ if (expr[0]<'A' || expr[0]>'Z') { - rasm_printf(ae,"[%s] Error line %d - variable name must begin by a letter [%s]\n",GetExpFile(ae,0),GetExpLine(ae,0),expr); + rasm_printf(ae,"[%s:%d] variable name must begin by a letter [%s]\n",GetExpFile(ae,0),GetExpLine(ae,0),expr); MaxError(ae); return 0; } else { @@ -2943,6 +3931,11 @@ double ComputeExpression(struct s_assenv *ae,char *expr, int ptr, int didx, int v=ComputeExpressionCore(ae,ptr_exp+1,ptr,didx); *ptr_exp=0; crc=GetCRC(expr); + if ((ialias=SearchAlias(ae,crc,expr))>=0) { + rasm_printf(ae,"[%s:%d] Variable cannot override existing alias [%s]\n",GetExpFile(ae,0),GetExpLine(ae,0),expr); + MaxError(ae); + return 0; + } curdic=SearchDico(ae,expr,crc); if (curdic) { /* on affecte */ @@ -2968,6 +3961,11 @@ int RoundComputeExpression(struct s_assenv *ae,char *expr, int ptr, int didx, in 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 @@ -2982,8 +3980,11 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla double v; char tmpuchar[16]; char *expr,*locallabel; + int curly=0,curlyflag=0; + char *Automate; + int recurse=-1,recursecount=0; - if (!ae) { + if (!ae || !ptr_expr) { if (varbuffer) MemFree(varbuffer); varbuffer=NULL; maxivar=1; @@ -2994,6 +3995,8 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla StateMachineResizeBuffer(&varbuffer,128,&maxivar); expr=*ptr_expr; +//printf("fast [%s]\n",expr); + while (!ae->AutomateExpressionDecision[((int)expr[idx])&0xFF]) idx++; switch (ae->maxam) { @@ -3015,21 +4018,33 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla /* echappement */ if (expr[idx+1]=='\\') { if (expr[idx+2] && expr[idx+3]==c) { - sprintf(tmpuchar,"#%03X",expr[idx+2]); + /* 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 { - rasm_printf(ae,"[%s] Error line %d - expression [%s] - Only single escaped char may be quoted\n",GetExpFile(ae,0),GetExpLine(ae,0),expr); + rasm_printf(ae,"[%s:%d] expression [%s] - Only single escaped char may be quoted\n",GetExpFile(ae,0),GetExpLine(ae,0),expr); MaxError(ae); expr[0]=0; return; } } else if (expr[idx+1] && expr[idx+2]==c) { - sprintf(tmpuchar,"#%02X",(unsigned int)expr[idx+1]); + sprintf(tmpuchar,"#%02X",ae->charset[(int)expr[idx+1]]); memcpy(expr+idx,tmpuchar,3); idx+=2; } else { - rasm_printf(ae,"[%s] Error line %d - expression [%s] - Only single char may be quoted\n",GetExpFile(ae,0),GetExpLine(ae,0),expr); + rasm_printf(ae,"[%s:%d] expression [%s] - Only single char may be quoted\n",GetExpFile(ae,0),GetExpLine(ae,0),expr); MaxError(ae); expr[0]=0; return; @@ -3065,10 +4080,26 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla 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]; - while (ae->AutomateExpressionValidChar[((int)c)&0xFF]) { + + 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++; @@ -3077,12 +4108,45 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla } varbuffer[ivar]=0; if (!ivar) { - rasm_printf(ae,"[%s] Error line %d - invalid expression [%s]\n",GetExpFile(ae,0),GetExpLine(ae,0),expr); + rasm_printf(ae,"[%s:%d] invalid expression [%s] c=[%c] idx=%d\n",GetExpFile(ae,0),GetExpLine(ae,0),expr,c,idx); + MaxError(ae); + return; + } else if (curly) { + rasm_printf(ae,"[%s:%d] wrong curly brackets in expression [%s]\n",GetExpFile(ae,0),GetExpLine(ae,0),expr); MaxError(ae); return; } } - if (ivar) { + if (ivar && (varbuffer[0]<'0' || varbuffer[0]>'9')) { + /* numbering var or label */ + if (curlyflag) { + char *minivarbuffer; + int touched; + int newlen; + + minivarbuffer=TranslateTag(ae,TxtStrDup(varbuffer), &touched,0,E_TAGOPTION_NONE); + 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; @@ -3115,9 +4179,10 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla #ifdef OS_WIN snprintf(curval,sizeof(curval)-1,"%lf",v); - newlen=strlen(curval); + newlen=TrimFloatingPointString(curval); #else newlen=snprintf(curval,sizeof(curval)-1,"%lf",v); + newlen=TrimFloatingPointString(curval); #endif lenw=strlen(expr); if (newlen>ivar) { @@ -3168,12 +4233,19 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla if ((ialias=SearchAlias(ae,crc,varbuffer))>=0) { newlen=ae->alias[ialias].len; lenw=strlen(expr); - /* controle de recursivite a l'insertion des alias */ - if (lenw>(32+ae->ialias+ae->nbword+ae->idic)*32) { - rasm_printf(ae,"[%s] FATAL Error line %d - alias definition [%.30s] - infinite recursivity\n",GetExpFile(ae,0),GetExpLine(ae,0),expr); - exit(551); + /* 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; + rasm_printf(ae,"[%s:%d] alias definition of %s has infinite recursivity\n",GetExpFile(ae,0),GetExpLine(ae,0),expr); + MaxError(ae); + 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); @@ -3183,31 +4255,54 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla } 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) { - /* non trouve c'est peut-etre un label local */ - if (varbuffer[0]=='@') { - if (ae->ir || ae->iw || ae->imacro) { - lenbuf=strlen(varbuffer); - locallabel=MakeLocalLabel(ae,varbuffer,&dek); - /*** le grand remplacement ***/ - rlen=strlen(expr+startvar+lenbuf)+1; - expr=*ptr_expr=MemRealloc(expr,strlen(expr)+dek+1); - MemMove(expr+startvar+lenbuf+dek,expr+startvar+lenbuf,rlen); - strncpy(expr+startvar+lenbuf,locallabel,dek); - idx+=dek; - MemFree(locallabel); - found_replace=1; - } - /* non trouve c'est peut-etre un label local après un tag */ + //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')) { + lenbuf=strlen(varbuffer); + locallabel=MakeLocalLabel(ae,varbuffer,&dek); + /*** le grand remplacement ***/ + /* local to macro or loop */ + rlen=strlen(expr+startvar+lenbuf)+1; + expr=*ptr_expr=MemRealloc(expr,strlen(expr)+dek+1); + 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[0]=='.' && (varbuffer[1]<'0' || varbuffer[1]>'9')) { + /* proximity label */ + lenbuf=strlen(varbuffer); + 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; + if (strncmp(varbuffer,"{SIZEOF}",8)==0) tagoffset=8; else + { + tagoffset=0; + rasm_printf(ae,"[%s:%d] Unknown prefix tag\n",GetExpFile(ae,0),GetExpLine(ae,0)); + MaxError(ae); + } if (varbuffer[tagoffset]=='@') { startvar+=tagoffset; @@ -3221,9 +4316,80 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla 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 { + rasm_printf(ae,"[%s:%d] expression [%s] cannot use BANK $ in a temporary space!\n",GetExpFile(ae,0),GetExpLine(ae,0),TradExpression(expr)); + MaxError(ae); + tagvalue=0; + } + } else if (ae->forcesnapshot) { + if (ae->activebank<36) { + if (ae->bankset[ae->activebank>>2]) { + tagvalue=(ae->activebank&0xFC)+(ae->codeadr>>14); + } else { + tagvalue=ae->activebank; + } + } else { + rasm_printf(ae,"[%s:%d] expression [%s] cannot use BANK $ in a temporary space!\n",GetExpFile(ae,0),GetExpLine(ae,0),TradExpression(expr)); + MaxError(ae); + tagvalue=0; + } + } + } else if (strcmp(varbuffer,"{PAGE}$")==0) { + if (ae->activebank<36) { + if (ae->bankset[ae->activebank>>2]) { + tagvalue=ae->bankgate[(ae->activebank&0xFC)+(ae->codeadr>>14)]; + } else { + tagvalue=ae->bankgate[ae->activebank]; + } + } else { + rasm_printf(ae,"[%s:%d] expression [%s] cannot use PAGE $ in a temporary space!\n",GetExpFile(ae,0),GetExpLine(ae,0),TradExpression(expr)); + MaxError(ae); + tagvalue=ae->activebank; + } + } else if (strcmp(varbuffer,"{PAGESET}$")==0) { + if (ae->activebank<36) { + if (ae->activebank>3) tagvalue=((ae->activebank>>2)-1)*8+0xC2; else tagvalue=0xC0; + } else { + rasm_printf(ae,"[%s:%d] expression [%s] cannot use PAGESET $ in a temporary space!\n",GetExpFile(ae,0),GetExpLine(ae,0),TradExpression(expr)); + MaxError(ae); + 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; @@ -3247,7 +4413,7 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla idx=startvar+newlen; ivar=0; } else { - rasm_printf(ae,"[%s] FATAL Error line %d - cannot use REPEAT_COUNTER outside repeat loop\n",GetExpFile(ae,0),GetExpLine(ae,0)); + rasm_printf(ae,"[%s:%d] cannot use REPEAT_COUNTER outside repeat loop\n",GetExpFile(ae,0),GetExpLine(ae,0)); MaxError(ae); } } @@ -3274,12 +4440,16 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla idx=startvar+newlen; ivar=0; } else { - rasm_printf(ae,"[%s] FATAL Error line %d - cannot use WHILE_COUNTER outside repeat loop\n",GetExpFile(ae,0),GetExpLine(ae,0)); + rasm_printf(ae,"[%s:%d] cannot use WHILE_COUNTER outside repeat loop\n",GetExpFile(ae,0),GetExpLine(ae,0)); MaxError(ae); } } - ivar=0; + /* unknown symbol -> add to used symbol pool */ + if (!found_replace) { + InsertUsedToTree(ae,varbuffer,crc); + } } + ivar=0; } } @@ -3308,6 +4478,7 @@ void PushExpression(struct s_assenv *ae,int iw,enum e_expression zetype) 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; @@ -3334,6 +4505,7 @@ void PushExpression(struct s_assenv *ae,int iw,enum e_expression zetype) 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_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; @@ -3343,8 +4515,8 @@ void PushExpression(struct s_assenv *ae,int iw,enum e_expression zetype) if (ae->outputadr<=ae->maxptr) { ObjectArrayAddDynamicValueConcat((void **)&ae->expression,&ae->ie,&ae->me,&curexp,sizeof(curexp)); } else { - rasm_printf(ae,"[%s] Error line %d - output exceed limit %d\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->maxptr); - exit(3); + rasm_printf(ae,"[%s:%d] output exceed limit %d\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->maxptr); + FreeAssenv(ae);exit(3); } } else { switch (zetype) { @@ -3355,6 +4527,7 @@ void PushExpression(struct s_assenv *ae,int iw,enum e_expression zetype) 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_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; @@ -3363,8 +4536,8 @@ void PushExpression(struct s_assenv *ae,int iw,enum e_expression zetype) } if (ae->outputadr<=ae->maxptr) { } else { - rasm_printf(ae,"[%s] Error line %d - NOCODE output exceed limit %d\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->maxptr); - exit(3); + rasm_printf(ae,"[%s:%d] NOCODE output exceed limit %d\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->maxptr); + FreeAssenv(ae);exit(3); } } } @@ -3446,10 +4619,10 @@ char *MakeAMSDOS_name(struct s_assenv *ae, char *filename) /* warning */ if (strlen(filename)>12) { - rasm_printf(ae,"Warning - filename [%s] too long for AMSDOS, will be truncated\n",filename); + if (!ae->nowarning) rasm_printf(ae,"Warning - filename [%s] too long for AMSDOS, will be truncated\n",filename); } else if ((pp=strchr(filename,'.'))!=NULL) { if (pp-filename>8) { - rasm_printf(ae,"Warning - filename [%s] too long for AMSDOS, will be truncated\n",filename); + if (!ae->nowarning) rasm_printf(ae,"Warning - filename [%s] too long for AMSDOS, will be truncated\n",filename); } } /* copy filename */ @@ -3488,19 +4661,19 @@ void EDSK_load(struct s_assenv *ae,struct s_edsk_wrapper *curwrap, char *edskfil int curblock=0,curoffset=0; if (FileReadBinary(edskfilename,(char*)&header,0x100)!=0x100) { - logerr("Cannot read EDSK header!"); - exit(ABORT_ERROR); + rasm_printf(ae,"Cannot read EDSK header!"); + FreeAssenv(ae);exit(ABORT_ERROR); } if (strncmp((char *)header,"MV - CPC",8)==0) { - loginfo("updating DSK to EDSK [%s] / creator: %-14.14s",edskfilename,header+34); + rasm_printf(ae,"updating DSK to EDSK [%s] / creator: %-14.14s",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; - loginfo("tracks: %d sides:%d track size:%d",tracknumber,sidenumber,tracksize); + rasm_printf(ae,"tracks: %d sides:%d track size:%d",tracknumber,sidenumber,tracksize); if (tracknumber>40 || sidenumber>2) { rasm_printf(ae,"[%s] DSK format is not supported in update mode\n",edskfilename); - exit(ABORT_ERROR); + FreeAssenv(ae);exit(ABORT_ERROR); } if (face>=sidenumber) { rasm_printf(ae,"[%s] DSK has no face %d - DSK updated\n",edskfilename,face); @@ -3511,7 +4684,7 @@ void EDSK_load(struct s_assenv *ae,struct s_edsk_wrapper *curwrap, char *edskfil memset(data,0,tracksize*tracknumber*sidenumber); if (FileReadBinary(edskfilename,(char *)data,tracksize*tracknumber*sidenumber)!=tracksize*tracknumber*sidenumber) { rasm_printf(ae,"Cannot read DSK tracks!"); - exit(ABORT_ERROR); + FreeAssenv(ae);exit(ABORT_ERROR); } //loginfo("track data read (%dkb)",tracksize*tracknumber*sidenumber/1024); f=face; @@ -3520,41 +4693,41 @@ void EDSK_load(struct s_assenv *ae,struct s_edsk_wrapper *curwrap, char *edskfil i=(t*sidenumber+f)*tracksize; if (strncmp((char *)data+i,"Track-Info\r\n",12)) { - logerr("Invalid track information block side %d track %d",f,t); - exit(ABORT_ERROR); + rasm_printf(ae,"Invalid track information block side %d track %d",f,t); + FreeAssenv(ae);exit(ABORT_ERROR); } sectornumber=data[i+21]; sectorsize=data[i+20]; if (sectornumber!=9 || sectorsize!=2) { - logerr("Cannot read [%s] Invalid DATA format",edskfilename); - exit(ABORT_ERROR); + rasm_printf(ae,"Cannot read [%s] Invalid DATA format",edskfilename); + FreeAssenv(ae);exit(ABORT_ERROR); } memset(checksectorid,0,sizeof(checksectorid)); /* we want DATA format */ for (s=0;s0xC9) { - logerr("Invalid sector ID in sector %02X track %d",data[i+24+8*s+2],t); - exit(ABORT_ERROR); + 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) { - logerr("Invalid sector size in sector %02X track %d",data[i+24+8*s+2],t); - exit(ABORT_ERROR); + 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;s40 || sidenumber>2) { rasm_printf(ae,"[%s] DSK format is not supported in update mode\n",edskfilename); - exit(ABORT_ERROR); + FreeAssenv(ae);exit(ABORT_ERROR); } if (face>=sidenumber) { rasm_printf(ae,"[%s] DSK has no face %d - DSK updated\n",edskfilename,face); @@ -3591,8 +4764,8 @@ void EDSK_load(struct s_assenv *ae,struct s_edsk_wrapper *curwrap, char *edskfil data=MemMalloc(disksize); memset(data,0,disksize); if (FileReadBinary(edskfilename,(char *)data,disksize)!=disksize) { - logerr("Cannot read DSK tracks!"); - exit(ABORT_ERROR); + rasm_printf(ae,"Cannot read DSK tracks!"); + FreeAssenv(ae);exit(ABORT_ERROR); } f=face; @@ -3607,14 +4780,14 @@ void EDSK_load(struct s_assenv *ae,struct s_edsk_wrapper *curwrap, char *edskfil currenttrackposition+=header[0x34+curtrack]*256; if (strncmp((char *)data+i,"Track-Info\r\n",12)) { - logerr("Invalid track information block side %d track %d",f,t); - exit(ABORT_ERROR); + rasm_printf(ae,"Invalid track information block side %d track %d",f,t); + FreeAssenv(ae);exit(ABORT_ERROR); } sectornumber=data[i+21]; sectorsize=data[i+20]; if (sectornumber!=9 || sectorsize!=2) { rasm_printf(ae,"Unsupported track %d",t); - exit(ABORT_ERROR); + FreeAssenv(ae);exit(ABORT_ERROR); } memset(checksectorid,0,sizeof(checksectorid)); /* we want DATA format */ @@ -3657,8 +4830,8 @@ void EDSK_load(struct s_assenv *ae,struct s_edsk_wrapper *curwrap, char *edskfil } else { - logerr("file [%s] is not a valid (E)DSK floppy image",edskfilename); - exit(-923); + rasm_printf(ae,"file [%s] is not a valid (E)DSK floppy image",edskfilename); + FreeAssenv(ae);exit(-923); } FileReadBinaryClose(edskfilename); @@ -3753,6 +4926,7 @@ int EDSK_addfile(struct s_assenv *ae,char *edskfilename,int facenumber, char *fi if (!ae->edskoverwrite) { rasm_printf(ae,"Error - Cannot save [%s] in edsk [%s] with overwrite disabled as the file already exists\n",amsdos_name,edskfilename); MaxError(ae); + MemFree(data); return 0; } else { /* overwriting previous file */ @@ -4137,17 +5311,20 @@ void PopAllExpression(struct s_assenv *ae, int crunched_zone) case E_EXPRESSION_J8: r=r-ae->expression[i].ptr-2; if (r<-128 || r>127) { - rasm_printf(ae,"[%s] Error line %d - relative offset %d too far [%s]\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,ae->wl[ae->expression[i].iw].w); + rasm_printf(ae,"[%s:%d] relative offset %d too far [%s]\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,ae->wl[ae->expression[i].iw].w); MaxError(ae); } 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) { - rasm_printf(ae,"[%s] Warning line %d - truncating value #%X to #%X\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,r&0xFF); + if (!ae->nowarning) rasm_printf(ae,"[%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; @@ -4155,7 +5332,7 @@ void PopAllExpression(struct s_assenv *ae, int crunched_zone) case E_EXPRESSION_V16: case E_EXPRESSION_0V16: if (r>65535 || r<-32768) { - rasm_printf(ae,"[%s] Warning line %d - truncating value #%X to #%X\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,r&0xFFFF); + if (!ae->nowarning) rasm_printf(ae,"[%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>>8)&0xFF); @@ -4163,7 +5340,7 @@ void PopAllExpression(struct s_assenv *ae, int crunched_zone) case E_EXPRESSION_0V32: /* meaningless in 32 bits architecture... */ if (v>4294967295 || v<-2147483648) { - rasm_printf(ae,"[%s] Warning line %d - truncating value\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l); + if (!ae->nowarning) rasm_printf(ae,"[%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); @@ -4263,7 +5440,7 @@ void PopAllExpression(struct s_assenv *ae, int crunched_zone) /* exponent */ exp+=128; if (exp<0 || exp>255) { - rasm_printf(ae,"[%s] Error line %d - Exponent overflow\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l); + rasm_printf(ae,"[%s:%d] Exponent overflow\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l); MaxError(ae); exp=128; } @@ -4285,7 +5462,7 @@ void PopAllExpression(struct s_assenv *ae, int crunched_zone) case 0x01:mem[ae->expression[i].wptr]=0x56;break; case 0x02:mem[ae->expression[i].wptr]=0x5E;break; default: - rasm_printf(ae,"[%s] Error line %d - IM 0,1 or 2 only\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l); + rasm_printf(ae,"[%s:%d] IM 0,1 or 2 only\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l); MaxError(ae); mem[ae->expression[i].wptr]=0; } @@ -4301,14 +5478,14 @@ void PopAllExpression(struct s_assenv *ae, int crunched_zone) case 0x30:mem[ae->expression[i].wptr]=0xF7;break; case 0x38:mem[ae->expression[i].wptr]=0xFF;break; default: - rasm_printf(ae,"[%s] Error line %d - RST #0,#8,#10,#18,#20,#28,#30,#38 only\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l); + rasm_printf(ae,"[%s:%d] RST #0,#8,#10,#18,#20,#28,#30,#38 only\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l); MaxError(ae); mem[ae->expression[i].wptr]=0; } break; default: - rasm_printf(ae,"[%s] FATAL Error line %d - unknown expression type\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l); - exit(-8); + rasm_printf(ae,"[%s:%d] FATAL - unknown expression type\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l); + FreeAssenv(ae);exit(-8); } } } @@ -4333,7 +5510,7 @@ void InsertLabelToTree(struct s_assenv *ae, struct s_label *label) memset(curlabeltree,0,sizeof(struct s_crclabel_tree)); } } - ObjectArrayAddDynamicValueConcat((void**)&curlabeltree->label,&curlabeltree->nlabel,&curlabeltree->mlabel,label,sizeof(struct s_label)); + 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 */ @@ -4345,7 +5522,7 @@ void PushLabelLight(struct s_assenv *ae, struct s_label *curlabel) { /* PushLabel light */ if ((searched_label=SearchLabel(ae,curlabel->name,curlabel->crc))!=NULL) { - rasm_printf(ae,"[%s] Error line %d - %s caused duplicate label [%s]\n",GetExpFile(ae,0),GetExpLine(ae,0),ae->idx?"Structure insertion":"Label import",curlabel->name); + rasm_printf(ae,"[%s:%d] %s caused duplicate label [%s]\n",GetExpFile(ae,0),GetExpLine(ae,0),ae->idx?"Structure insertion":"Label import",curlabel->name); MaxError(ae); MemFree(curlabel->name); } else { @@ -4361,20 +5538,31 @@ void PushLabel(struct s_assenv *ae) 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->AutomateValidLabel[ae->wl[ae->idx].w[i]]) { - rasm_printf(ae,"[%s] Error line %d - Invalid char in label declaration\n",GetExpFile(ae,0),ae->wl[ae->idx].l); - MaxError(ae); - return; + 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]]) { + rasm_printf(ae,"[%s:%d] Invalid char in label declaration (%c)\n",GetExpFile(ae,0),ae->wl[ae->idx].l,ae->wl[ae->idx].w[i]); + MaxError(ae); + return; + } } } } else { - rasm_printf(ae,"[%s] Error line %d - Invalid first char in label declaration\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Invalid first char in label declaration (%c)\n",GetExpFile(ae,0),ae->wl[ae->idx].l,ae->wl[ae->idx].w[0]); MaxError(ae); return; } + switch (i) { case 1: switch (ae->wl[ae->idx].w[0]) { @@ -4388,7 +5576,7 @@ void PushLabel(struct s_assenv *ae) case 'L': case 'I': case 'R': - rasm_printf(ae,"[%s] Error line %d - Cannot use reserved word [%s] for label\n",GetExpFile(ae,0),ae->wl[ae->idx].l,ae->wl[ae->idx].w); + rasm_printf(ae,"[%s:%d] Cannot use reserved word [%s] for label\n",GetExpFile(ae,0),ae->wl[ae->idx].l,ae->wl[ae->idx].w); MaxError(ae); return; default:break; @@ -4399,69 +5587,126 @@ void PushLabel(struct s_assenv *ae) 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) { - rasm_printf(ae,"[%s] Error line %d - Cannot use reserved word [%s] for label\n",GetExpFile(ae,0),ae->wl[ae->idx].l,ae->wl[ae->idx].w); + rasm_printf(ae,"[%s:%d] Cannot use reserved word [%s] for label\n",GetExpFile(ae,0),ae->wl[ae->idx].l,ae->wl[ae->idx].w); MaxError(ae); 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) { - rasm_printf(ae,"[%s] Error line %d - Cannot use reserved word [%s] for label\n",GetExpFile(ae,0),ae->wl[ae->idx].l,ae->wl[ae->idx].w); + rasm_printf(ae,"[%s:%d] Cannot use reserved word [%s] for label\n",GetExpFile(ae,0),ae->wl[ae->idx].l,ae->wl[ae->idx].w); MaxError(ae); return; } break; case 4: if (strcmp(ae->wl[ae->idx].w,"VOID")==0) { - rasm_printf(ae,"[%s] Error line %d - Cannot use reserved word [%s] for label\n",GetExpFile(ae,0),ae->wl[ae->idx].l,ae->wl[ae->idx].w); + rasm_printf(ae,"[%s:%d] Cannot use reserved word [%s] for label\n",GetExpFile(ae,0),ae->wl[ae->idx].l,ae->wl[ae->idx].w); MaxError(ae); 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 (ae->wl[ae->idx].w[0]=='@') { - rasm_printf(ae,"[%s] Error line %d - Please no local label in a struct [%s]\n",GetExpFile(ae,0),ae->wl[ae->idx].l,ae->wl[ae->idx].w); + if (varbuffer[0]=='@') { + rasm_printf(ae,"[%s:%d] Please no local label in a struct [%s]\n",GetExpFile(ae,0),ae->wl[ae->idx].l,ae->wl[ae->idx].w); MaxError(ae); return; } /* copy label+offset in the structure */ - rasmstructfield.name=TxtStrDup(ae->wl[ae->idx].w); + 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(ae->wl[ae->idx].w)+2); - sprintf(curlabel.name,"%s.%s",ae->rasmstruct[ae->irasmstruct-1].name,ae->wl[ae->idx].w); + 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; } else { + /************************************************** + l a b e l s + **************************************************/ /* labels locaux */ - if (ae->wl[ae->idx].w[0]=='@' && (ae->ir || ae->iw || ae->imacro)) { + if (varbuffer[0]=='@' && (ae->ir || ae->iw || ae->imacro)) { curlabel.iw=-1; - curlabelname=curlabel.name=MakeLocalLabel(ae,ae->wl[ae->idx].w,NULL); + curlabelname=curlabel.name=MakeLocalLabel(ae,varbuffer,NULL); curlabel.crc=GetCRC(curlabel.name); } else { - /* ancien style */ - if (ae->wl[ae->idx].w[0]=='.') { - i=0; - do { - ae->wl[ae->idx].w[i]=ae->wl[ae->idx].w[i+1]; - i++; - } while (ae->wl[ae->idx].w[i]!=0); + 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 { + rasm_printf(ae,"[%s:%d] cannot create proximity label [%s] as there is no previous global label\n",GetExpFile(ae,0),ae->wl[ae->idx].l,varbuffer); + MaxError(ae); + return; + } + } + 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 */ + ae->lastgloballabel=ae->wl[ae->idx].w; + ae->lastgloballabellen=strlen(ae->wl[ae->idx].w); +//printf("SET global label [%s] l=%d\n",ae->lastgloballabel,ae->lastgloballabellen); + break; } - curlabel.iw=ae->idx; - curlabel.crc=GetCRC(ae->wl[ae->idx].w); - curlabelname=ae->wl[ae->idx].w; /* contrôle dico uniquement avec des labels non locaux */ if (SearchDico(ae,curlabelname,curlabel.crc)) { - rasm_printf(ae,"[%s] Error line %d - cannot create label [%s] as there is already a variable with the same name\n",GetExpFile(ae,0),ae->wl[ae->idx].l,curlabelname); + rasm_printf(ae,"[%s:%d] cannot create label [%s] as there is already a variable with the same name\n",GetExpFile(ae,0),ae->wl[ae->idx].l,curlabelname); + MaxError(ae); + return; + } + if(SearchAlias(ae,curlabel.crc,curlabelname)!=-1) { + rasm_printf(ae,"[%s:%d] cannot create label [%s] as there is already an alias with the same name\n",GetExpFile(ae,0),ae->wl[ae->idx].l,curlabelname); MaxError(ae); return; } @@ -4473,15 +5718,19 @@ void PushLabel(struct s_assenv *ae) } if ((searched_label=SearchLabel(ae,curlabelname,curlabel.crc))!=NULL) { - rasm_printf(ae,"[%s] Error line %d - Duplicate label [%s]\n",GetExpFile(ae,0),GetExpLine(ae,0),curlabelname); + rasm_printf(ae,"[%s:%d] Duplicate label [%s] - previously defined in [%s:%d]\n",GetExpFile(ae,0),GetExpLine(ae,0),curlabelname,ae->filename[searched_label->fileidx],searched_label->fileline); MaxError(ae); 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; 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) { @@ -4530,19 +5779,19 @@ void _IN(struct s_assenv *ae) { case CRC_H:___output(ae,0xED);___output(ae,0x60);break; case CRC_L:___output(ae,0xED);___output(ae,0x68);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is IN [0,F,A,B,C,D,E,H,L],(C)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is IN [0,F,A,B,C,D,E,H,L],(C)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } } 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); } else { - rasm_printf(ae,"[%s] Error line %d - IN [0,F,A,B,C,D,E,H,L],(C) or IN A,(n) only\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] IN [0,F,A,B,C,D,E,H,L],(C) or IN A,(n) only\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } ae->idx+=2; } else { - rasm_printf(ae,"[%s] Error line %d - IN [0,F,A,B,C,D,E,H,L],(C) or IN A,(n) only\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] IN [0,F,A,B,C,D,E,H,L],(C) or IN A,(n) only\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } } @@ -4560,19 +5809,19 @@ void _OUT(struct s_assenv *ae) { case CRC_H:___output(ae,0xED);___output(ae,0x61);break; case CRC_L:___output(ae,0xED);___output(ae,0x69);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is OUT (C),[A,B,C,D,E,H,L]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is OUT (C),[A,B,C,D,E,H,L]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } } 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); } else { - rasm_printf(ae,"[%s] Error line %d - OUT (C),[A,B,C,D,E,H,L] or OUT (n),A only\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] OUT (C),[A,B,C,D,E,H,L] or OUT (n),A only\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } ae->idx+=2; } else { - rasm_printf(ae,"[%s] Error line %d - OUT (C),[A,B,C,D,E,H,L] or OUT (n),A only\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] OUT (C),[A,B,C,D,E,H,L] or OUT (n),A only\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } } @@ -4585,7 +5834,7 @@ void _EX(struct s_assenv *ae) { case CRC_DE:___output(ae,0xEB);break; case CRC_SP:___output(ae,0xE3);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is EX HL,[SP,DE]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is EX HL,[SP,DE]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } break; @@ -4593,7 +5842,7 @@ void _EX(struct s_assenv *ae) { if (strcmp(ae->wl[ae->idx+2].w,"AF'")==0) { ___output(ae,0x08); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is EX AF,AF'\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is EX AF,AF'\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } break; @@ -4603,7 +5852,7 @@ void _EX(struct s_assenv *ae) { case CRC_IX:___output(ae,0xDD);___output(ae,0xE3);break; case CRC_IY:___output(ae,0xFD);___output(ae,0xE3);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is EX SP,[HL,IX,IY]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is EX SP,[HL,IX,IY]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } break; @@ -4611,7 +5860,7 @@ void _EX(struct s_assenv *ae) { switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_HL:___output(ae,0xEB);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is EX DE,HL\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is EX DE,HL\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } break; @@ -4619,7 +5868,7 @@ void _EX(struct s_assenv *ae) { switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_SP:___output(ae,0xDD);___output(ae,0xE3);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is EX IX,SP\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is EX IX,SP\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } break; @@ -4627,17 +5876,17 @@ void _EX(struct s_assenv *ae) { switch (GetCRC(ae->wl[ae->idx+2].w)) { case CRC_SP:___output(ae,0xFD);___output(ae,0xE3);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is EX IY,SP\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is EX IY,SP\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is EX [AF,DE,HL,SP,IX,IY],reg16\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is EX [AF,DE,HL,SP,IX,IY],reg16\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } ae->idx+=2; } else { - rasm_printf(ae,"[%s] Error line %d - Use EX reg16,reg16\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Use EX reg16,reg16\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } } @@ -4658,6 +5907,11 @@ void _SBC(struct s_assenv *ae) { case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x9D);break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x9C);break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x9D);break; + case CRC_IX:case CRC_IY: + rasm_printf(ae,"[%s:%d] Use SBC with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + MaxError(ae); + ae->idx++; + return; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0x9E); @@ -4680,17 +5934,17 @@ void _SBC(struct s_assenv *ae) { case CRC_HL:___output(ae,0xED);___output(ae,0x62);break; case CRC_SP:___output(ae,0xED);___output(ae,0x72);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is SBC HL,[BC,DE,HL,SP]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is SBC HL,[BC,DE,HL,SP]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is SBC HL,[BC,DE,HL,SP]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is SBC HL,[BC,DE,HL,SP]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } ae->idx+=2; } else { - rasm_printf(ae,"[%s] Error line %d - Invalid syntax for SBC\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Invalid syntax for SBC\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } } @@ -4711,6 +5965,11 @@ void _ADC(struct s_assenv *ae) { case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x8D);break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x8C);break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x8D);break; + case CRC_IX:case CRC_IY: + rasm_printf(ae,"[%s:%d] Use ADC with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + MaxError(ae); + ae->idx++; + return; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0x8E); @@ -4733,17 +5992,17 @@ void _ADC(struct s_assenv *ae) { case CRC_HL:___output(ae,0xED);___output(ae,0x6A);break; case CRC_SP:___output(ae,0xED);___output(ae,0x7A);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is ADC HL,[BC,DE,HL,SP]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is ADC HL,[BC,DE,HL,SP]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is ADC HL,[BC,DE,HL,SP]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is ADC HL,[BC,DE,HL,SP]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } ae->idx+=2; } else { - rasm_printf(ae,"[%s] Error line %d - Invalid syntax for ADC\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Invalid syntax for ADC\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } } @@ -4764,6 +6023,11 @@ void _ADD(struct s_assenv *ae) { case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x85);break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x84);break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x85);break; + case CRC_IX:case CRC_IY: + rasm_printf(ae,"[%s:%d] Use ADD with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + MaxError(ae); + ae->idx++; + return; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,0x86); @@ -4786,7 +6050,7 @@ void _ADD(struct s_assenv *ae) { case CRC_HL:___output(ae,0x29);break; case CRC_SP:___output(ae,0x39);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is ADD HL,[BC,DE,HL,SP]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is ADD HL,[BC,DE,HL,SP]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } break; @@ -4797,7 +6061,7 @@ void _ADD(struct s_assenv *ae) { case CRC_IX:___output(ae,0xDD);___output(ae,0x29);break; case CRC_SP:___output(ae,0xDD);___output(ae,0x39);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is ADD IX,[BC,DE,IX,SP]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is ADD IX,[BC,DE,IX,SP]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } break; @@ -4808,17 +6072,17 @@ void _ADD(struct s_assenv *ae) { case CRC_IY:___output(ae,0xFD);___output(ae,0x29);break; case CRC_SP:___output(ae,0xFD);___output(ae,0x39);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is ADD IY,[BC,DE,IY,SP]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is ADD IY,[BC,DE,IY,SP]\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is ADD [HL,IX,IY],reg16\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is ADD [HL,IX,IY],reg16\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } ae->idx+=2; } else { - rasm_printf(ae,"[%s] Error line %d - Invalid syntax for ADD\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Invalid syntax for ADD\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } } @@ -4852,7 +6116,7 @@ void _CP(struct s_assenv *ae) { } ae->idx++; } else { - rasm_printf(ae,"[%s] Error line %d - Syntax is CP reg8/(reg16)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Syntax is CP reg8/(reg16)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } } @@ -4869,14 +6133,14 @@ void _RET(struct s_assenv *ae) { case CRC_P:___output(ae,0xF0);break; case CRC_M:___output(ae,0xF8);break; default: - rasm_printf(ae,"[%s] Error line %d - Available flags for RET are C,NC,Z,NZ,PE,PO,P,M\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Available flags for RET are C,NC,Z,NZ,PE,PO,P,M\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } ae->idx++; } else if (ae->wl[ae->idx].t==1) { ___output(ae,0xC9); } else { - rasm_printf(ae,"[%s] Error line %d - Invalid RET syntax\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Invalid RET syntax\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } } @@ -4893,7 +6157,7 @@ void _CALL(struct s_assenv *ae) { case CRC_P:___output(ae,0xF4);break; case CRC_M:___output(ae,0xFC);break; default: - rasm_printf(ae,"[%s] Error line %d - Available flags for CALL are C,NC,Z,NZ,PE,PO,P,M\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Available flags for CALL are C,NC,Z,NZ,PE,PO,P,M\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } PushExpression(ae,ae->idx+2,E_EXPRESSION_V16); @@ -4903,7 +6167,7 @@ void _CALL(struct s_assenv *ae) { PushExpression(ae,ae->idx+1,E_EXPRESSION_V16); ae->idx++; } else { - rasm_printf(ae,"[%s] Error line %d - Invalid CALL syntax\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Invalid CALL syntax\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } } @@ -4916,7 +6180,7 @@ void _JR(struct s_assenv *ae) { case CRC_Z:___output(ae,0x28);break; case CRC_NC:___output(ae,0x30);break; default: - rasm_printf(ae,"[%s] Error line %d - Available flags for JR are C,NC,Z,NZ\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Available flags for JR are C,NC,Z,NZ\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } PushExpression(ae,ae->idx+2,E_EXPRESSION_J8); @@ -4926,7 +6190,7 @@ void _JR(struct s_assenv *ae) { PushExpression(ae,ae->idx+1,E_EXPRESSION_J8); ae->idx++; } else { - rasm_printf(ae,"[%s] Error line %d - Invalid JR syntax\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Invalid JR syntax\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } } @@ -4943,7 +6207,7 @@ void _JP(struct s_assenv *ae) { case CRC_P:___output(ae,0xF2);break; case CRC_M:___output(ae,0xFA);break; default: - rasm_printf(ae,"[%s] Error line %d - Available flags for JP are C,NC,Z,NZ,PE,PO,P,M\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Available flags for JP are C,NC,Z,NZ,PE,PO,P,M\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } PushExpression(ae,ae->idx+2,E_EXPRESSION_V16); @@ -4959,87 +6223,91 @@ void _JP(struct s_assenv *ae) { } ae->idx++; } else { - rasm_printf(ae,"[%s] Error line %d - Invalid JP syntax\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Invalid JP syntax\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } } void _DEC(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_A:___output(ae,0x3D);break; - case CRC_B:___output(ae,0x05);break; - case CRC_C:___output(ae,0x0D);break; - case CRC_D:___output(ae,0x15);break; - case CRC_E:___output(ae,0x1D);break; - case CRC_H:___output(ae,0x25);break; - case CRC_L:___output(ae,0x2D);break; - case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x25);break; - case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x2D);break; - case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x25);break; - case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x2D);break; - case CRC_BC:___output(ae,0x0B);break; - case CRC_DE:___output(ae,0x1B);break; - case CRC_HL:___output(ae,0x2B);break; - case CRC_IX:___output(ae,0xDD);___output(ae,0x2B);break; - case CRC_IY:___output(ae,0xFD);___output(ae,0x2B);break; - case CRC_SP:___output(ae,0x3B);break; - case CRC_MHL:___output(ae,0x35);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); - } 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); - } else { - rasm_printf(ae,"[%s] Error line %d - Use DEC with A,B,C,D,E,H,L,XH,XL,YH,YL,BC,DE,HL,SP,(HL),(IX),(IY)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); - MaxError(ae); - } - } - ae->idx++; + if (!ae->wl[ae->idx].t) { + do { + switch (GetCRC(ae->wl[ae->idx+1].w)) { + case CRC_A:___output(ae,0x3D);break; + case CRC_B:___output(ae,0x05);break; + case CRC_C:___output(ae,0x0D);break; + case CRC_D:___output(ae,0x15);break; + case CRC_E:___output(ae,0x1D);break; + case CRC_H:___output(ae,0x25);break; + case CRC_L:___output(ae,0x2D);break; + case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x25);break; + case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x2D);break; + case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x25);break; + case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x2D);break; + case CRC_BC:___output(ae,0x0B);break; + case CRC_DE:___output(ae,0x1B);break; + case CRC_HL:___output(ae,0x2B);break; + case CRC_IX:___output(ae,0xDD);___output(ae,0x2B);break; + case CRC_IY:___output(ae,0xFD);___output(ae,0x2B);break; + case CRC_SP:___output(ae,0x3B);break; + case CRC_MHL:___output(ae,0x35);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); + } 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); + } else { + rasm_printf(ae,"[%s:%d] Use DEC with A,B,C,D,E,H,L,XH,XL,YH,YL,BC,DE,HL,SP,(HL),(IX),(IY)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + MaxError(ae); + } + } + ae->idx++; + } while (ae->wl[ae->idx].t==0); } else { - rasm_printf(ae,"[%s] Error line %d - Use DEC with A,B,C,D,E,H,L,XH,XL,YH,YL,BC,DE,HL,SP,(HL),(IX),(IY)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Use DEC with A,B,C,D,E,H,L,XH,XL,YH,YL,BC,DE,HL,SP,(HL),(IX),(IY)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } } void _INC(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_A:___output(ae,0x3C);break; - case CRC_B:___output(ae,0x04);break; - case CRC_C:___output(ae,0x0C);break; - case CRC_D:___output(ae,0x14);break; - case CRC_E:___output(ae,0x1C);break; - case CRC_H:___output(ae,0x24);break; - case CRC_L:___output(ae,0x2C);break; - case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x24);break; - case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x2C);break; - case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x24);break; - case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x2C);break; - case CRC_BC:___output(ae,0x03);break; - case CRC_DE:___output(ae,0x13);break; - case CRC_HL:___output(ae,0x23);break; - case CRC_IX:___output(ae,0xDD);___output(ae,0x23);break; - case CRC_IY:___output(ae,0xFD);___output(ae,0x23);break; - case CRC_SP:___output(ae,0x33);break; - case CRC_MHL:___output(ae,0x34);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); - } 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); - } else { - rasm_printf(ae,"[%s] Error line %d - Use INC with A,B,C,D,E,H,L,XH,XL,YH,YL,BC,DE,HL,SP,(HL),(IX),(IY)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); - MaxError(ae); - } - } - ae->idx++; + if (!ae->wl[ae->idx].t) { + do { + switch (GetCRC(ae->wl[ae->idx+1].w)) { + case CRC_A:___output(ae,0x3C);break; + case CRC_B:___output(ae,0x04);break; + case CRC_C:___output(ae,0x0C);break; + case CRC_D:___output(ae,0x14);break; + case CRC_E:___output(ae,0x1C);break; + case CRC_H:___output(ae,0x24);break; + case CRC_L:___output(ae,0x2C);break; + case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x24);break; + case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x2C);break; + case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x24);break; + case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x2C);break; + case CRC_BC:___output(ae,0x03);break; + case CRC_DE:___output(ae,0x13);break; + case CRC_HL:___output(ae,0x23);break; + case CRC_IX:___output(ae,0xDD);___output(ae,0x23);break; + case CRC_IY:___output(ae,0xFD);___output(ae,0x23);break; + case CRC_SP:___output(ae,0x33);break; + case CRC_MHL:___output(ae,0x34);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); + } 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); + } else { + rasm_printf(ae,"[%s:%d] Use INC with A,B,C,D,E,H,L,XH,XL,YH,YL,BC,DE,HL,SP,(HL),(IX),(IY)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + MaxError(ae); + } + } + ae->idx++; + } while (ae->wl[ae->idx].t==0); } else { - rasm_printf(ae,"[%s] Error line %d - Use INC with A,B,C,D,E,H,L,XH,XL,YH,YL,BC,DE,HL,SP,(HL),(IX),(IY)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Use INC with A,B,C,D,E,H,L,XH,XL,YH,YL,BC,DE,HL,SP,(HL),(IX),(IY)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5065,6 +6333,11 @@ void _SUB(struct s_assenv *ae) { case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,OPCODE+5);break; case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,OPCODE+4);break; case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,OPCODE+5);break; + case CRC_IX:case CRC_IY: + rasm_printf(ae,"[%s:%d] Use SUB with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + MaxError(ae); + ae->idx++; + return; default: if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) { ___output(ae,0xDD);___output(ae,OPCODE+6); @@ -5079,7 +6352,7 @@ void _SUB(struct s_assenv *ae) { } ae->idx++; } else { - rasm_printf(ae,"[%s] Error line %d - Use SUB with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Use SUB with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5117,7 +6390,7 @@ void _AND(struct s_assenv *ae) { } ae->idx++; } else { - rasm_printf(ae,"[%s] Error line %d - Use AND with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Use AND with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5155,7 +6428,7 @@ void _OR(struct s_assenv *ae) { } ae->idx++; } else { - rasm_printf(ae,"[%s] Error line %d - Use OR with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Use OR with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n",GetExpFile(ae,0),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5193,7 +6466,7 @@ void _XOR(struct s_assenv *ae) { } ae->idx++; } else { - rasm_printf(ae,"[%s] Error line %d - Use XOR with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Use XOR with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5211,12 +6484,12 @@ void _POP(struct s_assenv *ae) { case CRC_IX:___output(ae,0xDD);___output(ae,0xE1);break; case CRC_IY:___output(ae,0xFD);___output(ae,0xE1);break; default: - rasm_printf(ae,"Error line %d - Use POP with AF,BC,DE,HL,IX,IY\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Use POP with AF,BC,DE,HL,IX,IY\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } while (ae->wl[ae->idx].t!=1); } else { - rasm_printf(ae,"[%s] Error line %d - POP need at least one parameter\n",ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] POP need at least one parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5232,12 +6505,12 @@ void _PUSH(struct s_assenv *ae) { case CRC_IX:___output(ae,0xDD);___output(ae,0xE5);break; case CRC_IY:___output(ae,0xFD);___output(ae,0xE5);break; default: - rasm_printf(ae,"Error line %d - Use PUSH with AF,BC,DE,HL,IX,IY\n",ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Use PUSH with AF,BC,DE,HL,IX,IY\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } while (ae->wl[ae->idx].t!=1); } else { - rasm_printf(ae,"[%s] Error line %d - PUSH need at least one parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] PUSH need at least one parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5249,7 +6522,7 @@ void _IM(struct s_assenv *ae) { PushExpression(ae,ae->idx+1,E_EXPRESSION_IM); ae->idx++; } else { - rasm_printf(ae,"[%s] Error line %d - IM need one parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] IM need one parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5258,7 +6531,7 @@ void _RLCA(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0x7); } else { - rasm_printf(ae,"[%s] Error line %d - RLCA does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] RLCA does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5266,7 +6539,7 @@ void _RRCA(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xF); } else { - rasm_printf(ae,"[%s] Error line %d - RRCA does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] RRCA does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5275,7 +6548,7 @@ void _NEG(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0x44); } else { - rasm_printf(ae,"[%s] Error line %d - NEG does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] NEG does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5283,7 +6556,7 @@ void _DAA(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0x27); } else { - rasm_printf(ae,"[%s] Error line %d - DAA does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] DAA does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5291,7 +6564,7 @@ void _CPL(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0x2F); } else { - rasm_printf(ae,"[%s] Error line %d - CPL does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] CPL does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5300,7 +6573,7 @@ void _RETI(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0x4D); } else { - rasm_printf(ae,"[%s] Error line %d - RETI does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] RETI does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5308,7 +6581,7 @@ void _SCF(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0x37); } else { - rasm_printf(ae,"[%s] Error line %d - SCF does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] SCF does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5317,7 +6590,7 @@ void _LDD(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0xA8); } else { - rasm_printf(ae,"[%s] Error line %d - LDD does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] LDD does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5326,7 +6599,7 @@ void _LDDR(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0xB8); } else { - rasm_printf(ae,"[%s] Error line %d - LDDR does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] LDDR does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5335,7 +6608,7 @@ void _LDI(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0xA0); } else { - rasm_printf(ae,"[%s] Error line %d - LDI does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] LDI does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5344,7 +6617,7 @@ void _LDIR(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0xB0); } else { - rasm_printf(ae,"[%s] Error line %d - LDIR does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] LDIR does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5352,7 +6625,7 @@ void _CCF(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0x3F); } else { - rasm_printf(ae,"[%s] Error line %d - CCF does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] CCF does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5361,7 +6634,7 @@ void _CPD(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0xA9); } else { - rasm_printf(ae,"[%s] Error line %d - CPD does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] CPD does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5370,7 +6643,7 @@ void _CPDR(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0xB9); } else { - rasm_printf(ae,"[%s] Error line %d - CPDR does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] CPDR does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5379,7 +6652,7 @@ void _CPI(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0xA1); } else { - rasm_printf(ae,"[%s] Error line %d - CPI does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] CPI does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5388,7 +6661,7 @@ void _CPIR(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0xB1); } else { - rasm_printf(ae,"[%s] Error line %d - CPIR does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] CPIR does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5397,7 +6670,7 @@ void _OUTD(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0xAB); } else { - rasm_printf(ae,"[%s] Error line %d - OUTD does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] OUTD does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5406,7 +6679,7 @@ void _OTDR(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0xBB); } else { - rasm_printf(ae,"[%s] Error line %d - OTDR does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] OTDR does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5415,7 +6688,7 @@ void _OUTI(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0xA3); } else { - rasm_printf(ae,"[%s] Error line %d - OUTI does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] OUTI does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5424,7 +6697,7 @@ void _OTIR(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0xB3); } else { - rasm_printf(ae,"[%s] Error line %d - OTIR does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] OTIR does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5433,7 +6706,7 @@ void _RETN(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0x45); } else { - rasm_printf(ae,"[%s] Error line %d - RETN does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] RETN does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5442,7 +6715,7 @@ void _IND(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0xAA); } else { - rasm_printf(ae,"[%s] Error line %d - IND does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] IND does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5451,7 +6724,7 @@ void _INDR(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0xBA); } else { - rasm_printf(ae,"[%s] Error line %d - INDR does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] INDR does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5460,7 +6733,7 @@ void _INI(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0xA2); } else { - rasm_printf(ae,"[%s] Error line %d - INI does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] INI does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5469,7 +6742,7 @@ void _INIR(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0xB2); } else { - rasm_printf(ae,"[%s] Error line %d - INIR does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] INIR does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5477,7 +6750,7 @@ void _EXX(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xD9); } else { - rasm_printf(ae,"[%s] Error line %d - EXX does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] EXX does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5485,7 +6758,7 @@ void _HALT(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0x76); } else { - rasm_printf(ae,"[%s] Error line %d - HALT does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] HALT does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5494,7 +6767,7 @@ void _RLA(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0x17); } else { - rasm_printf(ae,"[%s] Error line %d - RLA does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] RLA does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5502,7 +6775,7 @@ void _RRA(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0x1F); } else { - rasm_printf(ae,"[%s] Error line %d - RRA does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] RRA does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5511,7 +6784,7 @@ void _RLD(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0x6F); } else { - rasm_printf(ae,"[%s] Error line %d - RLD does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] RLD does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5520,7 +6793,7 @@ void _RRD(struct s_assenv *ae) { ___output(ae,0xED); ___output(ae,0x67); } else { - rasm_printf(ae,"[%s] Error line %d - RRD does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] RRD does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5541,7 +6814,7 @@ void _NOP(struct s_assenv *ae) { } } } else { - rasm_printf(ae,"[%s] Error line %d - NOP is supposed to be used without parameter or with one optional parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] NOP is supposed to be used without parameter or with one optional parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5549,7 +6822,7 @@ void _DI(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xF3); } else { - rasm_printf(ae,"[%s] Error line %d - DI does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] DI does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5557,7 +6830,7 @@ void _EI(struct s_assenv *ae) { if (ae->wl[ae->idx].t) { ___output(ae,0xFB); } else { - rasm_printf(ae,"[%s] Error line %d - EI does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] EI does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5568,7 +6841,7 @@ void _RST(struct s_assenv *ae) { PushExpression(ae,ae->idx+1,E_EXPRESSION_RST); ae->idx++; } else { - rasm_printf(ae,"[%s] Error line %d - RST need one parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] RST need one parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -5579,14 +6852,14 @@ void _DJNZ(struct s_assenv *ae) { PushExpression(ae,ae->idx+1,E_EXPRESSION_J8); ae->idx++; } else { - rasm_printf(ae,"[%s] Error line %d - DJNZ need one parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] DJNZ need one parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } 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!=2) { + 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)) { @@ -5627,7 +6900,7 @@ void _LD(struct s_assenv *ae) { if (GetCRC(ae->wl[ae->idx+2].w)==CRC_A) { ___output(ae,0xED);___output(ae,0x47); } else { - rasm_printf(ae,"[%s] Error line %d - LD I,A only\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] LD I,A only\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } break; @@ -5635,7 +6908,7 @@ void _LD(struct s_assenv *ae) { if (GetCRC(ae->wl[ae->idx+2].w)==CRC_A) { ___output(ae,0xED);___output(ae,0x4F); } else { - rasm_printf(ae,"[%s] Error line %d - LD R,A only\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] LD R,A only\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } break; @@ -5874,7 +7147,7 @@ void _LD(struct s_assenv *ae) { if (GetCRC(ae->wl[ae->idx+2].w)==CRC_A) { ___output(ae,0x02); } else { - rasm_printf(ae,"[%s] Error line %d - LD (BC),A only\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] LD (BC),A only\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } break; @@ -5882,7 +7155,7 @@ void _LD(struct s_assenv *ae) { if (GetCRC(ae->wl[ae->idx+2].w)==CRC_A) { ___output(ae,0x12); } else { - rasm_printf(ae,"[%s] Error line %d - LD (DE),A only\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] LD (DE),A only\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } break; @@ -5892,7 +7165,19 @@ void _LD(struct s_assenv *ae) { case CRC_DE:___output(ae,0x62);___output(ae,0x6B);break; case CRC_HL:___output(ae,0x64);___output(ae,0x6D);break; default: - if (StringIsMem(ae->wl[ae->idx+2].w)) { + 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); + } 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); + } else if (StringIsMem(ae->wl[ae->idx+2].w)) { ___output(ae,0x2A); PushExpression(ae,ae->idx+2,E_EXPRESSION_V16); } else { @@ -5907,7 +7192,19 @@ void _LD(struct s_assenv *ae) { case CRC_DE:___output(ae,0x42);___output(ae,0x4B);break; case CRC_HL:___output(ae,0x44);___output(ae,0x4D);break; default: - if (StringIsMem(ae->wl[ae->idx+2].w)) { + 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); + } 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); + } else if (StringIsMem(ae->wl[ae->idx+2].w)) { ___output(ae,0xED);___output(ae,0x4B); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16); } else { @@ -5922,7 +7219,19 @@ void _LD(struct s_assenv *ae) { case CRC_DE:___output(ae,0x52);___output(ae,0x5B);break; case CRC_HL:___output(ae,0x54);___output(ae,0x5D);break; default: - if (StringIsMem(ae->wl[ae->idx+2].w)) { + 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); + } 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); + } else if (StringIsMem(ae->wl[ae->idx+2].w)) { ___output(ae,0xED);___output(ae,0x5B); PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16); } else { @@ -5975,6 +7284,9 @@ void _LD(struct s_assenv *ae) { case CRC_H:___output(ae,0xDD);___output(ae,0x74);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);break; case CRC_L:___output(ae,0xDD);___output(ae,0x75);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);break; case CRC_A:___output(ae,0xDD);___output(ae,0x77);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);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);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);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);break; default:___output(ae,0xDD);___output(ae,0x36); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); PushExpression(ae,ae->idx+2,E_EXPRESSION_3V8); @@ -5988,6 +7300,9 @@ void _LD(struct s_assenv *ae) { case CRC_H:___output(ae,0xFD);___output(ae,0x74);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);break; case CRC_L:___output(ae,0xFD);___output(ae,0x75);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);break; case CRC_A:___output(ae,0xFD);___output(ae,0x77);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);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);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);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);break; default:___output(ae,0xFD);___output(ae,0x36); PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); PushExpression(ae,ae->idx+2,E_EXPRESSION_3V8); @@ -6002,18 +7317,18 @@ void _LD(struct s_assenv *ae) { case CRC_IY:___output(ae,0xFD);___output(ae,0x22);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV16);break; case CRC_SP:___output(ae,0xED);___output(ae,0x73);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV16);break; default: - rasm_printf(ae,"[%s] Error line %d - LD (#nnnn),[A,BC,DE,HL,SP,IX,IY] only\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] LD (#nnnn),[A,BC,DE,HL,SP,IX,IY] only\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } else { - rasm_printf(ae,"[%s] Error line %d - Unknown LD format\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Unknown LD format\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } break; } ae->idx+=2; } else { - rasm_printf(ae,"[%s] Error line %d - LD needs two parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] LD needs two parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6041,7 +7356,7 @@ void _RLC(struct s_assenv *ae) { PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x6); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is RLC reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is RLC reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6052,7 +7367,7 @@ void _RLC(struct s_assenv *ae) { } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD); } else { - rasm_printf(ae,"(%s] Error line %d - syntax is RLC (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"(%s:%d] syntax is RLC (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ___output(ae,0xCB); @@ -6065,7 +7380,7 @@ void _RLC(struct s_assenv *ae) { case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x5);break; case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x7);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is RLC (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is RLC (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ae->idx++; @@ -6095,7 +7410,7 @@ void _RRC(struct s_assenv *ae) { PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0xE); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is RRC reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is RRC reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6106,7 +7421,7 @@ void _RRC(struct s_assenv *ae) { } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is RRC (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is RRC (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ___output(ae,0xCB); @@ -6119,7 +7434,7 @@ void _RRC(struct s_assenv *ae) { case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0xD);break; case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0xF);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is RRC (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is RRC (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ae->idx++; @@ -6132,10 +7447,13 @@ 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);break; case CRC_B:___output(ae,0xCB);___output(ae,0x10);break; case CRC_C:___output(ae,0xCB);___output(ae,0x11);break; + case CRC_DE:___output(ae,0xCB);___output(ae,0x12);___output(ae,0xCB);___output(ae,0x13);break; case CRC_D:___output(ae,0xCB);___output(ae,0x12);break; case CRC_E:___output(ae,0xCB);___output(ae,0x13);break; + case CRC_HL:___output(ae,0xCB);___output(ae,0x14);___output(ae,0xCB);___output(ae,0x15);break; case CRC_H:___output(ae,0xCB);___output(ae,0x14);break; case CRC_L:___output(ae,0xCB);___output(ae,0x15);break; case CRC_MHL:___output(ae,0xCB);___output(ae,0x16);break; @@ -6150,7 +7468,7 @@ void _RL(struct s_assenv *ae) { PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x16); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is RL reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is RL reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6161,7 +7479,7 @@ void _RL(struct s_assenv *ae) { } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is RL (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is RL (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ___output(ae,0xCB); @@ -6174,11 +7492,14 @@ void _RL(struct s_assenv *ae) { case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x15);break; case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x17);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is RL (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is RL (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ae->idx++; ae->idx++; + } else { + rasm_printf(ae,"[%s:%d] syntax is RL (IX+n),reg8 or RL reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); } } @@ -6186,10 +7507,13 @@ 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);break; case CRC_B:___output(ae,0xCB);___output(ae,0x18);break; case CRC_C:___output(ae,0xCB);___output(ae,0x19);break; + case CRC_DE:___output(ae,0xCB);___output(ae,0x1A);___output(ae,0xCB);___output(ae,0x1B);break; case CRC_D:___output(ae,0xCB);___output(ae,0x1A);break; case CRC_E:___output(ae,0xCB);___output(ae,0x1B);break; + case CRC_HL:___output(ae,0xCB);___output(ae,0x1C);___output(ae,0xCB);___output(ae,0x1D);break; case CRC_H:___output(ae,0xCB);___output(ae,0x1C);break; case CRC_L:___output(ae,0xCB);___output(ae,0x1D);break; case CRC_MHL:___output(ae,0xCB);___output(ae,0x1E);break; @@ -6204,7 +7528,7 @@ void _RR(struct s_assenv *ae) { PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x1E); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is RR reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is RR reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6215,7 +7539,7 @@ void _RR(struct s_assenv *ae) { } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is RR (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is RR (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ___output(ae,0xCB); @@ -6228,11 +7552,14 @@ void _RR(struct s_assenv *ae) { case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1D);break; case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1F);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is RR (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is RR (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ae->idx++; ae->idx++; + } else { + rasm_printf(ae,"[%s:%d] syntax is RR (IX+n),reg8 or RR reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); } } @@ -6244,10 +7571,13 @@ 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);break; /* SLA C : RL B */ case CRC_B:___output(ae,0xCB);___output(ae,0x20);break; case CRC_C:___output(ae,0xCB);___output(ae,0x21);break; + case CRC_DE:___output(ae,0xCB);___output(ae,0x23);___output(ae,0xCB);___output(ae,0x12);break; /* SLA E : RL D */ case CRC_D:___output(ae,0xCB);___output(ae,0x22);break; case CRC_E:___output(ae,0xCB);___output(ae,0x23);break; + case CRC_HL:___output(ae,0xCB);___output(ae,0x25);___output(ae,0xCB);___output(ae,0x14);break; /* SLA L : RL H */ case CRC_H:___output(ae,0xCB);___output(ae,0x24);break; case CRC_L:___output(ae,0xCB);___output(ae,0x25);break; case CRC_MHL:___output(ae,0xCB);___output(ae,0x26);break; @@ -6262,7 +7592,7 @@ void _SLA(struct s_assenv *ae) { PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x26); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is SLA reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is SLA reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6273,7 +7603,7 @@ void _SLA(struct s_assenv *ae) { } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is SLL (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is SLL (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ___output(ae,0xCB); @@ -6286,11 +7616,14 @@ void _SLA(struct s_assenv *ae) { case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x25);break; case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x27);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is SLA (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is SLA (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ae->idx++; ae->idx++; + } else { + rasm_printf(ae,"[%s:%d] syntax is SLA reg8/(HL)/(IX+n)/(IY+n) or SLA (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); } } @@ -6298,10 +7631,13 @@ 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);break; /* SRA B : RR C */ case CRC_B:___output(ae,0xCB);___output(ae,0x28);break; case CRC_C:___output(ae,0xCB);___output(ae,0x29);break; + case CRC_DE:___output(ae,0xCB);___output(ae,0x2A);___output(ae,0xCB);___output(ae,0x1B);break; /* SRA D : RR E */ case CRC_D:___output(ae,0xCB);___output(ae,0x2A);break; case CRC_E:___output(ae,0xCB);___output(ae,0x2B);break; + case CRC_HL:___output(ae,0xCB);___output(ae,0x2C);___output(ae,0xCB);___output(ae,0x1D);break; /* SRA H : RR L */ case CRC_H:___output(ae,0xCB);___output(ae,0x2C);break; case CRC_L:___output(ae,0xCB);___output(ae,0x2D);break; case CRC_MHL:___output(ae,0xCB);___output(ae,0x2E);break; @@ -6316,7 +7652,7 @@ void _SRA(struct s_assenv *ae) { PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x2E); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is SRA reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is SRA reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6327,7 +7663,7 @@ void _SRA(struct s_assenv *ae) { } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is SRA (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is SRA (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ___output(ae,0xCB); @@ -6340,11 +7676,14 @@ void _SRA(struct s_assenv *ae) { case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2D);break; case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2F);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is SRA (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is SRA (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ae->idx++; ae->idx++; + } else { + rasm_printf(ae,"[%s:%d] syntax is SRA reg8/(HL)/(IX+n)/(IY+n) or SRA (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); } } @@ -6353,10 +7692,13 @@ 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);break; /* SLL C : RL B */ case CRC_B:___output(ae,0xCB);___output(ae,0x30);break; case CRC_C:___output(ae,0xCB);___output(ae,0x31);break; + case CRC_DE:___output(ae,0xCB);___output(ae,0x33);___output(ae,0xCB);___output(ae,0x12);break; /* SLL E : RL D */ case CRC_D:___output(ae,0xCB);___output(ae,0x32);break; case CRC_E:___output(ae,0xCB);___output(ae,0x33);break; + case CRC_HL:___output(ae,0xCB);___output(ae,0x35);___output(ae,0xCB);___output(ae,0x14);break; /* SLL L : RL H */ case CRC_H:___output(ae,0xCB);___output(ae,0x34);break; case CRC_L:___output(ae,0xCB);___output(ae,0x35);break; case CRC_MHL:___output(ae,0xCB);___output(ae,0x36);break; @@ -6371,7 +7713,7 @@ void _SLL(struct s_assenv *ae) { PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x36); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is SLL reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is SLL reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6382,7 +7724,7 @@ void _SLL(struct s_assenv *ae) { } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is SLL (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is SLL (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ___output(ae,0xCB); @@ -6395,11 +7737,14 @@ void _SLL(struct s_assenv *ae) { case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x35);break; case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x37);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is SLL (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is SLL (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ae->idx++; ae->idx++; + } else { + rasm_printf(ae,"[%s:%d] syntax is SLL reg8/(HL)/(IX+n)/(IY+n) or SLL (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); } } @@ -6407,10 +7752,13 @@ 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);break; /* SRL B : RL C */ case CRC_B:___output(ae,0xCB);___output(ae,0x38);break; case CRC_C:___output(ae,0xCB);___output(ae,0x39);break; + case CRC_DE:___output(ae,0xCB);___output(ae,0x3A);___output(ae,0xCB);___output(ae,0x13);break; /* SRL D : RL E */ case CRC_D:___output(ae,0xCB);___output(ae,0x3A);break; case CRC_E:___output(ae,0xCB);___output(ae,0x3B);break; + case CRC_HL:___output(ae,0xCB);___output(ae,0x3C);___output(ae,0xCB);___output(ae,0x15);break; /* SRL H : RL L */ case CRC_H:___output(ae,0xCB);___output(ae,0x3C);break; case CRC_L:___output(ae,0xCB);___output(ae,0x3D);break; case CRC_MHL:___output(ae,0xCB);___output(ae,0x3E);break; @@ -6425,7 +7773,7 @@ void _SRL(struct s_assenv *ae) { PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8); ___output(ae,0x3E); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is SRL reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is SRL reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6436,7 +7784,7 @@ void _SRL(struct s_assenv *ae) { } else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) { ___output(ae,0xFD); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is SRL (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is SRL (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ___output(ae,0xCB); @@ -6449,11 +7797,14 @@ void _SRL(struct s_assenv *ae) { case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3D);break; case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3F);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is SRL (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is SRL (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ae->idx++; ae->idx++; + } else { + rasm_printf(ae,"[%s:%d] syntax is SRL reg8/(HL)/(IX+n)/(IY+n) or SRL (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); } } @@ -6464,7 +7815,7 @@ void _BIT(struct s_assenv *ae) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); o=RoundComputeExpressionCore(ae,ae->wl[ae->idx+1].w,ae->codeadr,0); if (o<0 || o>7) { - rasm_printf(ae,"[%s] Error line %d - syntax is BIT ,... (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,o); + rasm_printf(ae,"[%s:%d] syntax is BIT ,... (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,o); MaxError(ae); } else { o=0x40+o*8; @@ -6488,7 +7839,7 @@ void _BIT(struct s_assenv *ae) { PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ___output(ae,0x6+o); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is BIT n,reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is BIT n,reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6499,7 +7850,7 @@ void _BIT(struct s_assenv *ae) { } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) { ___output(ae,0xFD); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is BIT (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is BIT (IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ___output(ae,0xCB); @@ -6512,12 +7863,12 @@ void _BIT(struct s_assenv *ae) { case CRC_L:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);___output(ae,0x5+o);break; case CRC_A:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);___output(ae,0x7+o);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is BIT n,(IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is BIT n,(IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ae->idx+=3; } else { - rasm_printf(ae,"[%s] Error line %d - syntax is BIT n,reg8/(HL)/(IX+n)[,reg8]/(IY+n)[,reg8]\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is BIT n,reg8/(HL)/(IX+n)[,reg8]/(IY+n)[,reg8]\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6529,7 +7880,7 @@ void _RES(struct s_assenv *ae) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); o=RoundComputeExpressionCore(ae,ae->wl[ae->idx+1].w,ae->codeadr,0); if (o<0 || o>7) { - rasm_printf(ae,"[%s] Error line %d - syntax is RES ,... (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,o); + rasm_printf(ae,"[%s:%d] syntax is RES ,... (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,o); MaxError(ae); } else { o=0x80+o*8; @@ -6553,7 +7904,7 @@ void _RES(struct s_assenv *ae) { PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ___output(ae,0x6+o); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is RES n,reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is RES n,reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6564,7 +7915,7 @@ void _RES(struct s_assenv *ae) { } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) { ___output(ae,0xFD); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is RES n,(IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is RES n,(IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ___output(ae,0xCB); @@ -6577,12 +7928,12 @@ void _RES(struct s_assenv *ae) { case CRC_L:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);___output(ae,0x5+o);break; case CRC_A:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);___output(ae,0x7+o);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is RES n,(IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is RES n,(IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ae->idx+=3; } else { - rasm_printf(ae,"[%s] Error line %d - syntax is RES n,reg8/(HL)/(IX+n)[,reg8]/(IY+n)[,reg8]\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is RES n,reg8/(HL)/(IX+n)[,reg8]/(IY+n)[,reg8]\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6594,7 +7945,7 @@ void _SET(struct s_assenv *ae) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); o=RoundComputeExpressionCore(ae,ae->wl[ae->idx+1].w,ae->codeadr,0); if (o<0 || o>7) { - rasm_printf(ae,"[%s] Error line %d - syntax is SET ,... (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,o); + rasm_printf(ae,"[%s:%d] syntax is SET ,... (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,o); MaxError(ae); } else { o=0xC0+o*8; @@ -6618,7 +7969,7 @@ void _SET(struct s_assenv *ae) { PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8); ___output(ae,0x6+o); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is SET n,reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is SET n,reg8/(HL)/(IX+n)/(IY+n)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6629,7 +7980,7 @@ void _SET(struct s_assenv *ae) { } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) { ___output(ae,0xFD); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is SET n,(IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is SET n,(IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ___output(ae,0xCB); @@ -6642,12 +7993,12 @@ void _SET(struct s_assenv *ae) { case CRC_L:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);___output(ae,0x5+o);break; case CRC_A:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);___output(ae,0x7+o);break; default: - rasm_printf(ae,"[%s] Error line %d - syntax is SET n,(IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is SET n,(IX+n),reg8\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ae->idx+=3; } else { - rasm_printf(ae,"[%s] Error line %d - syntax is SET n,reg8/(HL)/(IX+n)[,reg8]/(IY+n)[,reg8]\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is SET n,reg8/(HL)/(IX+n)[,reg8]/(IY+n)[,reg8]\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6656,7 +8007,7 @@ void _SET(struct s_assenv *ae) { void _DEFS(struct s_assenv *ae) { int i,r,v; if (ae->wl[ae->idx].t) { - rasm_printf(ae,"[%s] Error line %d - Syntax is DEFS repeat,value or DEFS repeat\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Syntax is DEFS repeat,value or DEFS repeat\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } else do { ae->idx++; @@ -6666,7 +8017,7 @@ void _DEFS(struct s_assenv *ae) { 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) { - rasm_printf(ae,"[%s] Error line %d - DEFS size must be greater or equal to zero\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] DEFS size must be greater or equal to zero\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } for (i=0;iwl[ae->idx].w,ae->codeadr,0); v=0; if (r<0) { - rasm_printf(ae,"[%s] Error line %d - DEFS size must be greater or equal to zero\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] DEFS size must be greater or equal to zero\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } for (i=0;iwl[ae->idx].t) { @@ -6697,22 +8049,43 @@ void _STR(struct s_assenv *ae) { 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 */ - if (ae->wl[ae->idx].w[i+1]!=tquote) { - ___output(ae,ae->charset[(int)ae->wl[ae->idx].w[i]]); + 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 { - ___output(ae,ae->charset[(int)ae->wl[ae->idx].w[i]]|0x80); + /* 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 { - rasm_printf(ae,"[%s] Error line %d - STR handle only quoted strings!\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] STR handle only quoted strings!\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } while (ae->wl[ae->idx].t==0); } else { - rasm_printf(ae,"[%s] Error line %d - STR needs one or more quotes parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] STR needs one or more quotes parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6724,22 +8097,39 @@ void _DEFR(struct s_assenv *ae) { PushExpression(ae,ae->idx,E_EXPRESSION_0VR); } while (ae->wl[ae->idx].t==0); } else { - rasm_printf(ae,"[%s] Error line %d - DEFW needs one or more parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] DEFW needs one or more parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } 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++; - /* charset conversion on the fly */ - ___output(ae,ae->charset[(int)ae->wl[ae->idx].w[i]]); + 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++; } } else { @@ -6747,7 +8137,7 @@ void _DEFB(struct s_assenv *ae) { } } while (ae->wl[ae->idx].t==0); } else { - rasm_printf(ae,"[%s] Error line %d - DEFB needs one or more parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] DEFB needs one or more parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6759,7 +8149,7 @@ void _DEFW(struct s_assenv *ae) { PushExpression(ae,ae->idx,E_EXPRESSION_0V16); } while (ae->wl[ae->idx].t==0); } else { - rasm_printf(ae,"[%s] Error line %d - DEFW needs one or more parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] DEFW needs one or more parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6771,7 +8161,7 @@ void _DEFI(struct s_assenv *ae) { PushExpression(ae,ae->idx,E_EXPRESSION_0V32); } while (ae->wl[ae->idx].t==0); } else { - rasm_printf(ae,"[%s] Error line %d - DEFI needs one or more parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] DEFI needs one or more parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6799,7 +8189,7 @@ void _DEFB_as80(struct s_assenv *ae) { } while (ae->wl[ae->idx].t==0); ae->codeadr+=modadr; } else { - rasm_printf(ae,"[%s] Error line %d - DEFB needs one or more parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] DEFB needs one or more parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6814,7 +8204,7 @@ void _DEFW_as80(struct s_assenv *ae) { } while (ae->wl[ae->idx].t==0); ae->codeadr+=modadr; } else { - rasm_printf(ae,"[%s] Error line %d - DEFW needs one or more parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] DEFW needs one or more parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -6829,11 +8219,47 @@ void _DEFI_as80(struct s_assenv *ae) { } while (ae->wl[ae->idx].t==0); ae->codeadr+=modadr; } else { - rasm_printf(ae,"[%s] Error line %d - DEFI needs one or more parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] DEFI needs one or more parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } - +#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 { + rasm_printf(ae,"[%s:%d] DEFSTR needs two parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); + } +} +#endif #undef FUNC #define FUNC "Directive CORE" @@ -6854,14 +8280,14 @@ void __AMSDOS(struct s_assenv *ae) { void __BUILDCPR(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { - rasm_printf(ae,"[%s] Error line %d - BUILDCPR does not need a parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); - exit(-771); + rasm_printf(ae,"[%s:%d] BUILDCPR does not need a parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); } if (!ae->forcesnapshot) { ae->forcecpr=1; } else { - rasm_printf(ae,"[%s] Error line %d - Cannot select cartridge output when already in snapshot output\n",GetCurrentFile(ae),ae->wl[ae->idx].l); - exit(-771); + rasm_printf(ae,"[%s:%d] Cannot select cartridge output when already in snapshot output\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); } } void __BUILDSNA(struct s_assenv *ae) { @@ -6869,15 +8295,15 @@ void __BUILDSNA(struct s_assenv *ae) { if (strcmp(ae->wl[ae->idx+1].w,"V2")==0) { ae->snapshot.version=2; } else { - rasm_printf(ae,"[%s] Error line %d - BUILDSNA unrecognized option\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] BUILDSNA unrecognized option\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } if (!ae->forcecpr) { ae->forcesnapshot=1; } else { - rasm_printf(ae,"[%s] Error line %d - Cannot select snapshot output when already in cartridge output\n",GetCurrentFile(ae),ae->wl[ae->idx].l); - exit(-772); + rasm_printf(ae,"[%s:%d] Cannot select snapshot output when already in cartridge output\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); } } @@ -6886,12 +8312,14 @@ void __LZ4(struct s_assenv *ae) { struct s_lz_section curlz; #ifdef NO_3RD_PARTIES - rasm_printf(ae,"[%s] Error line %d - Cannot use 3rd parties cruncher with this version of RASM\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] 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) { - rasm_printf(ae,"[%s] Error line %d - Cannot start a new LZ section inside another one (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->lz); + rasm_printf(ae,"[%s:%d] 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; @@ -6907,12 +8335,14 @@ void __LZX7(struct s_assenv *ae) { struct s_lz_section curlz; #ifdef NO_3RD_PARTIES - rasm_printf(ae,"[%s] Error line %d - Cannot use 3rd parties cruncher with this version of RASM\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] 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) { - rasm_printf(ae,"[%s] Error line %d - Cannot start a new LZ section inside another one (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->lz); + rasm_printf(ae,"[%s:%d] 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; @@ -6928,12 +8358,14 @@ void __LZEXO(struct s_assenv *ae) { struct s_lz_section curlz; #ifdef NO_3RD_PARTIES - rasm_printf(ae,"[%s] Error line %d - Cannot use 3rd parties cruncher with this version of RASM\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] 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) { - rasm_printf(ae,"[%s] Error line %d - Cannot start a new LZ section inside another one (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->lz); + rasm_printf(ae,"[%s:%d] 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; @@ -6947,9 +8379,9 @@ void __LZEXO(struct s_assenv *ae) { } void __LZ48(struct s_assenv *ae) { struct s_lz_section curlz; - if (ae->lz>=0 && ae->lzilz) { - rasm_printf(ae,"[%s] Error line %d - Cannot start a new LZ section inside another one (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->lz); + rasm_printf(ae,"[%s:%d] 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; @@ -6965,7 +8397,8 @@ void __LZ49(struct s_assenv *ae) { struct s_lz_section curlz; if (ae->lz>=0 && ae->lzilz) { - rasm_printf(ae,"[%s] Error line %d - Cannot start a new LZ section inside another one (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->lz); + rasm_printf(ae,"[%s:%d] Cannot start a new LZ section inside another one (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->lz); + FreeAssenv(ae); exit(-5); } @@ -6980,7 +8413,7 @@ void __LZ49(struct s_assenv *ae) { } void __LZCLOSE(struct s_assenv *ae) { if (!ae->ilz || ae->lz==-1) { - rasm_printf(ae,"[%s] Error line %d - Cannot close LZ section as it wasn't opened\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Cannot close LZ section as it wasn't opened\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); return; } @@ -6998,7 +8431,7 @@ void __LIMIT(struct s_assenv *ae) { ___output_set_limit(ae,RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->outputadr,0,0)); ae->idx++; } else { - rasm_printf(ae,"[%s] Error line %d - LIMIT directive need one integer parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] LIMIT directive need one integer parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -7046,7 +8479,7 @@ void ___new_memory_space(struct s_assenv *ae) ae->orgzone[ae->io-1].memend=ae->outputadr; } if (ae->lz>=0) { - rasm_printf(ae,"[%s] Warning line %d - LZ section wasn't closed before a new memory space directive\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + if (!ae->nowarning) rasm_printf(ae,"[%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; @@ -7085,26 +8518,28 @@ void __BANK(struct s_assenv *ae) { 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)) { - rasm_printf(ae,"[%s] FATAL Error line %d - Bank selection must be from 0 to 31 in cartridge mode\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] 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->forcesnapshot && (ae->activebank<0 || ae->activebank>35)) { - rasm_printf(ae,"[%s] FATAL Error line %d - Bank selection must be from 0 to 35 in snapshot mode\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] FATAL - Bank selection must be from 0 to 35 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]) { - rasm_printf(ae,"[%s] Error line %d - Bank was already select by a previous BANKSET %d\n",GetCurrentFile(ae),ae->wl[ae->idx].l,(int)ae->activebank/4); + rasm_printf(ae,"[%s:%d] Cannot BANK %d was already select by a previous BANKSET %d\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->activebank,(int)ae->activebank/4); MaxError(ae); } else { ae->bankused[ae->activebank]=1; } ae->idx++; } else { - rasm_printf(ae,"[%s] Error line %d - BANK directive need one integer parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] BANK directive need one integer parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } if (ae->lz>=0) { - rasm_printf(ae,"[%s] Warning line %d - LZ section wasn't closed before a new BANK directive\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + if (!ae->nowarning) rasm_printf(ae,"[%s:%d] Warning: LZ section wasn't closed before a new BANK directive\n",GetCurrentFile(ae),ae->wl[ae->idx].l); __LZCLOSE(ae); } @@ -7126,7 +8561,7 @@ void __BANKSET(struct s_assenv *ae) { if (!ae->forcesnapshot && !ae->forcecpr) ae->forcesnapshot=1; if (!ae->forcesnapshot) { - rasm_printf(ae,"[%s] Error line %d - BANKSET directive is specific to snapshot output\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] BANKSET directive is specific to snapshot output\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); return; } @@ -7135,31 +8570,31 @@ void __BANKSET(struct s_assenv *ae) { ae->orgzone[ae->io-1].memend=ae->outputadr; } ae->bankmode=1; - if (!ae->forcecpr && !ae->forcesnapshot) ae->forcecpr=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>35)) { - rasm_printf(ae,"[%s] FATAL Error line %d - Bank set selection must be from 0 to 8 in snapshot mode\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] FATAL - Bank set selection must be from 0 to 8 in snapshot mode\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); exit(2); } /* control */ - ibank=ae->activebank/4; + ibank=ae->activebank; if (ae->bankused[ibank] || ae->bankused[ibank+1]|| ae->bankused[ibank+2]|| ae->bankused[ibank+3]) { - rasm_printf(ae,"[%s] Error line %d - Cannot BANKSET because bank was already selected in single page mode\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Cannot BANKSET because bank %d was already selected in single page mode\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ibank); MaxError(ae); } else { ae->bankset[ae->activebank/4]=1; /* pas très heureux mais bon... */ } ae->idx++; } else { - rasm_printf(ae,"[%s] Error line %d - BANKSET directive need one integer parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] BANKSET directive need one integer parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } if (ae->lz>=0) { - rasm_printf(ae,"[%s] Warning line %d - LZ section wasn't closed before a new BANKSET directive\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + if (!ae->nowarning) rasm_printf(ae,"[%s:%d] Warning: LZ section wasn't closed before a new BANKSET directive\n",GetCurrentFile(ae),ae->wl[ae->idx].l); __LZCLOSE(ae); } @@ -7181,13 +8616,13 @@ void __NameBANK(struct s_assenv *ae) { 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)) { - rasm_printf(ae,"[%s] Error line %d - Syntax is NAMEBANK ,''\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Syntax is NAMEBANK ,''\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } 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>35) { - rasm_printf(ae,"[%s] Error line %d - NAMEBANK selection must be from 0 to 31\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] NAMEBANK selection must be from 0 to 31\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } else { ae->iwnamebank[ibank]=ae->idx+2; @@ -7195,7 +8630,7 @@ void __NameBANK(struct s_assenv *ae) { } ae->idx+=2; } else { - rasm_printf(ae,"[%s] Error line %d - NAMEBANK directive need one integer parameter and a string\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] NAMEBANK directive need one integer parameter and a string\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -7231,7 +8666,7 @@ void __WRITE(struct s_assenv *ae) { __BANK(ae); ok=1; } else { - rasm_printf(ae,"[%s] Warning line %d - WRITE DIRECT lower ROM ignored (value %d out of bounds 0-7)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,lower); + if (!ae->nowarning) rasm_printf(ae,"[%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 && upper<36))) { @@ -7239,12 +8674,16 @@ void __WRITE(struct s_assenv *ae) { __BANK(ae); ok=1; } else { - rasm_printf(ae,"[%s] Warning line %d - WRITE DIRECT upper ROM ignored (value %d out of bounds 0-31)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,upper); + if (!ae->forcecpr && !ae->forcesnapshot) { + if (!ae->nowarning) rasm_printf(ae,"[%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,"[%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 { - rasm_printf(ae,"[%s] Warning line %d - meaningless WRITE DIRECT\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + if (!ae->nowarning) rasm_printf(ae,"[%s:%d] Warning: meaningless WRITE DIRECT\n",GetCurrentFile(ae),ae->wl[ae->idx].l); } } while (!ae->wl[ae->idx].t) ae->idx++; @@ -7273,7 +8712,7 @@ void __CHARSET(struct s_assenv *ae) { i++; } } else { - rasm_printf(ae,"[%s] Error line %d - CHARSET string,value has invalid quote!\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] CHARSET string,value has invalid quote!\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } else { @@ -7281,7 +8720,7 @@ void __CHARSET(struct s_assenv *ae) { if (i>=0 && i<256) { ae->charset[i]=(unsigned char)v; } else { - rasm_printf(ae,"[%s] Error line %d - CHARSET byte value must be 0-255\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] CHARSET byte value must be 0-255\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -7300,11 +8739,11 @@ void __CHARSET(struct s_assenv *ae) { ae->charset[i]=(unsigned char)v++; } } else { - rasm_printf(ae,"[%s] Error line %d - CHARSET winape directive wrong interval value\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] CHARSET winape directive wrong interval value\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } else { - rasm_printf(ae,"[%s] Error line %d - CHARSET winape directive wrong parameter count\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] CHARSET winape directive wrong parameter count\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -7324,7 +8763,7 @@ void __MACRO(struct s_assenv *ae) { } /* overload forbidden */ if (SearchMacro(ae,curmacro.crc,curmacro.mnemo)>=0) { - rasm_printf(ae,"[%s] Error line %d - Macro already defined with this name\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Macro already defined with this name\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } idx=ae->idx+2; @@ -7334,7 +8773,8 @@ void __MACRO(struct s_assenv *ae) { referentfilename=GetCurrentFile(ae); refidx=ae->idx; ae->idx=idx; - rasm_printf(ae,"[%s] Error line %d - You cannot define a macro inside another one (MACRO %s in [%s] L%d\n",GetCurrentFile(ae),ae->wl[idx].l,ae->wl[refidx+1].w,referentfilename,ae->wl[refidx].l); + rasm_printf(ae,"[%s:%d] You cannot define a macro inside another one (MACRO %s in [%s] L%d\n",GetCurrentFile(ae),ae->wl[idx].l,ae->wl[refidx+1].w,referentfilename,ae->wl[refidx].l); + FreeAssenv(ae); exit(-52); } if (getparam) { @@ -7360,7 +8800,7 @@ void __MACRO(struct s_assenv *ae) { idx++; } if (ae->wl[idx].t==2) { - rasm_printf(ae,"[%s] Error line %d - Macro was not closed\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Macro was not closed\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ObjectArrayAddDynamicValueConcat((void**)&ae->macro,&ae->imacro,&ae->mmacro,&curmacro,sizeof(curmacro)); @@ -7371,7 +8811,7 @@ void __MACRO(struct s_assenv *ae) { if (ae->wl[idx].t==2) idx--; ae->idx=idx; } else { - rasm_printf(ae,"[%s] Error line %d - MACRO definition need at least one parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] MACRO definition need at least one parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -7399,7 +8839,7 @@ struct s_wordlist *__MACRO_EXECUTE(struct s_assenv *ae, int imacro) { } if (ae->macro[imacro].nbparam && nbparam!=ae->macro[imacro].nbparam) { - rasm_printf(ae,"[%s] Error line %d - MACRO [%s] was defined with %d parameter%s\n",GetCurrentFile(ae),ae->wl[idx].l,ae->macro[imacro].mnemo,ae->macro[imacro].nbparam,ae->macro[imacro].nbparam>1?"s":""); + rasm_printf(ae,"[%s:%d] MACRO [%s] was defined with %d parameter%s\n",GetCurrentFile(ae),ae->wl[idx].l,ae->macro[imacro].mnemo,ae->macro[imacro].nbparam,ae->macro[imacro].nbparam>1?"s":""); MaxError(ae); ae->idx++; } else { @@ -7471,6 +8911,13 @@ struct s_wordlist *__MACRO_EXECUTE(struct s_assenv *ae, int imacro) { 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); @@ -7491,23 +8938,37 @@ void __LET(struct s_assenv *ae) { ExpressionFastTranslate(ae,&ae->wl[ae->idx].w,0); RoundComputeExpression(ae,ae->wl[ae->idx].w,ae->codeadr,0,0); } else { - rasm_printf(ae,"[%s] Error line %d - LET useless winape directive need one expression\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] LET useless winape directive need one expression\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } void __RUN(struct s_assenv *ae) { int mypc=0; - if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { + int ramconf=0xC0; + + if (!ae->wl[ae->idx].t) { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); mypc=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0); ae->idx++; + if (mypc<0 || mypc>65535) { + if (!ae->nowarning) rasm_printf(ae,"[%s:%d] Warning: run adress truncated from %X to %X\n",GetCurrentFile(ae),ae->wl[ae->idx].l,mypc,mypc&0xFFFF); + } + 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,"[%s:%d] Warning: ram configuration out of bound %X forced to #C0\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ramconf); + } + } } else { - rasm_printf(ae,"[%s] Error line %d - RUN winape directive need one integer parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] RUN winape directive need one integer parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ae->snapshot.registers.LPC=mypc&0xFF; ae->snapshot.registers.HPC=(mypc>>8)&0xFF; + ae->snapshot.ramconfiguration=ramconf; } void __BREAKPOINT(struct s_assenv *ae) { struct s_breakpoint breakpoint={0}; @@ -7519,7 +8980,7 @@ void __BREAKPOINT(struct s_assenv *ae) { } 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); } else { - rasm_printf(ae,"[%s] Error line %d - syntax is BREAKPOINT [adress]\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is BREAKPOINT [adress]\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -7529,30 +8990,30 @@ void __SETCPC(struct s_assenv *ae) { if (!ae->forcecpr) { ae->forcesnapshot=1; } else { - rasm_printf(ae,"[%s] Warning line %d - Cannot SETCPC when already in cartridge output\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + if (!ae->nowarning) rasm_printf(ae,"[%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: + rasm_printf(ae,"[%s:%d] SETCPC directive has wrong value (0,1,2,4,5,6 only)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); + } } else { - rasm_printf(ae,"[%s] Error line %d - SETCPC directive need one integer parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] SETCPC directive need one integer parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } - switch (mycpc) { - case 0: - case 1: - case 2: - case 4: - case 5: - case 6: - ae->snapshot.CPCType=mycpc; - break; - default: - rasm_printf(ae,"[%s] Error line %d - SETCPC directive has wrong value (0,1,2,4,5,6 only)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); - MaxError(ae); - } } void __SETCRTC(struct s_assenv *ae) { int mycrtc; @@ -7560,7 +9021,7 @@ void __SETCRTC(struct s_assenv *ae) { if (!ae->forcecpr) { ae->forcesnapshot=1; } else { - rasm_printf(ae,"[%s] Warning line %d - Cannot SETCRTC when already in cartridge output\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + if (!ae->nowarning) rasm_printf(ae,"[%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) { @@ -7568,7 +9029,7 @@ void __SETCRTC(struct s_assenv *ae) { mycrtc=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0); ae->idx++; } else { - rasm_printf(ae,"[%s] Error line %d - SETCRTC directive need one integer parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] SETCRTC directive need one integer parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } switch (mycrtc) { @@ -7580,7 +9041,7 @@ void __SETCRTC(struct s_assenv *ae) { ae->snapshot.crtcstate.model=mycrtc; break; default: - rasm_printf(ae,"[%s] Error line %d - SETCRTC directive has wrong value (0,1,2,3,4 only)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] SETCRTC directive has wrong value (0,1,2,3,4 only)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -7588,30 +9049,26 @@ void __SETCRTC(struct s_assenv *ae) { void __LIST(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { - rasm_printf(ae,"[%s] Error line %d - LIST winape directive do not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] LIST winape directive do not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } void __NOLIST(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { - rasm_printf(ae,"[%s] Error line %d - NOLIST winape directive do not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] NOLIST winape directive do not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } void __BRK(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { - rasm_printf(ae,"[%s] Error line %d - BRK winape directive do not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] BRK winape directive do not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } void __STOP(struct s_assenv *ae) { - if (!ae->wl[ae->idx].t) { - rasm_printf(ae,"[%s] Error line %d - STOP winape directive do not need parameter. Anyway, STOP assembling...\n",GetCurrentFile(ae),ae->wl[ae->idx].l); - MaxError(ae); - } - rasm_printf(ae,"stop assembling\n"); + 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; @@ -7699,40 +9156,82 @@ void __PRINT(struct s_assenv *ae) { } MemFree(string2print); } else { - int lm; + char *varbuffer; + int lm,touched; lm=strlen(ae->wl[ae->idx+1].w)-2; - if (lm) rasm_printf(ae,"%-*.*s ",lm,lm,ae->wl[ae->idx+1].w+1); + 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; + int aval,ifill=-1; if (ae->io) { ae->orgzone[ae->io-1].memend=ae->outputadr; } - if (ae->wl[ae->idx+1].t!=2) { + 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) { + rasm_printf(ae,"[%s:%d] ALIGN fill value must be 0 to 255\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); + ifill=0; + } + } if (aval<1 || aval>65535) { - rasm_printf(ae,"[%s] Error line %d - ALIGN directive need one integer\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] ALIGN boundary must be greater than zero and lower than 65536\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); aval=1; } - /* touch codeadr only if adress is misaligned */ + /* touch codeadr only if adress is misaligned */ if (ae->codeadr%aval) { - /* move outputadr the same value as codeadr move */ - ae->outputadr=ae->outputadr-(ae->codeadr%aval)+aval; - ae->codeadr=ae->codeadr-(ae->codeadr%aval)+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); + } + } } } else { - rasm_printf(ae,"[%s] Error line %d - ALIGN directive need one integer parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] ALIGN [,fill] directive need one or two integers parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -7754,32 +9253,37 @@ void ___internal_skip_loop_block(struct s_assenv *ae, int eloopstyle) { } else if (ae->wl[cidx+1].t) { IntArrayAddDynamicValueConcat(&loopstyle,&iloop,&mloop,E_LOOPSTYLE_REPEATN); } else { - rasm_printf(ae,"[%s] FATAL Error line %d - Invalid REPEAT syntax\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] FATAL - Invalid REPEAT syntax\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); exit(7); } } 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 { - rasm_printf(ae,"[%s] FATAL Error line %d - Invalid WHILE syntax\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] FATAL - Invalid WHILE syntax\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); exit(7); } } else if (strcmp(ae->wl[cidx].w,"WEND")==0) { iloop--; if (loopstyle[iloop]!=E_LOOPSTYLE_WHILE) { - rasm_printf(ae,"[%s] FATAL Error line %d - WEND encountered but expecting %s\n",GetCurrentFile(ae),ae->wl[ae->idx].l,loopstyle[iloop]==E_LOOPSTYLE_REPEATN?"REND":"UNTIL"); + rasm_printf(ae,"[%s:%d] FATAL - WEND encountered but expecting %s\n",GetCurrentFile(ae),ae->wl[ae->idx].l,loopstyle[iloop]==E_LOOPSTYLE_REPEATN?"REND":"UNTIL"); + FreeAssenv(ae); exit(7); } } else if (strcmp(ae->wl[cidx].w,"REND")==0) { iloop--; if (loopstyle[iloop]!=E_LOOPSTYLE_REPEATN) { - rasm_printf(ae,"[%s] FATAL Error line %d - REND encountered but expecting %s\n",GetCurrentFile(ae),ae->wl[ae->idx].l,loopstyle[iloop]==E_LOOPSTYLE_REPEATUNTIL?"UNTIL":"WEND"); + rasm_printf(ae,"[%s:%d] FATAL - REND encountered but expecting %s\n",GetCurrentFile(ae),ae->wl[ae->idx].l,loopstyle[iloop]==E_LOOPSTYLE_REPEATUNTIL?"UNTIL":"WEND"); + FreeAssenv(ae); exit(7); } } else if (strcmp(ae->wl[cidx].w,"UNTIL")==0) { iloop--; if (loopstyle[iloop]!=E_LOOPSTYLE_REPEATUNTIL) { - rasm_printf(ae,"[%s] FATAL Error line %d - UNTIL encountered but expecting %s\n",GetCurrentFile(ae),ae->wl[ae->idx].l,loopstyle[iloop]==E_LOOPSTYLE_REPEATN?"REND":"WEND"); + rasm_printf(ae,"[%s:%d] FATAL - UNTIL encountered but expecting %s\n",GetCurrentFile(ae),ae->wl[ae->idx].l,loopstyle[iloop]==E_LOOPSTYLE_REPEATN?"REND":"WEND"); + FreeAssenv(ae); exit(7); } } @@ -7813,7 +9317,7 @@ void __WHILE(struct s_assenv *ae) { ObjectArrayAddDynamicValueConcat((void**)&ae->whilewend,&ae->iw,&ae->mw,&whilewend,sizeof(whilewend)); } } else { - rasm_printf(ae,"[%s] Error line %d - syntax is WHILE \n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] syntax is WHILE \n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -7823,7 +9327,7 @@ void __WEND(struct s_assenv *ae) { //ExpressionFastTranslate(ae,&ae->wl[ae->whilewend[ae->iw-1].start].w,0); //TOTEST §§§ 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) { - rasm_printf(ae,"[%s] Error line %d - Bypass infinite WHILE loop\n",GetExpFile(ae,0),GetExpLine(ae,0)); + rasm_printf(ae,"[%s:%d] Bypass infinite WHILE loop\n",GetExpFile(ae,0),GetExpLine(ae,0)); MaxError(ae); ae->iw--; /* refresh macro check index */ @@ -7841,20 +9345,21 @@ void __WEND(struct s_assenv *ae) { if (ae->iw) ae->imacropos=ae->whilewend[ae->iw-1].maxim; } } else { - rasm_printf(ae,"[%s] Error line %d, WEND does not need any parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] WEND does not need any parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } else { - rasm_printf(ae,"[%s] Error line %d, WEND encounter whereas there is no referent WHILE\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] WEND encounter whereas there is no referent WHILE\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } void __REPEAT(struct s_assenv *ae) { struct s_repeat currepeat={0}; + struct s_expr_dico *rvar; int *loopstyle; int iloop,mloop; - int cidx; + int cidx,crc; if (ae->wl[ae->idx+1].t!=2) { if (ae->wl[ae->idx].t==0) { @@ -7865,11 +9370,30 @@ void __REPEAT(struct s_assenv *ae) { ___internal_skip_loop_block(ae,E_LOOPSTYLE_REPEATN); return; } else if (currepeat.cpt<1 || currepeat.cpt>65536) { - rasm_printf(ae,"[%s] Error line %d - Repeat value (%d) must be from 1 to 65535\n",GetCurrentFile(ae),ae->wl[ae->idx].l,currepeat.cpt); + rasm_printf(ae,"[%s:%d] Repeat value (%d) must be from 1 to 65535\n",GetCurrentFile(ae),ae->wl[ae->idx].l,currepeat.cpt); + FreeAssenv(ae); exit(2); } 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 { + rasm_printf(ae,"[%s:%d] extended syntax is REPEAT ,\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); + } + } } else { currepeat.start=ae->idx; currepeat.cpt=-1; @@ -7883,19 +9407,23 @@ void __REPEAT(struct s_assenv *ae) { if (ae->imacropos>currepeat.maxim) currepeat.maxim=ae->imacropos; ObjectArrayAddDynamicValueConcat((void**)&ae->repeat,&ae->ir,&ae->mr,&currepeat,sizeof(currepeat)); } else { - rasm_printf(ae,"[%s] Error line %d - wrong REPEAT usage\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] wrong REPEAT usage\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } void __REND(struct s_assenv *ae) { + struct s_expr_dico *rvar; if (ae->ir>0) { if (ae->repeat[ae->ir-1].cpt==-1) { - rasm_printf(ae,"[%s] Error line %d, REND encounter whereas referent REPEAT was waiting for UNTIL\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] REND encounter whereas referent REPEAT was waiting for UNTIL\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } 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 */ @@ -7907,7 +9435,7 @@ void __REND(struct s_assenv *ae) { } } } else { - rasm_printf(ae,"[%s] Error line %d, REND encounter whereas there is no referent REPEAT\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] REND encounter whereas there is no referent REPEAT\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -7915,7 +9443,7 @@ void __REND(struct s_assenv *ae) { void __UNTIL(struct s_assenv *ae) { if (ae->ir>0) { if (ae->repeat[ae->ir-1].cpt>=0) { - rasm_printf(ae,"[%s] Error line %d, UNTIL encounter whereas referent REPEAT n was waiting for REND\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] UNTIL encounter whereas referent REPEAT n was waiting for REND\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } else { if (ae->wl[ae->idx].t==0 && ae->wl[ae->idx+1].t==1) { @@ -7923,7 +9451,7 @@ void __UNTIL(struct s_assenv *ae) { 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) { - rasm_printf(ae,"[%s] Error line %d - Bypass infinite REPEAT loop\n",GetExpFile(ae,0),GetExpLine(ae,0)); + rasm_printf(ae,"[%s:%d] Bypass infinite REPEAT loop\n",GetExpFile(ae,0),GetExpLine(ae,0)); MaxError(ae); ae->ir--; /* refresh macro check index */ @@ -7940,50 +9468,148 @@ void __UNTIL(struct s_assenv *ae) { if (ae->ir) ae->imacropos=ae->repeat[ae->ir-1].maxim; } } else { - rasm_printf(ae,"[%s] Error line %d, UNTIL need one expression/evaluation as parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] UNTIL need one expression/evaluation as parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } } else { - rasm_printf(ae,"[%s] Error line %d, UNTIL encounter whereas there is no referent REPEAT\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] UNTIL encounter whereas there is no referent REPEAT\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } void __ASSERT(struct s_assenv *ae) { + char Dot3[4]; int rexpr; - if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { + 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) { - rasm_printf(ae,"[%s] Error line %d, ASSERT failed!\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] ASSERT %.29s%s failed with ",GetCurrentFile(ae),ae->wl[ae->idx].l,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); + MaxError(ae); + if (!ae->wl[ae->idx+1].t) { + ae->idx++; + rasm_printf(ae,"-> "); + __PRINT(ae); + } __STOP(ae); } else { - ae->idx++; + while (!ae->wl[ae->idx].t) ae->idx++; } } else { - rasm_printf(ae,"[%s] Error line %d, ASSERT need one expression\n",GetCurrentFile(ae),ae->wl[ae->idx].l); - exit(2); + rasm_printf(ae,"[%s:%d] ASSERT need one expression\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); } } 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); - IntArrayAddDynamicValueConcat(&ae->ifthen,&ae->ii,&ae->mi,rexpr); + 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)); + //IntArrayAddDynamicValueConcat(&ae->ifthen,&ae->ii,&ae->mi,rexpr); + ae->idx++; + } else { + rasm_printf(ae,"[%s:%d] IF need one expression\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); + exit(2); + } +} + +void __IF_light(struct s_assenv *ae) { + struct s_ifthen ifthen={0}; + int rexpr; + + 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)); + //IntArrayAddDynamicValueConcat(&ae->ifthen,&ae->ii,&ae->mi,rexpr); + ae->idx++; + } else { + rasm_printf(ae,"[%s:%d] IF need one expression\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); + exit(2); + } +} + +/* 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)); + //IntArrayAddDynamicValueConcat(&ae->ifthen,&ae->ii,&ae->mi,rexpr); + ae->idx++; + } else { + rasm_printf(ae,"[%s:%d] FATAL - IFUSED need one variable or label\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); + exit(2); + } +} +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)); + //IntArrayAddDynamicValueConcat(&ae->ifthen,&ae->ii,&ae->mi,rexpr); ae->idx++; } else { - rasm_printf(ae,"[%s] Error line %d, IF need one expression\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] FATAL - IFUSED need one variable or label\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); exit(2); } } +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) { @@ -8001,16 +9627,40 @@ void __IFDEF(struct s_assenv *ae) { } } } - IntArrayAddDynamicValueConcat(&ae->ifthen,&ae->ii,&ae->mi,rexpr); + 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)); + //IntArrayAddDynamicValueConcat(&ae->ifthen,&ae->ii,&ae->mi,rexpr); + ae->idx++; + } else { + rasm_printf(ae,"[%s:%d] FATAL - IFDEF need one variable or label\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); + exit(2); + } +} +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)); + //IntArrayAddDynamicValueConcat(&ae->ifthen,&ae->ii,&ae->mi,rexpr); ae->idx++; } else { - rasm_printf(ae,"[%s] FATAL Error line %d, IFDEF need one variable or label\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] FATAL - IFDEF need one variable or label\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); exit(2); } } 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) { @@ -8028,14 +9678,54 @@ void __IFNDEF(struct s_assenv *ae) { } } } - IntArrayAddDynamicValueConcat(&ae->ifthen,&ae->ii,&ae->mi,rexpr); + 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)); + //IntArrayAddDynamicValueConcat(&ae->ifthen,&ae->ii,&ae->mi,rexpr); + ae->idx++; + } else { + rasm_printf(ae,"[%s:%d] FATAL - IFNDEF need one variable or label\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); + exit(2); + } +} +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)); + //IntArrayAddDynamicValueConcat(&ae->ifthen,&ae->ii,&ae->mi,rexpr); ae->idx++; } else { - rasm_printf(ae,"[%s] FATAL Error line %d, IFNDEF need one variable or label\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] FATAL - IFNDEF need one variable or label\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); exit(2); } } +void __UNDEF(struct s_assenv *ae) { + + if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { + if (!DelDico(ae,ae->wl[ae->idx+1].w,GetCRC(ae->wl[ae->idx+1].w))) { + rasm_printf(ae,"[%s:%d] variable to UNDEF not found!\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); + } + ae->idx++; + } else { + rasm_printf(ae,"[%s:%d] syntax is UNDEF \n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); + } + +} + void __SWITCH(struct s_assenv *ae) { struct s_switchcase curswitch={0}; @@ -8047,7 +9737,8 @@ void __SWITCH(struct s_assenv *ae) { ObjectArrayAddDynamicValueConcat((void**)&ae->switchcase,&ae->isw,&ae->msw,&curswitch,sizeof(curswitch)); ae->idx++; } else { - rasm_printf(ae,"[%s] Error line %d, SWITCH need one expression\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] SWITCH need one expression\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); exit(2); } } @@ -8064,11 +9755,11 @@ void __CASE(struct s_assenv *ae) { ae->switchcase[ae->isw-1].casematch=1; } } else { - rasm_printf(ae,"[%s] Error line %d, CASE not need one parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] CASE not need one parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } else { - rasm_printf(ae,"[%s] Error line %d, CASE encounter whereas there is no referent SWITCH\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] CASE encounter whereas there is no referent SWITCH\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -8081,11 +9772,11 @@ void __DEFAULT(struct s_assenv *ae) { ae->switchcase[ae->isw-1].execute=1; } } else { - rasm_printf(ae,"[%s] Error line %d, DEFAULT do not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] DEFAULT do not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } else { - rasm_printf(ae,"[%s] Error line %d, DEFAULT encounter whereas there is no referent SWITCH\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] DEFAULT encounter whereas there is no referent SWITCH\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -8095,11 +9786,53 @@ void __BREAK(struct s_assenv *ae) { if (ae->wl[ae->idx].t==1) { ae->switchcase[ae->isw-1].execute=0; } else { - rasm_printf(ae,"[%s] Error line %d, BREAK do not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] BREAK do not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } else { - rasm_printf(ae,"[%s] Error line %d, BREAK encounter whereas there is no referent SWITCH\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] BREAK encounter whereas there is no referent SWITCH\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); + } +} +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 { + rasm_printf(ae,"[%s:%d] SWITCH need one expression\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); + exit(2); + } +} +void __CASE_light(struct s_assenv *ae) { + int rexpr; + + if (ae->isw) { + /* shadowed execution */ + } else { + rasm_printf(ae,"[%s:%d] CASE encounter whereas there is no referent SWITCH\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); + } +} +void __DEFAULT_light(struct s_assenv *ae) { + + if (ae->isw) { + /* shadowed execution */ + } else { + rasm_printf(ae,"[%s:%d] DEFAULT encounter whereas there is no referent SWITCH\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); + } +} +void __BREAK_light(struct s_assenv *ae) { + if (ae->isw) { + /* shadowed execution */ + } else { + rasm_printf(ae,"[%s:%d] BREAK encounter whereas there is no referent SWITCH\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -8108,25 +9841,49 @@ void __ENDSWITCH(struct s_assenv *ae) { if (ae->wl[ae->idx].t==1) { ae->isw--; } else { - rasm_printf(ae,"[%s] Error line %d, ENDSWITCH does not need any parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] ENDSWITCH does not need any parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } else { - rasm_printf(ae,"[%s] Error line %d, ENDSWITCH encounter whereas there is no referent SWITCH\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] ENDSWITCH encounter whereas there is no referent SWITCH\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } 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); - IntArrayAddDynamicValueConcat(&ae->ifthen,&ae->ii,&ae->mi,rexpr); + 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 { + rasm_printf(ae,"[%s:%d] IFNOT need one expression\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); + exit(2); + } +} +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 { - rasm_printf(ae,"[%s] Error line %d, IFNOT need one expression\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] IFNOT need one expression\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); exit(2); } } @@ -8135,33 +9892,59 @@ 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]) { + switch (ae->ifthen[ae->ii-1].v) { case -1:break; - case 0:ae->ifthen[ae->ii-1]=1;break; - case 1:ae->ifthen[ae->ii-1]=0;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 { - rasm_printf(ae,"[%s] Error line %d, ELSE does not need any parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] ELSE does not need any parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } else { - rasm_printf(ae,"[%s] Error line %d, ELSE encounter whereas there is no referent IF\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] ELSE encounter whereas there is no referent IF\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } void __ELSEIF(struct s_assenv *ae) { if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) { - if (ae->ifthen[ae->ii-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]=-1; + ae->ifthen[ae->ii-1].v=-1; } else { ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0); - ae->ifthen[ae->ii-1]=!!RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,1); + ae->ifthen[ae->ii-1].v=!!RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,1); + } + ae->idx++; + } else { + rasm_printf(ae,"[%s:%d] ELSEIF need one expression\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); + exit(2); + } +} +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 { - rasm_printf(ae,"[%s] Error line %d, ELSEIF need one expression\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] ELSEIF need one expression\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); exit(2); } } @@ -8170,11 +9953,11 @@ void __ENDIF(struct s_assenv *ae) { if (ae->wl[ae->idx].t==1) { ae->ii--; } else { - rasm_printf(ae,"[%s] Error line %d, ENDIF does not need any parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] ENDIF does not need any parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } else { - rasm_printf(ae,"[%s] Error line %d, ENDIF encounter whereas there is no referent IF\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] ENDIF encounter whereas there is no referent IF\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -8196,14 +9979,15 @@ void __PROTECT(struct s_assenv *ae) { ae->orgzone[ae->io-1]=orgzone; } else { - rasm_printf(ae,"[%s] Error line %d, PROTECT need two parameters: startadr,endadr\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] PROTECT need two parameters: startadr,endadr\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } void ___org_close(struct s_assenv *ae) { if (ae->lz>=0) { - rasm_printf(ae,"[%s] Error line %d - Cannot ORG inside a LZ section\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Cannot ORG inside a LZ section\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); exit(-5); } __internal_UpdateLZBlockIfAny(ae); @@ -8224,9 +10008,9 @@ void ___org_new(struct s_assenv *ae, int nocode) { if (ae->orgzone[i].ibank==ae->activebank) { if (ae->outputadrorgzone[i].memend && ae->outputadr>=ae->orgzone[i].memstart) { if (ae->orgzone[i].protect) { - rasm_printf(ae,"[%s] Error line %d - ORG located a PROTECTED section [#%04X-#%04X-B%d] file [%s] line %d\n",GetCurrentFile(ae),ae->wl[ae->idx].l,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); + rasm_printf(ae,"[%s:%d] ORG located a PROTECTED section [#%04X-#%04X-B%d] file [%s] line %d\n",GetCurrentFile(ae),ae->wl[ae->idx].l,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 { - rasm_printf(ae,"[%s] Error line %d - ORG (output at #%04X) located in a previous ORG section [#%04X-#%04X-B%d] file [%s] line %d\n",GetCurrentFile(ae),ae->wl[ae->idx].l,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); + rasm_printf(ae,"[%s:%d] ORG (output at #%04X) located in a previous ORG section [#%04X-#%04X-B%d] file [%s] line %d\n",GetCurrentFile(ae),ae->wl[ae->idx].l,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); } MaxError(ae); } @@ -8269,7 +10053,7 @@ void __ORG(struct s_assenv *ae) { ae->idx++; } } else { - rasm_printf(ae,"[%s] Error line %d - ORG code location[,output location]\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] ORG code location[,output location]\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); return; } @@ -8281,7 +10065,7 @@ void __NOCODE(struct s_assenv *ae) { ___org_close(ae); ___org_new(ae,1); } else { - rasm_printf(ae,"[%s] Error line %d - NOCODE directive does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] NOCODE directive does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -8290,7 +10074,7 @@ void __CODE(struct s_assenv *ae) { ___org_close(ae); ___org_new(ae,0); } else { - rasm_printf(ae,"[%s] Error line %d - CODE directive does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] CODE directive does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -8310,7 +10094,7 @@ void __STRUCT(struct s_assenv *ae) { /* 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) { - rasm_printf(ae,"[%s] Error line %d - STRUCT name must be different from existing labels ou aliases\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] STRUCT name must be different from existing labels ou aliases\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } else { ae->backup_filename=GetCurrentFile(ae); @@ -8329,7 +10113,7 @@ void __STRUCT(struct s_assenv *ae) { ae->idx++; } } else { - rasm_printf(ae,"[%s] Error line %d - STRUCT cannot be declared inside previous opened STRUCT [%s] Line %d\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->backup_filename,ae->backup_line); + rasm_printf(ae,"[%s:%d] STRUCT cannot be declared inside previous opened STRUCT [%s] Line %d\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->backup_filename,ae->backup_line); MaxError(ae); } } else { @@ -8343,7 +10127,7 @@ void __STRUCT(struct s_assenv *ae) { if (ae->rasmstruct[irs].crc==crc && strcmp(ae->rasmstruct[irs].name,ae->wl[ae->idx+1].w)==0) break; } if (irs==ae->irasmstruct) { - rasm_printf(ae,"[%s] Error line %d - Unknown STRUCT %s\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->wl[ae->idx+1].w); + rasm_printf(ae,"[%s:%d] Unknown STRUCT %s\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->wl[ae->idx+1].w); MaxError(ae); } else { /* create alias for sizeof */ @@ -8372,7 +10156,7 @@ void __STRUCT(struct s_assenv *ae) { } else { /* or check for non-local name in struct declaration */ if (ae->wl[ae->idx+2].w[0]=='@') { - rasm_printf(ae,"[%s] Error line %d - Meaningless use of local label in a STRUCT definition\n",GetExpFile(ae,0),GetExpLine(ae,0)); + rasm_printf(ae,"[%s:%d] Meaningless use of local label in a STRUCT definition\n",GetExpFile(ae,0),GetExpLine(ae,0)); MaxError(ae); } else { curlabel.name=TxtStrDup(rasmstructalias.name); @@ -8424,106 +10208,418 @@ void __STRUCT(struct s_assenv *ae) { ae->idx+=2; } } - } else { - rasm_printf(ae,"[%s] Error line %d - STRUCT directive needs one or two parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + } else { + rasm_printf(ae,"[%s:%d] STRUCT directive needs one or two parameters\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); + } +} +void __ENDSTRUCT(struct s_assenv *ae) { + struct s_label curlabel={0},*searched_label; + + if (!ae->wl[ae->idx].t) { + rasm_printf(ae,"[%s:%d] ENDSTRUCT directive does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); + } else { + if (ae->getstruct) { + ae->rasmstruct[ae->irasmstruct-1].size=ae->codeadr; + ae->getstruct=0; + + 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; + + /* PushLabel light - sizeof like Vasm with struct name */ + PushLabelLight(ae,&curlabel); + + /* like there was no byte */ + ae->outputadr=ae->backup_outputadr; + ae->codeadr=ae->backup_codeadr; + ___org_close(ae); + ___org_new(ae,0); + } else { + rasm_printf(ae,"[%s:%d] ENDSTRUCT encountered outside STRUCT declaration\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); + } + } +} + +void __MEMSPACE(struct s_assenv *ae) { + if (ae->wl[ae->idx].t) { + ___new_memory_space(ae); + } else { + rasm_printf(ae,"[%s:%d] MEMSPACE directive does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); + } +} + +int (*_internal_getsample)(unsigned char *data, int *idx); +#undef FUNC +#define FUNC "_internal_AudioGetSampleValue" + +int __internal_getsample8(unsigned char *data, int *idx) { + return data[*idx++]+0x80; +} +int __internal_getsample16little(unsigned char *data, int *idx) { + int cursample; + cursample=data[*idx+1]+0x80;*idx+=2; + return cursample; +} +int __internal_getsample24little(unsigned char *data, int *idx) { + int cursample; + cursample=data[*idx+2+0x80];*idx+=3; + return cursample; +} +/* big-endian */ +int __internal_getsample16big(unsigned char *data, int *idx) { + int cursample; + cursample=data[*idx]+0x80;*idx+=2; + return cursample; +} +int __internal_getsample24big(unsigned char *data, int *idx) { + int cursample; + cursample=data[*idx]+0x80;*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+=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+=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; + + wav_header=(struct s_wav_header *)data; + + if (strncmp(wav_header->ChunkID,"RIFF",4)) { + if (strncmp(wav_header->ChunkID,"RIFX",4)) { + rasm_printf(ae,"[%s:%d] WAV import - unsupported audio sample type (chunkid must be 'RIFF' or 'RIFX')\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); + return; + } else { + bigendian=1; + } + } + if (strncmp(wav_header->Format,"WAVE",4)) { + rasm_printf(ae,"[%s:%d] WAV import - unsupported audio sample type (format must be 'WAVE')\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); + return; } -} -void __ENDSTRUCT(struct s_assenv *ae) { - struct s_label curlabel={0},*searched_label; - - if (!ae->wl[ae->idx].t) { - rasm_printf(ae,"[%s] Error line %d - ENDSTRUCT directive does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + controlsize=wav_header->SubChunk1Size[0]+wav_header->SubChunk1Size[1]*256+wav_header->SubChunk1Size[2]*65536+wav_header->SubChunk1Size[3]*256*65536; + if (controlsize!=16) { + rasm_printf(ae,"[%s:%d] WAV import - invalid wav chunk size (subchunk1 control)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); - } else { - if (ae->getstruct) { - ae->rasmstruct[ae->irasmstruct-1].size=ae->codeadr; - ae->getstruct=0; - - 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; + return; + } + if (strncmp(wav_header->SubChunk1ID,"fmt",3)) { + rasm_printf(ae,"[%s:%d] WAV import - unsupported audio sample type (subchunk1id must be 'fmt')\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); + return; + } - /* PushLabel light - sizeof like Vasm with struct name */ - PushLabelLight(ae,&curlabel); - - /* like there was no byte */ - ae->outputadr=ae->backup_outputadr; - ae->codeadr=ae->backup_codeadr; - ___org_close(ae); - ___org_new(ae,0); - } else { - rasm_printf(ae,"[%s] Error line %d - ENDSTRUCT encountered outside STRUCT declaration\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + 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) { + rasm_printf(ae,"[%s:%d] WAV import - data subchunk not found\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); + return; } + subchunk+=subchunksize; } -} + subchunksize=8+subchunk[4]+subchunk[5]*256+subchunk[6]*65536+subchunk[7]*256*65536; + controlsize=subchunksize; + subchunk+=8; -void __MEMSPACE(struct s_assenv *ae) { - if (ae->wl[ae->idx].t) { - ___new_memory_space(ae); - } else { - rasm_printf(ae,"[%s] Error line %d - MEMSPACE directive does not need parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + nbchannel=wav_header->NumChannels[0]+wav_header->NumChannels[1]*256; + if (nbchannel<1) { + rasm_printf(ae,"[%s:%d] WAV import - invalid number of audio channel\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); + return; + } + bitspersample=wav_header->BitsPerSample[0]+wav_header->BitsPerSample[1]*256; + 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: + rasm_printf(ae,"[%s:%d] WAV import - unsupported bits per sample (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,bitspersample); + MaxError(ae); + return; } -} + nbsample=controlsize/nbchannel/(bitspersample/8); + //rasm_printf(ae,"@@DBG nbsample=%d (sze=%d,chn=%d,bps=%d) st=%c\n",nbsample,controlsize,nbchannel,bitspersample,sample_type); + + idx=subchunk-data; + switch (sample_type) { + default: + case AUDIOSAMPLE_SMP: + for (i=0;ipsgfine[cursample]; + + /* output */ + ___output(ae,samplevalue); + } + break; + case AUDIOSAMPLE_SM2: + 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 + ***/ + 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,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; - unsigned int offset=0,idx; - int size=0; + int hbinidx,overwritecheck=1,crc; + struct s_expr_dico *rvar; + unsigned int idx; + int size=0,offset=0; + float normalize; 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 (!ae->wl[ae->idx+1].t) { - ExpressionFastTranslate(ae,&ae->wl[ae->idx+2].w,1); - offset=RoundComputeExpressionCore(ae,ae->wl[ae->idx+2].w,ae->codeadr,0); - if (!ae->wl[ae->idx+2].t) { - ExpressionFastTranslate(ae,&ae->wl[ae->idx+3].w,1); - size=RoundComputeExpressionCore(ae,ae->wl[ae->idx+3].w,ae->codeadr,0); - if (size<-65535 || size>65536) { - rasm_printf(ae,"[%s] Error line %d - INCBIN invalid size\n",GetCurrentFile(ae),ae->wl[ae->idx].l); - MaxError(ae); - } - if (size==0) { - /* rien */ - } - if (!ae->wl[ae->idx+3].t) { - ExpressionFastTranslate(ae,&ae->wl[ae->idx+4].w,1); - offset+=65536*RoundComputeExpressionCore(ae,ae->wl[ae->idx+4].w,ae->codeadr,0); - if (!ae->wl[ae->idx+4].t) { - if (strcmp(ae->wl[ae->idx+5].w,"OFF")==0) { - overwritecheck=0; + /* SMP,SM2,SM4,DMA */ + 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]) { + switch (ae->wl[ae->idx+2].w[2]) { + case 'P':_AudioLoadSample(ae,ae->hexbin[hbinidx].data,ae->hexbin[hbinidx].datalen, AUDIOSAMPLE_SMP,1.0);break; + case '2':_AudioLoadSample(ae,ae->hexbin[hbinidx].data,ae->hexbin[hbinidx].datalen, AUDIOSAMPLE_SM2,1.0);break; + case '4':_AudioLoadSample(ae,ae->hexbin[hbinidx].data,ae->hexbin[hbinidx].datalen, AUDIOSAMPLE_SM4,1.0);break; + case 'A':_AudioLoadSample(ae,ae->hexbin[hbinidx].data,ae->hexbin[hbinidx].datalen, AUDIOSAMPLE_DMA,1.0);break; + default:printf("warning remover\n");break; + } + ae->idx+=2; + return; + } else { + /* legacy binary file */ + ExpressionFastTranslate(ae,&ae->wl[ae->idx+2].w,1); + offset=RoundComputeExpressionCore(ae,ae->wl[ae->idx+2].w,ae->codeadr,0); + if (!ae->wl[ae->idx+2].t) { + if (ae->wl[ae->idx+3].w[0]) { + ExpressionFastTranslate(ae,&ae->wl[ae->idx+3].w,1); + size=RoundComputeExpressionCore(ae,ae->wl[ae->idx+3].w,ae->codeadr,0); + } else { + size=0; + } + if (size<-65535 || size>65536) { + rasm_printf(ae,"[%s:%d] INCBIN invalid size\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); + } + if (!ae->wl[ae->idx+3].t) { + if (ae->wl[ae->idx+4].w[0]) { + ExpressionFastTranslate(ae,&ae->wl[ae->idx+4].w,1); + offset+=65536*RoundComputeExpressionCore(ae,ae->wl[ae->idx+4].w,ae->codeadr,0); + } + 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; + } else if (ae->wl[ae->idx+5].w[0]) { + rasm_printf(ae,"[%s:%d] INCBIN invalid overwrite value. Must be 'OFF' or 'ON'\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + MaxError(ae); + } + 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 { - rasm_printf(ae,"[%s] Error line %d - INCBIN invalid overwrite value. Must be 'OFF' or nothing\n",GetCurrentFile(ae),ae->wl[ae->idx].l); - MaxError(ae); + ae->idx+=4; } - ae->idx+=5; } else { - ae->idx+=4; + ae->idx+=3; } } else { - ae->idx+=3; + ae->idx+=2; } - } else { - ae->idx+=2; } } else { ae->idx++; } if (ae->hexbin[hbinidx].datalen<0) { - rasm_printf(ae,"[%s] Error line %d - file not found [%s]\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->hexbin[hbinidx].filename); + rasm_printf(ae,"[%s:%d] file not found [%s]\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->hexbin[hbinidx].filename); MaxError(ae); } else { if (hbinidxih && hbinidx>=0) { if (size<0) { size=ae->hexbin[hbinidx].datalen-size; if (size<1) { - rasm_printf(ae,"[%s] Error line %d - INCBIN negative size is greater or equal to filesize\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] INCBIN negative size is greater or equal to filesize\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } @@ -8539,11 +10635,11 @@ void __HEXBIN(struct s_assenv *ae) { } } if (size>ae->hexbin[hbinidx].datalen) { - rasm_printf(ae,"[%s] Error line %d - INCBIN size is greater than filesize\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] INCBIN size is greater than filesize\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } else { if (size+offset>ae->hexbin[hbinidx].datalen) { - rasm_printf(ae,"[%s] Error line %d - INCBIN size+offset is greater than filesize\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] INCBIN size+offset is greater than filesize\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } else { if (overwritecheck) { @@ -8564,12 +10660,13 @@ void __HEXBIN(struct s_assenv *ae) { } } } else { - rasm_printf(ae,"[%s] INTERNAL error line %d - HEXBIN refer to unknown structure\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] INTERNAL - HEXBIN refer to unknown structure\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } } else { - rasm_printf(ae,"[%s] INTERNAL error line %d - HEXBIN need one HEX parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] INTERNAL - HEXBIN need one HEX parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + FreeAssenv(ae); exit(2); } } @@ -8590,7 +10687,7 @@ void __SAVE(struct s_assenv *ae) { if (!ae->wl[ae->idx].t) { /* nom de fichier entre quotes ou bien mot clef DSK */ if (!StringIsQuote(ae->wl[ae->idx+1].w)) { - rasm_printf(ae,"[%s] Error line %d - SAVE invalid filename quote\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] SAVE invalid filename quote\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); ko=0; } else { @@ -8627,12 +10724,12 @@ void __SAVE(struct s_assenv *ae) { cursave.face=ae->save[ae->nbsave-1].face; /* previous face */ } else { cursave.iwdskname=-1; - rasm_printf(ae,"[%s] Error line %d - cannot autoselect DSK as there was not a previous selection\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] cannot autoselect DSK as there was not a previous selection\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } } } else { - rasm_printf(ae,"[%s] Error line %d - SAVE 4th parameter must be empty or AMSDOS or DSK\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] SAVE 4th parameter must be empty or AMSDOS or DSK\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); ko=0; } @@ -8644,7 +10741,7 @@ void __SAVE(struct s_assenv *ae) { } } if (ko) { - rasm_printf(ae,"[%s] Error line %d - Use SAVE 'filename',offset,size[,AMSDOS|DSK[,A|B|'dskname'[,A|B]]]\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] Use SAVE 'filename',offset,size[,AMSDOS|DSK[,A|B|'dskname'[,A|B]]]\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } @@ -8660,7 +10757,7 @@ void __MODULE(struct s_assenv *ae) { strcpy(ae->module,ae->wl[ae->idx+1].w+1); ae->module[strlen(ae->module)-1]=0; } else { - rasm_printf(ae,"[%s] Error line %d - MODULE directive need one text parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + rasm_printf(ae,"[%s:%d] MODULE directive need one text parameter\n",GetCurrentFile(ae),ae->wl[ae->idx].l); MaxError(ae); } ae->idx++; @@ -8670,7 +10767,6 @@ void __MODULE(struct s_assenv *ae) { } } - struct s_asm_keyword instruction[]={ {"LD",0,_LD}, {"DEC",0,_DEC}, @@ -8769,6 +10865,9 @@ struct s_asm_keyword instruction[]={ {"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}, @@ -8789,6 +10888,7 @@ struct s_asm_keyword instruction[]={ {"LIST",0,__LIST}, {"STOP",0,__STOP}, {"PRINT",0,__PRINT}, +{"FAIL",0,__FAIL}, {"BREAKPOINT",0,__BREAKPOINT}, {"BANK",0,__BANK}, {"BANKSET",0,__BANKSET}, @@ -8852,12 +10952,12 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) orgzone.ibank=36; 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['<']='<'; @@ -8875,32 +10975,34 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) 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 '*':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_MUL;ae->AutomateElement[i].priority=1;break; - case '/':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_DIV;ae->AutomateElement[i].priority=1;break; - case 'm':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_MOD;ae->AutomateElement[i].priority=1;break; + 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_ADD;ae->AutomateElement[i].priority=2;break; - case '-':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_SUB;ae->AutomateElement[i].priority=2;break; + 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_SHL;ae->AutomateElement[i].priority=3;break; - case ']':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_SHR;ae->AutomateElement[i].priority=3;break; + 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 'l':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_LOWER;ae->AutomateElement[i].priority=4;break; - case 'g':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_GREATER;ae->AutomateElement[i].priority=4;break; - case 'e':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_EQUAL;ae->AutomateElement[i].priority=4;break; - case 'n':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_NOTEQUAL;ae->AutomateElement[i].priority=4;break; - case 'k':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_LOWEREQ;ae->AutomateElement[i].priority=4;break; - case 'h':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_GREATEREQ;ae->AutomateElement[i].priority=4;break; + 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 '&':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_AND;ae->AutomateElement[i].priority=5;break; + 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_XOR;ae->AutomateElement[i].priority=6;break; + 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_OR;ae->AutomateElement[i].priority=7;break; + case '^':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_XOR;ae->AutomateElement[i].priority=7;break; /* priority 8 */ - case 'a':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_BAND;ae->AutomateElement[i].priority=8;break; + case '|':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_OR;ae->AutomateElement[i].priority=8;break; /* priority 9 */ - case 'o':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_BOR;ae->AutomateElement[i].priority=9;break; + 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; } } @@ -8910,6 +11012,8 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) /* 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; @@ -8936,6 +11040,35 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) } } + /* 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 */ ExpressionSetDicoVar(ae,"PI",3.1415926545); ExpressionSetDicoVar(ae,"ASSEMBLER_RASM",1); @@ -8970,8 +11103,8 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) *********************/ if (ae->verbose&4) { int iiii=0; - rasm_printf(ae,"%d [%s] L%d [%s]",ae->idx,ae->filename[wordlist[ae->idx].ifile],wordlist[ae->idx].l,wordlist[ae->idx].w); - while (!wordlist[ae->idx+iiii++].t) rasm_printf(ae," [%s]",wordlist[ae->idx+iiii].w); + rasm_printf(ae,"%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++) { rasm_printf(ae,"M[%d] s=%d e=%d ",iiii,ae->macropos[iiii].start,ae->macropos[iiii].end); @@ -8984,53 +11117,92 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) if (ae->ii || ae->isw) { /* inhibition of if/endif */ for (inhibe=curii=0;curiiii;curii++) { - if (!ae->ifthen[curii] || ae->ifthen[curii]==-1) { + if (!ae->ifthen[curii].v || ae->ifthen[curii].v==-1) { inhibe=1; break; } } - /* inhibition of switch/case */ - if (!inhibe) { - for (curii=0;curiiisw;curii++) { - if (!ae->switchcase[curii].execute) { - 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 !!! */ - - /* sorted by probability */ if (curcrc==CRC_ELSEIF && strcmp(wordlist[ae->idx].w,"ELSEIF")==0) { - __ELSEIF(ae); - } else if (curcrc==CRC_CASE && strcmp(wordlist[ae->idx].w,"CASE")==0) { - __CASE(ae); - } else if (curcrc==CRC_BREAK && strcmp(wordlist[ae->idx].w,"BREAK")==0) { - __BREAK(ae); - } else if (curcrc==CRC_IF && strcmp(wordlist[ae->idx].w,"IF")==0) { - __IF(ae); - } else if (curcrc==CRC_SWITCH && strcmp(wordlist[ae->idx].w,"SWITCH")==0) { - __SWITCH(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); + /* 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_IFNDEF && strcmp(wordlist[ae->idx].w,"IFNDEF")==0) { - __IFNDEF(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(ae); + __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) { @@ -9088,7 +11260,7 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) /* end of assembly, check there is no opened struct */ if (ae->getstruct) { - rasm_printf(ae,"[%s] Error line %d - STRUCT declaration was not closed\n",ae->backup_filename,ae->backup_line); + rasm_printf(ae,"[%s:%d] STRUCT declaration was not closed\n",ae->backup_filename,ae->backup_line); MaxError(ae); } /* end of assembly, close the last ORG zone */ @@ -9100,15 +11272,33 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) __internal_UpdateLZBlockIfAny(ae); /* end of assembly, check for opened repeat and opened while loop */ - for (i=0;iir;i++) { - rasm_printf(ae,"[%s] Error line %d - REPEAT was not closed\n",ae->filename[wordlist[ae->repeat[i].start].ifile],wordlist[ae->repeat[i].start].l); - MaxError(ae); - } - for (i=0;iiw;i++) { - rasm_printf(ae,"[%s] Error line %d - WHILE was not closed\n",ae->filename[wordlist[ae->whilewend[i].start].ifile],wordlist[ae->whilewend[i].start].l); - MaxError(ae); + if (!ae->stop) { + for (i=0;iir;i++) { + rasm_printf(ae,"[%s:%d] REPEAT was not closed\n",ae->filename[wordlist[ae->repeat[i].start].ifile],wordlist[ae->repeat[i].start].l); + MaxError(ae); + } + for (i=0;iiw;i++) { + rasm_printf(ae,"[%s:%d] WHILE was not closed\n",ae->filename[wordlist[ae->whilewend[i].start].ifile],wordlist[ae->whilewend[i].start].l); + MaxError(ae); + } + /* 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,""); + } + rasm_printf(ae,"[%s:%d] %s conditionnal block was not closed\n",ae->ifthen[i].filename,ae->ifthen[i].line,instr); + MaxError(ae); + } } - /*************************************************** c r u n c h L Z s e c t i o n s @@ -9208,6 +11398,11 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) **************************************************************************************************************************************************************************************** ***************************************************************************************************************************************************************************************/ 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 (!ae->nberr && !ae->checkmode) { @@ -9256,6 +11451,7 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) 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; @@ -9273,6 +11469,7 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) rasm_printf(ae,"\nROM is too big!!!\n"); FileWriteBinaryClose(TMP_filename); FileRemoveIfExists(TMP_filename); + FreeAssenv(ae); exit(ABORT_ERROR); } if (lm) { @@ -9317,7 +11514,7 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) int bankset; if (ae->snapshot.version==2 && ae->snapshot.CPCType>2) { - rasm_printf(ae,"[%s] Warning line %d - V2 snapshot cannot select a Plus model (forced to 6128)\n",GetCurrentFile(ae),ae->wl[ae->idx].l); + if (!ae->nowarning) rasm_printf(ae,"[%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 */ } @@ -9336,7 +11533,7 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) } /* construction du SNA */ if (ae->snapshot.version==2) { - if (maxrom>4) { + if (maxrom>=4) { ae->snapshot.dumpsize[0]=128; } else { ae->snapshot.dumpsize[0]=64; @@ -9359,6 +11556,7 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) 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; @@ -9369,6 +11567,7 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) rasm_printf(ae,"\nBANK is too big!!!\n"); FileWriteBinaryClose(TMP_filename); FileRemoveIfExists(TMP_filename); + FreeAssenv(ae); exit(ABORT_ERROR); } /* banks are gathered in the 64K block */ @@ -9390,6 +11589,7 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) rasm_printf(ae,"\nRAM block is too big!!!\n"); FileWriteBinaryClose(TMP_filename); FileRemoveIfExists(TMP_filename); + FreeAssenv(ae); exit(ABORT_ERROR); } if (lm) { @@ -9454,7 +11654,7 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) ObjectArrayAddDynamicValueConcat((void **)&ae->breakpoint,&ae->ibreakpoint,&ae->maxbreakpoint,&breakpoint,sizeof(struct s_breakpoint)); } } else { - if (strncmp(ae->label[i].name,"@BRK",4)==0) { + 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)); @@ -9588,6 +11788,13 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) 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,"Warning: breakpoint export is not supported with snapshot version 2\n"); + } + if (ae->export_sna) { + if (!ae->nowarning) rasm_printf(ae,"Warning: symbol export is not supported with snapshot version 2\n"); + } } FileWriteBinaryClose(TMP_filename); @@ -9617,6 +11824,7 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) } 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; @@ -9626,7 +11834,10 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) } if (maxmem-minmem<=0) { if (!ae->stop) { - rasm_printf(ae,"Warning: Not a single byte to output\n"); + if (!ae->nowarning) rasm_printf(ae,"Warning: Not a single byte to output\n"); + } + if (ae->flux) { + *lenout=0; } } else { if (!ae->flux) { @@ -9789,134 +12000,85 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout) FileWriteLine(TMP_filename,symbol_line); } FileWriteLineClose(TMP_filename); - } else { - rasm_printf(ae,"no breakpoint to output (previous file [%s] deleted anyway)\n",TMP_filename); - } - } - - } else { - rasm_printf(ae,"%d error%s\n",ae->nberr,ae->nberr>1?"s":""); - minmem=65536; - maxmem=0; - for (i=0;iio;i++) { - /* uniquement si le ORG a ete suivi d'ecriture */ - if (ae->orgzone[i].memstart!=ae->orgzone[i].memend) { - if (ae->orgzone[i].memstartorgzone[i].memstart; - if (ae->orgzone[i].memend>maxmem) maxmem=ae->orgzone[i].memend; - } - } - } - - if (ae->verbose & 7) { - rasm_printf(ae,"------ statistics ------------------\n"); - rasm_printf(ae,"%d file%s\n",ae->ifile,ae->ifile>1?"s":""); - rasm_printf(ae,"%d binary include%s\n",ae->ih,ae->ih>1?"s":""); - rasm_printf(ae,"%d word%s\n",ae->nbword-1,ae->nbword>2?"s":""); - rasm_printf(ae,"%d label%s\n",ae->il,ae->il>1?"s":""); - rasm_printf(ae,"%d var%s\n",ae->idic,ae->idic>1?"s":""); - rasm_printf(ae,"%d expression%s\n",ae->ie,ae->ie>1?"s":""); - rasm_printf(ae,"%d macro%s\n",ae->imacro,ae->imacro>1?"s":""); - rasm_printf(ae,"%d alias%s\n",ae->ialias,ae->ialias>1?"s":""); - rasm_printf(ae,"%d ORG zone%s\n",ae->io-1,ae->io>2?"s":""); - rasm_printf(ae,"%d virtual space%s\n",ae->nbbank,ae->nbbank>1?"s":""); - } - -/******************************************************************************************* - M E M O R Y C L E A N U P -*******************************************************************************************/ - 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].iw==-1) printf("label[%d]=%s (v=%d)\n",i,ae->label[i].name,ae->label[i].ptr); - if (ae->label[i].name && ae->label[i].iw==-1) MemFree(ae->label[i].name); - } - /* structures */ - for (i=0;iirasmstructalias;i++) { - //printf("structalias[%d]=%s (%d)\n",i,ae->rasmstructalias[i].name,ae->rasmstructalias[i].size); - 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].name); - } - if (ae->rasmstruct[i].mrasmstructfield) MemFree(ae->rasmstruct[i].rasmstructfield); - } - 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); - 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); + } else { + rasm_printf(ae,"no breakpoint to output (previous file [%s] deleted anyway)\n",TMP_filename); + } + } - for (i=2;iialias;i++) { - MemFree(ae->alias[i].alias); - MemFree(ae->alias[i].translation); + } else { + if (!ae->dependencies) rasm_printf(ae,"%d error%s\n",ae->nberr,ae->nberr>1?"s":""); + minmem=65536; + maxmem=0; + for (i=0;iio;i++) { + /* uniquement si le ORG a ete suivi d'ecriture */ + if (ae->orgzone[i].memstart!=ae->orgzone[i].memend) { + if (ae->orgzone[i].memstartorgzone[i].memstart; + if (ae->orgzone[i].memend>maxmem) maxmem=ae->orgzone[i].memend; + } + } + } +/******************************************************************************************* + 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"); } - if (ae->malias) MemFree(ae->alias); - for (i=0;wordlist[i].t!=2;i++) { - MemFree(wordlist[i].w); +/******************************************************************************************* + V E R B O S E S H I T +*******************************************************************************************/ + if (ae->verbose & 7) { + rasm_printf(ae,"------ statistics ------------------\n"); + rasm_printf(ae,"%d file%s\n",ae->ifile,ae->ifile>1?"s":""); + rasm_printf(ae,"%d binary include%s\n",ae->ih,ae->ih>1?"s":""); + rasm_printf(ae,"%d word%s\n",ae->nbword-1,ae->nbword>2?"s":""); + rasm_printf(ae,"%d label%s\n",ae->il,ae->il>1?"s":""); + rasm_printf(ae,"%d struct%s\n",ae->irasmstruct,ae->irasmstruct>1?"s":""); + rasm_printf(ae,"%d var%s\n",ae->idic,ae->idic>1?"s":""); + rasm_printf(ae,"%d expression%s\n",ae->ie,ae->ie>1?"s":""); + rasm_printf(ae,"%d macro%s\n",ae->imacro,ae->imacro>1?"s":""); + rasm_printf(ae,"%d alias%s\n",ae->ialias,ae->ialias>1?"s":""); + rasm_printf(ae,"%d ORG zone%s\n",ae->io-1,ae->io>2?"s":""); + rasm_printf(ae,"%d virtual space%s\n",ae->nbbank,ae->nbbank>1?"s":""); } - MemFree(wordlist); +/******************************************************************************************* + C L E A N U P +*******************************************************************************************/ + if (TMP_filename) MemFree(TMP_filename); if (ae->nberr) { ok=-1; - if (ae->flux) { + if (ae->flux && *dataout) { MemFree(*dataout); *dataout=NULL; - *lenout=0; } + *lenout=0; } else { ok=0; } - MemFree(TMP_filename); - MemFree(ae->outputfilename); - FreeLabelTree(ae); - FreeDicoTree(ae); - if (ae->mmacropos) MemFree(ae->macropos); - TradExpression(NULL); - MemFree(ae); + + FreeAssenv(ae); + return ok; } @@ -9995,7 +12157,7 @@ int cmpkeyword(const void * a, const void * b) return strcmp(sa->mnemo,sb->mnemo); } -struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int datalen, int verbose, char *outputfilename, char **labelfilename, int as80) +struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int datalen, struct s_parameter *param) { #undef FUNC #define FUNC "PreProcessing" @@ -10046,7 +12208,7 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int int escape_code=0; int quote_type=0; int incbin=0,include=0,crunch=0; - int rewrite=0; + int rewrite=0,hadcomma=0; int nbinstruction; int ifast,texpr; int ispace=0; @@ -10058,6 +12220,63 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int ae=MemMalloc(sizeof(struct s_assenv)); memset(ae,0,sizeof(struct s_assenv)); + + 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->edskoverwrite=param->edskoverwrite; + ae->rough=param->rough; + ae->as80=param->as80; + ae->dams=param->dams; + 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->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; + ae->verbose=param->verbose; + } + /* 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 @@ -10105,7 +12324,6 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int } } memcpy(ae->snapshot.idmark,"MV - SNA",8); - ae->snapshot.version=3; ae->snapshot.registers.IM=1; ae->snapshot.gatearray.palette[0]=0x04; @@ -10142,6 +12360,7 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int ae->snapshot.crtc.registervalue[9]=7; ae->snapshot.crtc.registervalue[12]=0x30; ae->snapshot.psg.registervalue[7]=0x3F; /* audio mix all channels OFF */ + /* standard stack */ ae->snapshot.registers.HSP=0xC0; /* @@ -10149,12 +12368,12 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int 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 (labelfilename) { - for (j=0;labelfilename[j] && labelfilename[j][0];j++) { - rasm_printf(ae,"Label import from [%s]\n",labelfilename[j]); - ae->label_filename=labelfilename[j]; + 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(labelfilename[j]); + labelines=FileReadLines(param->labelfilename[j]); i=0; while (labelines[i]) { /* upper case */ @@ -10205,33 +12424,31 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int } ae->activebank=36; ae->maxptr=65536; - ae->verbose=verbose; for (i=0;i<256;i++) { ae->charset[i]=(unsigned char)i; } - if (outputfilename) { - ae->outputfilename=TxtStrDup(outputfilename); + if (param && param->outputfilename) { + ae->outputfilename=TxtStrDup(param->outputfilename); } else { ae->outputfilename=TxtStrDup("rasmoutput"); } - - if (filename && !strstr(filename,".") && !FileExists(filename)) { + if (param && param->filename && !strstr(param->filename,".") && !FileExists(param->filename)) { /* pas d'extension, fichier non trouvé */ - l=strlen(filename); - filename=MemRealloc(filename,l+5); - strcat(filename,".asm"); - if (!FileExists(filename)) { - TxtReplace(filename,".asm",".z80",0); /* no realloc with this */ - if (!FileExists(filename)) { - filename[l]=0; + l=strlen(param->filename); + filename=MemRealloc(param->filename,l+5); + strcat(param->filename,".asm"); + if (!FileExists(param->filename)) { + TxtReplace(param->filename,".asm",".z80",0); /* no realloc with this */ + if (!FileExists(param->filename)) { + param->filename[l]=0; } } } - if (filename && !FileExists(filename)) { - rasm_printf(ae,"Cannot find file [%s]\n",filename); + if (param && param->filename && !FileExists(param->filename)) { + rasm_printf(ae,"Cannot find file [%s]\n",param->filename); exit(-1802); } - rasm_printf(ae,"Pre-processing [%s]\n",filename); + if (param) rasm_printf(ae,"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; } @@ -10288,7 +12505,6 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int } /* virer les commentaires, scanner un ; */ for (l=0;lfilename[listing[l].ifile],qval); - curhexbin.filename=TxtStrDup(filename_toread); - 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); + if (fileok) { /* lecture */ - curhexbin.datalen=FileGetSize(filename_toread); + curhexbin.rawlen=curhexbin.datalen=FileGetSize(filename_toread); curhexbin.data=MemMalloc(curhexbin.datalen*1.3+10); if (ae->verbose & 7) { switch (crunch) { @@ -10435,14 +12662,26 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int incbin=0; } else if (include) { /* qval contient le nom du fichier a lire */ - filename_toread=TxtStrDup(MergePath(ae,ae->filename[listing[l].ifile],qval)); + 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) { if (ae->verbose & 7) rasm_printf(ae,"include [%s]\n",filename_toread); /* lecture */ listing_include=FileReadLines(filename_toread); FieldArrayAddDynamicValueConcat(&ae->filename,&ae->ifile,&ae->maxfile,filename_toread); - MemFree(filename_toread); /* virer les commentaires */ for (li=0;listing_include[li];li++) { StateMachineRemoveComz(listing_include[li]); @@ -10592,7 +12831,7 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int } } if (wi==-1) { - rasm_printf(ae,"[%s] Error line %d - WEND refers to unknown WHILE\n",ae->filename[listing[l].ifile],listing[l].iline); + rasm_printf(ae,"[%s:%d] WEND refers to unknown WHILE\n",ae->filename[listing[l].ifile],listing[l].iline); exit(1); } } else if (strcmp(bval,"REND")==0 || strcmp(bval,"UNTIL")==0) { @@ -10605,7 +12844,7 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int } } if (ri==-1) { - rasm_printf(ae,"[%s] Error line %d - %s refers to unknown REPEAT\n",ae->filename[listing[l].ifile],listing[l].iline,bval); + rasm_printf(ae,"[%s:%d] %s refers to unknown REPEAT\n",ae->filename[listing[l].ifile],listing[l].iline,bval); exit(1); } @@ -10616,20 +12855,19 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int } } if (quote_type) { - rasm_printf(ae,"[%s] Error line %d - quote opened was not closed\n",ae->filename[listing[lquote].ifile],listing[lquote].iline); + rasm_printf(ae,"[%s:%d] quote opened was not closed\n",ae->filename[listing[lquote].ifile],listing[lquote].iline); exit(1); } /* repeat expansion check */ for (ri=0;rifilename[TABrindex[ri].ifile],TABrindex[ri].ol); + rasm_printf(ae,"[%s:%d] REPEAT was not closed\n",ae->filename[TABrindex[ri].ifile],TABrindex[ri].ol); MaxError(ae); } } /* creer une liste de mots */ - curw.w=TxtStrDup("BEGIN"); curw.l=0; curw.ifile=0; @@ -10644,8 +12882,8 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int curw.w=TxtStrDup("IY~0"); ObjectArrayAddDynamicValueConcat((void**)&wordlist,&nbword,&maxword,&curw,sizeof(curw)); curw.e=0; - -#if 0 + +#if DEBUG_PREPRO l=0; while (l31?c:'.',Automate[((int)c)&0xFF]); +#endif switch (Automate[((int)c)&0xFF]) { case 0: - rasm_printf(ae,"[%s] L%d - Invalid char '%c' (%d) char %d\n",ae->filename[listing[l].ifile],listing[l].iline,c,c,idx); + rasm_printf(ae,"[%s:%d] invalid char '%c' (%d) char %d\n",ae->filename[listing[l].ifile],listing[l].iline,c,c,idx); MaxError(ae); break; case 1: @@ -10681,7 +12922,9 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int quote_type=c; /* debut d'une quote, on finalise le mot -> POURQUOI DONC? */ //idx--; - +#if DEBUG_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--; @@ -10721,11 +12964,21 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int break; } case 2: - /* separator */ + /* separator (space, tab, comma) */ +#if DEBUG_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) { /* pour compatibilite winape avec AND,OR,XOR */ +#if DEBUG_PREPRO +printf("compat AND,OR,XOR en test\n"); +#endif if (strcmp(w,"AND")==0) { wtmp=TxtStrDup("&"); } else if (strcmp(w,"OR")==0) { @@ -10779,7 +13032,15 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int curw.l=listing[l].iline; curw.ifile=listing[l].ifile; curw.t=0; +#if DEBUG_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; @@ -10791,7 +13052,9 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int Automate['\t']=1; ispace=0; texpr=1; -//printf("macro trigger w=[%s]\n",curw.w); +#if DEBUG_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; @@ -10813,6 +13076,9 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int Automate['\t']=1; ispace=0; /* instruction en cours, le reste est a interpreter comme une expression */ +#if DEBUG_PREPRO +printf("instruction en cours\n"); +#endif texpr=1; } break; @@ -10838,11 +13104,17 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int } } } else { -//printf("mot vide\n"); + if (hadcomma) { + rasm_printf(ae,"[%s:%d] empty parameter\n",ae->filename[listing[l].ifile],listing[l].iline); + MaxError(ae); + } } break; case 3: /* fin de ligne, on remet l'automate comme il faut */ +#if DEBUG_PREPRO +printf("EOL\n"); +#endif macro_trigger=0; Automate[' ']=2; Automate['\t']=2; @@ -10850,28 +13122,23 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int texpr=0; /* si le mot lu a plus d'un caractère */ if (lw) { - if (texpr && nbword && wordlist[nbword-1].e) { + 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 DEBUG_PREPRO +printf("nbword=%d w=[%s] ->",nbword,w);fflush(stdout); +#endif 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); - - curw.w=TxtStrDup(w); - curw.l=listing[l].iline; - curw.ifile=listing[l].ifile; - curw.t=1; - ObjectArrayAddDynamicValueConcat((void**)&wordlist,&nbword,&maxword,&curw,sizeof(curw)); + wordlist[nbword].w=MemRealloc(wordlist[nbword].w,strlen(wordlist[nbword].w)+lw+1); + strcat(wordlist[nbword].w,w); +#if DEBUG_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; @@ -10893,22 +13160,35 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int 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 DEBUG_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 DEBUG_PREPRO +printf("expr operator=%c\n",c); +#endif /* expression/condition */ texpr=1; if (lw) { @@ -10934,17 +13214,52 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int */ } } else { - if (!wordlist[nbword-1].t) { + /* 2018.06.06 évolution sur le ! (not) */ +#if DEBUG_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 */ - nbword--; - for (li=0;wordlist[nbword].w[li];li++) { - w[lw++]=wordlist[nbword].w[li]; - StateMachineResizeBuffer(&w,lw,&mw); - w[lw]=0; + /* 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;i'\n",ae->filename[listing[l].ifile],listing[l].iline); + rasm_printf(ae,"[%s:%d] cannot start expression with '=','!','<','>'\n",ae->filename[listing[l].ifile],listing[l].iline); MaxError(ae); } } @@ -10963,6 +13278,9 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int } } else { /* lecture inconditionnelle de la quote */ +#if DEBUG_PREPRO +printf("quote[%d]=%c\n",lw,c); +#endif w[lw++]=c; StateMachineResizeBuffer(&w,lw,&mw); w[lw]=0; @@ -10982,11 +13300,11 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int curw.t=2; curw.ifile=0; ObjectArrayAddDynamicValueConcat((void**)&wordlist,&nbword,&maxword,&curw,sizeof(curw)); - if (ae->verbose & 7) rasm_printf(ae,"wordlist contains %d element%s\n",nbword,nbword>1?"s":""); ae->nbword=nbword; - if (as80) { + /* 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); return ae; } -void Rasm(char *filename, int export_sym, int verbose, char *outputfilename, float rough, int export_local, char **labelfilename, - int export_var, int export_equ, char *symbol_name, char *binary_name, char *cartridge_name, char *snapshot_name, - int export_sna, int checkmode, int export_snabrk, int maxerr, char *breakpoint_name, int export_brk, int edskoverwrite, - int as80, int v2) +int Rasm(struct s_parameter *param) { #undef FUNC #define FUNC "Rasm" @@ -11030,34 +13355,9 @@ void Rasm(char *filename, int export_sym, int verbose, char *outputfilename, flo struct s_assenv *ae=NULL; /* read and preprocess source */ - ae=PreProcessing(filename,0,NULL,0,verbose,outputfilename,labelfilename,as80); - ae->export_local=export_local; - ae->export_sym=export_sym; - ae->export_var=export_var; - ae->export_equ=export_equ; - ae->export_sna=export_sna; - ae->export_snabrk=export_snabrk; - if (export_sna || export_snabrk) { - ae->forcesnapshot=1; - } - ae->export_brk=export_brk; - ae->edskoverwrite=edskoverwrite; - ae->rough=rough; - ae->as80=as80; - if (v2) { - ae->forcesnapshot=1; - ae->snapshot.version=2; - } - ae->maxerr=maxerr; - ae->breakpoint_name=breakpoint_name; - ae->symbol_name=symbol_name; - ae->binary_name=binary_name; - ae->cartridge_name=cartridge_name; - ae->snapshot_name=snapshot_name; - ae->checkmode=checkmode; - if (rough) ae->maxam=0; else ae->maxam=1; + ae=PreProcessing(param->filename,0,NULL,0,param); /* assemble */ - Assemble(ae,NULL,NULL); + return Assemble(ae,NULL,NULL); } /* fonction d'export */ @@ -11066,14 +13366,42 @@ int RasmAssemble(const char *datain, int lenin, unsigned char **dataout, int *le { struct s_assenv *ae=NULL; - ae=PreProcessing(NULL,1,datain,lenin,0x0,NULL,NULL,0); + ae=PreProcessing(NULL,1,datain,lenin,NULL); return Assemble(ae,dataout,lenout); } +#define AUTOTEST_NOINCLUDE "truc equ 0:if truc:include'bite':endif: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_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:" \ @@ -11215,6 +13543,125 @@ int RasmAssemble(const char *datain, int lenin, unsigned char **dataout, int *le "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_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_ORG "ORG #8000,#1000:defw $:ORG $:defw $" + +#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==0xC0:assert {page}label2==0xC6:assert {pageset}label1==#C0:assert {pageset}label2==#C2: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==#C5:assert {pageset}maroutine==#C2:assert {page}autreroutine==#C4:" \ + "assert {pageset}autreroutine==#C2:assert {page}troize==#CE:assert {pageset}troize==#CA" + +#define AUTOTEST_PAGETAG3 "buildsna:bank 2:assert {bank}$==2:assert {page}$==0xC0:assert {pageset}$==#C0:" \ + "bankset 1:org #4000:assert {bank}$==5:assert {page}$==0xC5:assert {pageset}$==#C2" + +#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_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_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_MACROPROX " macro unemacro: nop: endm: global_label: ld hl, .table: .table" + +#define AUTOTEST_QUOTES "defb 'rdd':str 'rdd':charset 'rd',0:defb '\\r\\d':str '\\r\\d'" + +#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" + +/* 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 #101:org #100:add ix,ix" + +#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_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" + +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);MemFree(tmpsplit); + cpt++; + + + printf(".");fflush(stdout);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(".");fflush(stdout);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(".");fflush(stdout);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(".");fflush(stdout);ret=RasmAssemble(AUTOTEST_LZSEGMENT,strlen(AUTOTEST_LZSEGMENT),&opcode,&opcodelen); + if (!ret && opcodelen==23 && opcode[1]==21 && opcode[9]==23) {} else {printf("Autotest %03d ERROR (LZsegment relocation)\n",cpt);exit(-1);} + if (opcode) MemFree(opcode);opcode=NULL;cpt++; + + printf(".");fflush(stdout);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(".");fflush(stdout);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(".");fflush(stdout);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(".");fflush(stdout);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(".");fflush(stdout);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(".");fflush(stdout);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(".");fflush(stdout);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(".");fflush(stdout);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(".");fflush(stdout);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(".");fflush(stdout);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(".");fflush(stdout);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(".");fflush(stdout);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(".");fflush(stdout);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(".");fflush(stdout);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(".");fflush(stdout);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(".");fflush(stdout);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(".");fflush(stdout);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;i choose a full filename for snapshot output\n"); printf("-os choose a full filename for symbol 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("-sp export symbols with Pasmo convention\n"); @@ -11512,10 +14191,13 @@ void Usage(int help) 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("-ass AS80 behaviour mimic (see doc)\n"); - printf("-uz UZ80 (see doc for that too)\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("BANKING:\n"); printf("-c cartridge/snapshot summary\n"); printf("EDSK generation/update:\n"); @@ -11525,7 +14207,9 @@ void Usage(int help) 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==no maximum)\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("\n"); } else { printf("use option -h for help\n"); @@ -11539,8 +14223,14 @@ void Licenses() { #undef FUNC #define FUNC "Licenses" - -printf("RASM is using MIT 'expat' license\n"); + +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"); @@ -11672,134 +14362,161 @@ printf("\n\n"); used to parse command line and configuration file */ -int ParseOptions(char **argv,int argc,char **filename, int *export_sym, int *verbose, char **outputfilename, float *rough, int *export_local, - char ***labelfilename, int *export_var, int *export_equ, char **symbol_name, char **binary_name, char **cartridge_name, - char **snapshot_name, int *export_sna, int *checkmode, int *export_snabrk, int *maxerr, char **breakpoint_name, int *export_brk, - int *edskoverwrite, int *as80, int *v2) +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) { - *as80=2; + param->as80=2; } else if (strcmp(argv[i],"-ass")==0) { - *as80=1; + param->as80=1; } else if (strcmp(argv[i],"-eb")==0) { - *export_brk=1; + param->export_brk=1; + } else if (strcmp(argv[i],"-dams")==0) { + param->rough=0.0; + param->dams=1; + } else if (strcmp(argv[i],"-xr")==0) { + param->extended_error=1; } else if (strcmp(argv[i],"-eo")==0) { - *edskoverwrite=1; + 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) { - *checkmode=1; + param->checkmode=1; + } else if (strcmp(argv[i],"-w")==0) { + param->nowarning=1; } else if (argv[i][0]=='-') { switch(argv[i][1]) { - case 'M': + 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: - *rough=0.0; + param->rough=0.0; return i; - case 'E': case 'e': + if (argv[i][3]) Usage(1); if (i+1maxerr=atoi(argv[++i]); return i; } default:Usage(1); } Usage(1); break; - case 'S': case 's': + if (argv[i][2] && argv[i][3]) Usage(1); switch (argv[i][2]) { - case 0:*export_sym=1;return 0; + case 0:param->export_sym=1;return 0; case 'b': - case 'B': - *export_snabrk=1;return 0; + param->export_snabrk=1;return 0; case 'p': - case 'P': - *export_sym=2;return 0; + param->export_sym=2;return 0; case 'w': - case 'W': - *export_sym=3;return 0; + param->export_sym=3;return 0; case 'l': - case 'L': - *export_local=1;return 0; + param->export_local=1;return 0; case 'v': - case 'V': - *export_var=1;return 0; + param->export_var=1;return 0; case 'q': - case 'Q': - *export_equ=1;return 0; + param->export_equ=1;return 0; case 'a': - case 'A': - *export_local=1; - *export_var=1; - *export_equ=1; + param->export_local=1; + param->export_var=1; + param->export_equ=1; return 0; case 's': - case 'S': - *export_local=1; - *export_sym=1; - *export_sna=1;return 0; + param->export_local=1; + param->export_sym=1; + param->export_sna=1;return 0; default: break; } Usage(1); - case 'L': case 'l': + if (argv[i][2]) Usage(1); if (i+1labelfilename,argv[++i]); break; } Usage(1); - case 'O': + 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 '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); @@ -11807,35 +14524,29 @@ int ParseOptions(char **argv,int argc,char **filename, int *export_sym, int *ver Usage(1); } break; - case 'D': - case 'd':*verbose|=2; + case 'd':if (!argv[i][2]) param->verbose|=2; else Usage(1); break; - case 'A': - case 'a':*verbose|=4; + case 'a':if (!argv[i][2]) param->verbose|=4; else Usage(1); break; - case 'C': - case 'c':*verbose|=8; + case 'c':if (!argv[i][2]) param->verbose|=8; else Usage(1); break; - case 'V': case 'v': if (!argv[i][2]) { - *verbose=1; + param->verbose=1; } else if (argv[i][2]=='2') { - *v2=1; + param->v2=1; } break; - case 'N': - case 'n':Licenses(); - case 'H': + case 'n':if (!argv[i][2]) Licenses(); else Usage(1); case 'h':Usage(1); default: Usage(1); } } else { - if (*filename==NULL) { - *filename=TxtStrDup(argv[i]); - } else if (*outputfilename==NULL) { - *outputfilename=argv[i]; + if (param->filename==NULL) { + param->filename=TxtStrDup(argv[i]); + } else if (param->outputfilename==NULL) { + param->outputfilename=argv[i]; } else Usage(1); } return i; @@ -11845,22 +14556,17 @@ int ParseOptions(char **argv,int argc,char **filename, int *export_sym, int *ver GetParametersFromCommandLine retrieve parameters from command line and fill pointers to file names */ -void GetParametersFromCommandLine(int argc, char **argv, char **filename, int *export_sym, int *verbose, char **outputfilename, float *rough, - int *export_local, char ***labelfilename, int *export_var, int *export_equ, char **symbol_name, char **binary_name, char **cartridge_name, - char **snapshot_name, int *export_sna, int *checkmode, int *export_snabrk, int *maxerr, char **breakpoint_name, int *export_brk, - int *edskoverwrite, int *as80, int *v2) +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? } /* @@ -11876,44 +14582,23 @@ int main(int argc, char **argv) #undef FUNC #define FUNC "main" - char **labelfilename=NULL; - char *filename=NULL; - char *outputfilename=NULL; - int export_local=0; - int export_var=0; - int export_equ=0; - int export_sym=0; - int export_sna=0; - int export_snabrk=0; - int export_brk=0; - int verbose=0; - int checkmode=0; - int maxerr=20; - int edskoverwrite=0; - float rough=0.5; - int as80=0; - int v2=0; - char *symbol_name=NULL; - char *binary_name=NULL; - char *cartridge_name=NULL; - char *snapshot_name=NULL; - char *breakpoint_name=NULL; - - GetParametersFromCommandLine(argc,argv,&filename,&export_sym,&verbose,&outputfilename,&rough,&export_local,&labelfilename, - &export_var,&export_equ,&symbol_name,&binary_name,&cartridge_name,&snapshot_name,&export_sna,&checkmode,&export_snabrk, - &maxerr,&breakpoint_name,&export_brk,&edskoverwrite,&as80,&v2); - Rasm(filename,export_sym,verbose,outputfilename,rough,export_local,labelfilename,export_var,export_equ,symbol_name, - binary_name,cartridge_name,snapshot_name,export_sna,checkmode,export_snabrk,maxerr,breakpoint_name,export_brk, - edskoverwrite,as80,v2); + 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(0); + exit(ret); return 0; // Open WATCOM Warns without this... } #endif - diff --git a/updates.txt b/updates.txt index 9470a15..c380a05 100644 --- a/updates.txt +++ b/updates.txt @@ -1,9 +1,99 @@ +update v0.99 +- new directive UNDEF +- bugfix memory leaks +- bugfix calculations with a function followed by two or more opened parenthesis + +update v0.98 +- bugfix with snapshot v2 memory size detection +- new optional parameter to get file size when load and crunch on the fly +- new option to remove warnings +- new fake instructions RR,RL,SRL,SRA,SLL,SLA with 16 bits (BC,DE,HL) registers +- preprocessing does not allow empty parameter to avoid confusion +- extended error may suggest a name if a variable/label/alias looks similar to a 'not found' value + +update v0.97 +- bugfix conditionnal code inhibition with macro declaration +- better alias infinite recursivity detection + +update v0.96 +- bugfix memory leak in tag translation with PRINT directive +- bugfix negative offset with INCBIN +- bugfix autotests memory handling +- added include path in command line + +update v0.95 +- allow spaces in tags inside strings with PRINT directive +- display warning if you try to export symbols or breakpoints with snapshot version 2 +- proximity label beginning with BRK will generate an exportable breakpoint +- new enhanced LD instructions (see online documentation) + +update v0.94 +- bugfix using macro parameter inside print quote +- bugfix multiple memory leak with tag replacement +- bugfix command line side effect with wrong option +- better hack in expression calculator for expression beginning with negative value +- better equality processing in expression calculator +- dependencies export do not display preprocessing message anymore + +update v0.93 +- bugfix RUN gate array configuration +- overriding an alias with a label will trigger an error +- PRINT directive may use escaped chars in strings +- tags BANK,PAGE,PAGESET may be used with current adress $ + +update v0.92 +- bugfix PAGE tag when using BANK in snapshot mode + +update v0.91 +- bugfix school case with crunched block +- bugfix proximity labels when using loops or macros +- bugfix imbricated IFUSED/IFNUSED +- new directive FAIL will print a message before exiting with an error flag +- label usage may use formula +- escaped codes support in strings (disregarding the current charset) +- PRINT directive may compute formula in strings when using curly brackets +- RUN directive may set the gate array configuration for snapshots +- generated label with negative index will trigger an error +- overriding an alias with a variable will trigger an error +- overriding a variable with an alias will trigger an error +- missing ENDIF at the end of the source will trigger an error + +update v0.90 +- PROTECT directive does not increase automatic binary size anymore +- bugfix memory leak with proximity labels +- proximity label properties also for EQU aliases +- label declaration may use formula + +update v0.89 +- bugfix dependencies export +- multiple bugfix in preprocessor +- simplify path of dependencies when possible +- enhanced ASSERT may PRINT additional parameters + +update v0.88 +- bugfix another cases during preprocessing + +update v0.87 +- new proximity labels +- rasm is able to use variables inside label names +- INCBIN directive enhanced for WAV import as a CPC sample or DMA list +- REPEAT directive may export internal counter to a variable +- new directive IFUSED & IFNUSED +- new math operator ! for NOT +- new math function PSGVALUE +- rasm return 1 to shell when there is error(s) +- new options to export dependencies (makefile style) +- new option to define variable(s) from command line +- new option for extended error messages +- bugfix cases during preprocessing +- bugfix tags PAGE & PAGESET +- new autotests embedded in Rasm in order to reduce regressions + update v0.86 - fix many bugs in label import - fix multi-nops - fix automatic extension for primary source - fix infinite loop when error on reserved keyword in an expression -- shortcuts LD BC/DE/HL,BC/DE/HL (uz80 style) update v0.85 - fix some regressions introduced by STRUCT code modifications