aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2022-09-06 07:37:20 +0100
committerJuan J. Martinez <jjm@usebox.net>2022-09-06 07:37:20 +0100
commit30bf0f51335e87812ffeb54e9437f0b6a1514d67 (patch)
tree9c85a2de53b4da69fcfaa84488cc6c12ebd3e5d0 /tools
parentd8990284057e6401d0374f439df51879595d804d (diff)
downloadubox-msx-lib-30bf0f51335e87812ffeb54e9437f0b6a1514d67.tar.gz
ubox-msx-lib-30bf0f51335e87812ffeb54e9437f0b6a1514d67.zip
Updated rasm to 1.7
Diffstat (limited to 'tools')
-rw-r--r--tools/rasm/Makefile155
-rw-r--r--tools/rasm/Makefile.orig145
-rw-r--r--tools/rasm/ReadMe19
-rw-r--r--tools/rasm/ZX0-main/LICENSE29
-rw-r--r--tools/rasm/ZX0-main/README.md369
-rw-r--r--tools/rasm/ZX0-main/src/compress.c164
-rw-r--r--tools/rasm/ZX0-main/src/memory.c75
-rw-r--r--tools/rasm/ZX0-main/src/optimize.c137
-rw-r--r--tools/rasm/ZX0-main/src/zx0.h46
-rw-r--r--tools/rasm/apultra-master/src/apultra.c1035
-rw-r--r--tools/rasm/apultra-master/src/expand.c396
-rw-r--r--tools/rasm/apultra-master/src/expand.h71
-rw-r--r--tools/rasm/apultra-master/src/format.h47
-rw-r--r--tools/rasm/apultra-master/src/libapultra.h40
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/CHANGELOG.md21
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/CMakeLists.txt99
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/AppendCompilerFlags.cmake38
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/CheckFunctionKeywords.cmake15
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/CheckLFS.cmake109
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/ProjectCPack.cmake38
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/cmake_uninstall.cmake.in36
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/LICENSE21
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/README.md140
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/VERSION.cmake23
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/examples/CMakeLists.txt11
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/examples/bwt.c220
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/examples/mksary.c193
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/examples/sasearch.c165
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/examples/suftest.c164
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/examples/unbwt.c207
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/include/CMakeLists.txt162
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/include/config.h.cmake81
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/include/divsufsort.h189
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/include/divsufsort.h.cmake180
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/include/divsufsort_config.h9
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/include/divsufsort_private.h205
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/include/lfs.h.cmake56
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/pkgconfig/CMakeLists.txt9
-rw-r--r--tools/rasm/apultra-master/src/libdivsufsort/pkgconfig/libdivsufsort.pc.cmake11
-rw-r--r--tools/rasm/apultra-master/src/matchfinder.c449
-rw-r--r--tools/rasm/apultra-master/src/matchfinder.h94
-rw-r--r--tools/rasm/apultra-master/src/shrink.c1597
-rw-r--r--tools/rasm/apultra-master/src/shrink.h172
-rw-r--r--tools/rasm/compil.bat28
-rw-r--r--tools/rasm/decrunch/dzx0_fast.asm237
-rw-r--r--tools/rasm/decrunch/dzx0_standard.asm64
-rw-r--r--tools/rasm/decrunch/dzx0_standard_back.asm65
-rw-r--r--tools/rasm/decrunch/dzx0_turbo_back.asm101
-rw-r--r--tools/rasm/decrunch/dzx7_turbo.asm4
-rw-r--r--tools/rasm/decrunch/exomizer3megachur.asm210
-rw-r--r--tools/rasm/decrunch/lz48decrunch_v006.asm113
-rw-r--r--tools/rasm/decrunch/lz48decrunch_v006b.asm78
-rw-r--r--tools/rasm/decrunch/unaplib.asm (renamed from tools/rasm/decrunch/aplib_z80_todo.asm)8
-rw-r--r--tools/rasm/decrunch/unaplib_fast.asm266
-rw-r--r--tools/rasm/decrunch/unlzsa1_fast.asm204
-rwxr-xr-xtools/rasm/decrunch/unlzsa2_fast.asm189
-rw-r--r--tools/rasm/documentation_EN.pdfbin0 -> 278938 bytes
-rw-r--r--tools/rasm/documentation_FR.pdfbin0 -> 292302 bytes
-rw-r--r--tools/rasm/exomizer.h1
-rw-r--r--tools/rasm/lz4.h412
-rw-r--r--tools/rasm/lzsa-master/src/dictionary.c101
-rw-r--r--tools/rasm/lzsa-master/src/dictionary.h64
-rw-r--r--tools/rasm/lzsa-master/src/expand_block_v1.c224
-rw-r--r--tools/rasm/lzsa-master/src/expand_block_v1.h49
-rw-r--r--tools/rasm/lzsa-master/src/expand_block_v2.c253
-rw-r--r--tools/rasm/lzsa-master/src/expand_block_v2.h49
-rw-r--r--tools/rasm/lzsa-master/src/expand_context.c76
-rw-r--r--tools/rasm/lzsa-master/src/expand_context.h61
-rw-r--r--tools/rasm/lzsa-master/src/expand_inmem.c163
-rw-r--r--tools/rasm/lzsa-master/src/expand_inmem.h70
-rw-r--r--tools/rasm/lzsa-master/src/expand_streaming.c236
-rw-r--r--tools/rasm/lzsa-master/src/expand_streaming.h86
-rwxr-xr-xtools/rasm/lzsa-master/src/format.h51
-rw-r--r--tools/rasm/lzsa-master/src/frame.c189
-rw-r--r--tools/rasm/lzsa-master/src/frame.h122
-rwxr-xr-xtools/rasm/lzsa-master/src/lib.h95
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/.gitignore32
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/CHANGELOG.md21
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/CMakeLists.txt99
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/AppendCompilerFlags.cmake38
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/CheckFunctionKeywords.cmake15
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/CheckLFS.cmake109
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/ProjectCPack.cmake38
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/cmake_uninstall.cmake.in36
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/LICENSE21
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/README.md140
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/VERSION.cmake23
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/examples/CMakeLists.txt11
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/examples/bwt.c220
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/examples/mksary.c193
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/examples/sasearch.c165
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/examples/suftest.c164
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/examples/unbwt.c207
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/include/CMakeLists.txt162
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/include/config.h.cmake81
-rwxr-xr-xtools/rasm/lzsa-master/src/libdivsufsort/include/divsufsort.h189
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/include/divsufsort.h.cmake180
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/include/divsufsort_config.h9
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/include/divsufsort_private.h205
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/include/lfs.h.cmake56
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/pkgconfig/CMakeLists.txt9
-rw-r--r--tools/rasm/lzsa-master/src/libdivsufsort/pkgconfig/libdivsufsort.pc.cmake11
-rwxr-xr-xtools/rasm/lzsa-master/src/lzsa.c1109
-rw-r--r--tools/rasm/lzsa-master/src/matchfinder.c361
-rw-r--r--tools/rasm/lzsa-master/src/matchfinder.h91
-rw-r--r--tools/rasm/lzsa-master/src/shrink_block_v1.c710
-rw-r--r--tools/rasm/lzsa-master/src/shrink_block_v1.h53
-rw-r--r--tools/rasm/lzsa-master/src/shrink_block_v2.c1371
-rw-r--r--tools/rasm/lzsa-master/src/shrink_block_v2.h53
-rw-r--r--tools/rasm/lzsa-master/src/shrink_context.c254
-rw-r--r--tools/rasm/lzsa-master/src/shrink_context.h182
-rw-r--r--tools/rasm/lzsa-master/src/shrink_inmem.c185
-rw-r--r--tools/rasm/lzsa-master/src/shrink_inmem.h71
-rw-r--r--tools/rasm/lzsa-master/src/shrink_streaming.c320
-rw-r--r--tools/rasm/lzsa-master/src/shrink_streaming.h99
-rw-r--r--tools/rasm/lzsa-master/src/stream.c111
-rw-r--r--tools/rasm/lzsa-master/src/stream.h103
-rw-r--r--tools/rasm/makefile.MacOS101
-rw-r--r--tools/rasm/minilib.h106
-rw-r--r--tools/rasm/msdos.bat4
-rw-r--r--tools/rasm/rasm.c (renamed from tools/rasm/rasm_v0120.c)11079
-rw-r--r--tools/rasm/rasm.h7
-rw-r--r--tools/rasm/resources/opcodes_first_byte.asm542
-rwxr-xr-xtools/rasm/win32.bat7
-rw-r--r--tools/rasm/zx7.h54
125 files changed, 28021 insertions, 2697 deletions
diff --git a/tools/rasm/Makefile b/tools/rasm/Makefile
index 2fb4627..25d6b31 100644
--- a/tools/rasm/Makefile
+++ b/tools/rasm/Makefile
@@ -1,21 +1,150 @@
-all: rasm
-
-CC := gcc
-LDFLAGS := -lm -lrt
+CC=gcc
ifeq ($(OS),Windows_NT)
- TARGET := rasm.exe
+ EXEC=rasm.exe
else
- TARGET := rasm
+ EXEC=rasm
endif
-rasm: rasm_v0120.c
- $(CC) $< -s -O2 $(LDFLAGS) -march=native -o $@
- cp $(TARGET) ../../bin
- rm -f $(TARGET)
+CFLAGS=-lm -lrt -march=native -o $(EXEC)
+CFLAGS_OPT = $(CFLAGS) -O2
+CFLAGS_DBG = $(CFLAGS) -g -pthread -DRDD
+CFLAGS_3RD = $(CFLAGS) -g -pthread -DNO_3RD_PARTIES
-clean:
- rm -f $(TARGET)
+SRC_APUDIR=./apultra-master/src
+SRC_LZSADIR=./lzsa-master/src
+SRC_ZX0DIR=./ZX0-main/src
+
+APU_FLAGS=-c -O3 -fomit-frame-pointer -I$(SRC_LZSADIR)/libdivsufsort/include -I$(SRC_APUDIR)
+
+APU_OBJ =$(SRC_APUDIR)/expand.o
+APU_OBJ+=$(SRC_APUDIR)/matchfinder.o
+APU_OBJ+=$(SRC_APUDIR)/shrink.o
+APU_OBJ+=$(SRC_APUDIR)/libdivsufsort/lib/divsufsort.o
+APU_OBJ+=$(SRC_APUDIR)/libdivsufsort/lib/divsufsort_utils.o
+APU_OBJ+=$(SRC_APUDIR)/libdivsufsort/lib/sssort.o
+APU_OBJ+=$(SRC_APUDIR)/libdivsufsort/lib/trsort.o
+
+LZSA_FLAGS=-c -O3 -fomit-frame-pointer -I$(SRC_LZSADIR)/libdivsufsort/include -I$(SRC_LZSADIR)
+
+LZSA_OBJ =$(SRC_LZSADIR)/dictionary.o
+LZSA_OBJ+=$(SRC_LZSADIR)/expand_block_v1.o
+LZSA_OBJ+=$(SRC_LZSADIR)/expand_block_v2.o
+LZSA_OBJ+=$(SRC_LZSADIR)/expand_context.o
+LZSA_OBJ+=$(SRC_LZSADIR)/expand_inmem.o
+LZSA_OBJ+=$(SRC_LZSADIR)/frame.o
+LZSA_OBJ+=$(SRC_LZSADIR)/matchfinder.o
+LZSA_OBJ+=$(SRC_LZSADIR)/shrink_block_v1.o
+LZSA_OBJ+=$(SRC_LZSADIR)/shrink_block_v2.o
+LZSA_OBJ+=$(SRC_LZSADIR)/shrink_context.o
+LZSA_OBJ+=$(SRC_LZSADIR)/shrink_inmem.o
+LZSA_OBJ+=$(SRC_LZSADIR)/stream.o
+
+ZX0_FLAGS=-c -O2 -I$(SRC_ZX0DIR)
+ZX0_OBJ =$(SRC_ZX0DIR)/optimize.o
+ZX0_OBJ+=$(SRC_ZX0DIR)/compress.o
+ZX0_OBJ+=$(SRC_ZX0DIR)/memory.o
+
+.PHONY: prod third debug clean
+
+default: prod
+ cp $(EXEC) ../../bin
+ rm -f $(EXEC) *.o
+
+third:
+ $(CC) rasm.c $(CFLAGS_3RD)
+
+debug:
+ $(CC) $(SRC_ZX0DIR)/optimize.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/optimize.o
+ $(CC) $(SRC_ZX0DIR)/compress.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/compress.o
+ $(CC) $(SRC_ZX0DIR)/memory.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/memory.o
+
+ $(CC) $(SRC_APUDIR)/expand.c $(APU_FLAGS) -o $(SRC_APUDIR)/expand.o
+ $(CC) $(SRC_APUDIR)/matchfinder.c $(APU_FLAGS) -o $(SRC_APUDIR)/matchfinder.o
+ $(CC) $(SRC_APUDIR)/shrink.c $(APU_FLAGS) -o $(SRC_APUDIR)/shrink.o
+
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/divsufsort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/divsufsort.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/divsufsort_utils.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/divsufsort_utils.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/sssort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/sssort.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/trsort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/trsort.o
-.PHONY: all clean
+ $(CC) $(SRC_LZSADIR)/matchfinder.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/matchfinder.o
+ $(CC) $(SRC_LZSADIR)/dictionary.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/dictionary.o
+ $(CC) $(SRC_LZSADIR)/expand_block_v1.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_block_v1.o
+ $(CC) $(SRC_LZSADIR)/expand_block_v2.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_block_v2.o
+ $(CC) $(SRC_LZSADIR)/expand_context.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_context.o
+ $(CC) $(SRC_LZSADIR)/expand_inmem.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_inmem.o
+ $(CC) $(SRC_LZSADIR)/frame.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/frame.o
+ $(CC) $(SRC_LZSADIR)/shrink_block_v1.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_block_v1.o
+ $(CC) $(SRC_LZSADIR)/shrink_block_v2.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_block_v2.o
+ $(CC) $(SRC_LZSADIR)/shrink_context.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_context.o
+ $(CC) $(SRC_LZSADIR)/shrink_inmem.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_inmem.o
+ $(CC) $(SRC_LZSADIR)/stream.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/stream.o
+ $(CC) rasm.c $(CFLAGS_DBG)
+
+prod:
+ $(CC) $(SRC_ZX0DIR)/optimize.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/optimize.o
+ $(CC) $(SRC_ZX0DIR)/compress.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/compress.o
+ $(CC) $(SRC_ZX0DIR)/memory.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/memory.o
+
+ $(CC) $(SRC_APUDIR)/expand.c $(APU_FLAGS) -o $(SRC_APUDIR)/expand.o
+ $(CC) $(SRC_APUDIR)/matchfinder.c $(APU_FLAGS) -o $(SRC_APUDIR)/matchfinder.o
+ $(CC) $(SRC_APUDIR)/shrink.c $(APU_FLAGS) -o $(SRC_APUDIR)/shrink.o
+
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/divsufsort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/divsufsort.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/divsufsort_utils.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/divsufsort_utils.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/sssort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/sssort.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/trsort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/trsort.o
+
+ $(CC) $(SRC_LZSADIR)/matchfinder.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/matchfinder.o
+ $(CC) $(SRC_LZSADIR)/dictionary.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/dictionary.o
+ $(CC) $(SRC_LZSADIR)/expand_block_v1.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_block_v1.o
+ $(CC) $(SRC_LZSADIR)/expand_block_v2.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_block_v2.o
+ $(CC) $(SRC_LZSADIR)/expand_context.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_context.o
+ $(CC) $(SRC_LZSADIR)/expand_inmem.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_inmem.o
+ $(CC) $(SRC_LZSADIR)/frame.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/frame.o
+ $(CC) $(SRC_LZSADIR)/shrink_block_v1.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_block_v1.o
+ $(CC) $(SRC_LZSADIR)/shrink_block_v2.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_block_v2.o
+ $(CC) $(SRC_LZSADIR)/shrink_context.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_context.o
+ $(CC) $(SRC_LZSADIR)/shrink_inmem.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_inmem.o
+ $(CC) $(SRC_LZSADIR)/stream.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/stream.o
+
+ $(CC) rasm.c $(CFLAGS_OPT) $(APU_OBJ) $(LZSA_OBJ) $(ZX0_OBJ)
+ strip $(EXEC)
+
+reload:
+ $(CC) rasm.c $(CFLAGS_OPT) $(APU_OBJ) $(LZSA_OBJ) $(ZX0_OBJ)
+ strip $(EXEC)
+
+release:
+ $(CC) $(SRC_ZX0DIR)/optimize.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/optimize.o
+ $(CC) $(SRC_ZX0DIR)/compress.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/compress.o
+ $(CC) $(SRC_ZX0DIR)/memory.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/memory.o
+
+ $(CC) $(SRC_APUDIR)/expand.c $(APU_FLAGS) -o $(SRC_APUDIR)/expand.o
+ $(CC) $(SRC_APUDIR)/matchfinder.c $(APU_FLAGS) -o $(SRC_APUDIR)/matchfinder.o
+ $(CC) $(SRC_APUDIR)/shrink.c $(APU_FLAGS) -o $(SRC_APUDIR)/shrink.o
+
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/divsufsort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/divsufsort.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/divsufsort_utils.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/divsufsort_utils.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/sssort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/sssort.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/trsort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/trsort.o
+
+ $(CC) $(SRC_LZSADIR)/matchfinder.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/matchfinder.o
+ $(CC) $(SRC_LZSADIR)/dictionary.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/dictionary.o
+ $(CC) $(SRC_LZSADIR)/expand_block_v1.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_block_v1.o
+ $(CC) $(SRC_LZSADIR)/expand_block_v2.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_block_v2.o
+ $(CC) $(SRC_LZSADIR)/expand_context.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_context.o
+ $(CC) $(SRC_LZSADIR)/expand_inmem.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_inmem.o
+ $(CC) $(SRC_LZSADIR)/frame.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/frame.o
+ $(CC) $(SRC_LZSADIR)/shrink_block_v1.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_block_v1.o
+ $(CC) $(SRC_LZSADIR)/shrink_block_v2.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_block_v2.o
+ $(CC) $(SRC_LZSADIR)/shrink_context.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_context.o
+ $(CC) $(SRC_LZSADIR)/shrink_inmem.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_inmem.o
+ $(CC) $(SRC_LZSADIR)/stream.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/stream.o
+ $(CC) rasm.c $(CFLAGS_OPT) $(APU_OBJ) $(LZSA_OBJ) $(ZX0_OBJ)
+ strip $(EXEC)
+
+clean:
+ rm -f *.o $(EXEC)
diff --git a/tools/rasm/Makefile.orig b/tools/rasm/Makefile.orig
new file mode 100644
index 0000000..ad43112
--- /dev/null
+++ b/tools/rasm/Makefile.orig
@@ -0,0 +1,145 @@
+CC=cc
+EXEC=rasm.exe
+
+CFLAGS=-lm -lrt -march=native -o $(EXEC)
+CFLAGS_OPT = $(CFLAGS) -O2
+CFLAGS_DBG = $(CFLAGS) -g -pthread -DRDD
+CFLAGS_3RD = $(CFLAGS) -g -pthread -DNO_3RD_PARTIES
+
+SRC_APUDIR=./apultra-master/src
+SRC_LZSADIR=./lzsa-master/src
+SRC_ZX0DIR=./ZX0-main/src
+
+APU_FLAGS=-c -O3 -fomit-frame-pointer -I$(SRC_LZSADIR)/libdivsufsort/include -I$(SRC_APUDIR)
+
+APU_OBJ =$(SRC_APUDIR)/expand.o
+APU_OBJ+=$(SRC_APUDIR)/matchfinder.o
+APU_OBJ+=$(SRC_APUDIR)/shrink.o
+APU_OBJ+=$(SRC_APUDIR)/libdivsufsort/lib/divsufsort.o
+APU_OBJ+=$(SRC_APUDIR)/libdivsufsort/lib/divsufsort_utils.o
+APU_OBJ+=$(SRC_APUDIR)/libdivsufsort/lib/sssort.o
+APU_OBJ+=$(SRC_APUDIR)/libdivsufsort/lib/trsort.o
+
+LZSA_FLAGS=-c -O3 -fomit-frame-pointer -I$(SRC_LZSADIR)/libdivsufsort/include -I$(SRC_LZSADIR)
+
+LZSA_OBJ =$(SRC_LZSADIR)/dictionary.o
+LZSA_OBJ+=$(SRC_LZSADIR)/expand_block_v1.o
+LZSA_OBJ+=$(SRC_LZSADIR)/expand_block_v2.o
+LZSA_OBJ+=$(SRC_LZSADIR)/expand_context.o
+LZSA_OBJ+=$(SRC_LZSADIR)/expand_inmem.o
+LZSA_OBJ+=$(SRC_LZSADIR)/frame.o
+LZSA_OBJ+=$(SRC_LZSADIR)/matchfinder.o
+LZSA_OBJ+=$(SRC_LZSADIR)/shrink_block_v1.o
+LZSA_OBJ+=$(SRC_LZSADIR)/shrink_block_v2.o
+LZSA_OBJ+=$(SRC_LZSADIR)/shrink_context.o
+LZSA_OBJ+=$(SRC_LZSADIR)/shrink_inmem.o
+LZSA_OBJ+=$(SRC_LZSADIR)/stream.o
+
+ZX0_FLAGS=-c -O2 -I$(SRC_ZX0DIR)
+ZX0_OBJ =$(SRC_ZX0DIR)/optimize.o
+ZX0_OBJ+=$(SRC_ZX0DIR)/compress.o
+ZX0_OBJ+=$(SRC_ZX0DIR)/memory.o
+
+.PHONY: prod third debug clean
+
+default: prod
+
+third:
+ $(CC) rasm.c $(CFLAGS_3RD)
+
+debug:
+ $(CC) $(SRC_ZX0DIR)/optimize.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/optimize.o
+ $(CC) $(SRC_ZX0DIR)/compress.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/compress.o
+ $(CC) $(SRC_ZX0DIR)/memory.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/memory.o
+
+ $(CC) $(SRC_APUDIR)/expand.c $(APU_FLAGS) -o $(SRC_APUDIR)/expand.o
+ $(CC) $(SRC_APUDIR)/matchfinder.c $(APU_FLAGS) -o $(SRC_APUDIR)/matchfinder.o
+ $(CC) $(SRC_APUDIR)/shrink.c $(APU_FLAGS) -o $(SRC_APUDIR)/shrink.o
+
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/divsufsort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/divsufsort.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/divsufsort_utils.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/divsufsort_utils.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/sssort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/sssort.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/trsort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/trsort.o
+
+ $(CC) $(SRC_LZSADIR)/matchfinder.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/matchfinder.o
+ $(CC) $(SRC_LZSADIR)/dictionary.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/dictionary.o
+ $(CC) $(SRC_LZSADIR)/expand_block_v1.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_block_v1.o
+ $(CC) $(SRC_LZSADIR)/expand_block_v2.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_block_v2.o
+ $(CC) $(SRC_LZSADIR)/expand_context.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_context.o
+ $(CC) $(SRC_LZSADIR)/expand_inmem.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_inmem.o
+ $(CC) $(SRC_LZSADIR)/frame.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/frame.o
+ $(CC) $(SRC_LZSADIR)/shrink_block_v1.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_block_v1.o
+ $(CC) $(SRC_LZSADIR)/shrink_block_v2.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_block_v2.o
+ $(CC) $(SRC_LZSADIR)/shrink_context.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_context.o
+ $(CC) $(SRC_LZSADIR)/shrink_inmem.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_inmem.o
+ $(CC) $(SRC_LZSADIR)/stream.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/stream.o
+
+ $(CC) rasm.c $(CFLAGS_DBG)
+
+prod:
+ $(CC) $(SRC_ZX0DIR)/optimize.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/optimize.o
+ $(CC) $(SRC_ZX0DIR)/compress.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/compress.o
+ $(CC) $(SRC_ZX0DIR)/memory.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/memory.o
+
+ $(CC) $(SRC_APUDIR)/expand.c $(APU_FLAGS) -o $(SRC_APUDIR)/expand.o
+ $(CC) $(SRC_APUDIR)/matchfinder.c $(APU_FLAGS) -o $(SRC_APUDIR)/matchfinder.o
+ $(CC) $(SRC_APUDIR)/shrink.c $(APU_FLAGS) -o $(SRC_APUDIR)/shrink.o
+
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/divsufsort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/divsufsort.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/divsufsort_utils.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/divsufsort_utils.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/sssort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/sssort.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/trsort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/trsort.o
+
+ $(CC) $(SRC_LZSADIR)/matchfinder.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/matchfinder.o
+ $(CC) $(SRC_LZSADIR)/dictionary.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/dictionary.o
+ $(CC) $(SRC_LZSADIR)/expand_block_v1.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_block_v1.o
+ $(CC) $(SRC_LZSADIR)/expand_block_v2.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_block_v2.o
+ $(CC) $(SRC_LZSADIR)/expand_context.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_context.o
+ $(CC) $(SRC_LZSADIR)/expand_inmem.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_inmem.o
+ $(CC) $(SRC_LZSADIR)/frame.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/frame.o
+ $(CC) $(SRC_LZSADIR)/shrink_block_v1.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_block_v1.o
+ $(CC) $(SRC_LZSADIR)/shrink_block_v2.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_block_v2.o
+ $(CC) $(SRC_LZSADIR)/shrink_context.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_context.o
+ $(CC) $(SRC_LZSADIR)/shrink_inmem.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_inmem.o
+ $(CC) $(SRC_LZSADIR)/stream.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/stream.o
+
+ $(CC) rasm.c $(CFLAGS_OPT) $(APU_OBJ) $(LZSA_OBJ) $(ZX0_OBJ)
+ strip $(EXEC)
+
+reload:
+ $(CC) rasm.c $(CFLAGS_OPT) $(APU_OBJ) $(LZSA_OBJ) $(ZX0_OBJ)
+ strip $(EXEC)
+
+release:
+ $(CC) $(SRC_ZX0DIR)/optimize.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/optimize.o
+ $(CC) $(SRC_ZX0DIR)/compress.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/compress.o
+ $(CC) $(SRC_ZX0DIR)/memory.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/memory.o
+
+ $(CC) $(SRC_APUDIR)/expand.c $(APU_FLAGS) -o $(SRC_APUDIR)/expand.o
+ $(CC) $(SRC_APUDIR)/matchfinder.c $(APU_FLAGS) -o $(SRC_APUDIR)/matchfinder.o
+ $(CC) $(SRC_APUDIR)/shrink.c $(APU_FLAGS) -o $(SRC_APUDIR)/shrink.o
+
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/divsufsort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/divsufsort.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/divsufsort_utils.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/divsufsort_utils.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/sssort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/sssort.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/trsort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/trsort.o
+
+ $(CC) $(SRC_LZSADIR)/matchfinder.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/matchfinder.o
+ $(CC) $(SRC_LZSADIR)/dictionary.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/dictionary.o
+ $(CC) $(SRC_LZSADIR)/expand_block_v1.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_block_v1.o
+ $(CC) $(SRC_LZSADIR)/expand_block_v2.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_block_v2.o
+ $(CC) $(SRC_LZSADIR)/expand_context.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_context.o
+ $(CC) $(SRC_LZSADIR)/expand_inmem.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_inmem.o
+ $(CC) $(SRC_LZSADIR)/frame.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/frame.o
+ $(CC) $(SRC_LZSADIR)/shrink_block_v1.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_block_v1.o
+ $(CC) $(SRC_LZSADIR)/shrink_block_v2.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_block_v2.o
+ $(CC) $(SRC_LZSADIR)/shrink_context.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_context.o
+ $(CC) $(SRC_LZSADIR)/shrink_inmem.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_inmem.o
+ $(CC) $(SRC_LZSADIR)/stream.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/stream.o
+ $(CC) rasm.c $(CFLAGS_OPT) $(APU_OBJ) $(LZSA_OBJ) $(ZX0_OBJ)
+ strip $(EXEC)
+ ./upx --brute rasm.exe
+
+clean:
+ rm -rf *.o
+
diff --git a/tools/rasm/ReadMe b/tools/rasm/ReadMe
new file mode 100644
index 0000000..7aa21a9
--- /dev/null
+++ b/tools/rasm/ReadMe
@@ -0,0 +1,19 @@
+
+Yes! Another Z80 assembler but this one has...
+
+- DAMN fast assembling (millions of instructions in a blink of an eye)
+- integrated crunched sections (LZ48/LZ49/LZ4/ZX0/ZX7/Exomizer/APlib/LZSA1/LZSA2) + load&crunch on the fly
+- CPC cartridge, ZX snapshots, CPC snapshots up to 4M, TAPE output
+- save unlimited binaries with or without AMSDOS/HOBETA header
+- handle multiple EDSK update or generation simultaneously
+- symbols import/export, breakpoint and dependencies export
+- ORG checking, unlimited memory workspaces where labels are shared, bank management, structures
+- ALL undocumented instructions
+- conditionnal macro, unlimited & embeded loops with local labels, switch/case
+- floating point engine, mathematical functions, ...
+- MAXAM, AS80, UZ80, Pasmo compatibility option
+- Amsdos real & Microsoft basic 40bits float support
+- English & French documentation
+
+The project was born a few years ago (2017) because i needed a really fast assembler in order to finish my demo before the deadline of the Alchemy 2017. The project was quite huge with approx 350.000 words to assemble but thanks to rasm, the 512K cartridge compiled in a blink of an eye even on my slow Atom CPU. Now Rasm is the reference for huge projects and ultra-fast assembling.
+
diff --git a/tools/rasm/ZX0-main/LICENSE b/tools/rasm/ZX0-main/LICENSE
new file mode 100644
index 0000000..a0b5162
--- /dev/null
+++ b/tools/rasm/ZX0-main/LICENSE
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2021, Einar Saukas
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/tools/rasm/ZX0-main/README.md b/tools/rasm/ZX0-main/README.md
new file mode 100644
index 0000000..404ac54
--- /dev/null
+++ b/tools/rasm/ZX0-main/README.md
@@ -0,0 +1,369 @@
+# ZX0
+
+**ZX0** is an optimal data compressor for a custom
+[LZ77/LZSS](https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Storer%E2%80%93Szymanski)
+based compression format, that provides a tradeoff between high compression
+ratio, and extremely simple fast decompression. Therefore it's especially
+appropriate for low-end platforms, including 8-bit computers like the ZX
+Spectrum.
+
+
+## Usage
+
+To compress a file, use the command-line compressor as follows:
+
+```
+zx0 Cobra.scr
+```
+
+This will generate a compressed file called "Cobra.scr.zx0".
+
+Afterwards you can choose a decompressor routine in assembly Z80, according to
+your requirements for speed and size:
+
+* "Standard" routine: 69 bytes only
+* "Turbo" routine: 128 bytes, about 20% faster
+* "Mega" routine: 414 bytes, about 25% faster
+
+Finally compile the chosen decompressor routine and load the compressed file
+somewhere in memory. To decompress data, just call the routine specifying the
+source address of compressed data in HL and the target address in DE.
+
+For instance, if you compile the decompressor routine to address 65000, load
+"Cobra.scr.zx0" at address 51200, and you want to decompress it directly to the
+screen, then execute the following code:
+
+```
+ LD HL, 51200 ; source address (put "Cobra.scr.zx0" there)
+ LD DE, 16384 ; target address (screen memory in this case)
+ CALL 65000 ; decompress routine compiled at this address
+```
+
+It's also possible to decompress data into a memory area that partially overlaps
+the compressed data itself (only if you won't need to decompress it again later,
+obviously). In this case, the last address of compressed data must be at least
+"delta" bytes higher than the last address of decompressed data. The exact value
+of "delta" for each case is reported by **ZX0** during compression. See image
+below:
+
+```
+ |------------------| compressed data
+ |---------------------------------| decompressed data
+ start >> <--->
+ delta
+```
+
+For convenience, there's also a command-line decompressor that works as follows:
+
+```
+dzx0 Cobra.scr.zx0
+```
+
+
+## Performance
+
+The **ZX0** optimal compressor algorithm is fairly complex, thus compressing
+typical files can take a few seconds. During development, you can speed up this
+process simply using **ZX0** in "quick" mode. This will produce a non-optimal
+larger compressed file but execute almost instantly:
+
+```
+zx0 -q Cobra.scr
+```
+
+This way, you can repeatedly modify your files, then quickly compress and test
+them. Later, when you finish changing these files, you can compress them again
+without "quick" mode for maximum compression. Notice that using "quick" mode
+will only affect the size of the compressed file, not its format. Therefore
+all decompressor routines will continue to work exactly the same way.
+
+Fortunately all complexity lies on the compression process only. The **ZX0**
+compression format itself is very simple and efficient, providing a high
+compression ratio that can be decompressed quickly and easily. The provided
+**ZX0** decompressor routines in assembly Z80 are small and fast, they only use
+main registers BC, DE, HL, A and optionally alternate register A' (use the
+backwards variant to avoid using A'), consume very little stack space and does
+not require additional decompression buffer.
+
+The provided **ZX0** decompressor in C writes the output file while reading the
+compressed file, without keeping it in memory. Therefore it always use the same
+amount of memory, regardless of file size. Thus even large compressed files can
+be decompressed in very small computers with limited memory, even if it took
+considerable time and memory to compress it originally. It means decompressing
+within asymptotically optimal space and time O(n) only, using storage space O(n)
+for input and output files, and only memory space O(w) for processing.
+
+
+## File Format
+
+The ZX0 compressed format is very simple. There are only 3 kinds of blocks:
+
+* Literal (copy next N bytes from compressed file)
+```
+0 Elias(length) byte[1] byte[2] ... byte[N]
+```
+
+* Copy from last offset (repeat N bytes from last offset)
+```
+0 Elias(length)
+```
+
+* Copy from new offset (repeat N bytes from new offset)
+```
+1 Elias(MSB(offset)) LSB(offset) Elias(length-1)
+```
+
+**ZX0** needs only 1 bit to distinguish between these blocks, because literal
+blocks cannot be consecutive, and reusing last offset can only happen after a
+literal block. The first block is always a literal, so the first bit is omitted.
+
+The offset MSB and all lengths are stored using interlaced
+[Elias Gamma Coding](https://en.wikipedia.org/wiki/Elias_gamma_coding). When
+offset MSB equals 256 it means EOF. The offset LSB is stored using 7 bits
+instead of 8, because it produces better results in most practical cases.
+
+
+## Advanced Features
+
+The **ZX0** compressor contains a few extra "hidden" features, that are slightly
+harder to use properly, and not supported by the **ZX0** decompressor in C. Please
+read carefully these instructions before attempting to use any of them!
+
+
+#### _COMPRESSING BACKWARDS_
+
+When using **ZX0** for "in-place" decompression (decompressing data to overlap the
+same memory area storing the compressed data), you must always leave a small
+margin of "delta" bytes of compressed data at the end. However it won't work to
+decompress some large data that will occupy all the upper memory until the last
+memory address, since there won't be even a couple bytes left at the end.
+
+A possible workaround is to compress and decompress data backwards, starting at
+the last memory address. Therefore you will only need to leave a small margin of
+"delta" bytes of compressed data at the beginning instead. Technically, it will
+require that lowest address of compressed data should be at least "delta" bytes
+lower than lowest address of decompressed data. See image below:
+
+ compressed data |------------------|
+ decompressed data |---------------------------------|
+ <---> << start
+ delta
+
+To compress a file backwards, use the command-line compressor as follows:
+
+```
+zx0 -b Cobra.scr
+```
+
+To decompress it later, you must call one of the supplied "backwards" variants
+of the Assembly decompressor, specifying last source address of compressed data
+in HL and last target address in DE.
+
+For instance, if you compile a "backwards" Assembly decompressor routine to
+address 64000, load backwards compressed file "Cobra.scr.zx0" (with size 2202
+bytes) to address 51200, and want to decompress it directly to the ZX Spectrum
+screen (with 6912 bytes), then execute the following code:
+
+```
+ LD HL, 51200+2202-1 ; source (last address of "Cobra.scr.zx0")
+ LD DE, 16384+6912-1 ; target (last address of screen memory)
+ CALL 64000 ; backwards decompress routine
+```
+
+Notice that compressing backwards may sometimes produce slightly smaller
+compressed files in certain cases, slightly larger compressed files in others.
+Overall it shouldn't make much difference either way.
+
+
+#### _COMPRESSING WITH PREFIX_
+
+The LZ77/LZSS compression is achieved by "abbreviating repetitions", such that
+certain sequences of bytes are replaced with much shorter references to previous
+occurrences of these same sequences. For this reason, it's harder to get very
+good compression ratio on very short files, or in the initial parts of larger
+files, due to lack of choices for previous sequences that could be referenced.
+
+A possible improvement is to compress data while also taking into account what
+else will be already stored in memory during decompression later. Thus the
+compressed data may even contain shorter references to repetitions stored in
+some previous "prefix" memory area, instead of just repetitions within the
+decompressed area itself.
+
+An input file may contain both some prefix data to be referenced only, and the
+actual data to be compressed. An optional parameter can specify how many bytes
+must be skipped before compression. See below:
+
+```
+ compressed data
+ |-------------------|
+ prefix decompressed data
+ |--------------|---------------------------------|
+ start >>
+ <--------------> <--->
+ skip delta
+```
+
+As usual, if you want to decompress data into a memory area that partially
+overlaps the compressed data itself, the last address of compressed data must be
+at least "delta" bytes higher than the last address of decompressed data.
+
+For instance, if you want the first 6144 bytes of a certain file to be skipped
+(not compressed but possibly referenced), then use the command-line compressor
+as follows:
+
+```
+zx0 +6144 Cobra.cbr
+```
+
+In practice, suppose an action game uses a few generic sprites that are common
+for all levels (such as player graphics), and other sprites are specific for
+each level (such as enemies). All generic sprites must stay always accessible at
+a certain memory area, but any level specific data can be only decompressed as
+needed, to the memory area immediately following it. In this case, the generic
+sprites area could be used as prefix when compressing and decompressing each
+level, in an attempt to improve compression. For instance, suppose generic
+graphics are loaded from file "generic.gfx" to address 56000, occupying 2500
+bytes, and level specific graphics will be decompressed immediately afterwards,
+to address 58500. To compress each level using "generic.gfx" as a 2500 bytes
+prefix, use the command-line compressor as follows:
+
+```
+copy /b generic.gfx+level_1.gfx prefixed_level_1.gfx
+zx0 +2500 prefixed_level_1.gfx
+
+copy /b generic.gfx+level_2.gfx prefixed_level_2.gfx
+zx0 +2500 prefixed_level_2.gfx
+
+copy /b generic.gfx+level_3.gfx prefixed_level_3.gfx
+zx0 +2500 prefixed_level_3.gfx
+```
+
+To decompress it later, you simply need to use one of the normal variants of the
+Assembly decompressor, as usual. In this case, if you loaded compressed file
+"prefixed_level_1.gfx.zx0" to address 48000 for instance, decompressing it will
+require the following code:
+
+```
+ LD HL, 48000 ; source address (put "prefixed_level_1.gfx.zx0" there)
+ LD DE, 58500 ; target address (level specific memory area in this case)
+ CALL 65000 ; decompress routine compiled at this address
+```
+
+However decompression will only work properly if exactly the same prefix data is
+present in the memory area immediately preceding the decompression address.
+Therefore you must be extremely careful to ensure the prefix area does not store
+variables, self-modifying code, or anything else that may change prefix content
+between compression and decompression. Also don't forget to recompress your
+files whenever you modify a prefix!
+
+In certain cases, compressing with a prefix may considerably help compression.
+In others, it may not even make any difference. It mostly depends on how much
+similarity exists between data to be compressed and its provided prefix.
+
+
+#### _COMPRESSING BACKWARDS WITH SUFIX_
+
+Both features above can be used together. A file can be compressed backwards,
+with an optional parameter to specify how many bytes should be skipped (not
+compressed but possibly referenced) from the end of the input file instead. See
+below:
+
+```
+ compressed data
+ |-------------------|
+ decompressed data sufix
+ |---------------------------------|--------------|
+ << start
+ <---> <-------------->
+ delta skip
+```
+
+As usual, if you want to decompress data into a memory area that partially
+overlaps the compressed data itself, lowest address of compressed data must be
+at least "delta" bytes lower than lowest address of decompressed data.
+
+For instance, if you want to skip the last 768 bytes of a certain input file and
+compress everything else (possibly referencing this "sufix" of 768 bytes), then
+use the command-line compressor as follows:
+
+```
+zx0 -b +768 Cobra.cbr
+```
+
+In previous example, suppose the action game now stores level-specific sprites
+in the memory area from address 33000 to 33511 (512 bytes), just before generic
+sprites that are stored from address 33512 to 34535 (1024 bytes). In this case,
+these generic sprites could be used as sufix when compressing and decompressing
+level-specific data as needed, in an attempt to improve compression. To compress
+each level using "generic.gfx" as a 1024 bytes sufix, use the command-line
+compressor as follows:
+
+```
+copy /b "level_1.gfx+generic.gfx level_1_sufixed.gfx
+zx0 -b +1024 level_1_sufixed.gfx
+
+copy /b "level_2.gfx+generic.gfx level_2_sufixed.gfx
+zx0 -b +1024 level_2_sufixed.gfx
+
+copy /b "level_3.gfx+generic.gfx level_3_sufixed.gfx
+zx0 -b +1024 level_3_sufixed.gfx
+```
+
+To decompress it later, use the backwards variant of the Assembly decompressor.
+In this case, if you compile a "backwards" decompressor routine to address
+64000, and load compressed file "level_1_sufixed.gfx.zx0" (with 217 bytes) to
+address 39000 for instance, decompressing it will require the following code:
+
+```
+ LD HL, 39000+217-1 ; source (last address of "level_1_sufixed.gfx.zx0")
+ LD DE, 33000+512-1 ; target (last address of level-specific data)
+ CALL 64000 ; backwards decompress routine
+```
+
+Analogously, decompression will only work properly if exactly the same sufix
+data is present in the memory area immediately following the decompression area.
+Therefore you must be extremely careful to ensure the sufix area does not store
+variables, self-modifying code, or anything else that may change sufix content
+between compression and decompression. Also don't forget to recompress your
+files whenever you modify a sufix!
+
+Also if you are using "in-place" decompression, you must leave a small margin of
+"delta" bytes of compressed data just before the decompression area.
+
+
+## License
+
+The **ZX0** data compression format and algorithm was designed and implemented
+by **Einar Saukas**. Special thanks to **introspec/spke** for several
+suggestions and improvements!
+
+The optimal C compressor is available under the "BSD-3" license. In practice,
+this is relevant only if you want to modify its source code and/or incorporate
+the compressor within your own products. Otherwise, if you just execute it to
+compress files, you can simply ignore these conditions.
+
+The decompressors can be used freely within your own programs (either for the
+ZX Spectrum or any other platform), even for commercial releases. The only
+condition is that you must indicate somehow in your documentation that you have
+used **ZX0**.
+
+
+## Links
+
+Projects using **ZX0**:
+
+* [MSXlib](https://github.com/theNestruo/msx-msxlib) - A set of libraries to
+create MSX videogame cartridges, that includes **ZX0** and **ZX7**.
+
+
+Related projects (by the same author):
+
+* [RCS](https://github.com/einar-saukas/RCS) - Use **ZX0** and **RCS** together
+to improve compression of ZX Spectrum screens.
+
+* [ZX1](https://github.com/einar-saukas/ZX1) - A simpler but faster version
+of **ZX0** (**ZX1** sacrifices about 1.5% compression to run about 15% faster).
+
+* [ZX7](https://spectrumcomputing.co.uk/entry/27996/ZX-Spectrum/ZX7) - A widely
+popular predecessor compressor (now superseded by **ZX0**).
+
diff --git a/tools/rasm/ZX0-main/src/compress.c b/tools/rasm/ZX0-main/src/compress.c
new file mode 100644
index 0000000..7feb567
--- /dev/null
+++ b/tools/rasm/ZX0-main/src/compress.c
@@ -0,0 +1,164 @@
+/*
+ * (c) Copyright 2021 by Einar Saukas. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of its author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "zx0.h"
+
+unsigned char* output_data;
+int output_index;
+int input_index;
+int bit_index;
+int bit_mask;
+int diff;
+int backtrack;
+
+void read_bytes(int n, int *delta) {
+ input_index += n;
+ diff += n;
+ if (*delta < diff)
+ *delta = diff;
+}
+
+void write_byte(int value) {
+ output_data[output_index++] = value;
+ diff--;
+}
+
+void write_bit(int value) {
+ if (backtrack) {
+ if (value)
+ output_data[output_index-1] |= 1;
+ backtrack = FALSE;
+ } else {
+ if (!bit_mask) {
+ bit_mask = 128;
+ bit_index = output_index;
+ write_byte(0);
+ }
+ if (value)
+ output_data[bit_index] |= bit_mask;
+ bit_mask >>= 1;
+ }
+}
+
+void write_interlaced_elias_gamma(int value, int backwards_mode, int invert_mode) {
+ int i;
+
+ for (i = 2; i <= value; i <<= 1)
+ ;
+ i >>= 1;
+ while (i >>= 1) {
+ write_bit(backwards_mode);
+ write_bit(invert_mode ? !(value & i) : (value & i));
+ }
+ write_bit(!backwards_mode);
+}
+
+unsigned char *zx0_compress(BLOCK *optimal, unsigned char *input_data, int input_size, int skip, int backwards_mode, int invert_mode, int *output_size, int *delta) {
+ BLOCK *prev;
+ BLOCK *next;
+ int last_offset = INITIAL_OFFSET;
+ int length;
+ int i;
+
+ /* calculate and allocate output buffer */
+ *output_size = (optimal->bits+25)/8;
+ output_data = (unsigned char *)malloc(*output_size);
+ if (!output_data) {
+ fprintf(stderr, "Error: Insufficient memory\n");
+ exit(1);
+ }
+
+ /* un-reverse optimal sequence */
+ prev = NULL;
+ while (optimal) {
+ next = optimal->chain;
+ optimal->chain = prev;
+ prev = optimal;
+ optimal = next;
+ }
+
+ /* initialize data */
+ diff = *output_size-input_size+skip;
+ *delta = 0;
+ input_index = skip;
+ output_index = 0;
+ bit_mask = 0;
+ backtrack = TRUE;
+
+ /* generate output */
+ for (optimal = prev->chain; optimal; prev=optimal, optimal = optimal->chain) {
+ length = optimal->index-prev->index;
+
+ if (!optimal->offset) {
+ /* copy literals indicator */
+ write_bit(0);
+
+ /* copy literals length */
+ write_interlaced_elias_gamma(length, backwards_mode, FALSE);
+
+ /* copy literals values */
+ for (i = 0; i < length; i++) {
+ write_byte(input_data[input_index]);
+ read_bytes(1, delta);
+ }
+ } else if (optimal->offset == last_offset) {
+ /* copy from last offset indicator */
+ write_bit(0);
+
+ /* copy from last offset length */
+ write_interlaced_elias_gamma(length, backwards_mode, FALSE);
+ read_bytes(length, delta);
+ } else {
+ /* copy from new offset indicator */
+ write_bit(1);
+
+ /* copy from new offset MSB */
+ write_interlaced_elias_gamma((optimal->offset-1)/128+1, backwards_mode, invert_mode);
+
+ /* copy from new offset LSB */
+ if (backwards_mode)
+ write_byte(((optimal->offset-1)%128)<<1);
+ else
+ write_byte((127-(optimal->offset-1)%128)<<1);
+
+ /* copy from new offset length */
+ backtrack = TRUE;
+ write_interlaced_elias_gamma(length-1, backwards_mode, FALSE);
+ read_bytes(length, delta);
+
+ last_offset = optimal->offset;
+ }
+ }
+
+ /* end marker */
+ write_bit(1);
+ write_interlaced_elias_gamma(256, backwards_mode, invert_mode);
+
+ /* done! */
+ return output_data;
+}
diff --git a/tools/rasm/ZX0-main/src/memory.c b/tools/rasm/ZX0-main/src/memory.c
new file mode 100644
index 0000000..be52c3a
--- /dev/null
+++ b/tools/rasm/ZX0-main/src/memory.c
@@ -0,0 +1,75 @@
+/*
+ * (c) Copyright 2021 by Einar Saukas. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of its author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "zx0.h"
+
+#define QTY_BLOCKS 10000
+
+BLOCK *ghost_root = NULL;
+BLOCK *dead_array = NULL;
+int dead_array_size = 0;
+
+BLOCK *allocate(int bits, int index, int offset, BLOCK *chain) {
+ BLOCK *ptr;
+
+ if (ghost_root) {
+ ptr = ghost_root;
+ ghost_root = ptr->ghost_chain;
+ if (ptr->chain && !--ptr->chain->references) {
+ ptr->chain->ghost_chain = ghost_root;
+ ghost_root = ptr->chain;
+ }
+ } else {
+ if (!dead_array_size) {
+ dead_array = (BLOCK *)malloc(QTY_BLOCKS*sizeof(BLOCK));
+ if (!dead_array) {
+ fprintf(stderr, "Error: Insufficient memory\n");
+ exit(1);
+ }
+ dead_array_size = QTY_BLOCKS;
+ }
+ ptr = &dead_array[--dead_array_size];
+ }
+ ptr->bits = bits;
+ ptr->index = index;
+ ptr->offset = offset;
+ if (chain)
+ chain->references++;
+ ptr->chain = chain;
+ ptr->references = 0;
+ return ptr;
+}
+
+void assign(BLOCK **ptr, BLOCK *chain) {
+ chain->references++;
+ if (*ptr && !--(*ptr)->references) {
+ (*ptr)->ghost_chain = ghost_root;
+ ghost_root = *ptr;
+ }
+ *ptr = chain;
+}
diff --git a/tools/rasm/ZX0-main/src/optimize.c b/tools/rasm/ZX0-main/src/optimize.c
new file mode 100644
index 0000000..263837c
--- /dev/null
+++ b/tools/rasm/ZX0-main/src/optimize.c
@@ -0,0 +1,137 @@
+/*
+ * (c) Copyright 2021 by Einar Saukas. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of its author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "zx0.h"
+
+#define MAX_SCALE 50
+
+int offset_ceiling(int index, int offset_limit) {
+ return index > offset_limit ? offset_limit : index < INITIAL_OFFSET ? INITIAL_OFFSET : index;
+}
+
+int elias_gamma_bits(int value) {
+ int bits = 1;
+ while (value >>= 1)
+ bits += 2;
+ return bits;
+}
+
+BLOCK* zx0_optimize(unsigned char *input_data, int input_size, int skip, int offset_limit) {
+ BLOCK **last_literal;
+ BLOCK **last_match;
+ BLOCK **optimal;
+ int* match_length;
+ int* best_length;
+ int best_length_size;
+ int bits;
+ int index;
+ int offset;
+ int length;
+ int bits2;
+ int dots = 2;
+ int max_offset = offset_ceiling(input_size-1, offset_limit);
+
+ /* allocate all main data structures at once */
+ last_literal = (BLOCK **)calloc(max_offset+1, sizeof(BLOCK *));
+ last_match = (BLOCK **)calloc(max_offset+1, sizeof(BLOCK *));
+ optimal = (BLOCK **)calloc(input_size, sizeof(BLOCK *));
+ match_length = (int *)calloc(max_offset+1, sizeof(int));
+ best_length = (int *)malloc(input_size*sizeof(int));
+ if (!last_literal || !last_match || !optimal || !match_length || !best_length) {
+ fprintf(stderr, "Error: Insufficient memory\n");
+ exit(1);
+ }
+ best_length[2] = 2;
+
+ /* start with fake block */
+ assign(&last_match[INITIAL_OFFSET], allocate(-1, skip-1, INITIAL_OFFSET, NULL));
+
+ printf("[");
+
+ /* process remaining bytes */
+ for (index = skip; index < input_size; index++) {
+ best_length_size = 2;
+ max_offset = offset_ceiling(index, offset_limit);
+ for (offset = 1; offset <= max_offset; offset++) {
+ if (index != skip && index >= offset && input_data[index] == input_data[index-offset]) {
+ /* copy from last offset */
+ if (last_literal[offset]) {
+ length = index-last_literal[offset]->index;
+ bits = last_literal[offset]->bits + 1 + elias_gamma_bits(length);
+ assign(&last_match[offset], allocate(bits, index, offset, last_literal[offset]));
+ if (!optimal[index] || optimal[index]->bits > bits)
+ assign(&optimal[index], last_match[offset]);
+ }
+ /* copy from new offset */
+ if (++match_length[offset] > 1) {
+ if (best_length_size < match_length[offset]) {
+ bits = optimal[index-best_length[best_length_size]]->bits + elias_gamma_bits(best_length[best_length_size]-1);
+ do {
+ best_length_size++;
+ bits2 = optimal[index-best_length_size]->bits + elias_gamma_bits(best_length_size-1);
+ if (bits2 <= bits) {
+ best_length[best_length_size] = best_length_size;
+ bits = bits2;
+ } else {
+ best_length[best_length_size] = best_length[best_length_size-1];
+ }
+ } while(best_length_size < match_length[offset]);
+ }
+ length = best_length[match_length[offset]];
+ bits = optimal[index-length]->bits + 8 + elias_gamma_bits((offset-1)/128+1) + elias_gamma_bits(length-1);
+ if (!last_match[offset] || last_match[offset]->index != index || last_match[offset]->bits > bits) {
+ assign(&last_match[offset], allocate(bits, index, offset, optimal[index-length]));
+ if (!optimal[index] || optimal[index]->bits > bits)
+ assign(&optimal[index], last_match[offset]);
+ }
+ }
+ } else {
+ /* copy literals */
+ match_length[offset] = 0;
+ if (last_match[offset]) {
+ length = index-last_match[offset]->index;
+ bits = last_match[offset]->bits + 1 + elias_gamma_bits(length) + length*8;
+ assign(&last_literal[offset], allocate(bits, index, 0, last_match[offset]));
+ if (!optimal[index] || optimal[index]->bits > bits)
+ assign(&optimal[index], last_literal[offset]);
+ }
+ }
+ }
+
+ /* indicate progress */
+ if (index*MAX_SCALE/input_size > dots) {
+ printf(".");
+ fflush(stdout);
+ dots++;
+ }
+ }
+
+ printf("]\n");
+
+ return optimal[input_size-1];
+}
diff --git a/tools/rasm/ZX0-main/src/zx0.h b/tools/rasm/ZX0-main/src/zx0.h
new file mode 100644
index 0000000..3b60402
--- /dev/null
+++ b/tools/rasm/ZX0-main/src/zx0.h
@@ -0,0 +1,46 @@
+/*
+ * (c) Copyright 2021 by Einar Saukas. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of its author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define INITIAL_OFFSET 1
+
+#define FALSE 0
+#define TRUE 1
+
+typedef struct block_t {
+ struct block_t *chain;
+ struct block_t *ghost_chain;
+ int bits;
+ int index;
+ int offset;
+ int references;
+} BLOCK;
+
+BLOCK *allocate(int bits, int index, int offset, BLOCK *chain);
+
+void assign(BLOCK **ptr, BLOCK *chain);
+
+BLOCK *zx0_optimize(unsigned char *input_data, int input_size, int skip, int offset_limit);
+
+unsigned char *zx0_compress(BLOCK *optimal, unsigned char *input_data, int input_size, int skip, int backwards_mode, int invert_mode, int *output_size, int *delta);
diff --git a/tools/rasm/apultra-master/src/apultra.c b/tools/rasm/apultra-master/src/apultra.c
new file mode 100644
index 0000000..baababf
--- /dev/null
+++ b/tools/rasm/apultra-master/src/apultra.c
@@ -0,0 +1,1035 @@
+/*
+ * apultra.c - command line compression utility for the apultra library
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by cap by Sven-Åke Dahl. https://github.com/svendahl/cap
+ * Also inspired by Charles Bloom's compression blog. http://cbloomrants.blogspot.com/
+ * With ideas from LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help and support from spke <zxintrospec@gmail.com>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _WIN32
+#include <windows.h>
+#include <sys/timeb.h>
+#else
+#include <sys/time.h>
+#endif
+#include "libapultra.h"
+
+#define OPT_VERBOSE 1
+#define OPT_STATS 2
+#define OPT_BACKWARD 4
+
+#define TOOL_VERSION "1.3.6"
+
+/*---------------------------------------------------------------------------*/
+
+#ifdef _WIN32
+LARGE_INTEGER hpc_frequency;
+BOOL hpc_available = FALSE;
+#endif
+
+static void do_init_time() {
+#ifdef _WIN32
+ hpc_frequency.QuadPart = 0;
+ hpc_available = QueryPerformanceFrequency(&hpc_frequency);
+#endif
+}
+
+static long long do_get_time() {
+ long long nTime;
+
+#ifdef _WIN32
+ if (hpc_available) {
+ LARGE_INTEGER nCurTime;
+
+ /* Use HPC hardware for best precision */
+ QueryPerformanceCounter(&nCurTime);
+ nTime = (long long)(nCurTime.QuadPart * 1000000LL / hpc_frequency.QuadPart);
+ }
+ else {
+ struct _timeb tb;
+ _ftime(&tb);
+
+ nTime = ((long long)tb.time * 1000LL + (long long)tb.millitm) * 1000LL;
+ }
+#else
+ struct timeval tm;
+ gettimeofday(&tm, NULL);
+
+ nTime = (long long)tm.tv_sec * 1000000LL + (long long)tm.tv_usec;
+#endif
+ return nTime;
+}
+
+static void do_reverse_buffer(unsigned char *pBuffer, size_t nBufferSize) {
+ size_t nMidPoint = nBufferSize / 2;
+ size_t i, j;
+
+ for (i = 0, j = nBufferSize - 1; i < nMidPoint; i++, j--) {
+ unsigned char c = pBuffer[i];
+ pBuffer[i] = pBuffer[j];
+ pBuffer[j] = c;
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void compression_progress(long long nOriginalSize, long long nCompressedSize) {
+ if (nOriginalSize >= 512 * 1024) {
+ fprintf(stdout, "\r%lld => %lld (%g %%) \b\b\b\b\b", nOriginalSize, nCompressedSize, (double)(nCompressedSize * 100.0 / nOriginalSize));
+ fflush(stdout);
+ }
+}
+
+static int do_compress(const char *pszInFilename, const char *pszOutFilename, const char *pszDictionaryFilename, const unsigned int nOptions, const unsigned int nMaxWindowSize) {
+ long long nStartTime = 0LL, nEndTime = 0LL;
+ size_t nOriginalSize = 0L, nCompressedSize = 0L, nMaxCompressedSize;
+ int nFlags = 0;
+ apultra_stats stats;
+ unsigned char *pDecompressedData;
+ unsigned char *pCompressedData;
+
+ if (nOptions & OPT_VERBOSE) {
+ nStartTime = do_get_time();
+ }
+
+ FILE* f_dict = NULL;
+ size_t nDictionarySize = 0;
+ if (pszDictionaryFilename) {
+ /* Open the dictionary */
+ f_dict = fopen(pszDictionaryFilename, "rb");
+ if (!f_dict) {
+ fprintf(stderr, "error opening dictionary '%s' for reading\n", pszDictionaryFilename);
+ return 100;
+ }
+
+ /* Get dictionary size */
+ fseek(f_dict, 0, SEEK_END);
+ nDictionarySize = (size_t)ftell(f_dict);
+ fseek(f_dict, 0, SEEK_SET);
+
+ if (nDictionarySize > BLOCK_SIZE) nDictionarySize = BLOCK_SIZE;
+ }
+
+ /* Read the whole original file in memory */
+
+ FILE *f_in = fopen(pszInFilename, "rb");
+ if (!f_in) {
+ if (f_dict) fclose(f_dict);
+ fprintf(stderr, "error opening '%s' for reading\n", pszInFilename);
+ return 100;
+ }
+
+ fseek(f_in, 0, SEEK_END);
+ nOriginalSize = (size_t)ftell(f_in);
+ fseek(f_in, 0, SEEK_SET);
+
+ pDecompressedData = (unsigned char*)malloc(nDictionarySize + nOriginalSize);
+ if (!pDecompressedData) {
+ fclose(f_in);
+ if (f_dict) fclose(f_dict);
+ fprintf(stderr, "out of memory for reading '%s', %zd bytes needed\n", pszInFilename, nOriginalSize);
+ return 100;
+ }
+
+ if (f_dict) {
+ /* Read dictionary data */
+ if (fread(pDecompressedData + ((nOptions & OPT_BACKWARD) ? nOriginalSize : 0), 1, nDictionarySize, f_dict) != nDictionarySize) {
+ free(pDecompressedData);
+ fclose(f_in);
+ fclose(f_dict);
+ fprintf(stderr, "I/O error while reading dictionary '%s'\n", pszDictionaryFilename);
+ return 100;
+ }
+
+ fclose(f_dict);
+ f_dict = NULL;
+ }
+
+ /* Read input file data */
+ if (fread(pDecompressedData + ((nOptions & OPT_BACKWARD) ? 0 : nDictionarySize), 1, nOriginalSize, f_in) != nOriginalSize) {
+ free(pDecompressedData);
+ fclose(f_in);
+ fprintf(stderr, "I/O error while reading '%s'\n", pszInFilename);
+ return 100;
+ }
+
+ fclose(f_in);
+
+ if (nOptions & OPT_BACKWARD)
+ do_reverse_buffer(pDecompressedData, nDictionarySize + nOriginalSize);
+
+ /* Allocate max compressed size */
+
+ nMaxCompressedSize = apultra_get_max_compressed_size(nDictionarySize + nOriginalSize);
+
+ pCompressedData = (unsigned char*)malloc(nMaxCompressedSize);
+ if (!pCompressedData) {
+ free(pDecompressedData);
+ fprintf(stderr, "out of memory for compressing '%s', %zd bytes needed\n", pszInFilename, nMaxCompressedSize);
+ return 100;
+ }
+
+ memset(pCompressedData, 0, nMaxCompressedSize);
+
+ nCompressedSize = apultra_compress(pDecompressedData, pCompressedData, nDictionarySize + nOriginalSize, nMaxCompressedSize, nFlags, nMaxWindowSize, nDictionarySize, compression_progress, &stats);
+
+ if ((nOptions & OPT_VERBOSE)) {
+ nEndTime = do_get_time();
+ }
+
+ if (nCompressedSize == -1) {
+ free(pCompressedData);
+ free(pDecompressedData);
+ fprintf(stderr, "compression error for '%s'\n", pszInFilename);
+ return 100;
+ }
+
+ if (nOptions & OPT_BACKWARD)
+ do_reverse_buffer(pCompressedData, nCompressedSize);
+
+ if (pszOutFilename) {
+ FILE *f_out;
+
+ /* Write whole compressed file out */
+
+ f_out = fopen(pszOutFilename, "wb");
+ if (f_out) {
+ fwrite(pCompressedData, 1, nCompressedSize, f_out);
+ fclose(f_out);
+ }
+ }
+
+ free(pCompressedData);
+ free(pDecompressedData);
+
+ if ((nOptions & OPT_VERBOSE)) {
+ double fDelta = ((double)(nEndTime - nStartTime)) / 1000000.0;
+ double fSpeed = ((double)nOriginalSize / 1048576.0) / fDelta;
+ fprintf(stdout, "\rCompressed '%s' in %g seconds, %.02g Mb/s, %d tokens (%g bytes/token), %d into %d bytes ==> %g %%\n",
+ pszInFilename, fDelta, fSpeed, stats.commands_divisor, (double)nOriginalSize / (double)stats.commands_divisor,
+ (int)nOriginalSize, (int)nCompressedSize, (double)(nCompressedSize * 100.0 / nOriginalSize));
+ }
+
+ if (nOptions & OPT_STATS) {
+ fprintf(stdout, "Tokens: literals: %d short matches: %d normal matches: %d large matches: %d rep matches: %d EOD: %d\n",
+ stats.num_literals, stats.num_4bit_matches, stats.num_7bit_matches, stats.num_variable_matches, stats.num_rep_matches, stats.num_eod);
+ if (stats.match_divisor > 0) {
+ fprintf(stdout, "Offsets: min: %d avg: %d max: %d count: %d\n", stats.min_offset, (int)(stats.total_offsets / (long long)stats.match_divisor), stats.max_offset, stats.match_divisor);
+ fprintf(stdout, "Match lens: min: %d avg: %d max: %d count: %d\n", stats.min_match_len, stats.total_match_lens / stats.match_divisor, stats.max_match_len, stats.match_divisor);
+ }
+ else {
+ fprintf(stdout, "Offsets: none\n");
+ fprintf(stdout, "Match lens: none\n");
+ }
+ if (stats.rle1_divisor > 0) {
+ fprintf(stdout, "RLE1 lens: min: %d avg: %d max: %d count: %d\n", stats.min_rle1_len, stats.total_rle1_lens / stats.rle1_divisor, stats.max_rle1_len, stats.rle1_divisor);
+ }
+ else {
+ fprintf(stdout, "RLE1 lens: none\n");
+ }
+ if (stats.rle2_divisor > 0) {
+ fprintf(stdout, "RLE2 lens: min: %d avg: %d max: %d count: %d\n", stats.min_rle2_len, stats.total_rle2_lens / stats.rle2_divisor, stats.max_rle2_len, stats.rle2_divisor);
+ }
+ else {
+ fprintf(stdout, "RLE2 lens: none\n");
+ }
+ fprintf(stdout, "Safe distance: %d (0x%X)\n", stats.safe_dist, stats.safe_dist);
+ }
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static int do_decompress(const char *pszInFilename, const char *pszOutFilename, const char *pszDictionaryFilename, const unsigned int nOptions) {
+ long long nStartTime = 0LL, nEndTime = 0LL;
+ size_t nCompressedSize, nMaxDecompressedSize, nOriginalSize;
+ unsigned char *pCompressedData;
+ unsigned char *pDecompressedData;
+ int nFlags = 0;
+
+ /* Read the whole compressed file in memory */
+
+ FILE *f_in = fopen(pszInFilename, "rb");
+ if (!f_in) {
+ fprintf(stderr, "error opening '%s' for reading\n", pszInFilename);
+ return 100;
+ }
+
+ fseek(f_in, 0, SEEK_END);
+ nCompressedSize = (size_t)ftell(f_in);
+ fseek(f_in, 0, SEEK_SET);
+
+ pCompressedData = (unsigned char*)malloc(nCompressedSize);
+ if (!pCompressedData) {
+ fclose(f_in);
+ fprintf(stderr, "out of memory for reading '%s', %zd bytes needed\n", pszInFilename, nCompressedSize);
+ return 100;
+ }
+
+ if (fread(pCompressedData, 1, nCompressedSize, f_in) != nCompressedSize) {
+ free(pCompressedData);
+ fclose(f_in);
+ fprintf(stderr, "I/O error while reading '%s'\n", pszInFilename);
+ return 100;
+ }
+
+ fclose(f_in);
+
+ if (nOptions & OPT_BACKWARD)
+ do_reverse_buffer(pCompressedData, nCompressedSize);
+
+ /* Get max decompressed size */
+
+ nMaxDecompressedSize = apultra_get_max_decompressed_size(pCompressedData, nCompressedSize, nFlags);
+ if (nMaxDecompressedSize == -1) {
+ free(pCompressedData);
+ fprintf(stderr, "invalid compressed format for file '%s'\n", pszInFilename);
+ return 100;
+ }
+
+ FILE* f_dict = NULL;
+ size_t nDictionarySize = 0;
+ if (pszDictionaryFilename) {
+ /* Open the dictionary */
+ f_dict = fopen(pszDictionaryFilename, "rb");
+ if (!f_dict) {
+ fprintf(stderr, "error opening dictionary '%s' for reading\n", pszDictionaryFilename);
+ return 100;
+ }
+
+ /* Get dictionary size */
+ fseek(f_dict, 0, SEEK_END);
+ nDictionarySize = (size_t)ftell(f_dict);
+ fseek(f_dict, 0, SEEK_SET);
+
+ if (nDictionarySize > BLOCK_SIZE) nDictionarySize = BLOCK_SIZE;
+ }
+
+ /* Allocate max decompressed size */
+
+ pDecompressedData = (unsigned char*)malloc(nDictionarySize + nMaxDecompressedSize);
+ if (!pDecompressedData) {
+ free(pCompressedData);
+ if (f_dict) fclose(f_dict);
+ fprintf(stderr, "out of memory for decompressing '%s', %zd bytes needed\n", pszInFilename, nMaxDecompressedSize);
+ return 100;
+ }
+
+ memset(pDecompressedData, 0, nDictionarySize + nMaxDecompressedSize);
+
+ if (f_dict) {
+ /* Read dictionary data */
+ if (fread(pDecompressedData, 1, nDictionarySize, f_dict) != nDictionarySize) {
+ free(pDecompressedData);
+ fclose(f_in);
+ fclose(f_dict);
+ fprintf(stderr, "I/O error while reading dictionary '%s'\n", pszDictionaryFilename);
+ return 100;
+ }
+
+ fclose(f_dict);
+ f_dict = NULL;
+
+ if (nOptions & OPT_BACKWARD)
+ do_reverse_buffer(pDecompressedData, nDictionarySize);
+ }
+
+ if (nOptions & OPT_VERBOSE) {
+ nStartTime = do_get_time();
+ }
+
+ nOriginalSize = apultra_decompress(pCompressedData, pDecompressedData, nCompressedSize, nMaxDecompressedSize, nDictionarySize, nFlags);
+ if (nOriginalSize == -1) {
+ free(pDecompressedData);
+ free(pCompressedData);
+
+ fprintf(stderr, "decompression error for '%s'\n", pszInFilename);
+ return 100;
+ }
+
+ if (nOptions & OPT_BACKWARD)
+ do_reverse_buffer(pDecompressedData + nDictionarySize, nOriginalSize);
+
+ if (pszOutFilename) {
+ FILE *f_out;
+
+ /* Write whole decompressed file out */
+
+ f_out = fopen(pszOutFilename, "wb");
+ if (f_out) {
+ fwrite(pDecompressedData + nDictionarySize, 1, nOriginalSize, f_out);
+ fclose(f_out);
+ }
+ }
+
+ free(pDecompressedData);
+ free(pCompressedData);
+
+ if (nOptions & OPT_VERBOSE) {
+ nEndTime = do_get_time();
+ double fDelta = ((double)(nEndTime - nStartTime)) / 1000000.0;
+ double fSpeed = ((double)nOriginalSize / 1048576.0) / fDelta;
+ fprintf(stdout, "Decompressed '%s' in %g seconds, %g Mb/s\n",
+ pszInFilename, fDelta, fSpeed);
+ }
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static int do_compare(const char *pszInFilename, const char *pszOutFilename, const char *pszDictionaryFilename, const unsigned int nOptions) {
+ long long nStartTime = 0LL, nEndTime = 0LL;
+ size_t nCompressedSize, nMaxDecompressedSize, nOriginalSize, nDecompressedSize;
+ unsigned char *pCompressedData = NULL;
+ unsigned char *pOriginalData = NULL;
+ unsigned char *pDecompressedData = NULL;
+ int nFlags = 0;
+
+ /* Read the whole compressed file in memory */
+
+ FILE *f_in = fopen(pszInFilename, "rb");
+ if (!f_in) {
+ fprintf(stderr, "error opening '%s' for reading\n", pszInFilename);
+ return 100;
+ }
+
+ fseek(f_in, 0, SEEK_END);
+ nCompressedSize = (size_t)ftell(f_in);
+ fseek(f_in, 0, SEEK_SET);
+
+ pCompressedData = (unsigned char*)malloc(nCompressedSize);
+ if (!pCompressedData) {
+ fclose(f_in);
+ fprintf(stderr, "out of memory for reading '%s', %zd bytes needed\n", pszInFilename, nCompressedSize);
+ return 100;
+ }
+
+ if (fread(pCompressedData, 1, nCompressedSize, f_in) != nCompressedSize) {
+ free(pCompressedData);
+ fclose(f_in);
+ fprintf(stderr, "I/O error while reading '%s'\n", pszInFilename);
+ return 100;
+ }
+
+ fclose(f_in);
+
+ if (nOptions & OPT_BACKWARD)
+ do_reverse_buffer(pCompressedData, nCompressedSize);
+
+ /* Read the whole original file in memory */
+
+ f_in = fopen(pszOutFilename, "rb");
+ if (!f_in) {
+ free(pCompressedData);
+ fprintf(stderr, "error opening '%s' for reading\n", pszInFilename);
+ return 100;
+ }
+
+ fseek(f_in, 0, SEEK_END);
+ nOriginalSize = (size_t)ftell(f_in);
+ fseek(f_in, 0, SEEK_SET);
+
+ pOriginalData = (unsigned char*)malloc(nOriginalSize);
+ if (!pOriginalData) {
+ fclose(f_in);
+ free(pCompressedData);
+ fprintf(stderr, "out of memory for reading '%s', %zd bytes needed\n", pszInFilename, nOriginalSize);
+ return 100;
+ }
+
+ if (fread(pOriginalData, 1, nOriginalSize, f_in) != nOriginalSize) {
+ free(pOriginalData);
+ fclose(f_in);
+ free(pCompressedData);
+ fprintf(stderr, "I/O error while reading '%s'\n", pszInFilename);
+ return 100;
+ }
+
+ fclose(f_in);
+
+ /* Get max decompressed size */
+
+ nMaxDecompressedSize = apultra_get_max_decompressed_size(pCompressedData, nCompressedSize, nFlags);
+ if (nMaxDecompressedSize == -1) {
+ free(pOriginalData);
+ free(pCompressedData);
+ fprintf(stderr, "invalid compressed format for file '%s'\n", pszInFilename);
+ return 100;
+ }
+
+ FILE* f_dict = NULL;
+ size_t nDictionarySize = 0;
+ if (pszDictionaryFilename) {
+ /* Open the dictionary */
+ f_dict = fopen(pszDictionaryFilename, "rb");
+ if (!f_dict) {
+ fprintf(stderr, "error opening dictionary '%s' for reading\n", pszDictionaryFilename);
+ return 100;
+ }
+
+ /* Get dictionary size */
+ fseek(f_dict, 0, SEEK_END);
+ nDictionarySize = (size_t)ftell(f_dict);
+ fseek(f_dict, 0, SEEK_SET);
+
+ if (nDictionarySize > BLOCK_SIZE) nDictionarySize = BLOCK_SIZE;
+ }
+
+ /* Allocate max decompressed size */
+
+ pDecompressedData = (unsigned char*)malloc(nDictionarySize + nMaxDecompressedSize);
+ if (!pDecompressedData) {
+ free(pOriginalData);
+ free(pCompressedData);
+ if (f_dict) fclose(f_dict);
+ fprintf(stderr, "out of memory for decompressing '%s', %zd bytes needed\n", pszInFilename, nMaxDecompressedSize);
+ return 100;
+ }
+
+ memset(pDecompressedData, 0, nDictionarySize + nMaxDecompressedSize);
+
+ if (f_dict) {
+ /* Read dictionary data */
+ if (fread(pDecompressedData, 1, nDictionarySize, f_dict) != nDictionarySize) {
+ free(pDecompressedData);
+ fclose(f_in);
+ fclose(f_dict);
+ fprintf(stderr, "I/O error while reading dictionary '%s'\n", pszDictionaryFilename);
+ return 100;
+ }
+
+ fclose(f_dict);
+ f_dict = NULL;
+
+ if (nOptions & OPT_BACKWARD)
+ do_reverse_buffer(pDecompressedData, nDictionarySize);
+ }
+
+ if (nOptions & OPT_VERBOSE) {
+ nStartTime = do_get_time();
+ }
+
+ nDecompressedSize = apultra_decompress(pCompressedData, pDecompressedData, nCompressedSize, nMaxDecompressedSize, nDictionarySize, nFlags);
+ if (nDecompressedSize == -1) {
+ free(pDecompressedData);
+ free(pOriginalData);
+ free(pCompressedData);
+
+ fprintf(stderr, "decompression error for '%s'\n", pszInFilename);
+ return 100;
+ }
+
+ if (nOptions & OPT_BACKWARD)
+ do_reverse_buffer(pDecompressedData + nDictionarySize, nDecompressedSize);
+
+ if (nDecompressedSize != nOriginalSize || memcmp(pDecompressedData + nDictionarySize, pOriginalData, nOriginalSize)) {
+ fprintf(stderr, "error comparing compressed file '%s' with original '%s'\n", pszInFilename, pszOutFilename);
+ return 100;
+ }
+
+ free(pDecompressedData);
+ free(pOriginalData);
+ free(pCompressedData);
+
+ if (nOptions & OPT_VERBOSE) {
+ nEndTime = do_get_time();
+ double fDelta = ((double)(nEndTime - nStartTime)) / 1000000.0;
+ double fSpeed = ((double)nOriginalSize / 1048576.0) / fDelta;
+ fprintf(stdout, "Compared '%s' in %g seconds, %g Mb/s\n",
+ pszInFilename, fDelta, fSpeed);
+ }
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void generate_compressible_data(unsigned char *pBuffer, size_t nBufferSize, unsigned int nSeed, int nNumLiteralValues, float fMatchProbability) {
+ size_t nIndex = 0;
+ int nMatchProbability = (int)(fMatchProbability * 1023.0f);
+
+ srand(nSeed);
+
+ if (nIndex >= nBufferSize) return;
+ pBuffer[nIndex++] = rand() % nNumLiteralValues;
+
+ while (nIndex < nBufferSize) {
+ if ((rand() & 1023) >= nMatchProbability) {
+ size_t nLiteralCount = rand() & 127;
+ if (nLiteralCount > (nBufferSize - nIndex))
+ nLiteralCount = nBufferSize - nIndex;
+
+ while (nLiteralCount--)
+ pBuffer[nIndex++] = rand() % nNumLiteralValues;
+ }
+ else {
+ size_t nMatchLength = MIN_MATCH_SIZE + (rand() & 1023);
+ size_t nMatchOffset;
+
+ if (nMatchLength > (nBufferSize - nIndex))
+ nMatchLength = nBufferSize - nIndex;
+ if (nMatchLength > nIndex)
+ nMatchLength = nIndex;
+
+ if (nMatchLength < nIndex)
+ nMatchOffset = rand() % (nIndex - nMatchLength);
+ else
+ nMatchOffset = 0;
+
+ while (nMatchLength--) {
+ pBuffer[nIndex] = pBuffer[nIndex - nMatchOffset];
+ nIndex++;
+ }
+ }
+ }
+}
+
+static void xor_data(unsigned char *pBuffer, size_t nBufferSize, unsigned int nSeed, float fXorProbability) {
+ size_t nIndex = 0;
+ int nXorProbability = (int)(fXorProbability * 1023.0f);
+
+ srand(nSeed);
+
+ if (nIndex >= nBufferSize) return;
+
+ while (nIndex < nBufferSize) {
+ if ((rand() & 1023) < nXorProbability) {
+ pBuffer[nIndex] ^= 0xff;
+ }
+ nIndex++;
+ }
+}
+
+static int do_self_test(const unsigned int nOptions, const unsigned int nMaxWindowSize, const int nIsQuickTest) {
+ unsigned char *pGeneratedData;
+ unsigned char *pCompressedData;
+ unsigned char *pTmpCompressedData;
+ unsigned char *pTmpDecompressedData;
+ size_t nGeneratedDataSize;
+ size_t nMaxCompressedDataSize;
+ unsigned int nSeed = 123;
+ int nFlags = 0;
+ int i;
+
+ pGeneratedData = (unsigned char*)malloc(4 * BLOCK_SIZE);
+ if (!pGeneratedData) {
+ fprintf(stderr, "out of memory, %d bytes needed\n", 4 * BLOCK_SIZE);
+ return 100;
+ }
+
+ nMaxCompressedDataSize = apultra_get_max_compressed_size(4 * BLOCK_SIZE);
+ pCompressedData = (unsigned char*)malloc(nMaxCompressedDataSize);
+ if (!pCompressedData) {
+ free(pGeneratedData);
+ pGeneratedData = NULL;
+
+ fprintf(stderr, "out of memory, %zd bytes needed\n", nMaxCompressedDataSize);
+ return 100;
+ }
+
+ pTmpCompressedData = (unsigned char*)malloc(nMaxCompressedDataSize);
+ if (!pTmpCompressedData) {
+ free(pCompressedData);
+ pCompressedData = NULL;
+ free(pGeneratedData);
+ pGeneratedData = NULL;
+
+ fprintf(stderr, "out of memory, %zd bytes needed\n", nMaxCompressedDataSize);
+ return 100;
+ }
+
+ pTmpDecompressedData = (unsigned char*)malloc(4 * BLOCK_SIZE);
+ if (!pTmpDecompressedData) {
+ free(pTmpCompressedData);
+ pTmpCompressedData = NULL;
+ free(pCompressedData);
+ pCompressedData = NULL;
+ free(pGeneratedData);
+ pGeneratedData = NULL;
+
+ fprintf(stderr, "out of memory, %d bytes needed\n", 4 * BLOCK_SIZE);
+ return 100;
+ }
+
+ memset(pGeneratedData, 0, 4 * BLOCK_SIZE);
+ memset(pCompressedData, 0, nMaxCompressedDataSize);
+ memset(pTmpCompressedData, 0, nMaxCompressedDataSize);
+
+ /* Test compressing with a too small buffer to do anything, expect to fail cleanly */
+ for (i = 0; i < 12; i++) {
+ generate_compressible_data(pGeneratedData, i, nSeed, 256, 0.5f);
+ apultra_compress(pGeneratedData, pCompressedData, i, i, nFlags, nMaxWindowSize, 0 /* dictionary size */, NULL, NULL);
+ }
+
+ size_t nDataSizeStep = 128;
+ float fProbabilitySizeStep = nIsQuickTest ? 0.005f : 0.0005f;
+
+ for (nGeneratedDataSize = 1024; nGeneratedDataSize <= (nIsQuickTest ? 1024U : (4U * BLOCK_SIZE)); nGeneratedDataSize += nDataSizeStep) {
+ float fMatchProbability;
+
+ fprintf(stdout, "size %zd", nGeneratedDataSize);
+ for (fMatchProbability = 0; fMatchProbability <= 0.995f; fMatchProbability += fProbabilitySizeStep) {
+ int nNumLiteralValues[12] = { 1, 2, 3, 15, 30, 56, 96, 137, 178, 191, 255, 256 };
+ float fXorProbability;
+
+ fputc('.', stdout);
+ fflush(stdout);
+
+ for (i = 0; i < 12; i++) {
+ /* Generate data to compress */
+ generate_compressible_data(pGeneratedData, nGeneratedDataSize, nSeed, nNumLiteralValues[i], fMatchProbability);
+
+ /* Try to compress it, expected to succeed */
+ size_t nActualCompressedSize = apultra_compress(pGeneratedData, pCompressedData, nGeneratedDataSize, apultra_get_max_compressed_size(nGeneratedDataSize),
+ nFlags, nMaxWindowSize, 0 /* dictionary size */, NULL, NULL);
+ if (nActualCompressedSize == -1 || nActualCompressedSize < (1 + 1 + 1 /* footer */)) {
+ free(pTmpDecompressedData);
+ pTmpDecompressedData = NULL;
+ free(pTmpCompressedData);
+ pTmpCompressedData = NULL;
+ free(pCompressedData);
+ pCompressedData = NULL;
+ free(pGeneratedData);
+ pGeneratedData = NULL;
+
+ fprintf(stderr, "\nself-test: error compressing size %zd, seed %d, match probability %f, literals range %d\n", nGeneratedDataSize, nSeed, fMatchProbability, nNumLiteralValues[i]);
+ return 100;
+ }
+
+ /* Try to decompress it, expected to succeed */
+ size_t nActualDecompressedSize;
+ nActualDecompressedSize = apultra_decompress(pCompressedData, pTmpDecompressedData, nActualCompressedSize, nGeneratedDataSize, 0 /* dictionary size */, nFlags);
+ if (nActualDecompressedSize == -1) {
+ free(pTmpDecompressedData);
+ pTmpDecompressedData = NULL;
+ free(pTmpCompressedData);
+ pTmpCompressedData = NULL;
+ free(pCompressedData);
+ pCompressedData = NULL;
+ free(pGeneratedData);
+ pGeneratedData = NULL;
+
+ fprintf(stderr, "\nself-test: error decompressing size %zd, seed %d, match probability %f, literals range %d\n", nGeneratedDataSize, nSeed, fMatchProbability, nNumLiteralValues[i]);
+ return 100;
+ }
+
+ if (memcmp(pGeneratedData, pTmpDecompressedData, nGeneratedDataSize)) {
+ free(pTmpDecompressedData);
+ pTmpDecompressedData = NULL;
+ free(pTmpCompressedData);
+ pTmpCompressedData = NULL;
+ free(pCompressedData);
+ pCompressedData = NULL;
+ free(pGeneratedData);
+ pGeneratedData = NULL;
+
+ fprintf(stderr, "\nself-test: error comparing decompressed and original data, size %zd, seed %d, match probability %f, literals range %d\n", nGeneratedDataSize, nSeed, fMatchProbability, nNumLiteralValues[i]);
+ return 100;
+ }
+
+ /* Try to decompress corrupted data, expected to fail cleanly, without crashing or corrupting memory outside the output buffer */
+ for (fXorProbability = 0.05f; fXorProbability <= 0.5f; fXorProbability += 0.05f) {
+ memcpy(pTmpCompressedData, pCompressedData, nActualCompressedSize);
+ xor_data(pTmpCompressedData, nActualCompressedSize, nSeed, fXorProbability);
+ apultra_decompress(pTmpCompressedData, pGeneratedData, nActualCompressedSize, nGeneratedDataSize, 0 /* dictionary size */, nFlags);
+ }
+ }
+
+ nSeed++;
+ }
+
+ fputc(10, stdout);
+ fflush(stdout);
+
+ nDataSizeStep <<= 1;
+ if (nDataSizeStep > (128 * 4096))
+ nDataSizeStep = 128 * 4096;
+ fProbabilitySizeStep *= 1.25;
+ if (fProbabilitySizeStep > (0.0005f * 4096))
+ fProbabilitySizeStep = 0.0005f * 4096;
+ }
+
+ free(pTmpDecompressedData);
+ pTmpDecompressedData = NULL;
+
+ free(pTmpCompressedData);
+ pTmpCompressedData = NULL;
+
+ free(pCompressedData);
+ pCompressedData = NULL;
+
+ free(pGeneratedData);
+ pGeneratedData = NULL;
+
+ fprintf(stdout, "All tests passed.\n");
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static int do_compr_benchmark(const char *pszInFilename, const char *pszOutFilename, const char *pszDictionaryFilename, const unsigned int nOptions, const unsigned int nMaxWindowSize) {
+ size_t nFileSize, nMaxCompressedSize;
+ unsigned char *pFileData;
+ unsigned char *pCompressedData;
+ int nFlags = 0;
+ int i;
+
+ if (pszDictionaryFilename) {
+ fprintf(stderr, "in-memory benchmarking does not support dictionaries\n");
+ return 100;
+ }
+
+ /* Read the whole original file in memory */
+
+ FILE *f_in = fopen(pszInFilename, "rb");
+ if (!f_in) {
+ fprintf(stderr, "error opening '%s' for reading\n", pszInFilename);
+ return 100;
+ }
+
+ fseek(f_in, 0, SEEK_END);
+ nFileSize = (size_t)ftell(f_in);
+ fseek(f_in, 0, SEEK_SET);
+
+ pFileData = (unsigned char*)malloc(nFileSize);
+ if (!pFileData) {
+ fclose(f_in);
+ fprintf(stderr, "out of memory for reading '%s', %zd bytes needed\n", pszInFilename, nFileSize);
+ return 100;
+ }
+
+ if (fread(pFileData, 1, nFileSize, f_in) != nFileSize) {
+ free(pFileData);
+ fclose(f_in);
+ fprintf(stderr, "I/O error while reading '%s'\n", pszInFilename);
+ return 100;
+ }
+
+ fclose(f_in);
+
+ if (nOptions & OPT_BACKWARD)
+ do_reverse_buffer(pFileData, nFileSize);
+
+ /* Allocate max compressed size */
+
+ nMaxCompressedSize = apultra_get_max_compressed_size(nFileSize);
+
+ pCompressedData = (unsigned char*)malloc(nMaxCompressedSize + 2048);
+ if (!pCompressedData) {
+ free(pFileData);
+ fprintf(stderr, "out of memory for compressing '%s', %zd bytes needed\n", pszInFilename, nMaxCompressedSize);
+ return 100;
+ }
+
+ memset(pCompressedData + 1024, 0, nMaxCompressedSize);
+
+ long long nBestCompTime = -1;
+
+ size_t nActualCompressedSize = 0;
+ size_t nRightGuardPos = nMaxCompressedSize;
+
+ for (i = 0; i < 5; i++) {
+ unsigned char nGuard = 0x33 + i;
+ int j;
+
+ /* Write guard bytes around the output buffer, to help check for writes outside of it by the compressor */
+ memset(pCompressedData, nGuard, 1024);
+ memset(pCompressedData + 1024 + nRightGuardPos, nGuard, 1024);
+
+ long long t0 = do_get_time();
+ nActualCompressedSize = apultra_compress(pFileData, pCompressedData + 1024, nFileSize, nRightGuardPos, nFlags, nMaxWindowSize, 0 /* dictionary size */, NULL, NULL);
+ long long t1 = do_get_time();
+ if (nActualCompressedSize == -1) {
+ free(pCompressedData);
+ free(pFileData);
+ fprintf(stderr, "compression error\n");
+ return 100;
+ }
+
+ long long nCurDecTime = t1 - t0;
+ if (nBestCompTime == -1 || nBestCompTime > nCurDecTime)
+ nBestCompTime = nCurDecTime;
+
+ /* Check guard bytes before the output buffer */
+ for (j = 0; j < 1024; j++) {
+ if (pCompressedData[j] != nGuard) {
+ free(pCompressedData);
+ free(pFileData);
+ fprintf(stderr, "error, wrote outside of output buffer at %d!\n", j - 1024);
+ return 100;
+ }
+ }
+
+ /* Check guard bytes after the output buffer */
+ for (j = 0; j < 1024; j++) {
+ if (pCompressedData[1024 + nRightGuardPos + j] != nGuard) {
+ free(pCompressedData);
+ free(pFileData);
+ fprintf(stderr, "error, wrote outside of output buffer at %d!\n", j);
+ return 100;
+ }
+ }
+
+ nRightGuardPos = nActualCompressedSize;
+ }
+
+ if (nOptions & OPT_BACKWARD)
+ do_reverse_buffer(pCompressedData + 1024, nActualCompressedSize);
+
+ if (pszOutFilename) {
+ FILE *f_out;
+
+ /* Write whole compressed file out */
+
+ f_out = fopen(pszOutFilename, "wb");
+ if (f_out) {
+ fwrite(pCompressedData + 1024, 1, nActualCompressedSize, f_out);
+ fclose(f_out);
+ }
+ }
+
+ free(pCompressedData);
+ free(pFileData);
+
+ fprintf(stdout, "compressed size: %zd bytes\n", nActualCompressedSize);
+ fprintf(stdout, "compression time: %lld microseconds (%g Mb/s)\n", nBestCompTime, ((double)nActualCompressedSize / 1024.0) / ((double)nBestCompTime / 1000.0));
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static int do_dec_benchmark(const char *pszInFilename, const char *pszOutFilename, const char *pszDictionaryFilename, const unsigned int nOptions) {
+ size_t nFileSize, nMaxDecompressedSize;
+ unsigned char *pFileData;
+ unsigned char *pDecompressedData;
+ int nFlags = 0;
+ int i;
+
+ if (pszDictionaryFilename) {
+ fprintf(stderr, "in-memory benchmarking does not support dictionaries\n");
+ return 100;
+ }
+
+ /* Read the whole compressed file in memory */
+
+ FILE *f_in = fopen(pszInFilename, "rb");
+ if (!f_in) {
+ fprintf(stderr, "error opening '%s' for reading\n", pszInFilename);
+ return 100;
+ }
+
+ fseek(f_in, 0, SEEK_END);
+ nFileSize = (size_t)ftell(f_in);
+ fseek(f_in, 0, SEEK_SET);
+
+ pFileData = (unsigned char*)malloc(nFileSize);
+ if (!pFileData) {
+ fclose(f_in);
+ fprintf(stderr, "out of memory for reading '%s', %zd bytes needed\n", pszInFilename, nFileSize);
+ return 100;
+ }
+
+ if (fread(pFileData, 1, nFileSize, f_in) != nFileSize) {
+ free(pFileData);
+ fclose(f_in);
+ fprintf(stderr, "I/O error while reading '%s'\n", pszInFilename);
+ return 100;
+ }
+
+ fclose(f_in);
+
+ if (nOptions & OPT_BACKWARD)
+ do_reverse_buffer(pFileData, nFileSize);
+
+ /* Allocate max decompressed size */
+
+ nMaxDecompressedSize = apultra_get_max_decompressed_size(pFileData, nFileSize, nFlags);
+ if (nMaxDecompressedSize == -1) {
+ free(pFileData);
+ fprintf(stderr, "invalid compressed format for file '%s'\n", pszInFilename);
+ return 100;
+ }
+
+ pDecompressedData = (unsigned char*)malloc(nMaxDecompressedSize);
+ if (!pDecompressedData) {
+ free(pFileData);
+ fprintf(stderr, "out of memory for decompressing '%s', %zd bytes needed\n", pszInFilename, nMaxDecompressedSize);
+ return 100;
+ }
+
+ memset(pDecompressedData, 0, nMaxDecompressedSize);
+
+ long long nBestDecTime = -1;
+
+ size_t nActualDecompressedSize = 0;
+ for (i = 0; i < 50; i++) {
+ long long t0 = do_get_time();
+ nActualDecompressedSize = apultra_decompress(pFileData, pDecompressedData, nFileSize, nMaxDecompressedSize, 0 /* dictionary size */, nFlags);
+ long long t1 = do_get_time();
+ if (nActualDecompressedSize == -1) {
+ free(pDecompressedData);
+ free(pFileData);
+ fprintf(stderr, "decompression error\n");
+ return 100;
+ }
+
+ long long nCurDecTime = t1 - t0;
+ if (nBestDecTime == -1 || nBestDecTime > nCurDecTime)
+ nBestDecTime = nCurDecTime;
+ }
+
+ if (nOptions & OPT_BACKWARD)
+ do_reverse_buffer(pDecompressedData, nActualDecompressedSize);
+
+ if (pszOutFilename) {
+ FILE *f_out;
+
+ /* Write whole decompressed file out */
+
+ f_out = fopen(pszOutFilename, "wb");
+ if (f_out) {
+ fwrite(pDecompressedData, 1, nActualDecompressedSize, f_out);
+ fclose(f_out);
+ }
+ }
+
+ free(pDecompressedData);
+ free(pFileData);
+
+ fprintf(stdout, "decompressed size: %zd bytes\n", nActualDecompressedSize);
+ fprintf(stdout, "decompression time: %lld microseconds (%g Mb/s)\n", nBestDecTime, ((double)nActualDecompressedSize / 1024.0) / ((double)nBestDecTime / 1000.0));
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
diff --git a/tools/rasm/apultra-master/src/expand.c b/tools/rasm/apultra-master/src/expand.c
new file mode 100644
index 0000000..76b3bf1
--- /dev/null
+++ b/tools/rasm/apultra-master/src/expand.c
@@ -0,0 +1,396 @@
+/*
+ * expand.c - decompressor implementation
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by cap by Sven-Åke Dahl. https://github.com/svendahl/cap
+ * Also inspired by Charles Bloom's compression blog. http://cbloomrants.blogspot.com/
+ * With ideas from LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help and support from spke <zxintrospec@gmail.com>
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "format.h"
+#include "expand.h"
+#include "libapultra.h"
+
+#ifdef _MSC_VER
+#define FORCE_INLINE __forceinline
+#else /* _MSC_VER */
+#define FORCE_INLINE __attribute__((always_inline))
+#endif /* _MSC_VER */
+
+static inline FORCE_INLINE int apultra_read_bit(const unsigned char **ppInBlock, const unsigned char *pDataEnd, int *nCurBitMask, unsigned char *bits) {
+ const unsigned char *pInBlock = *ppInBlock;
+ int nBit;
+
+ if ((*nCurBitMask) == 0) {
+ if (pInBlock >= pDataEnd) return -1;
+ (*bits) = *pInBlock++;
+ (*nCurBitMask) = 128;
+ }
+
+ nBit = ((*bits) & 128) ? 1 : 0;
+
+ (*bits) <<= 1;
+ (*nCurBitMask) >>= 1;
+
+ *ppInBlock = pInBlock;
+ return nBit;
+}
+
+static inline FORCE_INLINE int apultra_read_gamma2(const unsigned char **ppInBlock, const unsigned char *pDataEnd, int *nCurBitMask, unsigned char *bits) {
+ int bit;
+ unsigned int v = 1;
+
+ do {
+ v = (v << 1) + apultra_read_bit(ppInBlock, pDataEnd, nCurBitMask, bits);
+ bit = apultra_read_bit(ppInBlock, pDataEnd, nCurBitMask, bits);
+ if (bit < 0) return bit;
+ } while (bit);
+
+ return v;
+}
+
+/**
+ * Get maximum decompressed size of compressed data
+ *
+ * @param pInputData compressed data
+ * @param nInputSize compressed size in bytes
+ * @param nFlags compression flags (set to 0)
+ *
+ * @return maximum decompressed size
+ */
+size_t apultra_get_max_decompressed_size(const unsigned char *pInputData, size_t nInputSize, const unsigned int nFlags) {
+ const unsigned char *pInputDataEnd = pInputData + nInputSize;
+ int nCurBitMask = 0;
+ unsigned char bits = 0;
+ int nMatchOffset = -1;
+ int nFollowsLiteral = 3;
+ size_t nDecompressedSize = 0;
+
+ if (pInputData >= pInputDataEnd)
+ return -1;
+ pInputData++;
+ nDecompressedSize++;
+
+ while (1) {
+ unsigned int nResult;
+
+ nResult = apultra_read_bit(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+ if (nResult < 0) return -1;
+
+ if (!nResult) {
+ /* '0': literal */
+ if (pInputData < pInputDataEnd) {
+ pInputData++;
+ nDecompressedSize++;
+ nFollowsLiteral = 3;
+ }
+ else {
+ return -1;
+ }
+ }
+ else {
+ nResult = apultra_read_bit(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+ if (nResult < 0) return -1;
+
+ if (nResult == 0) {
+ unsigned int nMatchLen;
+
+ /* '10': 8+n bits offset */
+ int nMatchOffsetHi = apultra_read_gamma2(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+ nMatchOffsetHi -= nFollowsLiteral;
+ if (nMatchOffsetHi >= 0) {
+ nMatchOffset = ((unsigned int) nMatchOffsetHi) << 8;
+ nMatchOffset |= (unsigned int)(*pInputData++);
+
+ nMatchLen = apultra_read_gamma2(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+
+ if (nMatchOffset < 128 || nMatchOffset >= MINMATCH4_OFFSET)
+ nMatchLen += 2;
+ else if (nMatchOffset >= MINMATCH3_OFFSET)
+ nMatchLen++;
+ }
+ else {
+ /* else rep-match */
+ nMatchLen = apultra_read_gamma2(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+ }
+
+ nFollowsLiteral = 2;
+
+ nDecompressedSize += nMatchLen;
+ }
+ else {
+ nResult = apultra_read_bit(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+ if (nResult < 0) return -1;
+
+ if (nResult == 0) {
+ unsigned int nCommand;
+ unsigned int nMatchLen;
+
+ /* '110': 7 bits offset + 1 bit length */
+ nCommand = (unsigned int)(*pInputData++);
+ if (nCommand == 0x00) {
+ /* EOD. No match len follows. */
+ break;
+ }
+
+ /* Bits 7-1: offset; bit 0: length */
+ nMatchOffset = (nCommand >> 1);
+ nMatchLen = (nCommand & 1) + 2;
+
+ nFollowsLiteral = 2;
+ nDecompressedSize += nMatchLen;
+ }
+ else {
+ unsigned int nShortMatchOffset;
+
+ /* '111': 4 bit offset */
+ nResult = apultra_read_bit(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+ if (nResult < 0) return -1;
+ nShortMatchOffset = nResult << 3;
+
+ nResult = apultra_read_bit(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+ if (nResult < 0) return -1;
+ nShortMatchOffset |= nResult << 2;
+
+ nResult = apultra_read_bit(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+ if (nResult < 0) return -1;
+ nShortMatchOffset |= nResult << 1;
+
+ nResult = apultra_read_bit(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+ if (nResult < 0) return -1;
+ nShortMatchOffset |= nResult << 0;
+
+ nFollowsLiteral = 3;
+ nDecompressedSize++;
+ }
+ }
+ }
+ }
+
+ return nDecompressedSize;
+}
+
+/**
+ * Decompress data in memory
+ *
+ * @param pInputData compressed data
+ * @param pOutBuffer buffer for decompressed data
+ * @param nInputSize compressed size in bytes
+ * @param nMaxOutBufferSize maximum capacity of decompression buffer
+ * @param nDictionarySize size of dictionary in front of input data (0 for none)
+ * @param nFlags compression flags (set to 0)
+ *
+ * @return actual decompressed size, or -1 for error
+ */
+size_t apultra_decompress(const unsigned char *pInputData, unsigned char *pOutData, size_t nInputSize, size_t nMaxOutBufferSize, size_t nDictionarySize, const unsigned int nFlags) {
+ const unsigned char *pInputDataEnd = pInputData + nInputSize;
+ unsigned char *pCurOutData = pOutData + nDictionarySize;
+ const unsigned char *pOutDataEnd = pCurOutData + nMaxOutBufferSize;
+ const unsigned char *pOutDataFastEnd = pOutDataEnd - 20;
+ int nCurBitMask = 0;
+ unsigned char bits = 0;
+ int nMatchOffset = -1;
+ int nFollowsLiteral = 3;
+
+ if (pInputData >= pInputDataEnd && pCurOutData < pOutDataEnd)
+ return -1;
+ *pCurOutData++ = *pInputData++;
+
+ while (1) {
+ unsigned int nResult;
+
+ nResult = apultra_read_bit(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+ if (nResult < 0) return -1;
+
+ if (!nResult) {
+ /* '0': literal */
+ if (pInputData < pInputDataEnd && pCurOutData < pOutDataEnd) {
+ *pCurOutData++ = *pInputData++;
+ nFollowsLiteral = 3;
+ }
+ else {
+ return -1;
+ }
+ }
+ else {
+ nResult = apultra_read_bit(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+ if (nResult < 0) return -1;
+
+ if (nResult == 0) {
+ unsigned int nMatchLen;
+
+ /* '10': 8+n bits offset */
+ int nMatchOffsetHi = apultra_read_gamma2(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+ nMatchOffsetHi -= nFollowsLiteral;
+ if (nMatchOffsetHi >= 0) {
+ nMatchOffset = ((unsigned int) nMatchOffsetHi) << 8;
+ nMatchOffset |= (unsigned int)(*pInputData++);
+
+ nMatchLen = apultra_read_gamma2(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+
+ if (nMatchOffset < 128 || nMatchOffset >= MINMATCH4_OFFSET)
+ nMatchLen += 2;
+ else if (nMatchOffset >= MINMATCH3_OFFSET)
+ nMatchLen++;
+ }
+ else {
+ /* else rep-match */
+ nMatchLen = apultra_read_gamma2(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+ }
+
+ nFollowsLiteral = 2;
+ const unsigned char *pSrc = pCurOutData - nMatchOffset;
+ if (pSrc >= pOutData && (pSrc + nMatchLen) <= pOutDataEnd) {
+ if (nMatchLen < 11 && nMatchOffset >= 8 && pCurOutData < pOutDataFastEnd) {
+ memcpy(pCurOutData, pSrc, 8);
+ memcpy(pCurOutData + 8, pSrc + 8, 2);
+ pCurOutData += nMatchLen;
+ }
+ else {
+ if ((pCurOutData + nMatchLen) <= pOutDataEnd) {
+ /* Do a deterministic, left to right byte copy instead of memcpy() so as to handle overlaps */
+
+ if (nMatchOffset >= 16 && (pCurOutData + nMatchLen) < (pOutDataFastEnd - 15)) {
+ const unsigned char *pCopySrc = pSrc;
+ unsigned char *pCopyDst = pCurOutData;
+ const unsigned char *pCopyEndDst = pCurOutData + nMatchLen;
+
+ do {
+ memcpy(pCopyDst, pCopySrc, 16);
+ pCopySrc += 16;
+ pCopyDst += 16;
+ } while (pCopyDst < pCopyEndDst);
+
+ pCurOutData += nMatchLen;
+ }
+ else {
+ while (nMatchLen) {
+ *pCurOutData++ = *pSrc++;
+ nMatchLen--;
+ }
+ }
+ }
+ else {
+ return -1;
+ }
+ }
+ }
+ else {
+ return -1;
+ }
+ }
+ else {
+ nResult = apultra_read_bit(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+ if (nResult < 0) return -1;
+
+ if (nResult == 0) {
+ unsigned int nCommand;
+ unsigned int nMatchLen;
+
+ /* '110': 7 bits offset + 1 bit length */
+ nCommand = (unsigned int)(*pInputData++);
+ if (nCommand == 0x00) {
+ /* EOD. No match len follows. */
+ break;
+ }
+
+ /* Bits 7-1: offset; bit 0: length */
+ nMatchOffset = (nCommand >> 1);
+ nMatchLen = (nCommand & 1) + 2;
+
+ nFollowsLiteral = 2;
+ const unsigned char *pSrc = pCurOutData - nMatchOffset;
+ if (pSrc >= pOutData && (pSrc + nMatchLen) <= pOutDataEnd) {
+ if (nMatchOffset >= 8 && pCurOutData < pOutDataFastEnd) {
+ memcpy(pCurOutData, pSrc, 8);
+ memcpy(pCurOutData + 8, pSrc + 8, 2);
+ pCurOutData += nMatchLen;
+ }
+ else {
+ if ((pCurOutData + nMatchLen) <= pOutDataEnd) {
+ while (nMatchLen) {
+ *pCurOutData++ = *pSrc++;
+ nMatchLen--;
+ }
+ }
+ else {
+ return -1;
+ }
+ }
+ }
+ else {
+ return -1;
+ }
+ }
+ else {
+ unsigned int nShortMatchOffset;
+
+ /* '111': 4 bit offset */
+ nResult = apultra_read_bit(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+ if (nResult < 0) return -1;
+ nShortMatchOffset = nResult << 3;
+
+ nResult = apultra_read_bit(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+ if (nResult < 0) return -1;
+ nShortMatchOffset |= nResult << 2;
+
+ nResult = apultra_read_bit(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+ if (nResult < 0) return -1;
+ nShortMatchOffset |= nResult << 1;
+
+ nResult = apultra_read_bit(&pInputData, pInputDataEnd, &nCurBitMask, &bits);
+ if (nResult < 0) return -1;
+ nShortMatchOffset |= nResult << 0;
+
+ nFollowsLiteral = 3;
+ if (nShortMatchOffset) {
+ /* Short offset, 1-15 */
+ const unsigned char *pSrc = pCurOutData - nShortMatchOffset;
+ if (pSrc >= pOutData && (pCurOutData + 1) <= pOutDataEnd && (pSrc + 1) <= pOutDataEnd) {
+ *pCurOutData++ = *pSrc++;
+ }
+ else {
+ return -1;
+ }
+ }
+ else {
+ /* Write zero */
+ if ((pCurOutData + 1) <= pOutDataEnd) {
+ *pCurOutData++ = 0;
+ }
+ else {
+ return -1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return (size_t)(pCurOutData - pOutData) - nDictionarySize;
+}
diff --git a/tools/rasm/apultra-master/src/expand.h b/tools/rasm/apultra-master/src/expand.h
new file mode 100644
index 0000000..474660c
--- /dev/null
+++ b/tools/rasm/apultra-master/src/expand.h
@@ -0,0 +1,71 @@
+/*
+ * expand.h - decompressor definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by cap by Sven-Åke Dahl. https://github.com/svendahl/cap
+ * Also inspired by Charles Bloom's compression blog. http://cbloomrants.blogspot.com/
+ * With ideas from LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help and support from spke <zxintrospec@gmail.com>
+ *
+ */
+
+#ifndef _EXPAND_H
+#define _EXPAND_H
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Get maximum decompressed size of compressed data
+ *
+ * @param pInputData compressed data
+ * @param nInputSize compressed size in bytes
+ * @param nFlags compression flags (set to 0)
+ *
+ * @return maximum decompressed size
+ */
+size_t apultra_get_max_decompressed_size(const unsigned char *pInputData, size_t nInputSize, const unsigned int nFlags);
+
+/**
+ * Decompress data in memory
+ *
+ * @param pInputData compressed data
+ * @param pOutBuffer buffer for decompressed data
+ * @param nInputSize compressed size in bytes
+ * @param nMaxOutBufferSize maximum capacity of decompression buffer
+ * @param nDictionarySize size of dictionary in front of input data (0 for none)
+ * @param nFlags compression flags (set to 0)
+ *
+ * @return actual decompressed size, or -1 for error
+ */
+size_t apultra_decompress(const unsigned char *pInputData, unsigned char *pOutBuffer, size_t nInputSize, size_t nMaxOutBufferSize, size_t nDictionarySize, const unsigned int nFlags);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _EXPAND_H */
diff --git a/tools/rasm/apultra-master/src/format.h b/tools/rasm/apultra-master/src/format.h
new file mode 100644
index 0000000..cf949b5
--- /dev/null
+++ b/tools/rasm/apultra-master/src/format.h
@@ -0,0 +1,47 @@
+/*
+ * format.h - byte stream format definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by cap by Sven-Åke Dahl. https://github.com/svendahl/cap
+ * Also inspired by Charles Bloom's compression blog. http://cbloomrants.blogspot.com/
+ * With ideas from LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help and support from spke <zxintrospec@gmail.com>
+ *
+ */
+
+#ifndef _FORMAT_H
+#define _FORMAT_H
+
+#define MIN_OFFSET 1
+#define MAX_OFFSET 0x1fffff
+
+#define MAX_VARLEN 0x1fffff
+
+#define BLOCK_SIZE 0x100000
+
+#define MIN_MATCH_SIZE 1
+#define MINMATCH3_OFFSET 1280
+#define MINMATCH4_OFFSET 32000
+
+#endif /* _FORMAT_H */
diff --git a/tools/rasm/apultra-master/src/libapultra.h b/tools/rasm/apultra-master/src/libapultra.h
new file mode 100644
index 0000000..f97e336
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libapultra.h
@@ -0,0 +1,40 @@
+/*
+ * libapultra.h - library definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by cap by Sven-Åke Dahl. https://github.com/svendahl/cap
+ * Also inspired by Charles Bloom's compression blog. http://cbloomrants.blogspot.com/
+ * With ideas from LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help and support from spke <zxintrospec@gmail.com>
+ *
+ */
+
+#ifndef _LIB_APULTRA_H
+#define _LIB_APULTRA_H
+
+#include "format.h"
+#include "shrink.h"
+#include "expand.h"
+
+#endif /* _LIB_APULTRA_H */
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/CHANGELOG.md b/tools/rasm/apultra-master/src/libdivsufsort/CHANGELOG.md
new file mode 100644
index 0000000..fe9d004
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/CHANGELOG.md
@@ -0,0 +1,21 @@
+# libdivsufsort Change Log
+
+See full changelog at: https://github.com/y-256/libdivsufsort/commits
+
+## [2.0.1] - 2010-11-11
+### Fixed
+* Wrong variable used in `divbwt` function
+* Enclose some string variables with double quotation marks in include/CMakeLists.txt
+* Fix typo in include/CMakeLists.txt
+
+## 2.0.0 - 2008-08-23
+### Changed
+* Switch the build system to [CMake](http://www.cmake.org/)
+* Improve the performance of the suffix-sorting algorithm
+
+### Added
+* OpenMP support
+* 64-bit version of divsufsort
+
+[Unreleased]: https://github.com/y-256/libdivsufsort/compare/2.0.1...HEAD
+[2.0.1]: https://github.com/y-256/libdivsufsort/compare/2.0.0...2.0.1
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/CMakeLists.txt b/tools/rasm/apultra-master/src/libdivsufsort/CMakeLists.txt
new file mode 100644
index 0000000..7859943
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/CMakeLists.txt
@@ -0,0 +1,99 @@
+### cmake file for building libdivsufsort Package ###
+cmake_minimum_required(VERSION 2.4.4)
+set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
+include(AppendCompilerFlags)
+
+## Project information ##
+project(libdivsufsort C)
+set(PROJECT_VENDOR "Yuta Mori")
+set(PROJECT_CONTACT "yuta.256@gmail.com")
+set(PROJECT_URL "https://github.com/y-256/libdivsufsort")
+set(PROJECT_DESCRIPTION "A lightweight suffix sorting library")
+include(VERSION.cmake)
+
+## CPack configuration ##
+set(CPACK_GENERATOR "TGZ;TBZ2;ZIP")
+set(CPACK_SOURCE_GENERATOR "TGZ;TBZ2;ZIP")
+include(ProjectCPack)
+
+## Project options ##
+option(BUILD_SHARED_LIBS "Set to OFF to build static libraries" ON)
+option(BUILD_EXAMPLES "Build examples" ON)
+option(BUILD_DIVSUFSORT64 "Build libdivsufsort64" OFF)
+option(USE_OPENMP "Use OpenMP for parallelization" OFF)
+option(WITH_LFS "Enable Large File Support" ON)
+
+## Installation directories ##
+set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32 or 64)")
+
+set(CMAKE_INSTALL_RUNTIMEDIR "" CACHE PATH "Specify the output directory for dll runtimes (default is bin)")
+if(NOT CMAKE_INSTALL_RUNTIMEDIR)
+ set(CMAKE_INSTALL_RUNTIMEDIR "${CMAKE_INSTALL_PREFIX}/bin")
+endif(NOT CMAKE_INSTALL_RUNTIMEDIR)
+
+set(CMAKE_INSTALL_LIBDIR "" CACHE PATH "Specify the output directory for libraries (default is lib)")
+if(NOT CMAKE_INSTALL_LIBDIR)
+ set(CMAKE_INSTALL_LIBDIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}")
+endif(NOT CMAKE_INSTALL_LIBDIR)
+
+set(CMAKE_INSTALL_INCLUDEDIR "" CACHE PATH "Specify the output directory for header files (default is include)")
+if(NOT CMAKE_INSTALL_INCLUDEDIR)
+ set(CMAKE_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/include")
+endif(NOT CMAKE_INSTALL_INCLUDEDIR)
+
+set(CMAKE_INSTALL_PKGCONFIGDIR "" CACHE PATH "Specify the output directory for pkgconfig files (default is lib/pkgconfig)")
+if(NOT CMAKE_INSTALL_PKGCONFIGDIR)
+ set(CMAKE_INSTALL_PKGCONFIGDIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+endif(NOT CMAKE_INSTALL_PKGCONFIGDIR)
+
+## Build type ##
+if(NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE "Release")
+elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
+ set(CMAKE_VERBOSE_MAKEFILE ON)
+endif(NOT CMAKE_BUILD_TYPE)
+
+## Compiler options ##
+if(MSVC)
+ append_c_compiler_flags("/W4" "VC" CMAKE_C_FLAGS)
+ append_c_compiler_flags("/Oi;/Ot;/Ox;/Oy" "VC" CMAKE_C_FLAGS_RELEASE)
+ if(USE_OPENMP)
+ append_c_compiler_flags("/openmp" "VC" CMAKE_C_FLAGS)
+ endif(USE_OPENMP)
+elseif(BORLAND)
+ append_c_compiler_flags("-w" "BCC" CMAKE_C_FLAGS)
+ append_c_compiler_flags("-Oi;-Og;-Os;-Ov;-Ox" "BCC" CMAKE_C_FLAGS_RELEASE)
+else(MSVC)
+ if(CMAKE_COMPILER_IS_GNUCC)
+ append_c_compiler_flags("-Wall" "GCC" CMAKE_C_FLAGS)
+ append_c_compiler_flags("-fomit-frame-pointer" "GCC" CMAKE_C_FLAGS_RELEASE)
+ if(USE_OPENMP)
+ append_c_compiler_flags("-fopenmp" "GCC" CMAKE_C_FLAGS)
+ endif(USE_OPENMP)
+ else(CMAKE_COMPILER_IS_GNUCC)
+ append_c_compiler_flags("-Wall" "UNKNOWN" CMAKE_C_FLAGS)
+ append_c_compiler_flags("-fomit-frame-pointer" "UNKNOWN" CMAKE_C_FLAGS_RELEASE)
+ if(USE_OPENMP)
+ append_c_compiler_flags("-fopenmp;-openmp;-omp" "UNKNOWN" CMAKE_C_FLAGS)
+ endif(USE_OPENMP)
+ endif(CMAKE_COMPILER_IS_GNUCC)
+endif(MSVC)
+
+## Add definitions ##
+add_definitions(-DHAVE_CONFIG_H=1 -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS)
+
+## Add subdirectories ##
+add_subdirectory(pkgconfig)
+add_subdirectory(include)
+add_subdirectory(lib)
+if(BUILD_EXAMPLES)
+ add_subdirectory(examples)
+endif(BUILD_EXAMPLES)
+
+## Add 'uninstall' target ##
+CONFIGURE_FILE(
+ "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/cmake_uninstall.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/CMakeModules/cmake_uninstall.cmake"
+ IMMEDIATE @ONLY)
+ADD_CUSTOM_TARGET(uninstall
+ "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/CMakeModules/cmake_uninstall.cmake")
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/AppendCompilerFlags.cmake b/tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/AppendCompilerFlags.cmake
new file mode 100644
index 0000000..58d3f99
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/AppendCompilerFlags.cmake
@@ -0,0 +1,38 @@
+include(CheckCSourceCompiles)
+include(CheckCXXSourceCompiles)
+
+macro(append_c_compiler_flags _flags _name _result)
+ set(SAFE_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
+ string(REGEX REPLACE "[-+/ ]" "_" cname "${_name}")
+ string(TOUPPER "${cname}" cname)
+ foreach(flag ${_flags})
+ string(REGEX REPLACE "^[-+/ ]+(.*)[-+/ ]*$" "\\1" flagname "${flag}")
+ string(REGEX REPLACE "[-+/ ]" "_" flagname "${flagname}")
+ string(TOUPPER "${flagname}" flagname)
+ set(have_flag "HAVE_${cname}_${flagname}")
+ set(CMAKE_REQUIRED_FLAGS "${flag}")
+ check_c_source_compiles("int main() { return 0; }" ${have_flag})
+ if(${have_flag})
+ set(${_result} "${${_result}} ${flag}")
+ endif(${have_flag})
+ endforeach(flag)
+ set(CMAKE_REQUIRED_FLAGS ${SAFE_CMAKE_REQUIRED_FLAGS})
+endmacro(append_c_compiler_flags)
+
+macro(append_cxx_compiler_flags _flags _name _result)
+ set(SAFE_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
+ string(REGEX REPLACE "[-+/ ]" "_" cname "${_name}")
+ string(TOUPPER "${cname}" cname)
+ foreach(flag ${_flags})
+ string(REGEX REPLACE "^[-+/ ]+(.*)[-+/ ]*$" "\\1" flagname "${flag}")
+ string(REGEX REPLACE "[-+/ ]" "_" flagname "${flagname}")
+ string(TOUPPER "${flagname}" flagname)
+ set(have_flag "HAVE_${cname}_${flagname}")
+ set(CMAKE_REQUIRED_FLAGS "${flag}")
+ check_cxx_source_compiles("int main() { return 0; }" ${have_flag})
+ if(${have_flag})
+ set(${_result} "${${_result}} ${flag}")
+ endif(${have_flag})
+ endforeach(flag)
+ set(CMAKE_REQUIRED_FLAGS ${SAFE_CMAKE_REQUIRED_FLAGS})
+endmacro(append_cxx_compiler_flags)
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/CheckFunctionKeywords.cmake b/tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/CheckFunctionKeywords.cmake
new file mode 100644
index 0000000..44601fd
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/CheckFunctionKeywords.cmake
@@ -0,0 +1,15 @@
+include(CheckCSourceCompiles)
+
+macro(check_function_keywords _wordlist)
+ set(${_result} "")
+ foreach(flag ${_wordlist})
+ string(REGEX REPLACE "[-+/ ()]" "_" flagname "${flag}")
+ string(TOUPPER "${flagname}" flagname)
+ set(have_flag "HAVE_${flagname}")
+ check_c_source_compiles("${flag} void func(); void func() { } int main() { func(); return 0; }" ${have_flag})
+ if(${have_flag} AND NOT ${_result})
+ set(${_result} "${flag}")
+# break()
+ endif(${have_flag} AND NOT ${_result})
+ endforeach(flag)
+endmacro(check_function_keywords)
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/CheckLFS.cmake b/tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/CheckLFS.cmake
new file mode 100644
index 0000000..e2b0099
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/CheckLFS.cmake
@@ -0,0 +1,109 @@
+## Checks for large file support ##
+include(CheckIncludeFile)
+include(CheckSymbolExists)
+include(CheckTypeSize)
+
+macro(check_lfs _isenable)
+ set(LFS_OFF_T "")
+ set(LFS_FOPEN "")
+ set(LFS_FSEEK "")
+ set(LFS_FTELL "")
+ set(LFS_PRID "")
+
+ if(${_isenable})
+ set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
+ set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+ -D_LARGEFILE_SOURCE -D_LARGE_FILES -D_FILE_OFFSET_BITS=64
+ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS)
+
+ check_include_file("sys/types.h" HAVE_SYS_TYPES_H)
+ check_include_file("inttypes.h" HAVE_INTTYPES_H)
+ check_include_file("stddef.h" HAVE_STDDEF_H)
+ check_include_file("stdint.h" HAVE_STDINT_H)
+
+ # LFS type1: 8 <= sizeof(off_t), fseeko, ftello
+ check_type_size("off_t" SIZEOF_OFF_T)
+ if(SIZEOF_OFF_T GREATER 7)
+ check_symbol_exists("fseeko" "stdio.h" HAVE_FSEEKO)
+ check_symbol_exists("ftello" "stdio.h" HAVE_FTELLO)
+ if(HAVE_FSEEKO AND HAVE_FTELLO)
+ set(LFS_OFF_T "off_t")
+ set(LFS_FOPEN "fopen")
+ set(LFS_FSEEK "fseeko")
+ set(LFS_FTELL "ftello")
+ check_symbol_exists("PRIdMAX" "inttypes.h" HAVE_PRIDMAX)
+ if(HAVE_PRIDMAX)
+ set(LFS_PRID "PRIdMAX")
+ else(HAVE_PRIDMAX)
+ check_type_size("long" SIZEOF_LONG)
+ check_type_size("int" SIZEOF_INT)
+ if(SIZEOF_OFF_T GREATER SIZEOF_LONG)
+ set(LFS_PRID "\"lld\"")
+ elseif(SIZEOF_LONG GREATER SIZEOF_INT)
+ set(LFS_PRID "\"ld\"")
+ else(SIZEOF_OFF_T GREATER SIZEOF_LONG)
+ set(LFS_PRID "\"d\"")
+ endif(SIZEOF_OFF_T GREATER SIZEOF_LONG)
+ endif(HAVE_PRIDMAX)
+ endif(HAVE_FSEEKO AND HAVE_FTELLO)
+ endif(SIZEOF_OFF_T GREATER 7)
+
+ # LFS type2: 8 <= sizeof(off64_t), fopen64, fseeko64, ftello64
+ if(NOT LFS_OFF_T)
+ check_type_size("off64_t" SIZEOF_OFF64_T)
+ if(SIZEOF_OFF64_T GREATER 7)
+ check_symbol_exists("fopen64" "stdio.h" HAVE_FOPEN64)
+ check_symbol_exists("fseeko64" "stdio.h" HAVE_FSEEKO64)
+ check_symbol_exists("ftello64" "stdio.h" HAVE_FTELLO64)
+ if(HAVE_FOPEN64 AND HAVE_FSEEKO64 AND HAVE_FTELLO64)
+ set(LFS_OFF_T "off64_t")
+ set(LFS_FOPEN "fopen64")
+ set(LFS_FSEEK "fseeko64")
+ set(LFS_FTELL "ftello64")
+ check_symbol_exists("PRIdMAX" "inttypes.h" HAVE_PRIDMAX)
+ if(HAVE_PRIDMAX)
+ set(LFS_PRID "PRIdMAX")
+ else(HAVE_PRIDMAX)
+ check_type_size("long" SIZEOF_LONG)
+ check_type_size("int" SIZEOF_INT)
+ if(SIZEOF_OFF64_T GREATER SIZEOF_LONG)
+ set(LFS_PRID "\"lld\"")
+ elseif(SIZEOF_LONG GREATER SIZEOF_INT)
+ set(LFS_PRID "\"ld\"")
+ else(SIZEOF_OFF64_T GREATER SIZEOF_LONG)
+ set(LFS_PRID "\"d\"")
+ endif(SIZEOF_OFF64_T GREATER SIZEOF_LONG)
+ endif(HAVE_PRIDMAX)
+ endif(HAVE_FOPEN64 AND HAVE_FSEEKO64 AND HAVE_FTELLO64)
+ endif(SIZEOF_OFF64_T GREATER 7)
+ endif(NOT LFS_OFF_T)
+
+ # LFS type3: 8 <= sizeof(__int64), _fseeki64, _ftelli64
+ if(NOT LFS_OFF_T)
+ check_type_size("__int64" SIZEOF___INT64)
+ if(SIZEOF___INT64 GREATER 7)
+ check_symbol_exists("_fseeki64" "stdio.h" HAVE__FSEEKI64)
+ check_symbol_exists("_ftelli64" "stdio.h" HAVE__FTELLI64)
+ if(HAVE__FSEEKI64 AND HAVE__FTELLI64)
+ set(LFS_OFF_T "__int64")
+ set(LFS_FOPEN "fopen")
+ set(LFS_FSEEK "_fseeki64")
+ set(LFS_FTELL "_ftelli64")
+ set(LFS_PRID "\"I64d\"")
+ endif(HAVE__FSEEKI64 AND HAVE__FTELLI64)
+ endif(SIZEOF___INT64 GREATER 7)
+ endif(NOT LFS_OFF_T)
+
+ set(CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
+ endif(${_isenable})
+
+ if(NOT LFS_OFF_T)
+ ## not found
+ set(LFS_OFF_T "long")
+ set(LFS_FOPEN "fopen")
+ set(LFS_FSEEK "fseek")
+ set(LFS_FTELL "ftell")
+ set(LFS_PRID "\"ld\"")
+ endif(NOT LFS_OFF_T)
+
+endmacro(check_lfs)
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/ProjectCPack.cmake b/tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/ProjectCPack.cmake
new file mode 100644
index 0000000..7c105f9
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/ProjectCPack.cmake
@@ -0,0 +1,38 @@
+# If the cmake version includes cpack, use it
+IF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
+ SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_DESCRIPTION}")
+ SET(CPACK_PACKAGE_VENDOR "${PROJECT_VENDOR}")
+ SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
+ SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
+ SET(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
+ SET(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
+ SET(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
+# SET(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME} ${PROJECT_VERSION}")
+ SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION_FULL}")
+
+ IF(NOT DEFINED CPACK_SYSTEM_NAME)
+ SET(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
+ ENDIF(NOT DEFINED CPACK_SYSTEM_NAME)
+
+ IF(${CPACK_SYSTEM_NAME} MATCHES Windows)
+ IF(CMAKE_CL_64)
+ SET(CPACK_SYSTEM_NAME win64-${CMAKE_SYSTEM_PROCESSOR})
+ ELSE(CMAKE_CL_64)
+ SET(CPACK_SYSTEM_NAME win32-${CMAKE_SYSTEM_PROCESSOR})
+ ENDIF(CMAKE_CL_64)
+ ENDIF(${CPACK_SYSTEM_NAME} MATCHES Windows)
+
+ IF(NOT DEFINED CPACK_PACKAGE_FILE_NAME)
+ SET(CPACK_PACKAGE_FILE_NAME "${CPACK_SOURCE_PACKAGE_FILE_NAME}-${CPACK_SYSTEM_NAME}")
+ ENDIF(NOT DEFINED CPACK_PACKAGE_FILE_NAME)
+
+ SET(CPACK_PACKAGE_CONTACT "${PROJECT_CONTACT}")
+ IF(UNIX)
+ SET(CPACK_STRIP_FILES "")
+ SET(CPACK_SOURCE_STRIP_FILES "")
+# SET(CPACK_PACKAGE_EXECUTABLES "ccmake" "CMake")
+ ENDIF(UNIX)
+ SET(CPACK_SOURCE_IGNORE_FILES "/CVS/" "/build/" "/\\\\.build/" "/\\\\.svn/" "~$")
+ # include CPack model once all variables are set
+ INCLUDE(CPack)
+ENDIF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/cmake_uninstall.cmake.in b/tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/cmake_uninstall.cmake.in
new file mode 100644
index 0000000..8366a83
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/CMakeModules/cmake_uninstall.cmake.in
@@ -0,0 +1,36 @@
+IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+ MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
+ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+
+FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
+STRING(REGEX REPLACE "\n" ";" files "${files}")
+
+SET(NUM 0)
+FOREACH(file ${files})
+ IF(EXISTS "$ENV{DESTDIR}${file}")
+ MESSAGE(STATUS "Looking for \"$ENV{DESTDIR}${file}\" - found")
+ SET(UNINSTALL_CHECK_${NUM} 1)
+ ELSE(EXISTS "$ENV{DESTDIR}${file}")
+ MESSAGE(STATUS "Looking for \"$ENV{DESTDIR}${file}\" - not found")
+ SET(UNINSTALL_CHECK_${NUM} 0)
+ ENDIF(EXISTS "$ENV{DESTDIR}${file}")
+ MATH(EXPR NUM "1 + ${NUM}")
+ENDFOREACH(file)
+
+SET(NUM 0)
+FOREACH(file ${files})
+ IF(${UNINSTALL_CHECK_${NUM}})
+ MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
+ EXEC_PROGRAM(
+ "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
+ OUTPUT_VARIABLE rm_out
+ RETURN_VALUE rm_retval
+ )
+ IF(NOT "${rm_retval}" STREQUAL 0)
+ MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
+ ENDIF(NOT "${rm_retval}" STREQUAL 0)
+ ENDIF(${UNINSTALL_CHECK_${NUM}})
+ MATH(EXPR NUM "1 + ${NUM}")
+ENDFOREACH(file)
+
+FILE(REMOVE "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/LICENSE b/tools/rasm/apultra-master/src/libdivsufsort/LICENSE
new file mode 100644
index 0000000..249efa4
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2003 Yuta Mori All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), 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/tools/rasm/apultra-master/src/libdivsufsort/README.md b/tools/rasm/apultra-master/src/libdivsufsort/README.md
new file mode 100644
index 0000000..381a188
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/README.md
@@ -0,0 +1,140 @@
+# libdivsufsort
+
+libdivsufsort is a software library that implements a lightweight suffix array construction algorithm.
+
+## News
+* 2015-03-21: The project has moved from [Google Code](http://code.google.com/p/libdivsufsort/) to [GitHub](https://github.com/y-256/libdivsufsort)
+
+## Introduction
+This library provides a simple and an efficient C API to construct a suffix array and a Burrows-Wheeler transformed string from a given string over a constant-size alphabet.
+The algorithm runs in O(n log n) worst-case time using only 5n+O(1) bytes of memory space, where n is the length of
+the string.
+
+## Build requirements
+* An ANSI C Compiler (e.g. GNU GCC)
+* [CMake](http://www.cmake.org/ "CMake") version 2.4.2 or newer
+* CMake-supported build tool
+
+## Building on GNU/Linux
+1. Get the source code from GitHub. You can either
+ * use git to clone the repository
+ ```
+ git clone https://github.com/y-256/libdivsufsort.git
+ ```
+ * or download a [zip file](../../archive/master.zip) directly
+2. Create a `build` directory in the package source directory.
+```shell
+$ cd libdivsufsort
+$ mkdir build
+$ cd build
+```
+3. Configure the package for your system.
+If you want to install to a different location, change the -DCMAKE_INSTALL_PREFIX option.
+```shell
+$ cmake -DCMAKE_BUILD_TYPE="Release" \
+-DCMAKE_INSTALL_PREFIX="/usr/local" ..
+```
+4. Compile the package.
+```shell
+$ make
+```
+5. (Optional) Install the library and header files.
+```shell
+$ sudo make install
+```
+
+## API
+```c
+/* Data types */
+typedef int32_t saint_t;
+typedef int32_t saidx_t;
+typedef uint8_t sauchar_t;
+
+/*
+ * Constructs the suffix array of a given string.
+ * @param T[0..n-1] The input string.
+ * @param SA[0..n-1] The output array or suffixes.
+ * @param n The length of the given string.
+ * @return 0 if no error occurred, -1 or -2 otherwise.
+ */
+saint_t
+divsufsort(const sauchar_t *T, saidx_t *SA, saidx_t n);
+
+/*
+ * Constructs the burrows-wheeler transformed string of a given string.
+ * @param T[0..n-1] The input string.
+ * @param U[0..n-1] The output string. (can be T)
+ * @param A[0..n-1] The temporary array. (can be NULL)
+ * @param n The length of the given string.
+ * @return The primary index if no error occurred, -1 or -2 otherwise.
+ */
+saidx_t
+divbwt(const sauchar_t *T, sauchar_t *U, saidx_t *A, saidx_t n);
+```
+
+## Example Usage
+```c
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <divsufsort.h>
+
+int main() {
+ // intput data
+ char *Text = "abracadabra";
+ int n = strlen(Text);
+ int i, j;
+
+ // allocate
+ int *SA = (int *)malloc(n * sizeof(int));
+
+ // sort
+ divsufsort((unsigned char *)Text, SA, n);
+
+ // output
+ for(i = 0; i < n; ++i) {
+ printf("SA[%2d] = %2d: ", i, SA[i]);
+ for(j = SA[i]; j < n; ++j) {
+ printf("%c", Text[j]);
+ }
+ printf("$\n");
+ }
+
+ // deallocate
+ free(SA);
+
+ return 0;
+}
+```
+See the [examples](examples) directory for a few other examples.
+
+## Benchmarks
+See [Benchmarks](https://github.com/y-256/libdivsufsort/blob/wiki/SACA_Benchmarks.md) page for details.
+
+## License
+libdivsufsort is released under the [MIT license](LICENSE "MIT license").
+> The MIT License (MIT)
+>
+> Copyright (c) 2003 Yuta Mori All rights reserved.
+>
+> Permission is hereby granted, free of charge, to any person obtaining a copy
+> of this software and associated documentation files (the "Software"), 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.
+
+## Author
+* Yuta Mori
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/VERSION.cmake b/tools/rasm/apultra-master/src/libdivsufsort/VERSION.cmake
new file mode 100644
index 0000000..3f11ac1
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/VERSION.cmake
@@ -0,0 +1,23 @@
+set(PROJECT_VERSION_MAJOR "2")
+set(PROJECT_VERSION_MINOR "0")
+set(PROJECT_VERSION_PATCH "2")
+set(PROJECT_VERSION_EXTRA "-1")
+set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
+set(PROJECT_VERSION_FULL "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${PROJECT_VERSION_EXTRA}")
+
+set(LIBRARY_VERSION "3.0.1")
+set(LIBRARY_SOVERSION "3")
+
+## Git revision number ##
+if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git")
+ execute_process(COMMAND git describe --tags HEAD
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ OUTPUT_VARIABLE GIT_DESCRIBE_TAGS ERROR_QUIET)
+ if(GIT_DESCRIBE_TAGS)
+ string(REGEX REPLACE "^v(.*)" "\\1" GIT_REVISION "${GIT_DESCRIBE_TAGS}")
+ string(STRIP "${GIT_REVISION}" GIT_REVISION)
+ if(GIT_REVISION)
+ set(PROJECT_VERSION_FULL "${GIT_REVISION}")
+ endif(GIT_REVISION)
+ endif(GIT_DESCRIBE_TAGS)
+endif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git")
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/examples/CMakeLists.txt b/tools/rasm/apultra-master/src/libdivsufsort/examples/CMakeLists.txt
new file mode 100644
index 0000000..e801c81
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/examples/CMakeLists.txt
@@ -0,0 +1,11 @@
+## Add definitions ##
+add_definitions(-D_LARGEFILE_SOURCE -D_LARGE_FILES -D_FILE_OFFSET_BITS=64)
+
+## Targets ##
+include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../include"
+ "${CMAKE_CURRENT_BINARY_DIR}/../include")
+link_directories("${CMAKE_CURRENT_BINARY_DIR}/../lib")
+foreach(src suftest mksary sasearch bwt unbwt)
+ add_executable(${src} ${src}.c)
+ target_link_libraries(${src} divsufsort)
+endforeach(src)
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/examples/bwt.c b/tools/rasm/apultra-master/src/libdivsufsort/examples/bwt.c
new file mode 100644
index 0000000..5a362d0
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/examples/bwt.c
@@ -0,0 +1,220 @@
+/*
+ * bwt.c for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+#if HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_IO_H && HAVE_FCNTL_H
+# include <io.h>
+# include <fcntl.h>
+#endif
+#include <time.h>
+#include <divsufsort.h>
+#include "lfs.h"
+
+
+static
+size_t
+write_int(FILE *fp, saidx_t n) {
+ unsigned char c[4];
+ c[0] = (unsigned char)((n >> 0) & 0xff), c[1] = (unsigned char)((n >> 8) & 0xff),
+ c[2] = (unsigned char)((n >> 16) & 0xff), c[3] = (unsigned char)((n >> 24) & 0xff);
+ return fwrite(c, sizeof(unsigned char), 4, fp);
+}
+
+static
+void
+print_help(const char *progname, int status) {
+ fprintf(stderr,
+ "bwt, a burrows-wheeler transform program, version %s.\n",
+ divsufsort_version());
+ fprintf(stderr, "usage: %s [-b num] INFILE OUTFILE\n", progname);
+ fprintf(stderr, " -b num set block size to num MiB [1..512] (default: 32)\n\n");
+ exit(status);
+}
+
+int
+main(int argc, const char *argv[]) {
+ FILE *fp, *ofp;
+ const char *fname, *ofname;
+ sauchar_t *T;
+ saidx_t *SA;
+ LFS_OFF_T n;
+ size_t m;
+ saidx_t pidx;
+ clock_t start,finish;
+ saint_t i, blocksize = 32, needclose = 3;
+
+ /* Check arguments. */
+ if((argc == 1) ||
+ (strcmp(argv[1], "-h") == 0) ||
+ (strcmp(argv[1], "--help") == 0)) { print_help(argv[0], EXIT_SUCCESS); }
+ if((argc != 3) && (argc != 5)) { print_help(argv[0], EXIT_FAILURE); }
+ i = 1;
+ if(argc == 5) {
+ if(strcmp(argv[i], "-b") != 0) { print_help(argv[0], EXIT_FAILURE); }
+ blocksize = atoi(argv[i + 1]);
+ if(blocksize < 0) { blocksize = 1; }
+ else if(512 < blocksize) { blocksize = 512; }
+ i += 2;
+ }
+ blocksize <<= 20;
+
+ /* Open a file for reading. */
+ if(strcmp(argv[i], "-") != 0) {
+#if HAVE_FOPEN_S
+ if(fopen_s(&fp, fname = argv[i], "rb") != 0) {
+#else
+ if((fp = LFS_FOPEN(fname = argv[i], "rb")) == NULL) {
+#endif
+ fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+#if HAVE__SETMODE && HAVE__FILENO
+ if(_setmode(_fileno(stdin), _O_BINARY) == -1) {
+ fprintf(stderr, "%s: Cannot set mode: ", argv[0]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+#endif
+ fp = stdin;
+ fname = "stdin";
+ needclose ^= 1;
+ }
+ i += 1;
+
+ /* Open a file for writing. */
+ if(strcmp(argv[i], "-") != 0) {
+#if HAVE_FOPEN_S
+ if(fopen_s(&ofp, ofname = argv[i], "wb") != 0) {
+#else
+ if((ofp = LFS_FOPEN(ofname = argv[i], "wb")) == NULL) {
+#endif
+ fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], ofname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+#if HAVE__SETMODE && HAVE__FILENO
+ if(_setmode(_fileno(stdout), _O_BINARY) == -1) {
+ fprintf(stderr, "%s: Cannot set mode: ", argv[0]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+#endif
+ ofp = stdout;
+ ofname = "stdout";
+ needclose ^= 2;
+ }
+
+ /* Get the file size. */
+ if(LFS_FSEEK(fp, 0, SEEK_END) == 0) {
+ n = LFS_FTELL(fp);
+ rewind(fp);
+ if(n < 0) {
+ fprintf(stderr, "%s: Cannot ftell `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ if(0x20000000L < n) { n = 0x20000000L; }
+ if((blocksize == 0) || (n < blocksize)) { blocksize = (saidx_t)n; }
+ } else if(blocksize == 0) { blocksize = 32 << 20; }
+
+ /* Allocate 5blocksize bytes of memory. */
+ T = (sauchar_t *)malloc(blocksize * sizeof(sauchar_t));
+ SA = (saidx_t *)malloc(blocksize * sizeof(saidx_t));
+ if((T == NULL) || (SA == NULL)) {
+ fprintf(stderr, "%s: Cannot allocate memory.\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Write the blocksize. */
+ if(write_int(ofp, blocksize) != 4) {
+ fprintf(stderr, "%s: Cannot write to `%s': ", argv[0], ofname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ fprintf(stderr, " BWT (blocksize %" PRIdSAINT_T ") ... ", blocksize);
+ start = clock();
+ for(n = 0; 0 < (m = fread(T, sizeof(sauchar_t), blocksize, fp)); n += m) {
+ /* Burrows-Wheeler Transform. */
+ pidx = divbwt(T, T, SA, m);
+ if(pidx < 0) {
+ fprintf(stderr, "%s (bw_transform): %s.\n",
+ argv[0],
+ (pidx == -1) ? "Invalid arguments" : "Cannot allocate memory");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Write the bwted data. */
+ if((write_int(ofp, pidx) != 4) ||
+ (fwrite(T, sizeof(sauchar_t), m, ofp) != m)) {
+ fprintf(stderr, "%s: Cannot write to `%s': ", argv[0], ofname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ }
+ if(ferror(fp)) {
+ fprintf(stderr, "%s: Cannot read from `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ finish = clock();
+ fprintf(stderr, "%" PRIdOFF_T " bytes: %.4f sec\n",
+ n, (double)(finish - start) / (double)CLOCKS_PER_SEC);
+
+ /* Close files */
+ if(needclose & 1) { fclose(fp); }
+ if(needclose & 2) { fclose(ofp); }
+
+ /* Deallocate memory. */
+ free(SA);
+ free(T);
+
+ return 0;
+}
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/examples/mksary.c b/tools/rasm/apultra-master/src/libdivsufsort/examples/mksary.c
new file mode 100644
index 0000000..b48177c
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/examples/mksary.c
@@ -0,0 +1,193 @@
+/*
+ * mksary.c for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+#if HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_IO_H && HAVE_FCNTL_H
+# include <io.h>
+# include <fcntl.h>
+#endif
+#include <time.h>
+#include <divsufsort.h>
+#include "lfs.h"
+
+
+static
+void
+print_help(const char *progname, int status) {
+ fprintf(stderr,
+ "mksary, a simple suffix array builder, version %s.\n",
+ divsufsort_version());
+ fprintf(stderr, "usage: %s INFILE OUTFILE\n\n", progname);
+ exit(status);
+}
+
+int
+main(int argc, const char *argv[]) {
+ FILE *fp, *ofp;
+ const char *fname, *ofname;
+ sauchar_t *T;
+ saidx_t *SA;
+ LFS_OFF_T n;
+ clock_t start, finish;
+ saint_t needclose = 3;
+
+ /* Check arguments. */
+ if((argc == 1) ||
+ (strcmp(argv[1], "-h") == 0) ||
+ (strcmp(argv[1], "--help") == 0)) { print_help(argv[0], EXIT_SUCCESS); }
+ if(argc != 3) { print_help(argv[0], EXIT_FAILURE); }
+
+ /* Open a file for reading. */
+ if(strcmp(argv[1], "-") != 0) {
+#if HAVE_FOPEN_S
+ if(fopen_s(&fp, fname = argv[1], "rb") != 0) {
+#else
+ if((fp = LFS_FOPEN(fname = argv[1], "rb")) == NULL) {
+#endif
+ fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+#if HAVE__SETMODE && HAVE__FILENO
+ if(_setmode(_fileno(stdin), _O_BINARY) == -1) {
+ fprintf(stderr, "%s: Cannot set mode: ", argv[0]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+#endif
+ fp = stdin;
+ fname = "stdin";
+ needclose ^= 1;
+ }
+
+ /* Open a file for writing. */
+ if(strcmp(argv[2], "-") != 0) {
+#if HAVE_FOPEN_S
+ if(fopen_s(&ofp, ofname = argv[2], "wb") != 0) {
+#else
+ if((ofp = LFS_FOPEN(ofname = argv[2], "wb")) == NULL) {
+#endif
+ fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], ofname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+#if HAVE__SETMODE && HAVE__FILENO
+ if(_setmode(_fileno(stdout), _O_BINARY) == -1) {
+ fprintf(stderr, "%s: Cannot set mode: ", argv[0]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+#endif
+ ofp = stdout;
+ ofname = "stdout";
+ needclose ^= 2;
+ }
+
+ /* Get the file size. */
+ if(LFS_FSEEK(fp, 0, SEEK_END) == 0) {
+ n = LFS_FTELL(fp);
+ rewind(fp);
+ if(n < 0) {
+ fprintf(stderr, "%s: Cannot ftell `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ if(0x7fffffff <= n) {
+ fprintf(stderr, "%s: Input file `%s' is too big.\n", argv[0], fname);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ fprintf(stderr, "%s: Cannot fseek `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Allocate 5blocksize bytes of memory. */
+ T = (sauchar_t *)malloc((size_t)n * sizeof(sauchar_t));
+ SA = (saidx_t *)malloc((size_t)n * sizeof(saidx_t));
+ if((T == NULL) || (SA == NULL)) {
+ fprintf(stderr, "%s: Cannot allocate memory.\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Read n bytes of data. */
+ if(fread(T, sizeof(sauchar_t), (size_t)n, fp) != (size_t)n) {
+ fprintf(stderr, "%s: %s `%s': ",
+ argv[0],
+ (ferror(fp) || !feof(fp)) ? "Cannot read from" : "Unexpected EOF in",
+ fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ if(needclose & 1) { fclose(fp); }
+
+ /* Construct the suffix array. */
+ fprintf(stderr, "%s: %" PRIdOFF_T " bytes ... ", fname, n);
+ start = clock();
+ if(divsufsort(T, SA, (saidx_t)n) != 0) {
+ fprintf(stderr, "%s: Cannot allocate memory.\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ finish = clock();
+ fprintf(stderr, "%.4f sec\n", (double)(finish - start) / (double)CLOCKS_PER_SEC);
+
+ /* Write the suffix array. */
+ if(fwrite(SA, sizeof(saidx_t), (size_t)n, ofp) != (size_t)n) {
+ fprintf(stderr, "%s: Cannot write to `%s': ", argv[0], ofname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ if(needclose & 2) { fclose(ofp); }
+
+ /* Deallocate memory. */
+ free(SA);
+ free(T);
+
+ return 0;
+}
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/examples/sasearch.c b/tools/rasm/apultra-master/src/libdivsufsort/examples/sasearch.c
new file mode 100644
index 0000000..7e5ca4f
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/examples/sasearch.c
@@ -0,0 +1,165 @@
+/*
+ * sasearch.c for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+#if HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_IO_H && HAVE_FCNTL_H
+# include <io.h>
+# include <fcntl.h>
+#endif
+#include <divsufsort.h>
+#include "lfs.h"
+
+
+static
+void
+print_help(const char *progname, int status) {
+ fprintf(stderr,
+ "sasearch, a simple SA-based full-text search tool, version %s\n",
+ divsufsort_version());
+ fprintf(stderr, "usage: %s PATTERN FILE SAFILE\n\n", progname);
+ exit(status);
+}
+
+int
+main(int argc, const char *argv[]) {
+ FILE *fp;
+ const char *P;
+ sauchar_t *T;
+ saidx_t *SA;
+ LFS_OFF_T n;
+ size_t Psize;
+ saidx_t i, size, left;
+
+ if((argc == 1) ||
+ (strcmp(argv[1], "-h") == 0) ||
+ (strcmp(argv[1], "--help") == 0)) { print_help(argv[0], EXIT_SUCCESS); }
+ if(argc != 4) { print_help(argv[0], EXIT_FAILURE); }
+
+ P = argv[1];
+ Psize = strlen(P);
+
+ /* Open a file for reading. */
+#if HAVE_FOPEN_S
+ if(fopen_s(&fp, argv[2], "rb") != 0) {
+#else
+ if((fp = LFS_FOPEN(argv[2], "rb")) == NULL) {
+#endif
+ fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], argv[2]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Get the file size. */
+ if(LFS_FSEEK(fp, 0, SEEK_END) == 0) {
+ n = LFS_FTELL(fp);
+ rewind(fp);
+ if(n < 0) {
+ fprintf(stderr, "%s: Cannot ftell `%s': ", argv[0], argv[2]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ fprintf(stderr, "%s: Cannot fseek `%s': ", argv[0], argv[2]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Allocate 5n bytes of memory. */
+ T = (sauchar_t *)malloc((size_t)n * sizeof(sauchar_t));
+ SA = (saidx_t *)malloc((size_t)n * sizeof(saidx_t));
+ if((T == NULL) || (SA == NULL)) {
+ fprintf(stderr, "%s: Cannot allocate memory.\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Read n bytes of data. */
+ if(fread(T, sizeof(sauchar_t), (size_t)n, fp) != (size_t)n) {
+ fprintf(stderr, "%s: %s `%s': ",
+ argv[0],
+ (ferror(fp) || !feof(fp)) ? "Cannot read from" : "Unexpected EOF in",
+ argv[2]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ fclose(fp);
+
+ /* Open the SA file for reading. */
+#if HAVE_FOPEN_S
+ if(fopen_s(&fp, argv[3], "rb") != 0) {
+#else
+ if((fp = LFS_FOPEN(argv[3], "rb")) == NULL) {
+#endif
+ fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], argv[3]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Read n * sizeof(saidx_t) bytes of data. */
+ if(fread(SA, sizeof(saidx_t), (size_t)n, fp) != (size_t)n) {
+ fprintf(stderr, "%s: %s `%s': ",
+ argv[0],
+ (ferror(fp) || !feof(fp)) ? "Cannot read from" : "Unexpected EOF in",
+ argv[3]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ fclose(fp);
+
+ /* Search and print */
+ size = sa_search(T, (saidx_t)n,
+ (const sauchar_t *)P, (saidx_t)Psize,
+ SA, (saidx_t)n, &left);
+ for(i = 0; i < size; ++i) {
+ fprintf(stdout, "%" PRIdSAIDX_T "\n", SA[left + i]);
+ }
+
+ /* Deallocate memory. */
+ free(SA);
+ free(T);
+
+ return 0;
+}
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/examples/suftest.c b/tools/rasm/apultra-master/src/libdivsufsort/examples/suftest.c
new file mode 100644
index 0000000..71892ac
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/examples/suftest.c
@@ -0,0 +1,164 @@
+/*
+ * suftest.c for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+#if HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_IO_H && HAVE_FCNTL_H
+# include <io.h>
+# include <fcntl.h>
+#endif
+#include <time.h>
+#include <divsufsort.h>
+#include "lfs.h"
+
+
+static
+void
+print_help(const char *progname, int status) {
+ fprintf(stderr,
+ "suftest, a suffixsort tester, version %s.\n",
+ divsufsort_version());
+ fprintf(stderr, "usage: %s FILE\n\n", progname);
+ exit(status);
+}
+
+int
+main(int argc, const char *argv[]) {
+ FILE *fp;
+ const char *fname;
+ sauchar_t *T;
+ saidx_t *SA;
+ LFS_OFF_T n;
+ clock_t start, finish;
+ saint_t needclose = 1;
+
+ /* Check arguments. */
+ if((argc == 1) ||
+ (strcmp(argv[1], "-h") == 0) ||
+ (strcmp(argv[1], "--help") == 0)) { print_help(argv[0], EXIT_SUCCESS); }
+ if(argc != 2) { print_help(argv[0], EXIT_FAILURE); }
+
+ /* Open a file for reading. */
+ if(strcmp(argv[1], "-") != 0) {
+#if HAVE_FOPEN_S
+ if(fopen_s(&fp, fname = argv[1], "rb") != 0) {
+#else
+ if((fp = LFS_FOPEN(fname = argv[1], "rb")) == NULL) {
+#endif
+ fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+#if HAVE__SETMODE && HAVE__FILENO
+ if(_setmode(_fileno(stdin), _O_BINARY) == -1) {
+ fprintf(stderr, "%s: Cannot set mode: ", argv[0]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+#endif
+ fp = stdin;
+ fname = "stdin";
+ needclose = 0;
+ }
+
+ /* Get the file size. */
+ if(LFS_FSEEK(fp, 0, SEEK_END) == 0) {
+ n = LFS_FTELL(fp);
+ rewind(fp);
+ if(n < 0) {
+ fprintf(stderr, "%s: Cannot ftell `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ if(0x7fffffff <= n) {
+ fprintf(stderr, "%s: Input file `%s' is too big.\n", argv[0], fname);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ fprintf(stderr, "%s: Cannot fseek `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Allocate 5n bytes of memory. */
+ T = (sauchar_t *)malloc((size_t)n * sizeof(sauchar_t));
+ SA = (saidx_t *)malloc((size_t)n * sizeof(saidx_t));
+ if((T == NULL) || (SA == NULL)) {
+ fprintf(stderr, "%s: Cannot allocate memory.\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Read n bytes of data. */
+ if(fread(T, sizeof(sauchar_t), (size_t)n, fp) != (size_t)n) {
+ fprintf(stderr, "%s: %s `%s': ",
+ argv[0],
+ (ferror(fp) || !feof(fp)) ? "Cannot read from" : "Unexpected EOF in",
+ argv[1]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ if(needclose & 1) { fclose(fp); }
+
+ /* Construct the suffix array. */
+ fprintf(stderr, "%s: %" PRIdOFF_T " bytes ... ", fname, n);
+ start = clock();
+ if(divsufsort(T, SA, (saidx_t)n) != 0) {
+ fprintf(stderr, "%s: Cannot allocate memory.\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ finish = clock();
+ fprintf(stderr, "%.4f sec\n", (double)(finish - start) / (double)CLOCKS_PER_SEC);
+
+ /* Check the suffix array. */
+ if(sufcheck(T, SA, (saidx_t)n, 1) != 0) { exit(EXIT_FAILURE); }
+
+ /* Deallocate memory. */
+ free(SA);
+ free(T);
+
+ return 0;
+}
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/examples/unbwt.c b/tools/rasm/apultra-master/src/libdivsufsort/examples/unbwt.c
new file mode 100644
index 0000000..c0f19e9
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/examples/unbwt.c
@@ -0,0 +1,207 @@
+/*
+ * unbwt.c for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+#if HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_IO_H && HAVE_FCNTL_H
+# include <io.h>
+# include <fcntl.h>
+#endif
+#include <time.h>
+#include <divsufsort.h>
+#include "lfs.h"
+
+
+static
+size_t
+read_int(FILE *fp, saidx_t *n) {
+ unsigned char c[4];
+ size_t m = fread(c, sizeof(unsigned char), 4, fp);
+ if(m == 4) {
+ *n = (c[0] << 0) | (c[1] << 8) |
+ (c[2] << 16) | (c[3] << 24);
+ }
+ return m;
+}
+
+static
+void
+print_help(const char *progname, int status) {
+ fprintf(stderr,
+ "unbwt, an inverse burrows-wheeler transform program, version %s.\n",
+ divsufsort_version());
+ fprintf(stderr, "usage: %s INFILE OUTFILE\n\n", progname);
+ exit(status);
+}
+
+int
+main(int argc, const char *argv[]) {
+ FILE *fp, *ofp;
+ const char *fname, *ofname;
+ sauchar_t *T;
+ saidx_t *A;
+ LFS_OFF_T n;
+ size_t m;
+ saidx_t pidx;
+ clock_t start, finish;
+ saint_t err, blocksize, needclose = 3;
+
+ /* Check arguments. */
+ if((argc == 1) ||
+ (strcmp(argv[1], "-h") == 0) ||
+ (strcmp(argv[1], "--help") == 0)) { print_help(argv[0], EXIT_SUCCESS); }
+ if(argc != 3) { print_help(argv[0], EXIT_FAILURE); }
+
+ /* Open a file for reading. */
+ if(strcmp(argv[1], "-") != 0) {
+#if HAVE_FOPEN_S
+ if(fopen_s(&fp, fname = argv[1], "rb") != 0) {
+#else
+ if((fp = LFS_FOPEN(fname = argv[1], "rb")) == NULL) {
+#endif
+ fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+#if HAVE__SETMODE && HAVE__FILENO
+ if(_setmode(_fileno(stdin), _O_BINARY) == -1) {
+ fprintf(stderr, "%s: Cannot set mode: ", argv[0]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+#endif
+ fp = stdin;
+ fname = "stdin";
+ needclose ^= 1;
+ }
+
+ /* Open a file for writing. */
+ if(strcmp(argv[2], "-") != 0) {
+#if HAVE_FOPEN_S
+ if(fopen_s(&ofp, ofname = argv[2], "wb") != 0) {
+#else
+ if((ofp = LFS_FOPEN(ofname = argv[2], "wb")) == NULL) {
+#endif
+ fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], ofname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+#if HAVE__SETMODE && HAVE__FILENO
+ if(_setmode(_fileno(stdout), _O_BINARY) == -1) {
+ fprintf(stderr, "%s: Cannot set mode: ", argv[0]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+#endif
+ ofp = stdout;
+ ofname = "stdout";
+ needclose ^= 2;
+ }
+
+ /* Read the blocksize. */
+ if(read_int(fp, &blocksize) != 4) {
+ fprintf(stderr, "%s: Cannot read from `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Allocate 5blocksize bytes of memory. */
+ T = (sauchar_t *)malloc(blocksize * sizeof(sauchar_t));
+ A = (saidx_t *)malloc(blocksize * sizeof(saidx_t));
+ if((T == NULL) || (A == NULL)) {
+ fprintf(stderr, "%s: Cannot allocate memory.\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ fprintf(stderr, "UnBWT (blocksize %" PRIdSAINT_T ") ... ", blocksize);
+ start = clock();
+ for(n = 0; (m = read_int(fp, &pidx)) != 0; n += m) {
+ /* Read blocksize bytes of data. */
+ if((m != 4) || ((m = fread(T, sizeof(sauchar_t), blocksize, fp)) == 0)) {
+ fprintf(stderr, "%s: %s `%s': ",
+ argv[0],
+ (ferror(fp) || !feof(fp)) ? "Cannot read from" : "Unexpected EOF in",
+ fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Inverse Burrows-Wheeler Transform. */
+ if((err = inverse_bw_transform(T, T, A, m, pidx)) != 0) {
+ fprintf(stderr, "%s (reverseBWT): %s.\n",
+ argv[0],
+ (err == -1) ? "Invalid data" : "Cannot allocate memory");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Write m bytes of data. */
+ if(fwrite(T, sizeof(sauchar_t), m, ofp) != m) {
+ fprintf(stderr, "%s: Cannot write to `%s': ", argv[0], ofname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ }
+ if(ferror(fp)) {
+ fprintf(stderr, "%s: Cannot read from `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ finish = clock();
+ fprintf(stderr, "%" PRIdOFF_T " bytes: %.4f sec\n",
+ n, (double)(finish - start) / (double)CLOCKS_PER_SEC);
+
+ /* Close files */
+ if(needclose & 1) { fclose(fp); }
+ if(needclose & 2) { fclose(ofp); }
+
+ /* Deallocate memory. */
+ free(A);
+ free(T);
+
+ return 0;
+}
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/include/CMakeLists.txt b/tools/rasm/apultra-master/src/libdivsufsort/include/CMakeLists.txt
new file mode 100644
index 0000000..37781cc
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/include/CMakeLists.txt
@@ -0,0 +1,162 @@
+include(CheckIncludeFiles)
+include(CheckIncludeFile)
+include(CheckSymbolExists)
+include(CheckTypeSize)
+include(CheckFunctionKeywords)
+include(CheckLFS)
+
+## Checks for header files ##
+check_include_file("inttypes.h" HAVE_INTTYPES_H)
+check_include_file("memory.h" HAVE_MEMORY_H)
+check_include_file("stddef.h" HAVE_STDDEF_H)
+check_include_file("stdint.h" HAVE_STDINT_H)
+check_include_file("stdlib.h" HAVE_STDLIB_H)
+check_include_file("string.h" HAVE_STRING_H)
+check_include_file("strings.h" HAVE_STRINGS_H)
+check_include_file("sys/types.h" HAVE_SYS_TYPES_H)
+if(HAVE_INTTYPES_H)
+ set(INCFILE "#include <inttypes.h>")
+elseif(HAVE_STDINT_H)
+ set(INCFILE "#include <stdint.h>")
+else(HAVE_INTTYPES_H)
+ set(INCFILE "")
+endif(HAVE_INTTYPES_H)
+
+## create configuration files from .cmake file ##
+if(BUILD_EXAMPLES)
+ ## Checks for WinIO ##
+ if(WIN32)
+ check_include_file("io.h" HAVE_IO_H)
+ check_include_file("fcntl.h" HAVE_FCNTL_H)
+ check_symbol_exists("_setmode" "io.h;fcntl.h" HAVE__SETMODE)
+ if(NOT HAVE__SETMODE)
+ check_symbol_exists("setmode" "io.h;fcntl.h" HAVE_SETMODE)
+ endif(NOT HAVE__SETMODE)
+ check_symbol_exists("_fileno" "stdio.h" HAVE__FILENO)
+ check_symbol_exists("fopen_s" "stdio.h" HAVE_FOPEN_S)
+ check_symbol_exists("_O_BINARY" "fcntl.h" HAVE__O_BINARY)
+ endif(WIN32)
+
+ ## Checks for large file support ##
+ check_lfs(WITH_LFS)
+ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/lfs.h.cmake" "${CMAKE_CURRENT_BINARY_DIR}/lfs.h" @ONLY)
+endif(BUILD_EXAMPLES)
+
+## generate config.h ##
+check_function_keywords("inline;__inline;__inline__;__declspec(dllexport);__declspec(dllimport)")
+if(HAVE_INLINE)
+ set(INLINE "inline")
+elseif(HAVE___INLINE)
+ set(INLINE "__inline")
+elseif(HAVE___INLINE__)
+ set(INLINE "__inline__")
+else(HAVE_INLINE)
+ set(INLINE "")
+endif(HAVE_INLINE)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake" "${CMAKE_CURRENT_BINARY_DIR}/config.h")
+
+## Checks for types ##
+# sauchar_t (8bit)
+check_type_size("uint8_t" UINT8_T)
+if(HAVE_UINT8_T)
+ set(SAUCHAR_TYPE "uint8_t")
+else(HAVE_UINT8_T)
+ check_type_size("unsigned char" SIZEOF_UNSIGNED_CHAR)
+ if("${SIZEOF_UNSIGNED_CHAR}" STREQUAL "1")
+ set(SAUCHAR_TYPE "unsigned char")
+ else("${SIZEOF_UNSIGNED_CHAR}" STREQUAL "1")
+ message(FATAL_ERROR "Cannot find unsigned 8-bit integer type")
+ endif("${SIZEOF_UNSIGNED_CHAR}" STREQUAL "1")
+endif(HAVE_UINT8_T)
+# saint_t (32bit)
+check_type_size("int32_t" INT32_T)
+if(HAVE_INT32_T)
+ set(SAINT32_TYPE "int32_t")
+ check_symbol_exists("PRId32" "inttypes.h" HAVE_PRID32)
+ if(HAVE_PRID32)
+ set(SAINT32_PRId "PRId32")
+ else(HAVE_PRID32)
+ set(SAINT32_PRId "\"d\"")
+ endif(HAVE_PRID32)
+else(HAVE_INT32_T)
+ check_type_size("int" SIZEOF_INT)
+ check_type_size("long" SIZEOF_LONG)
+ check_type_size("short" SIZEOF_SHORT)
+ check_type_size("__int32" SIZEOF___INT32)
+ if("${SIZEOF_INT}" STREQUAL "4")
+ set(SAINT32_TYPE "int")
+ set(SAINT32_PRId "\"d\"")
+ elseif("${SIZEOF_LONG}" STREQUAL "4")
+ set(SAINT32_TYPE "long")
+ set(SAINT32_PRId "\"ld\"")
+ elseif("${SIZEOF_SHORT}" STREQUAL "4")
+ set(SAINT32_TYPE "short")
+ set(SAINT32_PRId "\"d\"")
+ elseif("${SIZEOF___INT32}" STREQUAL "4")
+ set(SAINT32_TYPE "__int32")
+ set(SAINT32_PRId "\"d\"")
+ else("${SIZEOF_INT}" STREQUAL "4")
+ message(FATAL_ERROR "Cannot find 32-bit integer type")
+ endif("${SIZEOF_INT}" STREQUAL "4")
+endif(HAVE_INT32_T)
+# saint64_t (64bit)
+if(BUILD_DIVSUFSORT64)
+ check_type_size("int64_t" INT64_T)
+ if(HAVE_INT64_T)
+ set(SAINT64_TYPE "int64_t")
+ check_symbol_exists("PRId64" "inttypes.h" HAVE_PRID64)
+ if(HAVE_PRID64)
+ set(SAINT64_PRId "PRId64")
+ else(HAVE_PRID64)
+ set(SAINT64_PRId "\"lld\"")
+ endif(HAVE_PRID64)
+ else(HAVE_INT64_T)
+ check_type_size("int" SIZEOF_INT)
+ check_type_size("long" SIZEOF_LONG)
+ check_type_size("long long" SIZEOF_LONG_LONG)
+ check_type_size("__int64" SIZEOF___INT64)
+ if("${SIZEOF_INT}" STREQUAL "8")
+ set(SAINT64_TYPE "int")
+ set(SAINT64_PRId "\"d\"")
+ elseif("${SIZEOF_LONG}" STREQUAL "8")
+ set(SAINT64_TYPE "long")
+ set(SAINT64_PRId "\"ld\"")
+ elseif("${SIZEOF_LONG_LONG}" STREQUAL "8")
+ set(SAINT64_TYPE "long long")
+ set(SAINT64_PRId "\"lld\"")
+ elseif("${SIZEOF___INT64}" STREQUAL "8")
+ set(SAINT64_TYPE "__int64")
+ set(SAINT64_PRId "\"I64d\"")
+ else("${SIZEOF_INT}" STREQUAL "8")
+ message(SEND_ERROR "Cannot find 64-bit integer type")
+ set(BUILD_DIVSUFSORT64 OFF)
+ endif("${SIZEOF_INT}" STREQUAL "8")
+ endif(HAVE_INT64_T)
+endif(BUILD_DIVSUFSORT64)
+
+## generate divsufsort.h ##
+set(DIVSUFSORT_IMPORT "")
+set(DIVSUFSORT_EXPORT "")
+if(BUILD_SHARED_LIBS)
+ if(HAVE___DECLSPEC_DLLIMPORT_)
+ set(DIVSUFSORT_IMPORT "__declspec(dllimport)")
+ endif(HAVE___DECLSPEC_DLLIMPORT_)
+ if(HAVE___DECLSPEC_DLLEXPORT_)
+ set(DIVSUFSORT_EXPORT "__declspec(dllexport)")
+ endif(HAVE___DECLSPEC_DLLEXPORT_)
+endif(BUILD_SHARED_LIBS)
+set(W64BIT "")
+set(SAINDEX_TYPE "${SAINT32_TYPE}")
+set(SAINDEX_PRId "${SAINT32_PRId}")
+set(SAINT_PRId "${SAINT32_PRId}")
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/divsufsort.h.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/divsufsort.h" @ONLY)
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/divsufsort.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+if(BUILD_DIVSUFSORT64)
+ set(W64BIT "64")
+ set(SAINDEX_TYPE "${SAINT64_TYPE}")
+ set(SAINDEX_PRId "${SAINT64_PRId}")
+ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/divsufsort.h.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/divsufsort64.h" @ONLY)
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/divsufsort64.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+endif(BUILD_DIVSUFSORT64)
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/include/config.h.cmake b/tools/rasm/apultra-master/src/libdivsufsort/include/config.h.cmake
new file mode 100644
index 0000000..6a1cf47
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/include/config.h.cmake
@@ -0,0 +1,81 @@
+/*
+ * config.h for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#ifndef _CONFIG_H
+#define _CONFIG_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/** Define to the version of this package. **/
+#cmakedefine PROJECT_VERSION_FULL "${PROJECT_VERSION_FULL}"
+
+/** Define to 1 if you have the header files. **/
+#cmakedefine HAVE_INTTYPES_H 1
+#cmakedefine HAVE_STDDEF_H 1
+#cmakedefine HAVE_STDINT_H 1
+#cmakedefine HAVE_STDLIB_H 1
+#cmakedefine HAVE_STRING_H 1
+#cmakedefine HAVE_STRINGS_H 1
+#cmakedefine HAVE_MEMORY_H 1
+#cmakedefine HAVE_SYS_TYPES_H 1
+
+/** for WinIO **/
+#cmakedefine HAVE_IO_H 1
+#cmakedefine HAVE_FCNTL_H 1
+#cmakedefine HAVE__SETMODE 1
+#cmakedefine HAVE_SETMODE 1
+#cmakedefine HAVE__FILENO 1
+#cmakedefine HAVE_FOPEN_S 1
+#cmakedefine HAVE__O_BINARY 1
+#ifndef HAVE__SETMODE
+# if HAVE_SETMODE
+# define _setmode setmode
+# define HAVE__SETMODE 1
+# endif
+# if HAVE__SETMODE && !HAVE__O_BINARY
+# define _O_BINARY 0
+# define HAVE__O_BINARY 1
+# endif
+#endif
+
+/** for inline **/
+#ifndef INLINE
+# define INLINE @INLINE@
+#endif
+
+/** for VC++ warning **/
+#ifdef _MSC_VER
+#pragma warning(disable: 4127)
+#endif
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* _CONFIG_H */
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/include/divsufsort.h b/tools/rasm/apultra-master/src/libdivsufsort/include/divsufsort.h
new file mode 100644
index 0000000..7ebb412
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/include/divsufsort.h
@@ -0,0 +1,189 @@
+/*
+ * divsufsort.h for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#ifndef _DIVSUFSORT_H
+#define _DIVSUFSORT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define DIVSUFSORT_API
+
+/*- Datatypes -*/
+#ifndef SAUCHAR_T
+#define SAUCHAR_T
+typedef unsigned char sauchar_t;
+#endif /* SAUCHAR_T */
+#ifndef SAINT_T
+#define SAINT_T
+typedef int saint_t;
+#endif /* SAINT_T */
+#ifndef SAIDX_T
+#define SAIDX_T
+typedef int saidx_t;
+#endif /* SAIDX_T */
+#ifndef PRIdSAIDX_T
+#define PRIdSAIDX_T "d"
+#endif
+
+/*- divsufsort context */
+typedef struct _divsufsort_ctx_t {
+ saidx_t *bucket_A;
+ saidx_t *bucket_B;
+} divsufsort_ctx_t;
+
+/*- Prototypes -*/
+
+/**
+ * Initialize suffix array context
+ *
+ * @return 0 for success, or non-zero in case of an error
+ */
+int divsufsort_init(divsufsort_ctx_t *ctx);
+
+/**
+ * Destroy suffix array context
+ *
+ * @param ctx suffix array context to destroy
+ */
+void divsufsort_destroy(divsufsort_ctx_t *ctx);
+
+/**
+ * Constructs the suffix array of a given string.
+ * @param ctx suffix array context
+ * @param T[0..n-1] The input string.
+ * @param SA[0..n-1] The output array of suffixes.
+ * @param n The length of the given string.
+ * @return 0 if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saint_t divsufsort_build_array(divsufsort_ctx_t *ctx, const sauchar_t *T, saidx_t *SA, saidx_t n);
+
+#if 0
+/**
+ * Constructs the burrows-wheeler transformed string of a given string.
+ * @param T[0..n-1] The input string.
+ * @param U[0..n-1] The output string. (can be T)
+ * @param A[0..n-1] The temporary array. (can be NULL)
+ * @param n The length of the given string.
+ * @return The primary index if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saidx_t
+divbwt(const sauchar_t *T, sauchar_t *U, saidx_t *A, saidx_t n);
+
+/**
+ * Returns the version of the divsufsort library.
+ * @return The version number string.
+ */
+DIVSUFSORT_API
+const char *
+divsufsort_version(void);
+
+
+/**
+ * Constructs the burrows-wheeler transformed string of a given string and suffix array.
+ * @param T[0..n-1] The input string.
+ * @param U[0..n-1] The output string. (can be T)
+ * @param SA[0..n-1] The suffix array. (can be NULL)
+ * @param n The length of the given string.
+ * @param idx The output primary index.
+ * @return 0 if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saint_t
+bw_transform(const sauchar_t *T, sauchar_t *U,
+ saidx_t *SA /* can NULL */,
+ saidx_t n, saidx_t *idx);
+
+/**
+ * Inverse BW-transforms a given BWTed string.
+ * @param T[0..n-1] The input string.
+ * @param U[0..n-1] The output string. (can be T)
+ * @param A[0..n-1] The temporary array. (can be NULL)
+ * @param n The length of the given string.
+ * @param idx The primary index.
+ * @return 0 if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saint_t
+inverse_bw_transform(const sauchar_t *T, sauchar_t *U,
+ saidx_t *A /* can NULL */,
+ saidx_t n, saidx_t idx);
+
+/**
+ * Checks the correctness of a given suffix array.
+ * @param T[0..n-1] The input string.
+ * @param SA[0..n-1] The input suffix array.
+ * @param n The length of the given string.
+ * @param verbose The verbose mode.
+ * @return 0 if no error occurred.
+ */
+DIVSUFSORT_API
+saint_t
+sufcheck(const sauchar_t *T, const saidx_t *SA, saidx_t n, saint_t verbose);
+
+/**
+ * Search for the pattern P in the string T.
+ * @param T[0..Tsize-1] The input string.
+ * @param Tsize The length of the given string.
+ * @param P[0..Psize-1] The input pattern string.
+ * @param Psize The length of the given pattern string.
+ * @param SA[0..SAsize-1] The input suffix array.
+ * @param SAsize The length of the given suffix array.
+ * @param idx The output index.
+ * @return The count of matches if no error occurred, -1 otherwise.
+ */
+DIVSUFSORT_API
+saidx_t
+sa_search(const sauchar_t *T, saidx_t Tsize,
+ const sauchar_t *P, saidx_t Psize,
+ const saidx_t *SA, saidx_t SAsize,
+ saidx_t *left);
+
+/**
+ * Search for the character c in the string T.
+ * @param T[0..Tsize-1] The input string.
+ * @param Tsize The length of the given string.
+ * @param SA[0..SAsize-1] The input suffix array.
+ * @param SAsize The length of the given suffix array.
+ * @param c The input character.
+ * @param idx The output index.
+ * @return The count of matches if no error occurred, -1 otherwise.
+ */
+DIVSUFSORT_API
+saidx_t
+sa_simplesearch(const sauchar_t *T, saidx_t Tsize,
+ const saidx_t *SA, saidx_t SAsize,
+ saint_t c, saidx_t *left);
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* _DIVSUFSORT_H */
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/include/divsufsort.h.cmake b/tools/rasm/apultra-master/src/libdivsufsort/include/divsufsort.h.cmake
new file mode 100644
index 0000000..bcaba7c
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/include/divsufsort.h.cmake
@@ -0,0 +1,180 @@
+/*
+ * divsufsort@W64BIT@.h for libdivsufsort@W64BIT@
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#ifndef _DIVSUFSORT@W64BIT@_H
+#define _DIVSUFSORT@W64BIT@_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+@INCFILE@
+
+#ifndef DIVSUFSORT_API
+# ifdef DIVSUFSORT_BUILD_DLL
+# define DIVSUFSORT_API @DIVSUFSORT_EXPORT@
+# else
+# define DIVSUFSORT_API @DIVSUFSORT_IMPORT@
+# endif
+#endif
+
+/*- Datatypes -*/
+#ifndef SAUCHAR_T
+#define SAUCHAR_T
+typedef @SAUCHAR_TYPE@ sauchar_t;
+#endif /* SAUCHAR_T */
+#ifndef SAINT_T
+#define SAINT_T
+typedef @SAINT32_TYPE@ saint_t;
+#endif /* SAINT_T */
+#ifndef SAIDX@W64BIT@_T
+#define SAIDX@W64BIT@_T
+typedef @SAINDEX_TYPE@ saidx@W64BIT@_t;
+#endif /* SAIDX@W64BIT@_T */
+#ifndef PRIdSAINT_T
+#define PRIdSAINT_T @SAINT_PRId@
+#endif /* PRIdSAINT_T */
+#ifndef PRIdSAIDX@W64BIT@_T
+#define PRIdSAIDX@W64BIT@_T @SAINDEX_PRId@
+#endif /* PRIdSAIDX@W64BIT@_T */
+
+
+/*- Prototypes -*/
+
+/**
+ * Constructs the suffix array of a given string.
+ * @param T[0..n-1] The input string.
+ * @param SA[0..n-1] The output array of suffixes.
+ * @param n The length of the given string.
+ * @return 0 if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saint_t
+divsufsort@W64BIT@(const sauchar_t *T, saidx@W64BIT@_t *SA, saidx@W64BIT@_t n);
+
+/**
+ * Constructs the burrows-wheeler transformed string of a given string.
+ * @param T[0..n-1] The input string.
+ * @param U[0..n-1] The output string. (can be T)
+ * @param A[0..n-1] The temporary array. (can be NULL)
+ * @param n The length of the given string.
+ * @return The primary index if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saidx@W64BIT@_t
+divbwt@W64BIT@(const sauchar_t *T, sauchar_t *U, saidx@W64BIT@_t *A, saidx@W64BIT@_t n);
+
+/**
+ * Returns the version of the divsufsort library.
+ * @return The version number string.
+ */
+DIVSUFSORT_API
+const char *
+divsufsort@W64BIT@_version(void);
+
+
+/**
+ * Constructs the burrows-wheeler transformed string of a given string and suffix array.
+ * @param T[0..n-1] The input string.
+ * @param U[0..n-1] The output string. (can be T)
+ * @param SA[0..n-1] The suffix array. (can be NULL)
+ * @param n The length of the given string.
+ * @param idx The output primary index.
+ * @return 0 if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saint_t
+bw_transform@W64BIT@(const sauchar_t *T, sauchar_t *U,
+ saidx@W64BIT@_t *SA /* can NULL */,
+ saidx@W64BIT@_t n, saidx@W64BIT@_t *idx);
+
+/**
+ * Inverse BW-transforms a given BWTed string.
+ * @param T[0..n-1] The input string.
+ * @param U[0..n-1] The output string. (can be T)
+ * @param A[0..n-1] The temporary array. (can be NULL)
+ * @param n The length of the given string.
+ * @param idx The primary index.
+ * @return 0 if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saint_t
+inverse_bw_transform@W64BIT@(const sauchar_t *T, sauchar_t *U,
+ saidx@W64BIT@_t *A /* can NULL */,
+ saidx@W64BIT@_t n, saidx@W64BIT@_t idx);
+
+/**
+ * Checks the correctness of a given suffix array.
+ * @param T[0..n-1] The input string.
+ * @param SA[0..n-1] The input suffix array.
+ * @param n The length of the given string.
+ * @param verbose The verbose mode.
+ * @return 0 if no error occurred.
+ */
+DIVSUFSORT_API
+saint_t
+sufcheck@W64BIT@(const sauchar_t *T, const saidx@W64BIT@_t *SA, saidx@W64BIT@_t n, saint_t verbose);
+
+/**
+ * Search for the pattern P in the string T.
+ * @param T[0..Tsize-1] The input string.
+ * @param Tsize The length of the given string.
+ * @param P[0..Psize-1] The input pattern string.
+ * @param Psize The length of the given pattern string.
+ * @param SA[0..SAsize-1] The input suffix array.
+ * @param SAsize The length of the given suffix array.
+ * @param idx The output index.
+ * @return The count of matches if no error occurred, -1 otherwise.
+ */
+DIVSUFSORT_API
+saidx@W64BIT@_t
+sa_search@W64BIT@(const sauchar_t *T, saidx@W64BIT@_t Tsize,
+ const sauchar_t *P, saidx@W64BIT@_t Psize,
+ const saidx@W64BIT@_t *SA, saidx@W64BIT@_t SAsize,
+ saidx@W64BIT@_t *left);
+
+/**
+ * Search for the character c in the string T.
+ * @param T[0..Tsize-1] The input string.
+ * @param Tsize The length of the given string.
+ * @param SA[0..SAsize-1] The input suffix array.
+ * @param SAsize The length of the given suffix array.
+ * @param c The input character.
+ * @param idx The output index.
+ * @return The count of matches if no error occurred, -1 otherwise.
+ */
+DIVSUFSORT_API
+saidx@W64BIT@_t
+sa_simplesearch@W64BIT@(const sauchar_t *T, saidx@W64BIT@_t Tsize,
+ const saidx@W64BIT@_t *SA, saidx@W64BIT@_t SAsize,
+ saint_t c, saidx@W64BIT@_t *left);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* _DIVSUFSORT@W64BIT@_H */
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/include/divsufsort_config.h b/tools/rasm/apultra-master/src/libdivsufsort/include/divsufsort_config.h
new file mode 100644
index 0000000..4054a8a
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/include/divsufsort_config.h
@@ -0,0 +1,9 @@
+#define HAVE_STRING_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_STDINT_H 1
+#define INLINE inline
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4244 )
+#endif /* _MSC_VER */
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/include/divsufsort_private.h b/tools/rasm/apultra-master/src/libdivsufsort/include/divsufsort_private.h
new file mode 100644
index 0000000..b4d97ad
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/include/divsufsort_private.h
@@ -0,0 +1,205 @@
+/*
+ * divsufsort_private.h for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#ifndef _DIVSUFSORT_PRIVATE_H
+#define _DIVSUFSORT_PRIVATE_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "divsufsort_config.h"
+#include <assert.h>
+#include <stdio.h>
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+#if HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#endif
+#if defined(BUILD_DIVSUFSORT64)
+# include "divsufsort64.h"
+# ifndef SAIDX_T
+# define SAIDX_T
+# define saidx_t saidx64_t
+# endif /* SAIDX_T */
+# ifndef PRIdSAIDX_T
+# define PRIdSAIDX_T PRIdSAIDX64_T
+# endif /* PRIdSAIDX_T */
+# define divsufsort divsufsort64
+# define divbwt divbwt64
+# define divsufsort_version divsufsort64_version
+# define bw_transform bw_transform64
+# define inverse_bw_transform inverse_bw_transform64
+# define sufcheck sufcheck64
+# define sa_search sa_search64
+# define sa_simplesearch sa_simplesearch64
+# define sssort sssort64
+# define trsort trsort64
+#else
+# include "divsufsort.h"
+#endif
+
+
+/*- Constants -*/
+#if !defined(UINT8_MAX)
+# define UINT8_MAX (255)
+#endif /* UINT8_MAX */
+#if defined(ALPHABET_SIZE) && (ALPHABET_SIZE < 1)
+# undef ALPHABET_SIZE
+#endif
+#if !defined(ALPHABET_SIZE)
+# define ALPHABET_SIZE (UINT8_MAX + 1)
+#endif
+/* for divsufsort.c */
+#define BUCKET_A_SIZE (ALPHABET_SIZE)
+#define BUCKET_B_SIZE (ALPHABET_SIZE * ALPHABET_SIZE)
+/* for sssort.c */
+#if defined(SS_INSERTIONSORT_THRESHOLD)
+# if SS_INSERTIONSORT_THRESHOLD < 1
+# undef SS_INSERTIONSORT_THRESHOLD
+# define SS_INSERTIONSORT_THRESHOLD (1)
+# endif
+#else
+# define SS_INSERTIONSORT_THRESHOLD (8)
+#endif
+#if defined(SS_BLOCKSIZE)
+# if SS_BLOCKSIZE < 0
+# undef SS_BLOCKSIZE
+# define SS_BLOCKSIZE (0)
+# elif 32768 <= SS_BLOCKSIZE
+# undef SS_BLOCKSIZE
+# define SS_BLOCKSIZE (32767)
+# endif
+#else
+# define SS_BLOCKSIZE (1024)
+#endif
+/* minstacksize = log(SS_BLOCKSIZE) / log(3) * 2 */
+#if SS_BLOCKSIZE == 0
+# if defined(BUILD_DIVSUFSORT64)
+# define SS_MISORT_STACKSIZE (96)
+# else
+# define SS_MISORT_STACKSIZE (64)
+# endif
+#elif SS_BLOCKSIZE <= 4096
+# define SS_MISORT_STACKSIZE (16)
+#else
+# define SS_MISORT_STACKSIZE (24)
+#endif
+#if defined(BUILD_DIVSUFSORT64)
+# define SS_SMERGE_STACKSIZE (64)
+#else
+# define SS_SMERGE_STACKSIZE (32)
+#endif
+/* for trsort.c */
+#define TR_INSERTIONSORT_THRESHOLD (8)
+#if defined(BUILD_DIVSUFSORT64)
+# define TR_STACKSIZE (96)
+#else
+# define TR_STACKSIZE (64)
+#endif
+
+
+/*- Macros -*/
+#ifndef SWAP
+# define SWAP(_a, _b) do { t = (_a); (_a) = (_b); (_b) = t; } while(0)
+#endif /* SWAP */
+#ifndef MIN
+# define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b))
+#endif /* MIN */
+#ifndef MAX
+# define MAX(_a, _b) (((_a) > (_b)) ? (_a) : (_b))
+#endif /* MAX */
+#define STACK_PUSH(_a, _b, _c, _d)\
+ do {\
+ assert(ssize < STACK_SIZE);\
+ stack[ssize].a = (_a), stack[ssize].b = (_b),\
+ stack[ssize].c = (_c), stack[ssize++].d = (_d);\
+ } while(0)
+#define STACK_PUSH5(_a, _b, _c, _d, _e)\
+ do {\
+ assert(ssize < STACK_SIZE);\
+ stack[ssize].a = (_a), stack[ssize].b = (_b),\
+ stack[ssize].c = (_c), stack[ssize].d = (_d), stack[ssize++].e = (_e);\
+ } while(0)
+#define STACK_POP(_a, _b, _c, _d)\
+ do {\
+ assert(0 <= ssize);\
+ if(ssize == 0) { return; }\
+ (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\
+ (_c) = stack[ssize].c, (_d) = stack[ssize].d;\
+ } while(0)
+#define STACK_POP5(_a, _b, _c, _d, _e)\
+ do {\
+ assert(0 <= ssize);\
+ if(ssize == 0) { return; }\
+ (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\
+ (_c) = stack[ssize].c, (_d) = stack[ssize].d, (_e) = stack[ssize].e;\
+ } while(0)
+/* for divsufsort.c */
+#define BUCKET_A(_c0) bucket_A[(_c0)]
+#if ALPHABET_SIZE == 256
+#define BUCKET_B(_c0, _c1) (bucket_B[((_c1) << 8) | (_c0)])
+#define BUCKET_BSTAR(_c0, _c1) (bucket_B[((_c0) << 8) | (_c1)])
+#else
+#define BUCKET_B(_c0, _c1) (bucket_B[(_c1) * ALPHABET_SIZE + (_c0)])
+#define BUCKET_BSTAR(_c0, _c1) (bucket_B[(_c0) * ALPHABET_SIZE + (_c1)])
+#endif
+
+
+/*- Private Prototypes -*/
+/* sssort.c */
+void
+sssort(const sauchar_t *Td, const saidx_t *PA,
+ saidx_t *first, saidx_t *last,
+ saidx_t *buf, saidx_t bufsize,
+ saidx_t depth, saidx_t n, saint_t lastsuffix);
+/* trsort.c */
+void
+trsort(saidx_t *ISA, saidx_t *SA, saidx_t n, saidx_t depth);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* _DIVSUFSORT_PRIVATE_H */
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/include/lfs.h.cmake b/tools/rasm/apultra-master/src/libdivsufsort/include/lfs.h.cmake
new file mode 100644
index 0000000..d5b84a8
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/include/lfs.h.cmake
@@ -0,0 +1,56 @@
+/*
+ * lfs.h for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#ifndef _LFS_H
+#define _LFS_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef __STRICT_ANSI__
+# define LFS_OFF_T @LFS_OFF_T@
+# define LFS_FOPEN @LFS_FOPEN@
+# define LFS_FTELL @LFS_FTELL@
+# define LFS_FSEEK @LFS_FSEEK@
+# define LFS_PRId @LFS_PRID@
+#else
+# define LFS_OFF_T long
+# define LFS_FOPEN fopen
+# define LFS_FTELL ftell
+# define LFS_FSEEK fseek
+# define LFS_PRId "ld"
+#endif
+#ifndef PRIdOFF_T
+# define PRIdOFF_T LFS_PRId
+#endif
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* _LFS_H */
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/pkgconfig/CMakeLists.txt b/tools/rasm/apultra-master/src/libdivsufsort/pkgconfig/CMakeLists.txt
new file mode 100644
index 0000000..ee7063c
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/pkgconfig/CMakeLists.txt
@@ -0,0 +1,9 @@
+## generate libdivsufsort.pc ##
+set(W64BIT "")
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/libdivsufsort.pc.cmake" "${CMAKE_CURRENT_BINARY_DIR}/libdivsufsort.pc" @ONLY)
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libdivsufsort.pc" DESTINATION ${CMAKE_INSTALL_PKGCONFIGDIR})
+if(BUILD_DIVSUFSORT64)
+ set(W64BIT "64")
+ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/libdivsufsort.pc.cmake" "${CMAKE_CURRENT_BINARY_DIR}/libdivsufsort64.pc" @ONLY)
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libdivsufsort64.pc" DESTINATION ${CMAKE_INSTALL_PKGCONFIGDIR})
+endif(BUILD_DIVSUFSORT64)
diff --git a/tools/rasm/apultra-master/src/libdivsufsort/pkgconfig/libdivsufsort.pc.cmake b/tools/rasm/apultra-master/src/libdivsufsort/pkgconfig/libdivsufsort.pc.cmake
new file mode 100644
index 0000000..6419d1e
--- /dev/null
+++ b/tools/rasm/apultra-master/src/libdivsufsort/pkgconfig/libdivsufsort.pc.cmake
@@ -0,0 +1,11 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=${prefix}
+libdir=@CMAKE_INSTALL_LIBDIR@
+includedir=@CMAKE_INSTALL_INCLUDEDIR@
+
+Name: @PROJECT_NAME@@W64BIT@
+Description: @PROJECT_DESCRIPTION@
+Version: @PROJECT_VERSION_FULL@
+URL: @PROJECT_URL@
+Libs: -L${libdir} -ldivsufsort@W64BIT@
+Cflags: -I${includedir}
diff --git a/tools/rasm/apultra-master/src/matchfinder.c b/tools/rasm/apultra-master/src/matchfinder.c
new file mode 100644
index 0000000..a9987f9
--- /dev/null
+++ b/tools/rasm/apultra-master/src/matchfinder.c
@@ -0,0 +1,449 @@
+/*
+ * matchfinder.c - LZ match finder implementation
+ *
+ * The following copying information applies to this specific source code file:
+ *
+ * Written in 2019 by Emmanuel Marty <marty.emmanuel@gmail.com>
+ * Portions written in 2014-2015 by Eric Biggers <ebiggers3@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all copyright
+ * and related and neighboring rights to this software to the public domain
+ * worldwide via the Creative Commons Zero 1.0 Universal Public Domain
+ * Dedication (the "CC0").
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the CC0 for more details.
+ *
+ * You should have received a copy of the CC0 along with this software; if not
+ * see <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by cap by Sven-Åke Dahl. https://github.com/svendahl/cap
+ * Also inspired by Charles Bloom's compression blog. http://cbloomrants.blogspot.com/
+ * With ideas from LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help and support from spke <zxintrospec@gmail.com>
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "matchfinder.h"
+#include "format.h"
+#include "libapultra.h"
+
+/**
+ * Hash index into TAG_BITS
+ *
+ * @param nIndex index value
+ *
+ * @return hash
+ */
+static inline int apultra_get_index_tag(unsigned int nIndex) {
+ return (int)(((unsigned long long)nIndex * 11400714819323198485ULL) >> (64ULL - TAG_BITS));
+}
+
+/**
+ * Parse input data, build suffix array and overlaid data structures to speed up match finding
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param nInWindowSize total input size in bytes (previously compressed bytes + bytes to compress)
+ *
+ * @return 0 for success, non-zero for failure
+ */
+int apultra_build_suffix_array(apultra_compressor *pCompressor, const unsigned char *pInWindow, const int nInWindowSize) {
+ unsigned long long *intervals = pCompressor->intervals;
+
+ /* Build suffix array from input data */
+ saidx_t *suffixArray = (saidx_t*)intervals;
+ if (divsufsort_build_array(&pCompressor->divsufsort_context, pInWindow, suffixArray, nInWindowSize) != 0) {
+ return 100;
+ }
+
+ int i, r;
+
+ for (i = nInWindowSize - 1; i >= 0; i--) {
+ intervals[i] = suffixArray[i];
+ }
+
+ int *PLCP = (int*)pCompressor->pos_data; /* Use temporarily */
+ int *Phi = PLCP;
+ int nCurLen = 0;
+
+ /* Compute the permuted LCP first (Kärkkäinen method) */
+ Phi[intervals[0]] = -1;
+ for (i = 1; i < nInWindowSize; i++)
+ Phi[intervals[i]] = (unsigned int)intervals[i - 1];
+ for (i = 0; i < nInWindowSize; i++) {
+ if (Phi[i] == -1) {
+ PLCP[i] = 0;
+ continue;
+ }
+ int nMaxLen = (i > Phi[i]) ? (nInWindowSize - i) : (nInWindowSize - Phi[i]);
+ while (nCurLen < nMaxLen && pInWindow[i + nCurLen] == pInWindow[Phi[i] + nCurLen]) nCurLen++;
+ PLCP[i] = nCurLen;
+ if (nCurLen > 0)
+ nCurLen--;
+ }
+
+ /* Rotate permuted LCP into the LCP. This has better cache locality than the direct Kasai LCP method. This also
+ * saves us from having to build the inverse suffix array index, as the LCP is calculated without it using this method,
+ * and the interval builder below doesn't need it either. */
+ intervals[0] &= POS_MASK;
+
+ for (i = 1; i < nInWindowSize; i++) {
+ int nIndex = (int)(intervals[i] & POS_MASK);
+ int nLen = PLCP[nIndex];
+ if (nLen < MIN_MATCH_SIZE)
+ nLen = 0;
+ if (nLen > LCP_MAX)
+ nLen = LCP_MAX;
+ int nTaggedLen = 0;
+ if (nLen)
+ nTaggedLen = (nLen << TAG_BITS) | (apultra_get_index_tag((unsigned int)nIndex) & ((1 << TAG_BITS) - 1));
+ intervals[i] = ((unsigned long long)nIndex) | (((unsigned long long)nTaggedLen) << LCP_SHIFT);
+ }
+
+ /**
+ * Build intervals for finding matches
+ *
+ * Methodology and code fragment taken from wimlib (CC0 license):
+ * https://wimlib.net/git/?p=wimlib;a=blob_plain;f=src/lcpit_matchfinder.c;h=a2d6a1e0cd95200d1f3a5464d8359d5736b14cbe;hb=HEAD
+ */
+ unsigned long long * const SA_and_LCP = intervals;
+ unsigned long long *pos_data = pCompressor->pos_data;
+ unsigned long long next_interval_idx;
+ unsigned long long *top = pCompressor->open_intervals;
+ unsigned long long prev_pos = SA_and_LCP[0] & POS_MASK;
+
+ *top = 0;
+ intervals[0] = 0;
+ next_interval_idx = 1;
+
+ for (r = 1; r < nInWindowSize; r++) {
+ const unsigned long long next_pos = SA_and_LCP[r] & POS_MASK;
+ const unsigned long long next_lcp = SA_and_LCP[r] & LCP_MASK;
+ const unsigned long long top_lcp = *top & LCP_MASK;
+
+ if (next_lcp == top_lcp) {
+ /* Continuing the deepest open interval */
+ pos_data[prev_pos] = *top;
+ }
+ else if (next_lcp > top_lcp) {
+ /* Opening a new interval */
+ *++top = next_lcp | next_interval_idx++;
+ pos_data[prev_pos] = *top;
+ }
+ else {
+ /* Closing the deepest open interval */
+ pos_data[prev_pos] = *top;
+ for (;;) {
+ const unsigned long long closed_interval_idx = *top-- & POS_MASK;
+ const unsigned long long superinterval_lcp = *top & LCP_MASK;
+
+ if (next_lcp == superinterval_lcp) {
+ /* Continuing the superinterval */
+ intervals[closed_interval_idx] = *top;
+ break;
+ }
+ else if (next_lcp > superinterval_lcp) {
+ /* Creating a new interval that is a
+ * superinterval of the one being
+ * closed, but still a subinterval of
+ * its superinterval */
+ *++top = next_lcp | next_interval_idx++;
+ intervals[closed_interval_idx] = *top;
+ break;
+ }
+ else {
+ /* Also closing the superinterval */
+ intervals[closed_interval_idx] = *top;
+ }
+ }
+ }
+ prev_pos = next_pos;
+ }
+
+ /* Close any still-open intervals. */
+ pos_data[prev_pos] = *top;
+ for (; top > pCompressor->open_intervals; top--)
+ intervals[*top & POS_MASK] = *(top - 1);
+
+ /* Success */
+ return 0;
+}
+
+/**
+ * Find matches at the specified offset in the input window
+ *
+ * @param pCompressor compression context
+ * @param nOffset offset to find matches at, in the input window
+ * @param pMatches pointer to returned matches
+ * @param pMatchDepth pointer to returned match depths
+ * @param pMatch1 pointer to 1-byte length, 4 bit offset match
+ * @param nMaxMatches maximum number of matches to return (0 for none)
+ * @param nBlockFlags bit 0: 1 for first block, 0 otherwise; bit 1: 1 for last block, 0 otherwise
+ *
+ * @return number of matches
+ */
+int apultra_find_matches_at(apultra_compressor *pCompressor, const int nOffset, apultra_match *pMatches, unsigned short *pMatchDepth, unsigned char *pMatch1, const int nMaxMatches, const int nBlockFlags) {
+ unsigned long long *intervals = pCompressor->intervals;
+ unsigned long long *pos_data = pCompressor->pos_data;
+ unsigned long long ref;
+ unsigned long long super_ref;
+ unsigned long long match_pos;
+ apultra_match *matchptr;
+ unsigned short *depthptr;
+ const int nMaxOffset = pCompressor->max_offset;
+
+ *pMatch1 = 0;
+
+ /**
+ * Find matches using intervals
+ *
+ * Taken from wimlib (CC0 license):
+ * https://wimlib.net/git/?p=wimlib;a=blob_plain;f=src/lcpit_matchfinder.c;h=a2d6a1e0cd95200d1f3a5464d8359d5736b14cbe;hb=HEAD
+ */
+
+ /* Get the deepest lcp-interval containing the current suffix. */
+ ref = pos_data[nOffset];
+
+ pos_data[nOffset] = 0;
+
+ /* Ascend until we reach a visited interval, the root, or a child of the
+ * root. Link unvisited intervals to the current suffix as we go. */
+ while ((super_ref = intervals[ref & POS_MASK]) & LCP_MASK) {
+ intervals[ref & POS_MASK] = nOffset | VISITED_FLAG;
+ ref = super_ref;
+ }
+
+ if (super_ref == 0) {
+ /* In this case, the current interval may be any of:
+ * (1) the root;
+ * (2) an unvisited child of the root */
+
+ if (ref != 0) /* Not the root? */
+ intervals[ref & POS_MASK] = nOffset | VISITED_FLAG;
+ return 0;
+ }
+
+ /* Ascend indirectly via pos_data[] links. */
+ match_pos = super_ref & EXCL_VISITED_MASK;
+ matchptr = pMatches;
+ depthptr = pMatchDepth;
+ int nPrevOffset = 0;
+ int nPrevLen = 0;
+ int nCurDepth = 0;
+ unsigned short *cur_depth = NULL;
+
+ if (nOffset >= match_pos && (nBlockFlags & 3) == 3) {
+ int nMatchOffset = (int)(nOffset - match_pos);
+ int nMatchLen = (int)(ref >> (LCP_SHIFT + TAG_BITS));
+
+ if ((matchptr - pMatches) < nMaxMatches) {
+ if (nMatchOffset <= nMaxOffset) {
+ if (nPrevOffset && nPrevLen > 2 && nMatchOffset == (nPrevOffset - 1) && nMatchLen == (nPrevLen - 1) && cur_depth && nCurDepth < LCP_MAX) {
+ nCurDepth++;
+ *cur_depth = nCurDepth;
+ }
+ else {
+ nCurDepth = 0;
+
+ cur_depth = depthptr;
+ matchptr->length = nMatchLen;
+ matchptr->offset = nMatchOffset;
+ *depthptr = 0;
+ matchptr++;
+ depthptr++;
+ }
+
+ nPrevLen = nMatchLen;
+ nPrevOffset = nMatchOffset;
+ }
+ }
+ }
+
+ for (;;) {
+ if ((super_ref = pos_data[match_pos]) > ref) {
+ match_pos = intervals[super_ref & POS_MASK] & EXCL_VISITED_MASK;
+
+ if (nOffset >= match_pos && (nBlockFlags & 3) == 3) {
+ int nMatchOffset = (int)(nOffset - match_pos);
+ int nMatchLen = (int)(ref >> (LCP_SHIFT + TAG_BITS));
+
+ if ((matchptr - pMatches) < nMaxMatches) {
+ if (nMatchOffset <= nMaxOffset && abs(nMatchOffset - nPrevOffset) >= 128) {
+ if (nPrevOffset && nPrevLen > 2 && nMatchOffset == (nPrevOffset - 1) && nMatchLen == (nPrevLen - 1) && cur_depth && nCurDepth < LCP_MAX) {
+ nCurDepth++;
+ *cur_depth = nCurDepth | 0x8000;
+ }
+ else {
+ nCurDepth = 0;
+
+ cur_depth = depthptr;
+ matchptr->length = nMatchLen;
+ matchptr->offset = nMatchOffset;
+ *depthptr = 0x8000;
+ matchptr++;
+ depthptr++;
+ }
+
+ nPrevLen = nMatchLen;
+ nPrevOffset = nMatchOffset;
+ }
+ }
+ }
+ }
+
+ while ((super_ref = pos_data[match_pos]) > ref) {
+ match_pos = intervals[super_ref & POS_MASK] & EXCL_VISITED_MASK;
+
+ if (nOffset > match_pos && (nBlockFlags & 3) == 3) {
+ int nMatchOffset = (int)(nOffset - match_pos);
+ int nMatchLen = (int)(ref >> (LCP_SHIFT + TAG_BITS));
+
+ if ((matchptr - pMatches) < nMaxMatches) {
+ if (nMatchOffset <= nMaxOffset && (nMatchLen >= 3 || (nMatchLen >= 2 && (matchptr - pMatches) < (nMaxMatches - 1))) && nMatchLen < 1280 && abs(nMatchOffset - nPrevOffset) >= 128) {
+ if (nPrevOffset && nPrevLen > 2 && nMatchOffset == (nPrevOffset - 1) && nMatchLen == (nPrevLen - 1) && cur_depth && nCurDepth < LCP_MAX) {
+ nCurDepth++;
+ *cur_depth = nCurDepth | 0x8000;
+ }
+ else {
+ nCurDepth = 0;
+
+ cur_depth = depthptr;
+ matchptr->length = nMatchLen;
+ matchptr->offset = nMatchOffset;
+ *depthptr = 0x8000;
+ matchptr++;
+ depthptr++;
+ }
+
+ nPrevLen = nMatchLen;
+ nPrevOffset = nMatchOffset;
+ }
+ }
+ }
+ }
+
+ intervals[ref & POS_MASK] = nOffset | VISITED_FLAG;
+ pos_data[match_pos] = (unsigned long long)ref;
+
+ int nMatchOffset = (int)(nOffset - match_pos);
+ int nMatchLen = (int)(ref >> (LCP_SHIFT + TAG_BITS));
+
+ if ((matchptr - pMatches) < nMaxMatches) {
+ if (nMatchOffset <= nMaxOffset && nMatchOffset != nPrevOffset) {
+ if (nPrevOffset && nPrevLen > 2 && nMatchOffset == (nPrevOffset - 1) && nMatchLen == (nPrevLen - 1) && cur_depth && nCurDepth < LCP_MAX) {
+ nCurDepth++;
+ *cur_depth = nCurDepth;
+ }
+ else {
+ nCurDepth = 0;
+
+ cur_depth = depthptr;
+ matchptr->length = nMatchLen;
+ matchptr->offset = nMatchOffset;
+ *depthptr = 0;
+ matchptr++;
+ depthptr++;
+ }
+
+ nPrevLen = nMatchLen;
+ nPrevOffset = nMatchOffset;
+ }
+ }
+
+ if (nMatchOffset && nMatchOffset < 16 && nMatchLen)
+ *pMatch1 = nMatchOffset;
+
+ if (super_ref == 0)
+ break;
+ ref = super_ref;
+ match_pos = intervals[ref & POS_MASK] & EXCL_VISITED_MASK;
+
+ if (nOffset > match_pos && (nBlockFlags & 3) == 3) {
+ int nMatchOffset = (int)(nOffset - match_pos);
+ int nMatchLen = (int)(ref >> (LCP_SHIFT + TAG_BITS));
+
+ if ((matchptr - pMatches) < nMaxMatches) {
+ if (nMatchOffset <= nMaxOffset && nMatchLen >= 2 && abs(nMatchOffset - nPrevOffset) >= 128) {
+ if (nPrevOffset && nPrevLen > 2 && nMatchOffset == (nPrevOffset - 1) && nMatchLen == (nPrevLen - 1) && cur_depth && nCurDepth < LCP_MAX) {
+ nCurDepth++;
+ *cur_depth = nCurDepth | 0x8000;
+ }
+ else {
+ nCurDepth = 0;
+
+ cur_depth = depthptr;
+ matchptr->length = nMatchLen;
+ matchptr->offset = nMatchOffset;
+ *depthptr = 0x8000;
+ matchptr++;
+ depthptr++;
+ }
+
+ nPrevLen = nMatchLen;
+ nPrevOffset = nMatchOffset;
+ }
+ }
+ }
+ }
+
+ return (int)(matchptr - pMatches);
+}
+
+/**
+ * Skip previously compressed bytes
+ *
+ * @param pCompressor compression context
+ * @param nStartOffset current offset in input window (typically 0)
+ * @param nEndOffset offset to skip to in input window (typically the number of previously compressed bytes)
+ */
+void apultra_skip_matches(apultra_compressor *pCompressor, const int nStartOffset, const int nEndOffset) {
+ apultra_match match;
+ unsigned short depth;
+ unsigned char match1;
+ int i;
+
+ /* Skipping still requires scanning for matches, as this also performs a lazy update of the intervals. However,
+ * we don't store the matches. */
+ for (i = nStartOffset; i < nEndOffset; i++) {
+ apultra_find_matches_at(pCompressor, i, &match, &depth, &match1, 0, 0);
+ }
+}
+
+/**
+ * Find all matches for the data to be compressed
+ *
+ * @param pCompressor compression context
+ * @param nMatchesPerOffset maximum number of matches to store for each offset
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ * @param nBlockFlags bit 0: 1 for first block, 0 otherwise; bit 1: 1 for last block, 0 otherwise
+ */
+void apultra_find_all_matches(apultra_compressor *pCompressor, const int nMatchesPerOffset, const int nStartOffset, const int nEndOffset, const int nBlockFlags) {
+ apultra_match *pMatch = pCompressor->match;
+ unsigned short *pMatchDepth = pCompressor->match_depth;
+ unsigned char *pMatch1 = pCompressor->match1;
+ int i;
+
+ for (i = nStartOffset; i < nEndOffset; i++) {
+ int nMatches = apultra_find_matches_at(pCompressor, i, pMatch, pMatchDepth, pMatch1, nMatchesPerOffset, nBlockFlags);
+
+ while (nMatches < nMatchesPerOffset) {
+ pMatch[nMatches].length = 0;
+ pMatch[nMatches].offset = 0;
+ pMatchDepth[nMatches] = 0;
+ nMatches++;
+ }
+
+ pMatch += nMatchesPerOffset;
+ pMatchDepth += nMatchesPerOffset;
+ pMatch1++;
+ }
+}
diff --git a/tools/rasm/apultra-master/src/matchfinder.h b/tools/rasm/apultra-master/src/matchfinder.h
new file mode 100644
index 0000000..7d68eaf
--- /dev/null
+++ b/tools/rasm/apultra-master/src/matchfinder.h
@@ -0,0 +1,94 @@
+/*
+ * matchfinder.h - LZ match finder definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by cap by Sven-Åke Dahl. https://github.com/svendahl/cap
+ * Also inspired by Charles Bloom's compression blog. http://cbloomrants.blogspot.com/
+ * With ideas from LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help and support from spke <zxintrospec@gmail.com>
+ *
+ */
+
+#ifndef _MATCHFINDER_H
+#define _MATCHFINDER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declarations */
+typedef struct _apultra_match apultra_match;
+typedef struct _apultra_compressor apultra_compressor;
+
+/**
+ * Parse input data, build suffix array and overlaid data structures to speed up match finding
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param nInWindowSize total input size in bytes (previously compressed bytes + bytes to compress)
+ *
+ * @return 0 for success, non-zero for failure
+ */
+int apultra_build_suffix_array(apultra_compressor *pCompressor, const unsigned char *pInWindow, const int nInWindowSize);
+
+/**
+ * Find matches at the specified offset in the input window
+ *
+ * @param pCompressor compression context
+ * @param nOffset offset to find matches at, in the input window
+ * @param pMatches pointer to returned matches
+ * @param pMatchDepth pointer to returned match depths
+ * @param pMatch1 pointer to 1-byte length, 4 bit offset match
+ * @param nMaxMatches maximum number of matches to return (0 for none)
+ * @param nBlockFlags bit 0: 1 for first block, 0 otherwise; bit 1: 1 for last block, 0 otherwise
+ *
+ * @return number of matches
+ */
+int apultra_find_matches_at(apultra_compressor *pCompressor, const int nOffset, apultra_match *pMatches, unsigned short *pMatchDepth, unsigned char *pMatch1, const int nMaxMatches, const int nBlockFlags);
+
+/**
+ * Skip previously compressed bytes
+ *
+ * @param pCompressor compression context
+ * @param nStartOffset current offset in input window (typically 0)
+ * @param nEndOffset offset to skip to in input window (typically the number of previously compressed bytes)
+ */
+void apultra_skip_matches(apultra_compressor *pCompressor, const int nStartOffset, const int nEndOffset);
+
+/**
+ * Find all matches for the data to be compressed
+ *
+ * @param pCompressor compression context
+ * @param nMatchesPerOffset maximum number of matches to store for each offset
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ * @param nBlockFlags bit 0: 1 for first block, 0 otherwise; bit 1: 1 for last block, 0 otherwise
+ */
+void apultra_find_all_matches(apultra_compressor *pCompressor, const int nMatchesPerOffset, const int nStartOffset, const int nEndOffset, const int nBlockFlags);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MATCHFINDER_H */
diff --git a/tools/rasm/apultra-master/src/shrink.c b/tools/rasm/apultra-master/src/shrink.c
new file mode 100644
index 0000000..4b2a4db
--- /dev/null
+++ b/tools/rasm/apultra-master/src/shrink.c
@@ -0,0 +1,1597 @@
+/*
+ * shrink.c - compressor implementation
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by cap by Sven-Åke Dahl. https://github.com/svendahl/cap
+ * Also inspired by Charles Bloom's compression blog. http://cbloomrants.blogspot.com/
+ * With ideas from LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help and support from spke <zxintrospec@gmail.com>
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include "libapultra.h"
+#include "matchfinder.h"
+#include "shrink.h"
+#include "format.h"
+
+#define TOKEN_CODE_LARGE_MATCH 2 /* 10 */
+#define TOKEN_SIZE_LARGE_MATCH 2
+
+#define TOKEN_CODE_7BIT_MATCH 6 /* 110 */
+#define TOKEN_SIZE_7BIT_MATCH 3
+
+#define TOKEN_CODE_4BIT_MATCH 7 /* 111 */
+#define TOKEN_SIZE_4BIT_MATCH 3
+
+#define CountShift(N,bits) if ((N)>>(bits)) { (N)>>=(bits); (n) += (bits); }
+
+/** Gamma2 bit counts for common values, up to 255 */
+static char _gamma2_size[256] = {
+ 0, 0, 2, 2, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+};
+
+/**
+ * Write bitpacked value to output (compressed) buffer
+ *
+ * @param pOutData pointer to output buffer
+ * @param nOutOffset current write index into output buffer
+ * @param nMaxOutDataSize maximum size of output buffer, in bytes
+ * @param nValue value to write
+ * @param nBits number of least significant bits to write in value
+ * @param nCurBitsOffset write index into output buffer, of current byte being filled with bits
+ * @param nCurBitShift bit shift count
+ *
+ * @return updated write index into output buffer, or -1 in case of an error
+ */
+static int apultra_write_bits(unsigned char *pOutData, int nOutOffset, const int nMaxOutDataSize, const int nValue, const int nBits, int *nCurBitsOffset, int *nCurBitShift) {
+ int i;
+
+ if (nOutOffset < 0) return -1;
+
+ for (i = nBits - 1; i >= 0; i--) {
+ if ((*nCurBitsOffset) == INT_MIN) {
+ /* Allocate a new byte in the stream to pack bits in */
+ if (nOutOffset >= nMaxOutDataSize) return -1;
+ (*nCurBitsOffset) = nOutOffset;
+ (*nCurBitShift) = 7;
+ pOutData[nOutOffset++] = 0;
+ }
+
+ pOutData[(*nCurBitsOffset)] |= ((nValue >> i) & 1) << (*nCurBitShift);
+
+ (*nCurBitShift) --;
+ if ((*nCurBitShift) == -1) {
+ /* Current byte is full */
+ (*nCurBitsOffset) = INT_MIN;
+ }
+ }
+
+ return nOutOffset;
+}
+
+/**
+ * Get size of gamma2 encoded value
+ *
+ * @param nValue value of evaluate (2..n)
+ *
+ * @return number of bits required
+ */
+static int apultra_get_gamma2_size(int nValue) {
+ if (nValue >= 0 && nValue < 256)
+ return _gamma2_size[nValue];
+ else {
+ unsigned int n = 0;
+ CountShift(nValue, 16);
+ CountShift(nValue, 8);
+ CountShift(nValue, 4);
+ CountShift(nValue, 2);
+ CountShift(nValue, 1);
+
+ return n << 1;
+ }
+}
+
+/**
+ * Write gamma2 encoded value to output (compressed) buffer
+ *
+ * @param pOutData pointer to output buffer
+ * @param nOutOffset current write index into output buffer
+ * @param nMaxOutDataSize maximum size of output buffer, in bytes
+ * @param nValue value of write (2..n)
+ * @param nCurBitsOffset write index into output buffer, of current byte being filled with bits
+ * @param nCurBitShift bit shift count
+ *
+ * @return updated write index into output buffer, or -1 in case of an error
+ */
+static int apultra_write_gamma2_value(unsigned char *pOutData, int nOutOffset, const int nMaxOutDataSize, int nValue, int *nCurBitsOffset, int *nCurBitShift) {
+ int msb = 30;
+ while ((nValue >> msb--) == 0);
+
+ while (msb > 0) {
+ int bit = (nValue >> msb) & 1;
+
+ nOutOffset = apultra_write_bits(pOutData, nOutOffset, nMaxOutDataSize, bit, 1, nCurBitsOffset, nCurBitShift);
+ msb--;
+ nOutOffset = apultra_write_bits(pOutData, nOutOffset, nMaxOutDataSize, 1, 1, nCurBitsOffset, nCurBitShift);
+ }
+
+ nOutOffset = apultra_write_bits(pOutData, nOutOffset, nMaxOutDataSize, nValue & 1, 1, nCurBitsOffset, nCurBitShift);
+ nOutOffset = apultra_write_bits(pOutData, nOutOffset, nMaxOutDataSize, 0, 1, nCurBitsOffset, nCurBitShift);
+ return nOutOffset;
+}
+
+/**
+ * Get the number of extra bits required to represent a match offset
+ *
+ * @param nLength match length
+ * @param nMatchOffset match offset
+ * @param nFollowsLiteral non-zero if the match follows a literal, zero if it immediately follows another match
+ *
+ * @return number of extra bits required
+ */
+static inline int apultra_get_offset_varlen_size(const int nLength, const int nMatchOffset, const int nFollowsLiteral) {
+ if (nLength <= 3 && nMatchOffset < 128)
+ return 8 + TOKEN_SIZE_7BIT_MATCH;
+ else {
+ if (nFollowsLiteral)
+ return 8 + TOKEN_SIZE_LARGE_MATCH + apultra_get_gamma2_size((nMatchOffset >> 8) + 3);
+ else
+ return 8 + TOKEN_SIZE_LARGE_MATCH + apultra_get_gamma2_size((nMatchOffset >> 8) + 2);
+ }
+}
+
+/**
+ * Get the number of extra bits required to represent a match length
+ *
+ * @param nLength match length
+ * @param nMatchOffset match offset
+ *
+ * @return number of extra bits required
+ */
+static inline int apultra_get_match_varlen_size(int nLength, const int nMatchOffset) {
+ if (nLength <= 3 && nMatchOffset < 128)
+ return 0;
+ else {
+ if (nMatchOffset < 128 || nMatchOffset >= MINMATCH4_OFFSET)
+ return apultra_get_gamma2_size(nLength - 2);
+ else if (nMatchOffset < MINMATCH3_OFFSET)
+ return apultra_get_gamma2_size(nLength);
+ else
+ return apultra_get_gamma2_size(nLength - 1);
+ }
+}
+
+/**
+ * Insert forward rep candidate
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param i input data window position whose matches are being considered
+ * @param nMatchOffset match offset to use as rep candidate
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ * @param nArrivalsPerPosition maximum number of arrivals per input buffer position
+ * @param nDepth current insertion depth
+ */
+static void apultra_insert_forward_match(apultra_compressor *pCompressor, const unsigned char *pInWindow, const int i, const int nMatchOffset, const int nStartOffset, const int nEndOffset, const int nArrivalsPerPosition, int nDepth) {
+ apultra_arrival *arrival = pCompressor->arrival + ((i - nStartOffset) * nArrivalsPerPosition);
+ const int *rle_end = (int*)pCompressor->intervals /* reuse */;
+ int* visited = ((int*)pCompressor->pos_data) - nStartOffset /* reuse */;
+ int j;
+
+ for (j = 0; j < nArrivalsPerPosition && arrival[j].from_slot; j++) {
+ int nRepOffset = arrival[j].rep_offset;
+
+ if (arrival[j].follows_literal && nMatchOffset != nRepOffset && nRepOffset) {
+ int nRepPos = arrival[j].rep_pos;
+
+ if (nRepPos &&
+ nRepPos >= nMatchOffset &&
+ nRepPos < nEndOffset &&
+ pCompressor->match[((nRepPos - nStartOffset) << MATCHES_PER_INDEX_SHIFT) + NMATCHES_PER_INDEX - 1].length == 0) {
+
+ if (visited[nRepPos] != nMatchOffset) {
+ visited[nRepPos] = nMatchOffset;
+
+ const unsigned char* pInWindowAtRepOffset = pInWindow + nRepPos;
+
+ if (pInWindowAtRepOffset[0] == pInWindowAtRepOffset[-nMatchOffset]) {
+ int nMaxRepLen = nEndOffset - nRepPos;
+ if (nMaxRepLen > LCP_MAX)
+ nMaxRepLen = LCP_MAX;
+ const unsigned char* pInWindowMax = pInWindowAtRepOffset + nMaxRepLen;
+
+ int nLen0 = rle_end[nRepPos - nMatchOffset] - (nRepPos - nMatchOffset);
+ int nLen1 = rle_end[nRepPos] - (nRepPos);
+ int nMinLen = (nLen0 < nLen1) ? nLen0 : nLen1;
+
+ if (nMinLen > nMaxRepLen)
+ nMinLen = nMaxRepLen;
+ pInWindowAtRepOffset += nMinLen;
+
+ while ((pInWindowAtRepOffset + 8) < pInWindowMax && !memcmp(pInWindowAtRepOffset, pInWindowAtRepOffset - nMatchOffset, 8))
+ pInWindowAtRepOffset += 8;
+ while ((pInWindowAtRepOffset + 4) < pInWindowMax && !memcmp(pInWindowAtRepOffset, pInWindowAtRepOffset - nMatchOffset, 4))
+ pInWindowAtRepOffset += 4;
+ while (pInWindowAtRepOffset < pInWindowMax && pInWindowAtRepOffset[0] == pInWindowAtRepOffset[-nMatchOffset])
+ pInWindowAtRepOffset++;
+
+ int nCurRepLen = (int)(pInWindowAtRepOffset - (pInWindow + nRepPos));
+
+ if (nCurRepLen >= 2) {
+ apultra_match* fwd_match = pCompressor->match + ((nRepPos - nStartOffset) << MATCHES_PER_INDEX_SHIFT);
+ unsigned short* fwd_depth = pCompressor->match_depth + ((nRepPos - nStartOffset) << MATCHES_PER_INDEX_SHIFT);
+ int r;
+
+ for (r = 0; r < NMATCHES_PER_INDEX && fwd_match[r].length >= MIN_MATCH_SIZE; r++) {
+ if (fwd_match[r].offset == nMatchOffset && (fwd_depth[r] & 0x7fff) == 0) {
+ if ((int)fwd_match[r].length < nCurRepLen) {
+ fwd_match[r].length = nCurRepLen;
+ fwd_depth[r] = 0;
+ }
+ r = NMATCHES_PER_INDEX;
+ break;
+ }
+ }
+
+ if (r < NMATCHES_PER_INDEX) {
+ fwd_match[r].offset = nMatchOffset;
+ fwd_match[r].length = nCurRepLen;
+ fwd_depth[r] = 0;
+
+ if (nDepth < 9)
+ apultra_insert_forward_match(pCompressor, pInWindow, nRepPos, nMatchOffset, nStartOffset, nEndOffset, nArrivalsPerPosition, nDepth + 1);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Attempt to pick optimal matches, so as to produce the smallest possible output that decompresses to the same input
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ * @param nInsertForwardReps non-zero to insert forward repmatch candidates, zero to use the previously inserted candidates
+ * @param nCurRepMatchOffset starting rep offset for this block
+ * @param nBlockFlags bit 0: 1 for first block, 0 otherwise; bit 1: 1 for last block, 0 otherwise
+ * @param nArrivalsPerPosition maximum number of arrivals per input buffer position
+ */
+static void apultra_optimize_forward(apultra_compressor *pCompressor, const unsigned char *pInWindow, const int nStartOffset, const int nEndOffset, const int nInsertForwardReps, const int *nCurRepMatchOffset, const int nBlockFlags, const int nArrivalsPerPosition) {
+ apultra_arrival *arrival = pCompressor->arrival - (nStartOffset * nArrivalsPerPosition);
+ const int* rle_end = (int*)pCompressor->intervals /* reuse */;
+ int* visited = ((int*)pCompressor->pos_data) - nStartOffset /* reuse */;
+ int i, j, n;
+
+ if ((nEndOffset - nStartOffset) > pCompressor->block_size) return;
+
+ memset(arrival + (nStartOffset * nArrivalsPerPosition), 0, sizeof(apultra_arrival) * ((nEndOffset - nStartOffset + 1) * nArrivalsPerPosition));
+
+ arrival[nStartOffset * nArrivalsPerPosition].from_slot = -1;
+ arrival[nStartOffset * nArrivalsPerPosition].rep_offset = *nCurRepMatchOffset;
+
+ for (i = (nStartOffset * nArrivalsPerPosition); i != ((nEndOffset+1) * nArrivalsPerPosition); i++) {
+ arrival[i].cost = 0x40000000;
+ }
+
+ if (nInsertForwardReps) {
+ memset(visited + nStartOffset, 0, (nEndOffset - nStartOffset) * sizeof(int));
+ }
+
+ for (i = nStartOffset; i != nEndOffset; i++) {
+ apultra_arrival *cur_arrival = &arrival[i * nArrivalsPerPosition];
+ int m;
+
+ unsigned char *match1 = pCompressor->match1 + (i - nStartOffset);
+ int nShortOffset;
+ int nShortLen;
+ int nLiteralCost;
+
+ if ((pInWindow[i] != 0 && (*match1) == 0) || (i == nStartOffset && (nBlockFlags & 1))) {
+ nShortOffset = 0;
+ nShortLen = 0;
+ nLiteralCost = 9 /* literal bit + literal byte */;
+ }
+ else {
+ nShortOffset = (pInWindow[i] == 0) ? 0 : (*match1);
+ nShortLen = 1;
+ nLiteralCost = 4 + TOKEN_SIZE_4BIT_MATCH /* command and offset cost; no length cost */;
+ }
+
+ for (j = 0; j < nArrivalsPerPosition && cur_arrival[j].from_slot; j++) {
+ int nPrevCost = cur_arrival[j].cost & 0x3fffffff;
+ int nCodingChoiceCost = nPrevCost + nLiteralCost;
+
+ apultra_arrival *pDestSlots = &cur_arrival[nArrivalsPerPosition];
+ if (nCodingChoiceCost <= pDestSlots[nArrivalsPerPosition - 1].cost) {
+ int exists = 0;
+
+ for (n = 0;
+ n < nArrivalsPerPosition && pDestSlots[n].cost < nCodingChoiceCost;
+ n++) {
+ if (pDestSlots[n].rep_offset == cur_arrival[j].rep_offset) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (!exists) {
+ int nScore = cur_arrival[j].score + (nShortOffset ? 3 : 1);
+
+ for (;
+ n < nArrivalsPerPosition && pDestSlots[n].cost == nCodingChoiceCost && nScore >= pDestSlots[n].score;
+ n++) {
+ if (pDestSlots[n].rep_offset == cur_arrival[j].rep_offset) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (!exists) {
+ if (n < nArrivalsPerPosition) {
+ int nn;
+
+ for (nn = n;
+ nn < nArrivalsPerPosition && pDestSlots[nn].cost == nCodingChoiceCost;
+ nn++) {
+ if (pDestSlots[nn].rep_offset == cur_arrival[j].rep_offset) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (!exists) {
+ int z;
+
+ for (z = n; z < nArrivalsPerPosition - 1 && pDestSlots[z].from_slot; z++) {
+ if (pDestSlots[z].rep_offset == cur_arrival[j].rep_offset)
+ break;
+ }
+
+ apultra_arrival* pDestArrival = &pDestSlots[n];
+ memmove(&pDestSlots[n + 1],
+ &pDestSlots[n],
+ sizeof(apultra_arrival) * (z - n));
+
+ pDestArrival->cost = nCodingChoiceCost;
+ pDestArrival->from_pos = i;
+ pDestArrival->from_slot = j + 1;
+ pDestArrival->follows_literal = 1;
+ pDestArrival->rep_offset = cur_arrival[j].rep_offset;
+ pDestArrival->short_offset = nShortOffset;
+ pDestArrival->rep_pos = cur_arrival[j].rep_pos;
+ pDestArrival->match_len = nShortLen;
+ pDestArrival->score = nScore;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (i == nStartOffset && (nBlockFlags & 1)) continue;
+
+ apultra_match *match = pCompressor->match + ((i - nStartOffset) << MATCHES_PER_INDEX_SHIFT);
+ unsigned short *match_depth = pCompressor->match_depth + ((i - nStartOffset) << MATCHES_PER_INDEX_SHIFT);
+ int nNumArrivalsForThisPos = j, nOverallMinRepLen = 0, nOverallMaxRepLen = 0;
+
+ int nRepLenForArrival[NARRIVALS_PER_POSITION];
+ memset(nRepLenForArrival, 0, NARRIVALS_PER_POSITION * sizeof(int));
+
+ int nRepMatchArrivalIdx[NARRIVALS_PER_POSITION + 1];
+ int nNumRepMatchArrivals = 0;
+
+ int nMaxRepLenForPos = nEndOffset - i;
+ if (nMaxRepLenForPos > LCP_MAX)
+ nMaxRepLenForPos = LCP_MAX;
+ const unsigned char* pInWindowStart = pInWindow + i;
+ const unsigned char* pInWindowMax = pInWindowStart + nMaxRepLenForPos;
+
+ for (j = 0; j < nNumArrivalsForThisPos && (i + 2) <= nEndOffset; j++) {
+ int nRepOffset = cur_arrival[j].rep_offset;
+
+ if (cur_arrival[j].follows_literal &&
+ nRepOffset) {
+ if (i >= nRepOffset) {
+
+ if (pInWindowStart[0] == pInWindowStart[-nRepOffset]) {
+ const unsigned char* pInWindowAtRepOffset = pInWindowStart;
+
+ int nLen0 = rle_end[i - nRepOffset] - (i - nRepOffset);
+ int nLen1 = rle_end[i] - (i);
+ int nMinLen = (nLen0 < nLen1) ? nLen0 : nLen1;
+
+ if (nMinLen > nMaxRepLenForPos)
+ nMinLen = nMaxRepLenForPos;
+ pInWindowAtRepOffset += nMinLen;
+
+ while ((pInWindowAtRepOffset + 8) < pInWindowMax && !memcmp(pInWindowAtRepOffset, pInWindowAtRepOffset - nRepOffset, 8))
+ pInWindowAtRepOffset += 8;
+ while ((pInWindowAtRepOffset + 4) < pInWindowMax && !memcmp(pInWindowAtRepOffset, pInWindowAtRepOffset - nRepOffset, 4))
+ pInWindowAtRepOffset += 4;
+ while (pInWindowAtRepOffset < pInWindowMax && pInWindowAtRepOffset[0] == pInWindowAtRepOffset[-nRepOffset])
+ pInWindowAtRepOffset++;
+
+ int nCurMaxLen = (int)(pInWindowAtRepOffset - pInWindowStart);
+
+ if (nCurMaxLen >= 2) {
+ nRepLenForArrival[j] = nCurMaxLen;
+ nRepMatchArrivalIdx[nNumRepMatchArrivals++] = j;
+ }
+
+ if (nOverallMaxRepLen < nCurMaxLen)
+ nOverallMaxRepLen = nCurMaxLen;
+ }
+ }
+ }
+ }
+ nRepMatchArrivalIdx[nNumRepMatchArrivals++] = -1;
+
+ for (m = 0; m < NMATCHES_PER_INDEX && match[m].length; m++) {
+ const int nOrigMatchLen = match[m].length;
+ const int nOrigMatchOffset = match[m].offset;
+ const unsigned int nOrigMatchDepth = match_depth[m] & 0x7fff;
+ const int nScorePenalty = 3 + ((match_depth[m] & 0x8000) >> 15);
+ unsigned int d;
+
+ for (d = 0; d <= nOrigMatchDepth; d += (nOrigMatchDepth ? nOrigMatchDepth : 1)) {
+ const int nMatchOffset = nOrigMatchOffset - d;
+ int nMatchLen = nOrigMatchLen - d;
+
+ if ((i + nMatchLen) > nEndOffset)
+ nMatchLen = nEndOffset - i;
+
+ if (nInsertForwardReps) {
+ apultra_insert_forward_match(pCompressor, pInWindow, i, nMatchOffset, nStartOffset, nEndOffset, nArrivalsPerPosition, 0);
+ }
+
+ if (nMatchLen >= 2) {
+ int nStartingMatchLen, nJumpMatchLen, k;
+ int nNoRepMatchOffsetCostForLit[2], nNoRepMatchOffsetCostDelta;
+ int nMinMatchLenForOffset;
+ int nNoRepCostAdjusment = (nMatchLen >= LCP_MAX) ? 1 : 0;
+
+ if (nMatchOffset < MINMATCH3_OFFSET)
+ nMinMatchLenForOffset = 2;
+ else {
+ if (nMatchOffset < MINMATCH4_OFFSET)
+ nMinMatchLenForOffset = 3;
+ else
+ nMinMatchLenForOffset = 4;
+ }
+
+ if (nMatchLen >= LEAVE_ALONE_MATCH_SIZE && i >= nMatchLen)
+ nStartingMatchLen = nMatchLen;
+ else
+ nStartingMatchLen = 2;
+
+ if ((nBlockFlags & 3) == 3 && nMatchLen > 90 && i >= 90)
+ nJumpMatchLen = 90;
+ else
+ nJumpMatchLen = nMatchLen + 1;
+
+ if (nStartingMatchLen <= 3 && nMatchOffset < 128) {
+ nNoRepMatchOffsetCostForLit[0] = 8 + TOKEN_SIZE_7BIT_MATCH;
+ nNoRepMatchOffsetCostForLit[1] = 8 + TOKEN_SIZE_7BIT_MATCH;
+ }
+ else {
+ nNoRepMatchOffsetCostForLit[0] = 8 + TOKEN_SIZE_LARGE_MATCH + apultra_get_gamma2_size((nMatchOffset >> 8) + 2);
+ nNoRepMatchOffsetCostForLit[1] = 8 + TOKEN_SIZE_LARGE_MATCH + apultra_get_gamma2_size((nMatchOffset >> 8) + 3);
+ }
+ nNoRepMatchOffsetCostDelta = nNoRepMatchOffsetCostForLit[1] - nNoRepMatchOffsetCostForLit[0];
+
+ for (k = nStartingMatchLen; k <= nMatchLen; k++) {
+ int nRepMatchMatchLenCost = apultra_get_gamma2_size(k);
+ apultra_arrival *pDestSlots = &cur_arrival[k * nArrivalsPerPosition];
+
+ /* Insert non-repmatch candidate */
+
+ if (k >= nMinMatchLenForOffset) {
+ int nNoRepMatchMatchLenCost;
+
+ if (k <= 3 && nMatchOffset < 128)
+ nNoRepMatchMatchLenCost = 0;
+ else {
+ if (nMatchOffset < 128 || nMatchOffset >= MINMATCH4_OFFSET)
+ nNoRepMatchMatchLenCost = apultra_get_gamma2_size(k - 2);
+ else if (nMatchOffset < MINMATCH3_OFFSET)
+ nNoRepMatchMatchLenCost = nRepMatchMatchLenCost;
+ else
+ nNoRepMatchMatchLenCost = apultra_get_gamma2_size(k - 1);
+ }
+
+ for (j = 0; j < nNumArrivalsForThisPos; j++) {
+ if (nMatchOffset != cur_arrival[j].rep_offset || cur_arrival[j].follows_literal == 0) {
+ int nPrevCost = cur_arrival[j].cost & 0x3fffffff;
+ int nMatchCmdCost = nNoRepMatchMatchLenCost + nNoRepMatchOffsetCostForLit[cur_arrival[j].follows_literal];
+ int nCodingChoiceCost = nPrevCost + nMatchCmdCost;
+
+ if (nCodingChoiceCost <= (pDestSlots[nArrivalsPerPosition - 1].cost + 1)) {
+ int nScore = cur_arrival[j].score + nScorePenalty;
+
+ if (nCodingChoiceCost < pDestSlots[nArrivalsPerPosition - 2].cost ||
+ (nCodingChoiceCost == pDestSlots[nArrivalsPerPosition - 2].cost && nScore < pDestSlots[nArrivalsPerPosition - 2].score)) {
+ int exists = 0;
+
+ for (n = 0;
+ n < nArrivalsPerPosition && pDestSlots[n].cost < nCodingChoiceCost;
+ n++) {
+ if (pDestSlots[n].rep_offset == nMatchOffset) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (!exists) {
+ int nRevisedCodingChoiceCost = nCodingChoiceCost - nNoRepCostAdjusment;
+
+ for (;
+ n < nArrivalsPerPosition - 1 && pDestSlots[n].cost == nRevisedCodingChoiceCost && nScore >= pDestSlots[n].score;
+ n++) {
+ if (pDestSlots[n].rep_offset == nMatchOffset) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (!exists) {
+ if (n < nArrivalsPerPosition - 1) {
+ int nn;
+
+ for (nn = n;
+ nn < nArrivalsPerPosition && pDestSlots[nn].cost == nCodingChoiceCost;
+ nn++) {
+ if (pDestSlots[nn].rep_offset == nMatchOffset) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (!exists) {
+ int z;
+
+ for (z = n; z < nArrivalsPerPosition - 1 && pDestSlots[z].from_slot; z++) {
+ if (pDestSlots[z].rep_offset == nMatchOffset)
+ break;
+ }
+
+ apultra_arrival* pDestArrival = &pDestSlots[n];
+ memmove(&pDestSlots[n + 1],
+ &pDestSlots[n],
+ sizeof(apultra_arrival) * (z - n));
+
+ pDestArrival->cost = nRevisedCodingChoiceCost;
+ pDestArrival->from_pos = i;
+ pDestArrival->from_slot = j + 1;
+ pDestArrival->follows_literal = 0;
+ pDestArrival->rep_offset = nMatchOffset;
+ pDestArrival->short_offset = 0;
+ pDestArrival->rep_pos = i;
+ pDestArrival->match_len = k;
+ pDestArrival->score = nScore;
+ }
+ }
+ }
+ }
+ else {
+ if ((nCodingChoiceCost - pDestSlots[n].cost) >= nNoRepMatchOffsetCostDelta)
+ break;
+ }
+ }
+ if (cur_arrival[j].follows_literal == 0 || nNoRepMatchOffsetCostDelta == 0)
+ break;
+ }
+ else {
+ break;
+ }
+ }
+ }
+ }
+
+ /* Insert repmatch candidate */
+
+ if (k > nOverallMinRepLen && k <= nOverallMaxRepLen) {
+ int nRepMatchCmdCost = TOKEN_SIZE_LARGE_MATCH + 2 /* apultra_get_gamma2_size(2) */ + nRepMatchMatchLenCost;
+ int nCurRepMatchArrival;
+
+ if (k <= 90)
+ nOverallMinRepLen = k;
+
+ for (nCurRepMatchArrival = 0; (j = nRepMatchArrivalIdx[nCurRepMatchArrival]) >= 0; nCurRepMatchArrival++) {
+ if (nRepLenForArrival[j] >= k) {
+ int nPrevCost = cur_arrival[j].cost & 0x3fffffff;
+ int nRepCodingChoiceCost = nPrevCost + nRepMatchCmdCost;
+ int nScore = cur_arrival[j].score + 2;
+
+ if (nRepCodingChoiceCost < pDestSlots[nArrivalsPerPosition - 1].cost ||
+ (nRepCodingChoiceCost == pDestSlots[nArrivalsPerPosition - 1].cost && nScore < pDestSlots[nArrivalsPerPosition - 1].score)) {
+ int nRepOffset = cur_arrival[j].rep_offset;
+ int exists = 0;
+
+ for (n = 0;
+ n < nArrivalsPerPosition && pDestSlots[n].cost < nRepCodingChoiceCost;
+ n++) {
+ if (pDestSlots[n].rep_offset == nRepOffset) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (!exists) {
+ for (;
+ n < nArrivalsPerPosition && pDestSlots[n].cost == nRepCodingChoiceCost && nScore >= pDestSlots[n].score;
+ n++) {
+ if (pDestSlots[n].rep_offset == nRepOffset) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (!exists) {
+ if (n < nArrivalsPerPosition) {
+ int nn;
+
+ for (nn = n;
+ nn < nArrivalsPerPosition && pDestSlots[nn].cost == nRepCodingChoiceCost;
+ nn++) {
+ if (pDestSlots[nn].rep_offset == nRepOffset) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (!exists) {
+ int z;
+
+ for (z = n; z < nArrivalsPerPosition - 1 && pDestSlots[z].from_slot; z++) {
+ if (pDestSlots[z].rep_offset == nRepOffset)
+ break;
+ }
+
+ apultra_arrival* pDestArrival = &pDestSlots[n];
+ memmove(&pDestSlots[n + 1],
+ &pDestSlots[n],
+ sizeof(apultra_arrival) * (z - n));
+
+ pDestArrival->cost = nRepCodingChoiceCost;
+ pDestArrival->from_pos = i;
+ pDestArrival->from_slot = j + 1;
+ pDestArrival->follows_literal = 0;
+ pDestArrival->rep_offset = nRepOffset;
+ pDestArrival->short_offset = 0;
+ pDestArrival->rep_pos = i;
+ pDestArrival->match_len = k;
+ pDestArrival->score = nScore;
+ }
+ }
+ }
+ }
+ }
+ else {
+ break;
+ }
+ }
+ }
+ }
+
+ if (k == 3 && nMatchOffset < 128) {
+ nNoRepMatchOffsetCostForLit[0] = 8 + TOKEN_SIZE_LARGE_MATCH + 2 /* apultra_get_gamma2_size((nMatchOffset >> 8) + 2) */;
+ nNoRepMatchOffsetCostForLit[1] = 8 + TOKEN_SIZE_LARGE_MATCH + 2 /* apultra_get_gamma2_size((nMatchOffset >> 8) + 3) */;
+ }
+
+ if (k == nJumpMatchLen)
+ k = nMatchLen - 1;
+ }
+ }
+
+ if (nOrigMatchLen >= 512)
+ break;
+ }
+ }
+ }
+
+ if (!nInsertForwardReps) {
+ apultra_arrival* end_arrival = &arrival[(i * nArrivalsPerPosition) + 0];
+ apultra_final_match* pBestMatch = pCompressor->best_match - nStartOffset;
+
+ while (end_arrival->from_slot > 0 && end_arrival->from_pos >= 0 && (int)end_arrival->from_pos < nEndOffset) {
+ pBestMatch[end_arrival->from_pos].length = end_arrival->match_len;
+ if (end_arrival->match_len >= 2)
+ pBestMatch[end_arrival->from_pos].offset = end_arrival->rep_offset;
+ else
+ pBestMatch[end_arrival->from_pos].offset = end_arrival->short_offset;
+
+ end_arrival = &arrival[(end_arrival->from_pos * nArrivalsPerPosition) + (end_arrival->from_slot - 1)];
+ }
+ }
+}
+
+/**
+ * Attempt to replace matches by literals when it makes the final bitstream smaller, and merge large matches
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param pBestMatch optimal matches to evaluate and update
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ * @param nCurRepMatchOffset starting rep offset for this block
+ * @param nBlockFlags bit 0: 1 for first block, 0 otherwise; bit 1: 1 for last block, 0 otherwise
+ *
+ * @return non-zero if the number of tokens was reduced, 0 if it wasn't
+ */
+static int apultra_reduce_commands(apultra_compressor *pCompressor, const unsigned char *pInWindow, apultra_final_match *pBestMatch, const int nStartOffset, const int nEndOffset, const int *nCurRepMatchOffset, const int nBlockFlags) {
+ int i;
+ int nRepMatchOffset = *nCurRepMatchOffset;
+ int nFollowsLiteral = 0;
+ int nDidReduce = 0;
+ int nLastMatchLen = 0;
+ const unsigned char *match1 = pCompressor->match1 - nStartOffset;
+
+ for (i = nStartOffset + ((nBlockFlags & 1) ? 1 : 0); i < nEndOffset; ) {
+ apultra_final_match *pMatch = pBestMatch + i;
+
+ if (pMatch->length <= 1 &&
+ (i + 1) < nEndOffset &&
+ pBestMatch[i + 1].length >= 2 &&
+ pBestMatch[i + 1].length < MAX_VARLEN &&
+ pBestMatch[i + 1].offset &&
+ i >= pBestMatch[i + 1].offset &&
+ (i + pBestMatch[i + 1].length + 1) <= nEndOffset &&
+ !memcmp(pInWindow + i - (pBestMatch[i + 1].offset), pInWindow + i, pBestMatch[i + 1].length + 1)) {
+ if ((pBestMatch[i + 1].offset < MINMATCH3_OFFSET || (pBestMatch[i + 1].length + 1) >= 3 || (pBestMatch[i + 1].offset == nRepMatchOffset && nFollowsLiteral)) &&
+ (pBestMatch[i + 1].offset < MINMATCH4_OFFSET || (pBestMatch[i + 1].length + 1) >= 4 || (pBestMatch[i + 1].offset == nRepMatchOffset && nFollowsLiteral))) {
+
+ int nCurPartialCommandSize = (pMatch->length == 1) ? (TOKEN_SIZE_4BIT_MATCH + 4) : (1 /* literal bit */ + 8 /* literal size */);
+ if (pBestMatch[i + 1].offset == nRepMatchOffset /* always follows a literal, the one at the current position */) {
+ nCurPartialCommandSize += TOKEN_SIZE_LARGE_MATCH + 2 /* apultra_get_gamma2_size(2) */ + apultra_get_gamma2_size(pBestMatch[i + 1].length);
+ }
+ else {
+ nCurPartialCommandSize += apultra_get_offset_varlen_size(pBestMatch[i + 1].length, pBestMatch[i + 1].offset, 1) + apultra_get_match_varlen_size(pBestMatch[i + 1].length, pBestMatch[i + 1].offset);
+ }
+
+ int nReducedPartialCommandSize;
+ if (pBestMatch[i + 1].offset == nRepMatchOffset && nFollowsLiteral) {
+ nReducedPartialCommandSize = TOKEN_SIZE_LARGE_MATCH + 2 /* apultra_get_gamma2_size(2) */ + apultra_get_gamma2_size(pBestMatch[i + 1].length);
+ }
+ else {
+ nReducedPartialCommandSize = apultra_get_offset_varlen_size(pBestMatch[i + 1].length, pBestMatch[i + 1].offset, nFollowsLiteral) + apultra_get_match_varlen_size(pBestMatch[i + 1].length, pBestMatch[i + 1].offset);
+ }
+
+ if (nReducedPartialCommandSize < nCurPartialCommandSize || (nFollowsLiteral == 0 && nLastMatchLen >= LCP_MAX)) {
+ /* Merge */
+ pBestMatch[i].length = pBestMatch[i + 1].length + 1;
+ pBestMatch[i].offset = pBestMatch[i + 1].offset;
+ pBestMatch[i + 1].length = 0;
+ pBestMatch[i + 1].offset = 0;
+ nDidReduce = 1;
+ continue;
+ }
+ }
+ }
+
+ if (pMatch->length >= 2) {
+ if (pMatch->length < 32 && /* Don't waste time considering large matches, they will always win over literals */
+ (i + pMatch->length) < nEndOffset /* Don't consider the last match in the block, we can only reduce a match inbetween other tokens */) {
+ int nNextIndex = i + pMatch->length;
+ int nNextFollowsLiteral = 0;
+ int nCannotEncode = 0;
+
+ while (nNextIndex < nEndOffset && pBestMatch[nNextIndex].length < 2) {
+ nNextIndex++;
+ nNextFollowsLiteral = 1;
+ }
+
+ if (nNextIndex < nEndOffset && pBestMatch[nNextIndex].length >= 2) {
+ if (nRepMatchOffset && nRepMatchOffset != pMatch->offset && pBestMatch[nNextIndex].offset && pMatch->offset != pBestMatch[nNextIndex].offset &&
+ nNextFollowsLiteral) {
+ /* Try to gain a match forward */
+ if (i >= pBestMatch[nNextIndex].offset && (i - pBestMatch[nNextIndex].offset + pMatch->length) <= nEndOffset) {
+ if ((pBestMatch[nNextIndex].offset < MINMATCH3_OFFSET || pMatch->length >= 3) &&
+ (pBestMatch[nNextIndex].offset < MINMATCH4_OFFSET || pMatch->length >= 4)) {
+ int nMaxLen = 0;
+ const unsigned char* pInWindowAtPos = pInWindow + i;
+ while (nMaxLen < pMatch->length && pInWindowAtPos[nMaxLen - pBestMatch[nNextIndex].offset] == pInWindowAtPos[nMaxLen])
+ nMaxLen++;
+
+ if (nMaxLen >= pMatch->length) {
+ /* Replace */
+ pMatch->offset = pBestMatch[nNextIndex].offset;
+ nDidReduce = 1;
+ }
+ else if (nMaxLen >= 2) {
+ if ((nFollowsLiteral && nRepMatchOffset == pBestMatch[nNextIndex].offset) ||
+ ((pBestMatch[nNextIndex].offset < MINMATCH3_OFFSET || nMaxLen >= 3) &&
+ (pBestMatch[nNextIndex].offset < MINMATCH4_OFFSET || nMaxLen >= 4))) {
+
+ int nPartialSizeBefore, nPartialSizeAfter, j;
+
+ nPartialSizeBefore = apultra_get_offset_varlen_size(pMatch->length, pMatch->offset, nFollowsLiteral);
+ nPartialSizeBefore += apultra_get_match_varlen_size(pMatch->length, pMatch->offset);
+
+ nPartialSizeBefore += apultra_get_offset_varlen_size(pBestMatch[nNextIndex].length, pBestMatch[nNextIndex].offset, 1);
+ nPartialSizeBefore += apultra_get_match_varlen_size(pBestMatch[nNextIndex].length, pBestMatch[nNextIndex].offset);
+
+ nPartialSizeAfter = apultra_get_offset_varlen_size(nMaxLen, pBestMatch[nNextIndex].offset, nFollowsLiteral);
+ if (nFollowsLiteral && nRepMatchOffset == pBestMatch[nNextIndex].offset)
+ nPartialSizeAfter += apultra_get_gamma2_size(nMaxLen);
+ else
+ nPartialSizeAfter += apultra_get_match_varlen_size(nMaxLen, pBestMatch[nNextIndex].offset);
+
+ nPartialSizeAfter += TOKEN_SIZE_LARGE_MATCH + 2 /* apultra_get_gamma2_size(2) */;
+ nPartialSizeAfter += apultra_get_gamma2_size(pBestMatch[nNextIndex].length);
+
+ for (j = nMaxLen; j < pMatch->length; j++) {
+ if (pInWindow[i + j] == 0 || match1[i + j])
+ nPartialSizeAfter += TOKEN_SIZE_4BIT_MATCH + 4;
+ else
+ nPartialSizeAfter += 1 /* literal bit */ + 8 /* literal byte */;
+ }
+
+ if (nPartialSizeAfter < nPartialSizeBefore) {
+ /* We gain a repmatch that is shorter than the original match as this is the best we can do, so it is followed by extra literals, but
+ * we have calculated that this is shorter */
+
+ int nOrigLen = pMatch->length;
+ int j;
+
+ pMatch->offset = pBestMatch[nNextIndex].offset;
+ pMatch->length = nMaxLen;
+
+ for (j = nMaxLen; j < nOrigLen; j++) {
+ pBestMatch[i + j].offset = match1[i + j];
+ pBestMatch[i + j].length = (pInWindow[i + j] && match1[i+j] == 0) ? 0 : 1;
+ }
+
+ nDidReduce = 1;
+ continue;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Calculate this command's current cost */
+
+ int nCurCommandSize;
+ if (pMatch->offset == nRepMatchOffset && nFollowsLiteral) {
+ nCurCommandSize = TOKEN_SIZE_LARGE_MATCH + 2 /* apultra_get_gamma2_size(2) */ + apultra_get_gamma2_size(pMatch->length);
+ }
+ else {
+ nCurCommandSize = apultra_get_offset_varlen_size(pMatch->length, pMatch->offset, nFollowsLiteral) + apultra_get_match_varlen_size(pMatch->length, pMatch->offset);
+ }
+
+ /* Calculate the next command's current cost */
+ int nNextCommandSize;
+ if (pBestMatch[nNextIndex].offset == pMatch->offset && nNextFollowsLiteral && pBestMatch[nNextIndex].length >= 2) {
+ nNextCommandSize = TOKEN_SIZE_LARGE_MATCH + 2 /* apultra_get_gamma2_size(2) */ + apultra_get_gamma2_size(pBestMatch[nNextIndex].length);
+ }
+ else {
+ nNextCommandSize = apultra_get_offset_varlen_size(pBestMatch[nNextIndex].length, pBestMatch[nNextIndex].offset, nNextFollowsLiteral) + apultra_get_match_varlen_size(pBestMatch[nNextIndex].length, pBestMatch[nNextIndex].offset);
+ }
+
+ int nOriginalCombinedCommandSize = nCurCommandSize + nNextCommandSize;
+
+ /* Calculate the cost of replacing this match command by literals + the effect on the cost of the next command */
+ int nReducedCommandSize = 0;
+ int j;
+
+ for (j = 0; j < pMatch->length; j++) {
+ if (pInWindow[i + j] == 0 || match1[i + j])
+ nReducedCommandSize += TOKEN_SIZE_4BIT_MATCH + 4;
+ else
+ nReducedCommandSize += 1 /* literal bit */ + 8;
+ }
+
+ if (pBestMatch[nNextIndex].offset == nRepMatchOffset /* the new command would always follow literals, the ones we create */ && pBestMatch[nNextIndex].length >= 2) {
+ nReducedCommandSize += TOKEN_SIZE_LARGE_MATCH + 2 /* apultra_get_gamma2_size(2) */ + apultra_get_gamma2_size(pBestMatch[nNextIndex].length);
+ }
+ else {
+ if ((pBestMatch[nNextIndex].length < 3 && pBestMatch[nNextIndex].offset >= MINMATCH3_OFFSET) ||
+ (pBestMatch[nNextIndex].length < 4 && pBestMatch[nNextIndex].offset >= MINMATCH4_OFFSET)) {
+ /* This match length can only be encoded with a rep-match */
+ nCannotEncode = 1;
+ }
+ else {
+ nReducedCommandSize += apultra_get_offset_varlen_size(pBestMatch[nNextIndex].length, pBestMatch[nNextIndex].offset, 1 /* follows literals */) + apultra_get_match_varlen_size(pBestMatch[nNextIndex].length, pBestMatch[nNextIndex].offset);
+ }
+ }
+
+ if (!nCannotEncode && nOriginalCombinedCommandSize > nReducedCommandSize) {
+ /* Reduce */
+ int nMatchLen = pMatch->length;
+ int j;
+
+ for (j = 0; j < nMatchLen; j++) {
+ pBestMatch[i + j].offset = match1[i + j];
+ pBestMatch[i + j].length = (pInWindow[i + j] && match1[i + j] == 0) ? 0 : 1;
+ }
+
+ nDidReduce = 1;
+ continue;
+ }
+ }
+ }
+
+ if ((i + pMatch->length) < nEndOffset && pMatch->offset > 0 &&
+ pBestMatch[i + pMatch->length].offset > 0 &&
+ pBestMatch[i + pMatch->length].length >= 2 &&
+ (pMatch->length + pBestMatch[i + pMatch->length].length) >= LEAVE_ALONE_MATCH_SIZE &&
+ (pMatch->length + pBestMatch[i + pMatch->length].length) <= MAX_VARLEN &&
+ (i + pMatch->length) >= pMatch->offset &&
+ (i + pMatch->length) >= pBestMatch[i + pMatch->length].offset &&
+ (i + pMatch->length + pBestMatch[i + pMatch->length].length) <= nEndOffset &&
+ !memcmp(pInWindow + i + pMatch->length - pMatch->offset,
+ pInWindow + i + pMatch->length - pBestMatch[i + pMatch->length].offset,
+ pBestMatch[i + pMatch->length].length)) {
+ int nMatchLen = pMatch->length;
+
+ /* Join large matches */
+
+ int nNextIndex = i + pMatch->length + pBestMatch[i + pMatch->length].length;
+ int nNextFollowsLiteral = 0;
+ int nCannotEncode = 0;
+
+ while (nNextIndex < nEndOffset && pBestMatch[nNextIndex].length < 2) {
+ nNextIndex++;
+ nNextFollowsLiteral = 1;
+ }
+
+ if (nNextIndex < nEndOffset && nNextFollowsLiteral && pBestMatch[nNextIndex].length >= 2 &&
+ pBestMatch[nNextIndex].offset == pBestMatch[i + pMatch->length].offset) {
+ if ((pBestMatch[nNextIndex].offset >= MINMATCH3_OFFSET && pBestMatch[nNextIndex].length < 3) ||
+ (pBestMatch[nNextIndex].offset >= MINMATCH4_OFFSET && pBestMatch[nNextIndex].length < 4)) {
+ nCannotEncode = 1;
+ }
+ }
+
+ if (!nCannotEncode) {
+ pMatch->length += pBestMatch[i + nMatchLen].length;
+ pBestMatch[i + nMatchLen].offset = 0;
+ pBestMatch[i + nMatchLen].length = -1;
+ nDidReduce = 1;
+ continue;
+ }
+ }
+
+ nRepMatchOffset = pMatch->offset;
+ nFollowsLiteral = 0;
+ nLastMatchLen = pMatch->length;
+
+ i += pMatch->length;
+ }
+ else {
+ /* 4 bits offset (1 byte match) or literal */
+ i++;
+ nFollowsLiteral = 1;
+ nLastMatchLen = 0;
+ }
+ }
+
+ return nDidReduce;
+}
+
+/**
+ * Emit a block of compressed data
+ *
+ * @param pCompressor compression context
+ * @param pBestMatch optimal matches to emit
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ * @param pOutData pointer to output buffer
+ * @param nMaxOutDataSize maximum size of output buffer, in bytes
+ * @param nCurBitsOffset write index into output buffer, of current byte being filled with bits
+ * @param nCurBitShift bit shift count
+ * @param nFollowsLiteral non-zero if the next command to be issued follows a literal, 0 if not
+ * @param nCurRepMatchOffset starting rep offset for this block, updated after the block is compressed successfully
+ * @param nBlockFlags bit 0: 1 for first block, 0 otherwise; bit 1: 1 for last block, 0 otherwise
+ *
+ * @return size of compressed data in output buffer, or -1 if the data is uncompressible
+ */
+static int apultra_write_block(apultra_compressor *pCompressor, apultra_final_match *pBestMatch, const unsigned char *pInWindow, const int nStartOffset, const int nEndOffset, unsigned char *pOutData, int nOutOffset, const int nMaxOutDataSize, int *nCurBitsOffset, int *nCurBitShift, int *nFollowsLiteral, int *nCurRepMatchOffset, const int nBlockFlags) {
+ int i;
+ int nRepMatchOffset = *nCurRepMatchOffset;
+ const int nMaxOffset = pCompressor->max_offset;
+
+ if (nBlockFlags & 1) {
+ if (nOutOffset < 0 || nOutOffset >= nMaxOutDataSize)
+ return -1;
+ pOutData[nOutOffset++] = pInWindow[nStartOffset];
+ *nFollowsLiteral = 1;
+ }
+
+ for (i = nStartOffset + ((nBlockFlags & 1) ? 1 : 0); i < nEndOffset; ) {
+ const apultra_final_match *pMatch = pBestMatch + i;
+
+ if (pMatch->length >= 2) {
+ int nMatchOffset = pMatch->offset;
+ int nMatchLen = pMatch->length;
+
+ if (nMatchOffset < MIN_OFFSET || nMatchOffset > nMaxOffset)
+ return -1;
+
+ if (nMatchOffset == nRepMatchOffset && *nFollowsLiteral) {
+ /* Rep-match */
+ nOutOffset = apultra_write_bits(pOutData, nOutOffset, nMaxOutDataSize, TOKEN_CODE_LARGE_MATCH, TOKEN_SIZE_LARGE_MATCH, nCurBitsOffset, nCurBitShift);
+ nOutOffset = apultra_write_bits(pOutData, nOutOffset, nMaxOutDataSize, 0 /* length of 2 encoded as gamma 2 */, 2, nCurBitsOffset, nCurBitShift);
+
+ /* The match length isn't encoded in the command, emit elias gamma value */
+ nOutOffset = apultra_write_gamma2_value(pOutData, nOutOffset, nMaxOutDataSize, nMatchLen, nCurBitsOffset, nCurBitShift);
+ if (nOutOffset < 0) return -1;
+
+ *nFollowsLiteral = 0;
+
+ pCompressor->stats.num_rep_matches++;
+ }
+ else {
+ if (nMatchLen <= 3 && nMatchOffset < 128) {
+ /* 7 bits offset + 1 bit length */
+ nOutOffset = apultra_write_bits(pOutData, nOutOffset, nMaxOutDataSize, TOKEN_CODE_7BIT_MATCH, TOKEN_SIZE_7BIT_MATCH, nCurBitsOffset, nCurBitShift);
+
+ if (nOutOffset < 0 || nOutOffset >= nMaxOutDataSize)
+ return -1;
+ pOutData[nOutOffset++] = ((nMatchOffset) & 0x7f) << 1 | (nMatchLen - 2);
+
+ *nFollowsLiteral = 0;
+ nRepMatchOffset = nMatchOffset;
+
+ pCompressor->stats.num_7bit_matches++;
+ }
+ else {
+ /* 8+n bits offset */
+ nOutOffset = apultra_write_bits(pOutData, nOutOffset, nMaxOutDataSize, TOKEN_CODE_LARGE_MATCH, TOKEN_SIZE_LARGE_MATCH, nCurBitsOffset, nCurBitShift);
+
+ if (nOutOffset < 0 || nOutOffset >= nMaxOutDataSize)
+ return -1;
+ if (*nFollowsLiteral)
+ nOutOffset = apultra_write_gamma2_value(pOutData, nOutOffset, nMaxOutDataSize, (nMatchOffset >> 8) + 3, nCurBitsOffset, nCurBitShift);
+ else
+ nOutOffset = apultra_write_gamma2_value(pOutData, nOutOffset, nMaxOutDataSize, (nMatchOffset >> 8) + 2, nCurBitsOffset, nCurBitShift);
+ pOutData[nOutOffset++] = nMatchOffset & 0xff;
+
+ /* The match length isn't encoded in the command, emit elias gamma value */
+
+ if (nMatchOffset < 128 || nMatchOffset >= MINMATCH4_OFFSET)
+ nOutOffset = apultra_write_gamma2_value(pOutData, nOutOffset, nMaxOutDataSize, nMatchLen - 2, nCurBitsOffset, nCurBitShift);
+ else if (nMatchOffset < MINMATCH3_OFFSET)
+ nOutOffset = apultra_write_gamma2_value(pOutData, nOutOffset, nMaxOutDataSize, nMatchLen, nCurBitsOffset, nCurBitShift);
+ else
+ nOutOffset = apultra_write_gamma2_value(pOutData, nOutOffset, nMaxOutDataSize, nMatchLen - 1, nCurBitsOffset, nCurBitShift);
+ if (nOutOffset < 0) return -1;
+
+ *nFollowsLiteral = 0;
+ nRepMatchOffset = nMatchOffset;
+
+ pCompressor->stats.num_variable_matches++;
+ }
+ }
+
+ if (nMatchOffset < pCompressor->stats.min_offset || pCompressor->stats.min_offset == -1)
+ pCompressor->stats.min_offset = nMatchOffset;
+ if (nMatchOffset > pCompressor->stats.max_offset)
+ pCompressor->stats.max_offset = nMatchOffset;
+ pCompressor->stats.total_offsets += (long long)nMatchOffset;
+
+ if (nMatchLen < pCompressor->stats.min_match_len || pCompressor->stats.min_match_len == -1)
+ pCompressor->stats.min_match_len = nMatchLen;
+ if (nMatchLen > pCompressor->stats.max_match_len)
+ pCompressor->stats.max_match_len = nMatchLen;
+ pCompressor->stats.total_match_lens += nMatchLen;
+ pCompressor->stats.match_divisor++;
+
+ if (nMatchOffset == 1) {
+ if (nMatchLen < pCompressor->stats.min_rle1_len || pCompressor->stats.min_rle1_len == -1)
+ pCompressor->stats.min_rle1_len = nMatchLen;
+ if (nMatchLen > pCompressor->stats.max_rle1_len)
+ pCompressor->stats.max_rle1_len = nMatchLen;
+ pCompressor->stats.total_rle1_lens += nMatchLen;
+ pCompressor->stats.rle1_divisor++;
+ }
+ else if (nMatchOffset == 2) {
+ if (nMatchLen < pCompressor->stats.min_rle2_len || pCompressor->stats.min_rle2_len == -1)
+ pCompressor->stats.min_rle2_len = nMatchLen;
+ if (nMatchLen > pCompressor->stats.max_rle2_len)
+ pCompressor->stats.max_rle2_len = nMatchLen;
+ pCompressor->stats.total_rle2_lens += nMatchLen;
+ pCompressor->stats.rle2_divisor++;
+ }
+
+ i += nMatchLen;
+
+ pCompressor->stats.commands_divisor++;
+ }
+ else if (pMatch->length == 1) {
+ int nMatchOffset = pMatch->offset;
+
+ /* 4 bits offset */
+
+ if (nMatchOffset < 0 || nMatchOffset > 15)
+ return -1;
+
+ nOutOffset = apultra_write_bits(pOutData, nOutOffset, nMaxOutDataSize, TOKEN_CODE_4BIT_MATCH, TOKEN_SIZE_4BIT_MATCH, nCurBitsOffset, nCurBitShift);
+ nOutOffset = apultra_write_bits(pOutData, nOutOffset, nMaxOutDataSize, nMatchOffset, 4, nCurBitsOffset, nCurBitShift);
+ if (nOutOffset < 0) return -1;
+
+ pCompressor->stats.num_4bit_matches++;
+ pCompressor->stats.commands_divisor++;
+
+ i++;
+ *nFollowsLiteral = 1;
+ }
+ else {
+ /* Literal */
+
+ nOutOffset = apultra_write_bits(pOutData, nOutOffset, nMaxOutDataSize, 0 /* literal */, 1, nCurBitsOffset, nCurBitShift);
+
+ if (nOutOffset < 0 || nOutOffset >= nMaxOutDataSize)
+ return -1;
+ pOutData[nOutOffset++] = pInWindow[i];
+
+ pCompressor->stats.num_literals++;
+ pCompressor->stats.commands_divisor++;
+ i++;
+ *nFollowsLiteral = 1;
+ }
+
+ int nCurSafeDist = (i - nStartOffset) - nOutOffset;
+ if (nCurSafeDist >= 0 && pCompressor->stats.safe_dist < nCurSafeDist)
+ pCompressor->stats.safe_dist = nCurSafeDist;
+ }
+
+ if (nBlockFlags & 2) {
+ /* 8 bits offset */
+
+ nOutOffset = apultra_write_bits(pOutData, nOutOffset, nMaxOutDataSize, TOKEN_CODE_7BIT_MATCH, TOKEN_SIZE_7BIT_MATCH, nCurBitsOffset, nCurBitShift);
+
+ if (nOutOffset < 0 || nOutOffset >= nMaxOutDataSize)
+ return -1;
+ pOutData[nOutOffset++] = 0x00; /* Offset: EOD */
+ pCompressor->stats.num_eod++;
+ pCompressor->stats.commands_divisor++;
+
+ int nCurSafeDist = (i - nStartOffset) - nOutOffset;
+ if (nCurSafeDist >= 0 && pCompressor->stats.safe_dist < nCurSafeDist)
+ pCompressor->stats.safe_dist = nCurSafeDist;
+ }
+
+ *nCurRepMatchOffset = nRepMatchOffset;
+ return nOutOffset;
+}
+
+/**
+ * Select the most optimal matches, reduce the token count if possible, and then emit a block of compressed data
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param nPreviousBlockSize number of previously compressed bytes (or 0 for none)
+ * @param nInDataSize number of input bytes to compress
+ * @param pOutData pointer to output buffer
+ * @param nMaxOutDataSize maximum size of output buffer, in bytes
+ * @param nCurBitsOffset write index into output buffer, of current byte being filled with bits
+ * @param nCurBitShift bit shift count
+ * @param nCurFollowsLiteral non-zero if the next command to be issued follows a literal, 0 if not
+ * @param nCurRepMatchOffset starting rep offset for this block, updated after the block is compressed successfully
+ * @param nBlockFlags bit 0: 1 for first block, 0 otherwise; bit 1: 1 for last block, 0 otherwise
+ *
+ * @return size of compressed data in output buffer, or -1 if the data is uncompressible
+ */
+static int apultra_optimize_and_write_block(apultra_compressor *pCompressor, const unsigned char *pInWindow, const int nPreviousBlockSize, const int nInDataSize, unsigned char *pOutData, const int nMaxOutDataSize, int *nCurBitsOffset, int *nCurBitShift, int *nCurFollowsLiteral, int *nCurRepMatchOffset, const int nBlockFlags) {
+ int nOutOffset = 0;
+ const int nArrivalsPerPosition = pCompressor->max_arrivals;
+ int *rle_end = (int*)pCompressor->intervals /* reuse */;
+ int i, nPosition;
+
+ memset(pCompressor->best_match, 0, pCompressor->block_size * sizeof(apultra_final_match));
+
+ if ((nBlockFlags & 3) == 3) {
+ int *first_offset_for_byte = pCompressor->first_offset_for_byte;
+ int *next_offset_for_pos = pCompressor->next_offset_for_pos;
+
+ /* Supplement 2 and 3-byte matches */
+
+ memset(first_offset_for_byte, 0xff, sizeof(int) * 65536);
+ memset(next_offset_for_pos, 0xff, sizeof(int) * nInDataSize);
+
+ for (nPosition = nPreviousBlockSize; nPosition < nPreviousBlockSize + nInDataSize - 1; nPosition++) {
+ next_offset_for_pos[nPosition - nPreviousBlockSize] = first_offset_for_byte[((unsigned int)pInWindow[nPosition]) | (((unsigned int)pInWindow[nPosition + 1]) << 8)];
+ first_offset_for_byte[((unsigned int)pInWindow[nPosition]) | (((unsigned int)pInWindow[nPosition + 1]) << 8)] = nPosition;
+ }
+
+ for (nPosition = nPreviousBlockSize + 1; nPosition < (nPreviousBlockSize + nInDataSize - 1); nPosition++) {
+ apultra_match *match = pCompressor->match + ((nPosition - nPreviousBlockSize) << MATCHES_PER_INDEX_SHIFT);
+ unsigned short *match_depth = pCompressor->match_depth + ((nPosition - nPreviousBlockSize) << MATCHES_PER_INDEX_SHIFT);
+ int m = 0, nInserted = 0;
+ int nMatchPos;
+
+ while (m < 15 && match[m].length)
+ m++;
+
+ for (nMatchPos = next_offset_for_pos[nPosition - nPreviousBlockSize]; m < 15 && nMatchPos >= 0; nMatchPos = next_offset_for_pos[nMatchPos - nPreviousBlockSize]) {
+ int nMatchOffset = nPosition - nMatchPos;
+
+ if (nMatchOffset <= pCompressor->max_offset) {
+ int nExistingMatchIdx;
+ int nAlreadyExists = 0;
+
+ for (nExistingMatchIdx = 0; nExistingMatchIdx < m; nExistingMatchIdx++) {
+ if (match[nExistingMatchIdx].offset == nMatchOffset ||
+ (match[nExistingMatchIdx].offset - (match_depth[nExistingMatchIdx] & 0x7fff)) == nMatchOffset) {
+ nAlreadyExists = 1;
+ break;
+ }
+ }
+
+ if (!nAlreadyExists) {
+ match[m].length = (nPosition < (nPreviousBlockSize + nInDataSize - 2) && pInWindow[nMatchPos + 2] == pInWindow[nPosition + 2]) ? 3 : 2;
+ match[m].offset = nMatchOffset;
+ match_depth[m] = 0;
+ m++;
+ nInserted++;
+ if (nInserted >= 6)
+ break;
+ }
+ }
+ else {
+ break;
+ }
+ }
+ }
+ }
+
+ i = 0;
+ while (i < (nPreviousBlockSize + nInDataSize)) {
+ int nRangeStartIdx = i;
+ unsigned char c = pInWindow[nRangeStartIdx];
+ do {
+ i++;
+ }
+ while (i < (nPreviousBlockSize + nInDataSize) && pInWindow[i] == c);
+ while (nRangeStartIdx < i) {
+ rle_end[nRangeStartIdx++] = i;
+ }
+ }
+
+ apultra_optimize_forward(pCompressor, pInWindow, nPreviousBlockSize, nPreviousBlockSize + nInDataSize, 1 /* nInsertForwardReps */, nCurRepMatchOffset, nBlockFlags, nArrivalsPerPosition);
+
+ /* Pick optimal matches */
+ apultra_optimize_forward(pCompressor, pInWindow, nPreviousBlockSize, nPreviousBlockSize + nInDataSize, 0 /* nInsertForwardReps */, nCurRepMatchOffset, nBlockFlags, nArrivalsPerPosition);
+
+ /* Apply reduction and merge pass */
+ int nDidReduce;
+ int nPasses = 0;
+ do {
+ nDidReduce = apultra_reduce_commands(pCompressor, pInWindow, pCompressor->best_match - nPreviousBlockSize, nPreviousBlockSize, nPreviousBlockSize + nInDataSize, nCurRepMatchOffset, nBlockFlags);
+ nPasses++;
+ } while (nDidReduce && nPasses < 20);
+
+ /* Write compressed block */
+
+ return apultra_write_block(pCompressor, pCompressor->best_match - nPreviousBlockSize, pInWindow, nPreviousBlockSize, nPreviousBlockSize + nInDataSize, pOutData, nOutOffset, nMaxOutDataSize, nCurBitsOffset, nCurBitShift, nCurFollowsLiteral, nCurRepMatchOffset, nBlockFlags);
+}
+
+/* Forward declaration */
+static void apultra_compressor_destroy(apultra_compressor *pCompressor);
+
+/**
+ * Initialize compression context
+ *
+ * @param pCompressor compression context to initialize
+ * @param nBlockSize maximum size of input data (bytes to compress only)
+ * @param nMaxWindowSize maximum size of input data window (previously compressed bytes + bytes to compress)
+ * @param nMaxArrivals maximum number of arrivals per position
+ * @param nFlags compression flags
+ *
+ * @return 0 for success, non-zero for failure
+ */
+static int apultra_compressor_init(apultra_compressor *pCompressor, const int nBlockSize, const int nMaxWindowSize, const int nMaxArrivals, const int nFlags) {
+ int nResult;
+
+ nResult = divsufsort_init(&pCompressor->divsufsort_context);
+ pCompressor->intervals = NULL;
+ pCompressor->pos_data = NULL;
+ pCompressor->open_intervals = NULL;
+ pCompressor->match = NULL;
+ pCompressor->match_depth = NULL;
+ pCompressor->match1 = NULL;
+ pCompressor->best_match = NULL;
+ pCompressor->arrival = NULL;
+ pCompressor->first_offset_for_byte = NULL;
+ pCompressor->next_offset_for_pos = NULL;
+ pCompressor->flags = nFlags;
+ pCompressor->block_size = nBlockSize;
+ pCompressor->max_arrivals = nMaxArrivals;
+
+ memset(&pCompressor->stats, 0, sizeof(pCompressor->stats));
+ pCompressor->stats.min_match_len = -1;
+ pCompressor->stats.min_offset = -1;
+ pCompressor->stats.min_rle1_len = -1;
+ pCompressor->stats.min_rle2_len = -1;
+
+ if (!nResult) {
+ pCompressor->intervals = (unsigned long long *)malloc(nMaxWindowSize * sizeof(unsigned long long));
+
+ if (pCompressor->intervals) {
+ pCompressor->pos_data = (unsigned long long *)malloc(nMaxWindowSize * sizeof(unsigned long long));
+
+ if (pCompressor->pos_data) {
+ pCompressor->open_intervals = (unsigned long long *)malloc((LCP_AND_TAG_MAX + 1) * sizeof(unsigned long long));
+
+ if (pCompressor->open_intervals) {
+ pCompressor->arrival = (apultra_arrival *)malloc((nBlockSize + 1) * nMaxArrivals * sizeof(apultra_arrival));
+
+ if (pCompressor->arrival) {
+ pCompressor->best_match = (apultra_final_match *)malloc(nBlockSize * sizeof(apultra_final_match));
+
+ if (pCompressor->best_match) {
+ pCompressor->match = (apultra_match *)malloc(nBlockSize * NMATCHES_PER_INDEX * sizeof(apultra_match));
+ if (pCompressor->match) {
+ pCompressor->match_depth = (unsigned short *)malloc(nBlockSize * NMATCHES_PER_INDEX * sizeof(unsigned short));
+ if (pCompressor->match_depth) {
+ pCompressor->match1 = (unsigned char *)malloc(nBlockSize * sizeof(unsigned char));
+ if (pCompressor->match1) {
+ pCompressor->first_offset_for_byte = (int*)malloc(65536 * sizeof(int));
+ if (pCompressor->first_offset_for_byte) {
+ pCompressor->next_offset_for_pos = (int*)malloc(nBlockSize * sizeof(int));
+ if (pCompressor->next_offset_for_pos) {
+ return 0;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ apultra_compressor_destroy(pCompressor);
+ return 100;
+}
+
+/**
+ * Clean up compression context and free up any associated resources
+ *
+ * @param pCompressor compression context to clean up
+ */
+static void apultra_compressor_destroy(apultra_compressor *pCompressor) {
+ divsufsort_destroy(&pCompressor->divsufsort_context);
+
+ if (pCompressor->next_offset_for_pos) {
+ free(pCompressor->next_offset_for_pos);
+ pCompressor->next_offset_for_pos = NULL;
+ }
+
+ if (pCompressor->first_offset_for_byte) {
+ free(pCompressor->first_offset_for_byte);
+ pCompressor->first_offset_for_byte = NULL;
+ }
+
+ if (pCompressor->match1) {
+ free(pCompressor->match1);
+ pCompressor->match1 = NULL;
+ }
+
+ if (pCompressor->match_depth) {
+ free(pCompressor->match_depth);
+ pCompressor->match_depth = NULL;
+ }
+
+ if (pCompressor->match) {
+ free(pCompressor->match);
+ pCompressor->match = NULL;
+ }
+
+ if (pCompressor->arrival) {
+ free(pCompressor->arrival);
+ pCompressor->arrival = NULL;
+ }
+
+ if (pCompressor->best_match) {
+ free(pCompressor->best_match);
+ pCompressor->best_match = NULL;
+ }
+
+ if (pCompressor->open_intervals) {
+ free(pCompressor->open_intervals);
+ pCompressor->open_intervals = NULL;
+ }
+
+ if (pCompressor->pos_data) {
+ free(pCompressor->pos_data);
+ pCompressor->pos_data = NULL;
+ }
+
+ if (pCompressor->intervals) {
+ free(pCompressor->intervals);
+ pCompressor->intervals = NULL;
+ }
+}
+
+/**
+ * Compress one block of data
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param nPreviousBlockSize number of previously compressed bytes (or 0 for none)
+ * @param nInDataSize number of input bytes to compress
+ * @param pOutData pointer to output buffer
+ * @param nMaxOutDataSize maximum size of output buffer, in bytes
+ * @param nCurBitsOffset write index into output buffer, of current byte being filled with bits
+ * @param nCurBitShift bit shift count
+ * @param nCurFollowsLiteral non-zero if the next command to be issued follows a literal, 0 if not
+ * @param nCurRepMatchOffset starting rep offset for this block, updated after the block is compressed successfully
+ * @param nBlockFlags bit 0: 1 for first block, 0 otherwise; bit 1: 1 for last block, 0 otherwise
+ *
+ * @return size of compressed data in output buffer, or -1 if the data is uncompressible
+ */
+static int apultra_compressor_shrink_block(apultra_compressor *pCompressor, const unsigned char *pInWindow, const int nPreviousBlockSize, const int nInDataSize, unsigned char *pOutData, const int nMaxOutDataSize, int *nCurBitsOffset, int *nCurBitShift, int *nCurFollowsLiteral, int *nCurRepMatchOffset, const int nBlockFlags) {
+ int nCompressedSize;
+
+ if (apultra_build_suffix_array(pCompressor, pInWindow, nPreviousBlockSize + nInDataSize))
+ nCompressedSize = -1;
+ else {
+ if (nPreviousBlockSize) {
+ apultra_skip_matches(pCompressor, 0, nPreviousBlockSize);
+ }
+ apultra_find_all_matches(pCompressor, NMATCHES_PER_INDEX, nPreviousBlockSize, nPreviousBlockSize + nInDataSize, nBlockFlags);
+
+ nCompressedSize = apultra_optimize_and_write_block(pCompressor, pInWindow, nPreviousBlockSize, nInDataSize, pOutData, nMaxOutDataSize, nCurBitsOffset, nCurBitShift, nCurFollowsLiteral, nCurRepMatchOffset, nBlockFlags);
+ }
+
+ return nCompressedSize;
+}
+
+/**
+ * Get maximum compressed size of input(source) data
+ *
+ * @param nInputSize input(source) size in bytes
+ *
+ * @return maximum compressed size
+ */
+size_t apultra_get_max_compressed_size(size_t nInputSize) {
+ return ((nInputSize * 9 /* literals + literal bits */ + 1 /* match bit */ + 2 /* 7+1 command bits */ + 8 /* EOD offset bits */) + 7) >> 3;
+}
+
+/**
+ * Compress memory
+ *
+ * @param pInputData pointer to input(source) data to compress
+ * @param pOutBuffer buffer for compressed data
+ * @param nInputSize input(source) size in bytes
+ * @param nMaxOutBufferSize maximum capacity of compression buffer
+ * @param nFlags compression flags (set to 0)
+ * @param nMaxWindowSize maximum window size to use (0 for default)
+ * @param nDictionarySize size of dictionary in front of input data (0 for none)
+ * @param progress progress function, called after compressing each block, or NULL for none
+ * @param pStats pointer to compression stats that are filled if this function is successful, or NULL
+ *
+ * @return actual compressed size, or -1 for error
+ */
+size_t apultra_compress(const unsigned char *pInputData, unsigned char *pOutBuffer, size_t nInputSize, size_t nMaxOutBufferSize,
+ const unsigned int nFlags, size_t nMaxWindowSize, size_t nDictionarySize, void(*progress)(long long nOriginalSize, long long nCompressedSize), apultra_stats *pStats) {
+ apultra_compressor compressor;
+ size_t nOriginalSize = 0;
+ size_t nCompressedSize = 0L;
+ int nResult;
+ int nMaxArrivals = NARRIVALS_PER_POSITION_SMALL;
+ int nError = 0;
+ const int nBlockSize = (nInputSize < BLOCK_SIZE) ? ((nInputSize < 1024) ? 1024 : (int)nInputSize) : BLOCK_SIZE;
+ const int nMaxOutBlockSize = (int)apultra_get_max_compressed_size(nBlockSize);
+
+ if (nDictionarySize < nInputSize) {
+ int nInDataSize = (int)(nInputSize - nDictionarySize);
+ if (nInDataSize > nBlockSize)
+ nInDataSize = nBlockSize;
+
+ if (nInDataSize > 0 && (nDictionarySize + nInDataSize) >= nInputSize)
+ nMaxArrivals = NARRIVALS_PER_POSITION;
+ }
+
+ nResult = apultra_compressor_init(&compressor, nBlockSize, nBlockSize * 2, nMaxArrivals, nFlags);
+ if (nResult != 0) {
+ return -1;
+ }
+
+ compressor.max_offset = nMaxWindowSize ? (int)nMaxWindowSize : MAX_OFFSET;
+
+ int nPreviousBlockSize = 0;
+ int nNumBlocks = 0;
+ int nCurBitsOffset = INT_MIN, nCurBitShift = 0, nCurFollowsLiteral = 0;
+ int nBlockFlags = 1;
+ int nCurRepMatchOffset = 0;
+
+ if (nDictionarySize) {
+ nOriginalSize = (int)nDictionarySize;
+ nPreviousBlockSize = (int)nDictionarySize;
+ }
+
+ while (nOriginalSize < nInputSize && !nError) {
+ int nInDataSize;
+
+ nInDataSize = (int)(nInputSize - nOriginalSize);
+ if (nInDataSize > nBlockSize)
+ nInDataSize = nBlockSize;
+
+ if (nInDataSize > 0) {
+ int nOutDataSize;
+ int nOutDataEnd = (int)(nMaxOutBufferSize - nCompressedSize);
+
+ if (nOutDataEnd > nMaxOutBlockSize)
+ nOutDataEnd = nMaxOutBlockSize;
+
+ if ((nOriginalSize + nInDataSize) >= nInputSize)
+ nBlockFlags |= 2;
+ nOutDataSize = apultra_compressor_shrink_block(&compressor, pInputData + nOriginalSize - nPreviousBlockSize, nPreviousBlockSize, nInDataSize, pOutBuffer + nCompressedSize, nOutDataEnd,
+ &nCurBitsOffset, &nCurBitShift, &nCurFollowsLiteral, &nCurRepMatchOffset, nBlockFlags);
+ nBlockFlags &= (~1);
+
+ if (nOutDataSize >= 0) {
+ /* Write compressed block */
+
+ if (!nError) {
+ nOriginalSize += nInDataSize;
+ nCompressedSize += nOutDataSize;
+ if (nCurBitsOffset != INT_MIN)
+ nCurBitsOffset -= nOutDataSize;
+ }
+ }
+ else {
+ nError = -1;
+ }
+
+ nPreviousBlockSize = nInDataSize;
+ nNumBlocks++;
+ }
+
+ if (!nError && nOriginalSize < nInputSize) {
+ if (progress)
+ progress(nOriginalSize, nCompressedSize);
+ }
+ }
+
+ if (progress)
+ progress(nOriginalSize, nCompressedSize);
+ if (pStats)
+ *pStats = compressor.stats;
+
+ apultra_compressor_destroy(&compressor);
+
+ if (nError) {
+ return -1;
+ }
+ else {
+ return nCompressedSize;
+ }
+}
diff --git a/tools/rasm/apultra-master/src/shrink.h b/tools/rasm/apultra-master/src/shrink.h
new file mode 100644
index 0000000..b721ba9
--- /dev/null
+++ b/tools/rasm/apultra-master/src/shrink.h
@@ -0,0 +1,172 @@
+/*
+ * shrink.h - compressor definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by cap by Sven-Åke Dahl. https://github.com/svendahl/cap
+ * Also inspired by Charles Bloom's compression blog. http://cbloomrants.blogspot.com/
+ * With ideas from LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help and support from spke <zxintrospec@gmail.com>
+ *
+ */
+
+#ifndef _SHRINK_H
+#define _SHRINK_H
+
+#include "divsufsort.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LCP_BITS 15
+#define TAG_BITS 4
+#define LCP_MAX ((1U<<(LCP_BITS - TAG_BITS)) - 1)
+#define LCP_AND_TAG_MAX ((1U<<LCP_BITS) - 1)
+#define LCP_SHIFT (63-LCP_BITS)
+#define LCP_MASK (((1ULL<<LCP_BITS) - 1) << LCP_SHIFT)
+#define POS_MASK ((1ULL<<LCP_SHIFT) - 1)
+#define VISITED_FLAG 0x8000000000000000ULL
+#define EXCL_VISITED_MASK 0x7fffffffffffffffULL
+
+#define NARRIVALS_PER_POSITION 46
+#define NARRIVALS_PER_POSITION_SMALL 9
+
+#define NMATCHES_PER_INDEX 64
+#define MATCHES_PER_INDEX_SHIFT 6
+
+#define LEAVE_ALONE_MATCH_SIZE 120
+
+/** One match option */
+typedef struct _apultra_match {
+ unsigned int length:11;
+ unsigned int offset:21;
+} apultra_match;
+
+/** One finalized match */
+typedef struct _apultra_final_match {
+ int length;
+ int offset;
+} apultra_final_match;
+
+/** Forward arrival slot */
+typedef struct {
+ int cost;
+
+ unsigned int from_pos:21;
+ int from_slot:7;
+ unsigned int follows_literal:1;
+
+ unsigned int rep_offset:21;
+ unsigned int short_offset:4;
+ unsigned int rep_pos:21;
+ unsigned int match_len:11;
+
+ int score;
+} apultra_arrival;
+
+/** Compression statistics */
+typedef struct _apultra_stats {
+ int num_literals;
+ int num_4bit_matches;
+ int num_7bit_matches;
+ int num_variable_matches;
+ int num_rep_matches;
+ int num_eod;
+
+ int safe_dist;
+
+ int min_offset;
+ int max_offset;
+ long long total_offsets;
+
+ int min_match_len;
+ int max_match_len;
+ int total_match_lens;
+
+ int min_rle1_len;
+ int max_rle1_len;
+ int total_rle1_lens;
+
+ int min_rle2_len;
+ int max_rle2_len;
+ int total_rle2_lens;
+
+ int commands_divisor;
+ int match_divisor;
+ int rle1_divisor;
+ int rle2_divisor;
+} apultra_stats;
+
+/** Compression context */
+typedef struct _apultra_compressor {
+ divsufsort_ctx_t divsufsort_context;
+ unsigned long long *intervals;
+ unsigned long long *pos_data;
+ unsigned long long *open_intervals;
+ apultra_match *match;
+ unsigned short *match_depth;
+ unsigned char *match1;
+ apultra_final_match *best_match;
+ apultra_arrival *arrival;
+ int *first_offset_for_byte;
+ int *next_offset_for_pos;
+ int flags;
+ int block_size;
+ int max_offset;
+ int max_arrivals;
+ apultra_stats stats;
+} apultra_compressor;
+
+/**
+ * Get maximum compressed size of input(source) data
+ *
+ * @param nInputSize input(source) size in bytes
+ *
+ * @return maximum compressed size
+ */
+size_t apultra_get_max_compressed_size(size_t nInputSize);
+
+/**
+ * Compress memory
+ *
+ * @param pInputData pointer to input(source) data to compress
+ * @param pOutBuffer buffer for compressed data
+ * @param nInputSize input(source) size in bytes
+ * @param nMaxOutBufferSize maximum capacity of compression buffer
+ * @param nFlags compression flags (set to 0)
+ * @param nMaxWindowSize maximum window size to use (0 for default)
+ * @param nDictionarySize size of dictionary in front of input data (0 for none)
+ * @param progress progress function, called after compressing each block, or NULL for none
+ * @param pStats pointer to compression stats that are filled if this function is successful, or NULL
+ *
+ * @return actual compressed size, or -1 for error
+ */
+size_t apultra_compress(const unsigned char *pInputData, unsigned char *pOutBuffer, size_t nInputSize, size_t nMaxOutBufferSize,
+ const unsigned int nFlags, size_t nMaxWindowSize, size_t nDictionarySize, void(*progress)(long long nOriginalSize, long long nCompressedSize), apultra_stats *pStats);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SHRINK_H */
diff --git a/tools/rasm/compil.bat b/tools/rasm/compil.bat
new file mode 100644
index 0000000..722a468
--- /dev/null
+++ b/tools/rasm/compil.bat
@@ -0,0 +1,28 @@
+cl ZX0-main\src\compress.c /O2 /Qpar /Ob3 /c -I ZX0-main\src
+cl ZX0-main\src\optimize.c /O2 /Qpar /Ob3 /c -I ZX0-main\src
+cl ZX0-main\src\memory.c /O2 /Qpar /Ob3 /c -I ZX0-main\src
+
+cl apultra-master\src\expand.c /O2 /Qpar /Ob3 /c -I lzsa-master\src\libdivsufsort\include -I apultra-master\src
+cl apultra-master\src\matchfinder.c /O2 /Qpar /Ob3 /c -I lzsa-master\src\libdivsufsort\include -I apultra-master\src
+cl apultra-master\src\shrink.c /O2 /Qpar /Ob3 /c -I lzsa-master\src\libdivsufsort\include -I apultra-master\src
+
+cl lzsa-master\src\dictionary.c /O2 /Qpar /Ob3 /c -I lzsa-master\src\libdivsufsort\include -I lzsa-master\src
+cl lzsa-master\src\expand_block_v1.c /O2 /Qpar /Ob3 /c -I lzsa-master\src\libdivsufsort\include -I lzsa-master\src
+cl lzsa-master\src\expand_block_v2.c /O2 /Qpar /Ob3 /c -I lzsa-master\src\libdivsufsort\include -I lzsa-master\src
+cl lzsa-master\src\expand_context.c /O2 /Qpar /Ob3 /c -I lzsa-master\src\libdivsufsort\include -I lzsa-master\src
+cl lzsa-master\src\expand_inmem.c /O2 /Qpar /Ob3 /c -I lzsa-master\src\libdivsufsort\include -I lzsa-master\src
+cl lzsa-master\src\frame.c /O2 /Qpar /Ob3 /c -I lzsa-master\src\libdivsufsort\include -I lzsa-master\src
+cl lzsa-master\src\matchfinder.c /O2 /Qpar /Ob3 /c -I lzsa-master\src\libdivsufsort\include -I lzsa-master\src /Fomatchfinder_lzsa.obj
+cl lzsa-master\src\shrink_block_v1.c /O2 /Qpar /Ob3 /c -I lzsa-master\src\libdivsufsort\include -I lzsa-master\src
+cl lzsa-master\src\shrink_block_v2.c /O2 /Qpar /Ob3 /c -I lzsa-master\src\libdivsufsort\include -I lzsa-master\src
+cl lzsa-master\src\shrink_context.c /O2 /Qpar /Ob3 /c -I lzsa-master\src\libdivsufsort\include -I lzsa-master\src
+cl lzsa-master\src\shrink_inmem.c /O2 /Qpar /Ob3 /c -I lzsa-master\src\libdivsufsort\include -I lzsa-master\src
+
+cl lzsa-master\src\libdivsufsort\lib\divsufsort.c /O2 /Qpar /Ob3 /c -I lzsa-master\src\libdivsufsort\include
+cl lzsa-master\src\libdivsufsort\lib\divsufsort_utils.c /O2 /Qpar /Ob3 /c -I lzsa-master\src\libdivsufsort\include
+cl lzsa-master\src\libdivsufsort\lib\sssort.c /O2 /Qpar /Ob3 /c -I lzsa-master\src\libdivsufsort\include
+cl lzsa-master\src\libdivsufsort\lib\trsort.c /O2 /Qpar /Ob3 /c -I lzsa-master\src\libdivsufsort\include
+
+cl rasm.c /O2 expand.obj matchfinder.obj shrink.obj dictionary.obj expand_block_v1.obj expand_block_v2.obj expand_context.obj expand_inmem.obj frame.obj matchfinder_lzsa.obj shrink_block_v1.obj shrink_block_v2.obj shrink_context.obj shrink_inmem.obj divsufsort.obj divsufsort_utils.obj sssort.obj trsort.obj optimize.obj compress.obj memory.obj
+
+upx.exe --ultra-brute rasm.exe
diff --git a/tools/rasm/decrunch/dzx0_fast.asm b/tools/rasm/decrunch/dzx0_fast.asm
new file mode 100644
index 0000000..55f4388
--- /dev/null
+++ b/tools/rasm/decrunch/dzx0_fast.asm
@@ -0,0 +1,237 @@
+;
+; Speed-optimized ZX0 decompressor by spke (187 bytes)
+;
+; ver.00 by spke (27/01-23/03/2021, 191 bytes)
+; ver.01 by spke (24/03/2021, 193(+2) bytes - fixed a bug in the initialization)
+; ver.01patch2 by uniabis (25/03/2021, 191(-2) bytes - fixed a bug with elias over 8bits)
+; ver.01patch9 by uniabis (10/09/2021, 187(-4) bytes - support for new v2 format)
+;
+; Original ZX0 decompressors were written by Einar Saukas
+;
+; This decompressor was written on the basis of "Standard" decompressor by
+; Einar Saukas and optimized for speed by spke. This decompressor is
+; about 5% faster than the "Turbo" decompressor, which is 128 bytes long.
+; It has about the same speed as the 412 bytes version of the "Mega" decompressor.
+;
+; The decompressor uses AF, BC, DE, HL and IX and relies upon self-modified code.
+;
+; The decompression is done in the standard way:
+;
+; ld hl,FirstByteOfCompressedData
+; ld de,FirstByteOfMemoryForDecompressedData
+; call DecompressZX0
+;
+; Of course, ZX0 compression algorithms are (c) 2021 Einar Saukas,
+; see https://github.com/einar-saukas/ZX0 for more information
+;
+; Drop me an email if you have any comments/ideas/suggestions: zxintrospec@gmail.com
+;
+; This software is provided 'as-is', without any express or implied
+; warranty. In no event will the authors be held liable for any damages
+; arising from the use of this software.
+;
+; Permission is granted to anyone to use this software for any purpose,
+; including commercial applications, and to alter it and redistribute it
+; freely, subject to the following restrictions:
+;
+; 1. The origin of this software must not be misrepresented; you must not
+; claim that you wrote the original software. If you use this software
+; in a product, an acknowledgment in the product documentation would be
+; appreciated but is not required.
+; 2. Altered source versions must be plainly marked as such, and must not be
+; misrepresented as being the original software.
+; 3. This notice may not be removed or altered from any source distribution.
+
+macro DecompressZX0
+
+ ld ix, @CopyMatch1
+ ld bc, $ffff
+ ld (@PrevOffset+1), bc ; default offset is -1
+ inc bc
+ ld a, $80
+ jr @RunOfLiterals ; BC is assumed to contains 0 most of the time
+
+@ShorterOffsets:
+ ld b, $ff ; the top byte of the offset is always $FF
+ ld c, (hl)
+ inc hl
+ rr c
+ ld (@PrevOffset+1), bc
+ jr nc, @LongerMatch
+
+@CopyMatch2: ; the case of matches with len=2
+ ld bc, 2
+
+ ; the faster match copying code
+@CopyMatch1:
+ push hl ; preserve source
+
+@PrevOffset:
+ ld hl, $ffff ; restore offset (default offset is -1)
+ add hl, de ; HL = dest - offset
+ ldir
+ pop hl ; restore source
+
+ ; after a match you can have either
+ ; 0 + <elias length> = run of literals, or
+ ; 1 + <elias offset msb> + [7-bits of offset lsb + 1-bit of length] + <elias length> = another match
+@AfterMatch1:
+ add a, a
+ jr nc, @RunOfLiterals
+
+@UsualMatch: ; this is the case of usual match+offset
+ add a, a
+ jr nc, @LongerOffets
+ jr nz, @ShorterOffsets ; NZ after NC == "confirmed C"
+
+ ld a, (hl) ; reload bits
+ inc hl
+ rla
+
+ jr c, @ShorterOffsets
+
+@LongerOffets:
+ ld c, $fe
+
+ add a, a ; inline read gamma
+ rl c
+ add a, a
+ jr nc, $-4
+
+ call z, @ReloadReadGamma
+
+@ProcessOffset:
+
+ inc c
+ ret z ; end-of-data marker (only checked for longer offsets)
+ rr c
+ ld b, c
+ ld c, (hl)
+ inc hl
+ rr c
+ ld (@PrevOffset+1), bc
+
+ ; lowest bit is the first bit of the gamma code for length
+ jr c, @CopyMatch2
+
+@LongerMatch:
+ ld bc, 1
+
+ add a, a ; inline read gamma
+ rl c
+ add a, a
+ jr nc, $-4
+
+ call z,@ReloadReadGamma
+
+@CopyMatch3:
+ push hl ; preserve source
+ ld hl, (@PrevOffset+1) ; restore offset
+ add hl, de ; HL = dest - offset
+
+ ; because BC>=3-1, we can do 2 x LDI safely
+ ldi
+ ldir
+ inc c
+ ldi
+ pop hl ; restore source
+
+ ; after a match you can have either
+ ; 0 + <elias length> = run of literals, or
+ ; 1 + <elias offset msb> + [7-bits of offset lsb + 1-bit of length] + <elias length> = another match
+@AfterMatch3:
+ add a, a
+ jr c, @UsualMatch
+
+@RunOfLiterals:
+ inc c
+ add a, a
+ jr nc, @LongerRun
+ jr nz, @CopyLiteral ; NZ after NC == "confirmed C"
+
+ ld a, (hl) ; reload bits
+ inc hl
+ rla
+
+ jr c, @CopyLiteral
+
+@LongerRun:
+ add a, a ; inline read gamma
+ rl c
+ add a, a
+ jr nc, $-4
+
+ jr nz, @CopyLiterals
+
+ ld a, (hl) ; reload bits
+ inc hl
+ rla
+
+ call nc, @ReadGammaAligned
+
+@CopyLiterals:
+ ldi
+
+@CopyLiteral:
+ ldir
+
+ ; after a literal run you can have either
+ ; 0 + <elias length> = match using a repeated offset, or
+ ; 1 + <elias offset msb> + [7-bits of offset lsb + 1-bit of length] + <elias length> = another match
+ add a, a
+ jr c, @UsualMatch
+
+@RepMatch:
+ inc c
+ add a, a
+ jr nc, @LongerRepMatch
+ jr nz, @CopyMatch1 ; NZ after NC == "confirmed C"
+
+ ld a, (hl) ; reload bits
+ inc hl
+ rla
+
+ jr c, @CopyMatch1
+
+@LongerRepMatch:
+ add a, a ; inline read gamma
+ rl c
+ add a, a
+ jr nc, $-4
+
+ jp nz, @CopyMatch1
+
+ ; this is a crafty equivalent of CALL ReloadReadGamma : JP CopyMatch1
+ push ix
+
+ ; the subroutine for reading the remainder of the partly read Elias gamma code.
+ ; it has two entry points: ReloadReadGamma first refills the bit reservoir in A,
+ ; while ReadGammaAligned assumes that the bit reservoir has just been refilled.
+@ReloadReadGamma:
+ ld a, (hl) ; reload bits
+ inc hl
+ rla
+
+ ret c
+@ReadGammaAligned:
+ add a, a
+ rl c
+ add a, a
+ ret c
+ add a, a
+ rl c
+ add a, a
+@ReadingLongGamma: ; this loop does not need unrolling, as it does not get much use anyway
+ ret c
+ add a, a
+ rl c
+ rl b
+ add a, a
+ jr nz, @ReadingLongGamma
+
+ ld a, (hl) ; reload bits
+ inc hl
+ rla
+ jr @ReadingLongGamma
+mend
+
diff --git a/tools/rasm/decrunch/dzx0_standard.asm b/tools/rasm/decrunch/dzx0_standard.asm
new file mode 100644
index 0000000..6525c8b
--- /dev/null
+++ b/tools/rasm/decrunch/dzx0_standard.asm
@@ -0,0 +1,64 @@
+; -----------------------------------------------------------------------------
+; ZX0 decoder by Einar Saukas & Urusergi
+; "Standard" version (68 bytes only)
+; -----------------------------------------------------------------------------
+; Parameters:
+; HL: source address (compressed data)
+; DE: destination address (decompressing)
+; -----------------------------------------------------------------------------
+
+macro dzx0_standard
+ ld bc, $ffff ; preserve default offset 1
+ push bc
+ inc bc
+ ld a, $80
+@dzx0s_literals:
+ call @dzx0s_elias ; obtain length
+ ldir ; copy literals
+ add a, a ; copy from last offset or new offset?
+ jr c, @dzx0s_new_offset
+ call @dzx0s_elias ; obtain length
+@dzx0s_copy:
+ ex (sp), hl ; preserve source, restore offset
+ push hl ; preserve offset
+ add hl, de ; calculate destination - offset
+ ldir ; copy from offset
+ pop hl ; restore offset
+ ex (sp), hl ; preserve offset, restore source
+ add a, a ; copy from literals or new offset?
+ jr nc, @dzx0s_literals
+@dzx0s_new_offset:
+ pop bc ; discard last offset
+ ld c, $fe ; prepare negative offset
+ call @dzx0s_elias_loop ; obtain offset MSB
+ inc c
+ ret z ; check end marker
+ ld b, c
+ ld c, (hl) ; obtain offset LSB
+ inc hl
+ rr b ; last offset bit becomes first length bit
+ rr c
+ push bc ; preserve new offset
+ ld bc, 1 ; obtain length
+ call nc, @dzx0s_elias_backtrack
+ inc bc
+ jr @dzx0s_copy
+@dzx0s_elias:
+ inc c ; interlaced Elias gamma coding
+@dzx0s_elias_loop:
+ add a, a
+ jr nz, @dzx0s_elias_skip
+ ld a, (hl) ; load another group of 8 bits
+ inc hl
+ rla
+@dzx0s_elias_skip:
+ ret c
+@dzx0s_elias_backtrack:
+ add a, a
+ rl c
+ rl b
+ jr @dzx0s_elias_loop
+mend
+; -----------------------------------------------------------------------------
+
+
diff --git a/tools/rasm/decrunch/dzx0_standard_back.asm b/tools/rasm/decrunch/dzx0_standard_back.asm
new file mode 100644
index 0000000..3da94bd
--- /dev/null
+++ b/tools/rasm/decrunch/dzx0_standard_back.asm
@@ -0,0 +1,65 @@
+; -----------------------------------------------------------------------------
+; ZX0 decoder by Einar Saukas
+; "Standard" version (69 bytes only) - BACKWARDS VARIANT
+; -----------------------------------------------------------------------------
+; Parameters:
+; HL: last source address (compressed data)
+; DE: last destination address (decompressing)
+; -----------------------------------------------------------------------------
+
+Macro dzx0_standard_back
+ ld bc, 1 ; preserve default offset 1
+ push bc
+ ld a, $80
+@dzx0sb_literals:
+ call @dzx0sb_elias ; obtain length
+ lddr ; copy literals
+ inc c
+ add a, a ; copy from last offset or new offset?
+ jr c, @dzx0sb_new_offset
+ call @dzx0sb_elias ; obtain length
+@dzx0sb_copy:
+ ex (sp), hl ; preserve source, restore offset
+ push hl ; preserve offset
+ add hl, de ; calculate destination - offset
+ lddr ; copy from offset
+ inc c
+ pop hl ; restore offset
+ ex (sp), hl ; preserve offset, restore source
+ add a, a ; copy from literals or new offset?
+ jr nc, @dzx0sb_literals
+@dzx0sb_new_offset:
+ inc sp ; discard last offset
+ inc sp
+ call @dzx0sb_elias ; obtain offset MSB
+ dec b
+ ret z ; check end marker
+ dec c ; adjust for positive offset
+ ld b, c
+ ld c, (hl) ; obtain offset LSB
+ dec hl
+ srl b ; last offset bit becomes first length bit
+ rr c
+ inc bc
+ push bc ; preserve new offset
+ ld bc, 1 ; obtain length
+ call c, @dzx0sb_elias_backtrack
+ inc bc
+ jr @dzx0sb_copy
+@dzx0sb_elias_backtrack:
+ add a, a
+ rl c
+ rl b
+@dzx0sb_elias:
+ add a, a ; inverted interlaced Elias gamma coding
+ jr nz, @dzx0sb_elias_skip
+ ld a, (hl) ; load another group of 8 bits
+ dec hl
+ rla
+@dzx0sb_elias_skip:
+ jr c, @dzx0sb_elias_backtrack
+ ret
+mend
+; -----------------------------------------------------------------------------
+
+
diff --git a/tools/rasm/decrunch/dzx0_turbo_back.asm b/tools/rasm/decrunch/dzx0_turbo_back.asm
new file mode 100644
index 0000000..d009e92
--- /dev/null
+++ b/tools/rasm/decrunch/dzx0_turbo_back.asm
@@ -0,0 +1,101 @@
+; -----------------------------------------------------------------------------
+; ZX0 decoder by Einar Saukas & introspec
+; "Turbo" version (126 bytes, 21% faster) - BACKWARDS VARIANT
+; -----------------------------------------------------------------------------
+; Parameters:
+; HL: last source address (compressed data)
+; DE: last destination address (decompressing)
+; -----------------------------------------------------------------------------
+
+macro dzx0_turbo_back
+ ld bc, 1 ; preserve default offset 1
+ ld (@dzx0tb_last_offset+1), bc
+ ld a, $80
+ jr @dzx0tb_literals
+@dzx0tb_new_offset:
+ add a, a ; obtain offset MSB
+ call c, @dzx0tb_elias
+ dec b
+ ret z ; check end marker
+ dec c ; adjust for positive offset
+ ld b, c
+ ld c, (hl) ; obtain offset LSB
+ dec hl
+ srl b ; last offset bit becomes first length bit
+ rr c
+ inc bc
+ ld (@dzx0tb_last_offset+1), bc ; preserve new offset
+ ld bc, 1 ; obtain length
+ call c, @dzx0tb_elias_loop
+ inc bc
+@dzx0tb_copy:
+ push hl ; preserve source
+@dzx0tb_last_offset:
+ ld hl, 0 ; restore offset
+ add hl, de ; calculate destination - offset
+ lddr ; copy from offset
+ inc c
+ pop hl ; restore source
+ add a, a ; copy from literals or new offset?
+ jr c, @dzx0tb_new_offset
+@dzx0tb_literals:
+ add a, a ; obtain length
+ call c, @dzx0tb_elias
+ lddr ; copy literals
+ inc c
+ add a, a ; copy from last offset or new offset?
+ jr c, @dzx0tb_new_offset
+ add a, a ; obtain length
+ call c, @dzx0tb_elias
+ jp @dzx0tb_copy
+@dzx0tb_elias_loop:
+ add a, a
+ rl c
+ add a, a
+ ret nc
+@dzx0tb_elias:
+ jp nz, @dzx0tb_elias_loop ; inverted interlaced Elias gamma coding
+ ld a, (hl) ; load another group of 8 bits
+ dec hl
+ rla
+ ret nc
+ add a, a
+ rl c
+ add a, a
+ ret nc
+ add a, a
+ rl c
+ add a, a
+ ret nc
+ add a, a
+ rl c
+ add a, a
+ ret nc
+@dzx0tb_elias_reload:
+ add a, a
+ rl c
+ rl b
+ add a, a
+ ld a, (hl) ; load another group of 8 bits
+ dec hl
+ rla
+ ret nc
+ add a, a
+ rl c
+ rl b
+ add a, a
+ ret nc
+ add a, a
+ rl c
+ rl b
+ add a, a
+ ret nc
+ add a, a
+ rl c
+ rl b
+ add a, a
+ jr c, @dzx0tb_elias_reload
+ ret
+; -----------------------------------------------------------------------------
+mend
+
diff --git a/tools/rasm/decrunch/dzx7_turbo.asm b/tools/rasm/decrunch/dzx7_turbo.asm
index 779ced5..cb66be5 100644
--- a/tools/rasm/decrunch/dzx7_turbo.asm
+++ b/tools/rasm/decrunch/dzx7_turbo.asm
@@ -8,7 +8,7 @@
; -----------------------------------------------------------------------------
dzx7_turbo:
- ld a, $80
+ ld a, #80
dzx7t_copy_byte_loop:
ldi ; copy literal byte
dzx7t_main_loop:
@@ -42,7 +42,7 @@ dzx7t_len_value_start:
; determine offset
ld e, (hl) ; load offset flag (1 bit) + offset value (7 bits)
inc hl
- defb $cb, $33 ; opcode for undocumented instruction "SLL E" aka "SLS E"
+ defb #cb, #33 ; opcode for undocumented instruction "SLL E" aka "SLS E"
jr nc, dzx7t_offset_end ; if offset flag is set, load 4 extra bits
add a, a ; check next bit
call z, dzx7t_load_bits ; no more bits left?
diff --git a/tools/rasm/decrunch/exomizer3megachur.asm b/tools/rasm/decrunch/exomizer3megachur.asm
deleted file mode 100644
index ea1973e..0000000
--- a/tools/rasm/decrunch/exomizer3megachur.asm
+++ /dev/null
@@ -1,210 +0,0 @@
-;Exomizer 2 Z80 decoder
-;Copyright (C) 2008-2016 by Jaime Tejedor Gomez (Metalbrain)
-;
-;Optimized by Antonio Villena and Urusergi (169 bytes)
-;
-;Compression algorithm by Magnus Lind
-;
-; This depacker is free software; you can redistribute it and/or
-; modify it under the terms of the GNU Lesser General Public
-; License as published by the Free Software Foundation; either
-; version 2.1 of the License, or (at your option) any later version.
-;
-; This library is distributed in the hope that it will be useful,
-; but WITHOUT ANY WARRANTY; without even the implied warranty of
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-; Lesser General Public License for more details.
-;
-; You should have received a copy of the GNU Lesser General Public
-; License along with this library; if not, write to the Free Software
-; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-;
-;
-;input- hl=compressed data start
-; de=uncompressed destination start
-;
-; you may change exo_mapbasebits to point to any free buffer
-;
-;ATTENTION!
-;A huge speed boost (around 14%) can be gained at the cost of only 5 bytes.
-;If you want this, replace all instances of "call exo_getbit" with "srl a" followed by
-;"call z,exo_getbit", and remove the first two instructions in exo_getbit routine.
-; ---------------------------
-; modified by Megachur in 2018
-; ---------------------------
-; hl -> compressed data start
-; de -> uncompressed destination start
-; ---------------------------
-
-;EXO_BACKWARD equ 1
-ENABLE_MEXO_GETBIT equ 1
-
-list:EXOMIZER_ADDRESS:nolist
-; ---------------------------
-MACRO MEXO_GETBIT
- srl a
- jr nz,@1
- ld a,(hl)
- IFDEF EXO_BACKWARD
- dec hl
- ELSE
- inc hl
- ENDIF
- rra
-@1
-ENDM
-
-deexo:
- ld iy,exo_mapbasebits+11
- ld a,(hl)
-
- IFDEF EXO_BACKWARD
- dec hl
- ELSE
- inc hl
- ENDIF
-
- ld b,52
- push de
- cp a
-
-exo_initbits:
- ld c,16
- jr nz,exo_get4bits
- ld ixl,c
- ld de,1 ;DE=b2
-
-exo_get4bits:
- IFDEF ENABLE_MEXO_GETBIT
- MEXO_GETBIT
- ELSE
- srl a:call z,exo_getbit ;call exo_getbit ;get one bit
- ENDIF
- rl c
- jr nc,exo_get4bits
- inc c
- push hl
- ld hl,1
- ld (iy+41),c ;bits[i]=b1 (and opcode 41 == add hl,hl)
-
-exo_setbit:
- dec c
- jr nz,exo_setbit-1 ;jump to add hl,hl instruction
- ld (iy-11),e
- ld (iy+93),d ;base[i]=b2
- add hl,de
- ex de,hl
- inc iy
- pop hl
- dec ixl
- djnz exo_initbits
- pop de
- jr exo_mainloop
-
-exo_literalrun:
- ld e,c ;DE=1
-
-exo_getbits:
- dec b
- ret z
-
-exo_getbits1:
- IFDEF ENABLE_MEXO_GETBIT
- MEXO_GETBIT
- ELSE
- srl a:call z,exo_getbit ;call exo_getbit
- ENDIF
- rl e
- rl d
- jr nc,exo_getbits
- ld b,d
- ld c,e
- pop de
-
-exo_literalcopy:
- IFDEF EXO_BACKWARD
- lddr
- ELSE
- ldir
- ENDIF
-exo_mainloop:
- inc c
- IFDEF ENABLE_MEXO_GETBIT
- MEXO_GETBIT
- ELSE
- srl a:call z,exo_getbit ;call exo_getbit ;literal?
- ENDIF
- jr c,exo_literalcopy
- ld c,239
-exo_getindex:
- IFDEF ENABLE_MEXO_GETBIT
- MEXO_GETBIT
- ELSE
- srl a:call z,exo_getbit ;call exo_getbit
- ENDIF
- inc c
- jr nc,exo_getindex
- ret z
- push de
- ld d,b
- jp p,exo_literalrun
- ld iy,exo_mapbasebits-229
- call exo_getpair
- push de
- rlc d
- jr nz,exo_dontgo
- dec e
- ld bc,512+32 ;2 bits,48 offset
- jr z,exo_goforit
- dec e ;2?
-exo_dontgo:
- ld bc,1024+16 ;4 bits,32 offset
- jr z,exo_goforit
- ld de,0
- ld c,d ;16 offset
-exo_goforit:
- call exo_getbits1
- ld iy,exo_mapbasebits+27
- add iy,de
- call exo_getpair
- pop bc
- ex (sp),hl
- IFDEF EXO_BACKWARD
- ex de,hl
- add hl,de
- lddr
- ELSE
- push hl
- sbc hl,de
- pop de
- ldir
- ENDIF
- pop hl
- jr exo_mainloop ;Next!
-exo_getpair:
- add iy,bc
- ld e,d
- ld b,(iy+41)
- call exo_getbits
- ex de,hl
- ld c,(iy-11)
- ld b,(iy+93)
- add hl,bc ;Always clear C flag
- ex de,hl
- ret
-
- IFDEF ENABLE_MEXO_GETBIT
- ELSE
-exo_getbit:
-; srl a
-; ret nz
- ld a,(hl)
- inc hl
- rra
- ret
- ENDIF
-
-exo_mapbasebits:
- ds 156,#00 ;tables for bits,baseL,baseH
-; ---------------------------
-list:EXOMIZER_ADDRESS_LENGTH equ $-EXOMIZER_ADDRESS:nolist \ No newline at end of file
diff --git a/tools/rasm/decrunch/lz48decrunch_v006.asm b/tools/rasm/decrunch/lz48decrunch_v006.asm
deleted file mode 100644
index 750b571..0000000
--- a/tools/rasm/decrunch/lz48decrunch_v006.asm
+++ /dev/null
@@ -1,113 +0,0 @@
-;
-; LZ48 decrunch
-;
-; hl compressed data adress
-; de output adress of data
-;
-
-
-org #8000
-
-; CALL #8000,source,destination
-di
-
-; parameters
-ld h,(ix+3)
-ld l,(ix+2)
-ld d,(ix+1)
-ld e,(ix+0)
-
-call LZ48_decrunch
-
-ei
-ret
-
-
-
-
-
-LZ48_decrunch
-ldi
-ld b,0
-
-nextsequence
-ld a,(hl)
-inc hl
-ld lx,a
-and #F0
-jr z,lzunpack ; no litteral bytes
-rrca
-rrca
-rrca
-rrca
-
-ld c,a
-cp 15 ; more bytes for length?
-jr nz,copyliteral
-
-getadditionallength
-ld a,(hl)
-inc hl
-inc a
-jr nz,lengthnext
-inc b
-dec bc
-jr getadditionallength
-lengthnext
-dec a
-add a,c
-ld c,a
-ld a,b
-adc a,0
-ld b,a ; bc=length
-
-copyliteral
-ldir
-
-lzunpack
-ld a,lx
-and #F
-add 3
-ld c,a
-cp 18 ; more bytes for length?
-jr nz,readoffset
-
-getadditionallengthbis
-ld a,(hl)
-inc hl
-inc a
-jr nz,lengthnextbis
-inc b
-dec bc
-jr getadditionallengthbis
-lengthnextbis
-dec a
-add a,c
-ld c,a
-ld a,b
-adc a,0
-ld b,a ; bc=length
-
-readoffset
-; read encoded offset
-ld a,(hl)
-inc a
-ret z ; LZ48 end with zero offset
-inc hl
-push hl
-ld l,a
-ld a,e
-sub l
-ld l,a
-ld a,d
-sbc a,0
-ld h,a
-; source=dest-copyoffset
-
-copykey
-ldir
-
-pop hl
-jr nextsequence
-
-
diff --git a/tools/rasm/decrunch/lz48decrunch_v006b.asm b/tools/rasm/decrunch/lz48decrunch_v006b.asm
new file mode 100644
index 0000000..69162a4
--- /dev/null
+++ b/tools/rasm/decrunch/lz48decrunch_v006b.asm
@@ -0,0 +1,78 @@
+;
+; LZ48 decrunch
+;
+
+; In ; HL=compressed data address
+; ; DE=output data address
+; Out ; HL last address of compressed data read (you must inc once for LZ48 stream)
+; ; DE last address of decrunched data write +1
+; ; BC always 3
+; ; A always zero
+; ; IXL undetermined
+; ; flags (inc a -> 0)
+; Modif ; AF, BC, DE, HL, IXL
+LZ48_decrunch
+ ldi
+ ld b,0
+
+nextsequence
+ ld a,(hl)
+ inc hl
+ cp #10
+ jr c,lzunpack ; no literal bytes
+ ld ixl,a
+ and #f0
+ rrca
+ rrca
+ rrca
+ rrca
+
+ cp 15 ; more bytes for literal length?
+ jr nz,copyliteral
+getadditionallength
+ ld c,(hl) ; get additional literal length byte
+ inc hl
+ add a,c ; compute literal length total
+ jr nc,lengthNC
+ inc b
+lengthNC
+ inc c
+ jr z,getadditionallength ; if last literal length byte was 255, we have more bytes to process
+copyliteral
+ ld c,a
+ ldir
+ ld a,ixl
+ and #F
+lzunpack
+ add 3
+ cp 18 ; more bytes for match length?
+ jr nz,readoffset
+getadditionallengthbis
+ ld c,(hl) ; get additional match length byte
+ inc hl
+ add a,c ; compute match length size total
+ jr nc,lengthNCbis
+ inc b
+lengthNCbis
+ inc c
+ jr z,getadditionallengthbis ; if last match length byte was 255, we have more bytes to process
+
+readoffset
+ ld c,a
+; read encoded offset
+ ld a,(hl)
+ inc a
+ ret z ; LZ48 end with zero offset
+ inc hl
+ push hl
+; source=dest-copyoffset
+ ; A != 0 here
+ neg
+ ld l,a
+ ld h,#ff
+ add hl,de
+copykey
+ ldir
+
+ pop hl
+ jr nextsequence
diff --git a/tools/rasm/decrunch/aplib_z80_todo.asm b/tools/rasm/decrunch/unaplib.asm
index 6843a14..13c8678 100644
--- a/tools/rasm/decrunch/aplib_z80_todo.asm
+++ b/tools/rasm/decrunch/unaplib.asm
@@ -3,10 +3,10 @@
;hl = source
;de = dest
-ap_bits: .db 0
-ap_byte: .db 0
-lwm: .db 0
-r0: .dw 0
+ap_bits: db 0
+ap_byte: db 0
+lwm: db 0
+r0: dw 0
ap_getbit:
push bc
diff --git a/tools/rasm/decrunch/unaplib_fast.asm b/tools/rasm/decrunch/unaplib_fast.asm
new file mode 100644
index 0000000..47ad16b
--- /dev/null
+++ b/tools/rasm/decrunch/unaplib_fast.asm
@@ -0,0 +1,266 @@
+;
+; Speed-optimized ApLib decompressor by spke (ver.04 spring 2020, 236 bytes)
+;
+; The original Z80 decompressors for ApLib were written by Dan Weiss (Dwedit),
+; then tweaked by Francisco Javier Pena Pareja (utopian),
+; and optimized by Jaime Tejedor Gomez (Metalbrain) and Antonio Villena.
+;
+; This is a new "implicit state" decompressor heavily optimized for speed by spke.
+; (It is 11 bytes shorter and 14% faster than the previously fastest
+; 247b decompressor by Metalbrain and Antonio Villena.)
+;
+; ver.00 by spke (21/08/2018-01/09/2018, 244 bytes, an edit of the existing 247b decompressor);
+; ver.01 by spke (12-13/11/2018, 234(-10) bytes, +3% speed using the state machine for LWM);
+; ver.02 by spke (06/08/2019, +1% speed);
+; ver.03 by spke (27/08/2019, 236(+2) bytes, +1% speed using partly expanded LDIR);
+; ver.04 by spke (spring 2020, added full revision history and support for long offsets)
+;
+; The data must be compressed using any compressor for ApLib capable of generating raw data.
+; At present, two best available compressors are:
+;
+; "APC" by Sven-Ake Dahl: https://github.com/svendahl/cap or
+; "apultra" by Emmanuel Marty: https://github.com/emmanuel-marty/apultra
+;
+; The compression can done as follows:
+;
+; apc.exe e <sourcefile> <outfile>
+; or
+; apultra.exe <sourcefile> <outfile>
+;
+; A decent compressor was written by r57shell (although it is worse than compressors above):
+; http://gendev.spritesmind.net/forum/viewtopic.php?p=32548#p32548
+; The use of the official ApLib compressor by Joergen Ibsen is not recommended.
+;
+; The decompression is done in the standard way:
+;
+; ld hl,FirstByteOfCompressedData
+; ld de,FirstByteOfMemoryForDecompressedData
+; call DecompressApLib
+;
+; The decompressor modifies AF, AF', BC, DE, HL, IXH, IY.
+; (However, note that the option "AllowSelfmodifyingCode" removes the dependency on IY.)
+;
+; Of course, ApLib compression algorithms are (c) 1998-2014 Joergen Ibsen,
+; see http://www.ibsensoftware.com/ for more information
+;
+; Drop me an email if you have any comments/ideas/suggestions: zxintrospec@gmail.com
+;
+; This software is provided 'as-is', without any express or implied
+; warranty. In no event will the authors be held liable for any damages
+; arising from the use of this software.
+;
+; Permission is granted to anyone to use this software for any purpose,
+; including commercial applications, and to alter it and redistribute it
+; freely, subject to the following restrictions:
+;
+; 1. The origin of this software must not be misrepresented; you must not
+; claim that you wrote the original software. If you use this software
+; in a product, an acknowledgment in the product documentation would be
+; appreciated but is not required.
+; 2. Altered source versions must be plainly marked as such, and must not be
+; misrepresented as being the original software.
+; 3. This notice may not be removed or altered from any source distribution.
+
+; DEFINE SupportLongOffsets ; +4 bytes for long offset support. slows decompression down by 1%, but may be needed to decompress files >=32K
+
+MACRO ApUnpack
+
+ ld a,128 : jr @LWM0_CASE0
+
+;==================================================================================================================
+;==================================================================================================================
+;==================================================================================================================
+
+@LWM0: ;LWM = 0 (LWM stands for "Last Was Match"; a flag that we did not have a match)
+
+@LWM0_ReloadByteC0 ld a,(hl) : inc hl : rla
+ jr c,@LWM0_Check2ndBit
+
+;
+; case "0"+BYTE: copy a single literal
+
+@LWM0_CASE0: ldi ; first byte is always copied as literal
+
+;
+; main decompressor loop
+
+@LWM0_MainLoop: add a : jr z,@LWM0_ReloadByteC0 : jr nc,@LWM0_CASE0 ; "0"+BYTE = copy literal
+@LWM0_Check2ndBit add a : call z,@ReloadByte : jr nc,@LWM0_CASE10 ; "10"+gamma(offset/256)+BYTE+gamma(length) = the main matching mechanism
+ add a : call z,@ReloadByte : jp c,@LWM1_CASE111 ; "110"+[oooooool] = matched 2-3 bytes with a small offset
+
+;
+; branch "110"+[oooooool]: copy two or three bytes (bit "l") with the offset -1..-127 (bits "ooooooo"), or stop
+
+@LWM0_CASE110: ; "use 7 bit offset, length = 2 or 3"
+ ; "if a zero is found here, it's EOF"
+ ld c,(hl) : rr c : ret z ; process EOF
+ inc hl
+ ld b,0
+
+ ld iyl,c : ld iyh,b ; save offset for future LWMs
+
+ push hl ; save src
+ ld h,d : ld l,e ; HL = dest
+ jr c,@LWM0_LengthIs3
+
+@LWM0_LengthIs2 sbc hl,bc
+ ldi : ldi
+ jr @LWM0_PreMainLoop
+
+@LWM0_LengthIs3 or a : sbc hl,bc
+ ldi : ldi : ldi
+ jr @LWM0_PreMainLoop
+
+;
+; branch "10"+gamma(offset/256)+BYTE+gamma(length): the main matching mechanism
+
+@LWM0_CASE10: ; "use a gamma code * 256 for offset, another gamma code for length"
+ call @GetGammaCoded
+
+ ; the original decompressor contains
+ ;
+ ; if ((LWM == 0) && (offs == 2)) { ... }
+ ; else {
+ ; if (LWM == 0) { offs -= 3; }
+ ; else { offs -= 2; }
+ ; }
+ ;
+ ; so, the idea here is to use the fact that GetGammaCoded returns (offset/256)+2,
+ ; and to split the first condition by noticing that C-1 can never be zero
+ dec c : dec c : jr z,@LWM1_KickInLWM
+
+@LWM0_AfterLWM dec c : ld b,c : ld c,(hl) : inc hl ; BC = offset
+
+ ld iyl,c : ld iyh,b : push bc
+
+ call @GetGammaCoded ; BC = len*
+
+ ex (sp),hl
+
+ ; interpretation of length value is offset-dependent:
+ ; if (offs >= 32000) len++; if (offs >= 1280) len++; if (offs < 128) len+=2;
+ ; in other words,
+ ; (1 <= offs < 128) +=2
+ ; (128 <= offs < 1280) +=0
+ ; (1280 <= offs < 31999) +=1
+ ; NB offsets over 32000 need one more check, but other Z80 decompressors seem to ignore it. is it not needed?
+
+ ; interpretation of length value is offset-dependent
+ exa : ld a,h
+ IFDEF SupportLongOffsets
+ ; NB offsets over 32000 require an additional check, which is skipped in most
+ ; Z80 decompressors (seemingly as a performance optimization)
+ cp 32000>>8 : jr nc,@LWM0_Add2
+ ENDIF
+ cp 5 : jr nc,@LWM0_Add1
+ or a : jr nz,@LWM0_Add0
+ bit 7,l : jr nz,@LWM0_Add0
+@LWM0_Add2 inc bc
+@LWM0_Add1 inc bc
+@LWM0_Add0 ; for offs<128 : 4+4+7+7 + 4+7 + 8+7 + 6+6 = 60t
+ ; for offs>=1280 : 4+4+7+12 + 6 = 33t
+ ; for 128<=offs<1280 : 4+4+7+7 + 4+12 = 38t OR 4+4+7+7 + 4+7+8+12 = 53t
+; dec bc
+
+@LWM0_CopyMatch: ; this assumes that BC = len, DE = offset, HL = dest
+ ; and also that (SP) = src, while having NC
+ ld a,e : sub l : ld l,a
+ ld a,d : sbc h
+@LWM0_CopyMatchLDH ld h,a : ldi : ldir : exa
+@LWM0_PreMainLoop pop hl ; recover src
+
+;==================================================================================================================
+;==================================================================================================================
+;==================================================================================================================
+
+@LWM1: ; LWM = 1
+
+;
+; main decompressor loop
+
+@LWM1_MainLoop: add a : jr z,@LWM1_ReloadByteC0 : jr nc,@LWM0_CASE0 ; "0"+BYTE = copy literal
+@LWM1_Check2ndBit add a : call z,@ReloadByte : jr nc,@LWM1_CASE10 ; "10"+gamma(offset/256)+BYTE+gamma(length) = the main matching mechanism
+ add a : call z,@ReloadByte : jr nc,@LWM0_CASE110 ; "110"+[oooooool] = matched 2-3 bytes with a small offset
+
+;
+; case "111"+"oooo": copy a byte with offset -1..-15, or write zero to dest
+
+@LWM1_CASE111: ld bc,%11100000
+ add a : call z,@ReloadByte : rl c ; read short offset (4 bits)
+ add a : call z,@ReloadByte : rl c ; read short offset (4 bits)
+ add a : call z,@ReloadByte : rl c ; read short offset (4 bits)
+ add a : call z,@ReloadByte : rl c ; read short offset (4 bits)
+ ex de,hl : jr z,@LWM1_WriteZero ; zero offset means "write zero" (NB: B is zero here)
+
+ ; "write a previous byte (1-15 away from dest)"
+ push hl ; BC = offset, DE = src, HL = dest
+ sbc hl,bc ; HL = dest-offset (SBC works because branching above ensured NC)
+ ld b,(hl)
+ pop hl
+
+@LWM1_WriteZero ld (hl),b : ex de,hl
+ inc de : jp @LWM0_MainLoop ; 10+4*(4+10+8)+4+7 + 11+15+7+10 + 7+4+6+10 = 179t
+
+@LWM1_ReloadByteC0 ld a,(hl) : inc hl : rla
+ jp nc,@LWM0_CASE0
+ jr @LWM1_Check2ndBit
+
+;
+; branch "10"+gamma(offset/256)+BYTE+gamma(length): the main matching mechanism
+
+@LWM1_CASE10: ; "use a gamma code * 256 for offset, another gamma code for length"
+ call @GetGammaCoded
+
+ ; the original decompressor contains
+ ;
+ ; if ((LWM == 0) && (offs == 2)) { ... }
+ ; else {
+ ; if (LWM == 0) { offs -= 3; }
+ ; else { offs -= 2; }
+ ; }
+ ;
+ ; so, the idea here is to use the fact that GetGammaCoded returns (offset/256)+2,
+ ; and to split the first condition by noticing that C-1 can never be zero
+ dec c : jp @LWM0_AfterLWM
+
+;
+; the re-use of the previous offset (LWM magic)
+
+@LWM1_KickInLWM: ; "and a new gamma code for length"
+ call @GetGammaCoded ; BC = len
+ push hl
+ exa : ld a,e : sub iyl : ld l,a
+ ld a,d : sbc iyh
+ jp @LWM0_CopyMatchLDH
+
+;==================================================================================================================
+;==================================================================================================================
+;==================================================================================================================
+
+;
+; interlaced gamma code reader
+; x0 -> 1x
+; x1y0 -> 1xy
+; x1y1z0 -> 1xyz etc
+; (technically, this is a 2-based variation of Exp-Golomb-1)
+
+@GetGammaCoded: ld bc,1
+@ReadGamma add a : jr z,@ReloadByteRG1
+ rl c : rl b
+ add a : jr z,@ReloadByteRG2
+ jr c,@ReadGamma : ret
+
+@ReloadByteRG1 ld a,(hl) : inc hl : rla
+ rl c : rl b
+ add a : jr c,@ReadGamma : ret
+
+@ReloadByteRG2 ld a,(hl) : inc hl : rla
+ jr c,@ReadGamma : ret
+
+;
+; pretty usual getbit for mixed datastreams
+
+@ReloadByte: ld a,(hl) : inc hl : rla : ret
+
+MEND
+
diff --git a/tools/rasm/decrunch/unlzsa1_fast.asm b/tools/rasm/decrunch/unlzsa1_fast.asm
new file mode 100644
index 0000000..0e2617f
--- /dev/null
+++ b/tools/rasm/decrunch/unlzsa1_fast.asm
@@ -0,0 +1,204 @@
+;
+; Speed-optimized LZSA1 decompressor by spke & uniabis (109 bytes)
+;
+; ver.00 by spke for LZSA 0.5.4 (03-24/04/2019, 134 bytes);
+; ver.01 by spke for LZSA 0.5.6 (25/04/2019, 110(-24) bytes, +0.2% speed);
+; ver.02 by spke for LZSA 1.0.5 (24/07/2019, added support for backward decompression);
+; ver.03 by uniabis (30/07/2019, 109(-1) bytes, +3.5% speed);
+; ver.04 by spke (31/07/2019, small re-organization of macros);
+; ver.05 by uniabis (22/08/2019, 107(-2) bytes, same speed);
+; ver.06 by spke for LZSA 1.0.7 (27/08/2019, 111(+4) bytes, +2.1% speed);
+; ver.07 by spke for LZSA 1.1.0 (25/09/2019, added full revision history);
+; ver.08 by spke for LZSA 1.1.2 (22/10/2019, re-organized macros and added an option for unrolled copying of long matches);
+; ver.09 by spke for LZSA 1.2.1 (02/01/2020, 109(-2) bytes, same speed)
+;
+; The data must be compressed using the command line compressor by Emmanuel Marty
+; The compression is done as follows:
+;
+; lzsa.exe -f1 -r <sourcefile> <outfile>
+;
+; where option -r asks for the generation of raw (frame-less) data.
+;
+; The decompression is done in the standard way:
+;
+; ld hl,FirstByteOfCompressedData
+; ld de,FirstByteOfMemoryForDecompressedData
+; call DecompressLZSA1
+;
+; Backward compression is also supported; you can compress files backward using:
+;
+; lzsa.exe -f1 -r -b <sourcefile> <outfile>
+;
+; and decompress the resulting files using:
+;
+; ld hl,LastByteOfCompressedData
+; ld de,LastByteOfMemoryForDecompressedData
+; call DecompressLZSA1
+;
+; (do not forget to uncomment the BACKWARD_DECOMPRESS option in the decompressor).
+;
+; Of course, LZSA compression algorithms are (c) 2019 Emmanuel Marty,
+; see https://github.com/emmanuel-marty/lzsa for more information
+;
+; Drop me an email if you have any comments/ideas/suggestions: zxintrospec@gmail.com
+;
+; This software is provided 'as-is', without any express or implied
+; warranty. In no event will the authors be held liable for any damages
+; arising from the use of this software.
+;
+; Permission is granted to anyone to use this software for any purpose,
+; including commercial applications, and to alter it and redistribute it
+; freely, subject to the following restrictions:
+;
+; 1. The origin of this software must not be misrepresented; you must not
+; claim that you wrote the original software. If you use this software
+; in a product, an acknowledgment in the product documentation would be
+; appreciated but is not required.
+; 2. Altered source versions must be plainly marked as such, and must not be
+; misrepresented as being the original software.
+; 3. This notice may not be removed or altered from any source distribution.
+
+; DEFINE UNROLL_LONG_MATCHES ; uncomment for faster decompression of very compressible data (+57 bytes)
+; DEFINE BACKWARD_DECOMPRESS
+
+ IFNDEF BACKWARD_DECOMPRESS
+
+ MACRO NEXT_HL
+ inc hl
+ ENDM
+
+ MACRO ADD_OFFSET
+ ex de,hl : add hl,de
+ ENDM
+
+ MACRO COPY1
+ ldi
+ ENDM
+
+ MACRO COPYBC
+ ldir
+ ENDM
+
+ ELSE
+
+ MACRO NEXT_HL
+ dec hl
+ ENDM
+
+ MACRO ADD_OFFSET
+ ex de,hl : ld a,e : sub l : ld l,a
+ ld a,d : sbc h : ld h,a ; 4*4+3*4 = 28t / 7 bytes
+ ENDM
+
+ MACRO COPY1
+ ldd
+ ENDM
+
+ MACRO COPYBC
+ lddr
+ ENDM
+
+ ENDIF
+
+macro DecompressLZSA1
+ ld b,0 : jr @ReadToken
+
+@NoLiterals: xor (hl) : NEXT_HL : jp m,@LongOffset
+
+@ShortOffset: push de : ld e,(hl) : ld d,#FF
+
+ ; short matches have length 0+3..14+3
+ add 3 : cp 15+3 : jr nc,@LongerMatch
+
+ ; placed here this saves a JP per iteration
+@CopyMatch: ld c,a
+.UseC NEXT_HL : ex (sp),hl ; BC = len, DE = offset, HL = dest, SP ->[dest,src]
+ ADD_OFFSET ; BC = len, DE = dest, HL = dest-offset, SP->[src]
+ COPY1 : COPY1 : COPYBC ; BC = 0, DE = dest
+.popSrc pop hl ; HL = src
+
+@ReadToken: ; first a byte token "O|LLL|MMMM" is read from the stream,
+ ; where LLL is the number of literals and MMMM is
+ ; a length of the match that follows after the literals
+ ld a,(hl) : and #70 : jr z,@NoLiterals
+
+ cp #70 : jr z,@MoreLiterals ; LLL=7 means 7+ literals...
+ rrca : rrca : rrca : rrca : ld c,a ; LLL<7 means 0..6 literals...
+
+ ld a,(hl) : NEXT_HL
+ COPYBC
+
+ ; the top bit of token is set if the offset contains two bytes
+ and #8F : jp p,@ShortOffset
+
+@LongOffset: ; read second byte of the offset
+ push de : ld e,(hl) : NEXT_HL : ld d,(hl)
+ add -128+3 : cp 15+3 : jp c,@CopyMatch
+
+ IFNDEF UNROLL_LONG_MATCHES
+
+ ; MMMM=15 indicates a multi-byte number of literals
+@LongerMatch: NEXT_HL : add (hl) : jr nc,@CopyMatch
+
+ ; the codes are designed to overflow;
+ ; the overflow value 1 means read 1 extra byte
+ ; and overflow value 0 means read 2 extra bytes
+.code1 ld b,a : NEXT_HL : ld c,(hl) : jr nz,@CopyMatch.UseC
+.code0 NEXT_HL : ld b,(hl)
+
+ ; the two-byte match length equal to zero
+ ; designates the end-of-data marker
+ ld a,b : or c : jr nz,@CopyMatch.UseC
+ pop de : ret
+
+ ELSE
+
+ ; MMMM=15 indicates a multi-byte number of literals
+@LongerMatch: NEXT_HL : add (hl) : jr c,@VeryLongMatch
+
+ ld c,a
+.UseC NEXT_HL : ex (sp),hl
+ ADD_OFFSET
+ COPY1 : COPY1
+
+ ; this is an unrolled equivalent of LDIR
+ xor a : sub c
+ and 32-1 : add a
+ ld (.jrOffset),a : jr nz,$+2
+.jrOffset EQU $-1
+.fastLDIR repeat 32
+ COPY1
+ rend
+ jp pe,.fastLDIR
+ jp @CopyMatch.popSrc
+
+@VeryLongMatch: ; the codes are designed to overflow;
+ ; the overflow value 1 means read 1 extra byte
+ ; and overflow value 0 means read 2 extra bytes
+.code1 ld b,a : NEXT_HL : ld c,(hl) : jr nz,@LongerMatch.UseC
+.code0 NEXT_HL : ld b,(hl)
+
+ ; the two-byte match length equal to zero
+ ; designates the end-of-data marker
+ ld a,b : or c : jr nz,@LongerMatch.UseC
+ pop de : ret
+
+ ENDIF
+
+@MoreLiterals: ; there are three possible situations here
+ xor (hl) : NEXT_HL : exa
+ ld a,7 : add (hl) : jr c,@ManyLiterals
+
+@CopyLiterals: ld c,a
+.UseC NEXT_HL : COPYBC
+
+ exa : jp p,@ShortOffset : jr @LongOffset
+
+@ManyLiterals:
+.code1 ld b,a : NEXT_HL : ld c,(hl) : jr nz,@CopyLiterals.UseC
+.code0 NEXT_HL : ld b,(hl) : jr @CopyLiterals.UseC
+
+mend
+
+
+
diff --git a/tools/rasm/decrunch/unlzsa2_fast.asm b/tools/rasm/decrunch/unlzsa2_fast.asm
new file mode 100755
index 0000000..8c6b5b1
--- /dev/null
+++ b/tools/rasm/decrunch/unlzsa2_fast.asm
@@ -0,0 +1,189 @@
+;
+; Speed-optimized LZSA2 decompressor by spke & uniabis (216 bytes)
+;
+
+ DEFINE UNROLL_LONG_MATCHES ; uncomment for faster decompression of very compressible data (+38 bytes)
+; DEFINE BACKWARD_DECOMPRESS ; uncomment for data compressed with option -b
+
+ IFNDEF BACKWARD_DECOMPRESS
+
+ MACRO NEXT_HL
+ inc hl
+ ENDM
+
+ MACRO ADD_OFFSET
+ ex de,hl : add hl,de
+ ENDM
+
+ MACRO COPY1
+ ldi
+ ENDM
+
+ MACRO COPYBC
+ ldir
+ ENDM
+
+ ELSE
+
+ MACRO NEXT_HL
+ dec hl
+ ENDM
+
+ MACRO ADD_OFFSET
+ ex de,hl : ld a,e : sub l : ld l,a
+ ld a,d : sbc h : ld h,a ; 4*4+3*4 = 28t / 7 bytes
+ ENDM
+
+ MACRO COPY1
+ ldd
+ ENDM
+
+ MACRO COPYBC
+ lddr
+ ENDM
+
+ ENDIF
+
+
+macro DecompressLZSA2
+@lzsa2
+ ; A' stores next nibble as %1111.... or assumed to contain trash
+ ; B is assumed to be 0
+ ld b,0 : scf : exa : jr .ReadToken
+
+.ManyLiterals: ld a,18 : add (hl) : NEXT_HL : jr nc,.CopyLiterals
+ ld c,(hl) : NEXT_HL
+ ld a,b : ld b,(hl)
+ jr .NEXTHLuseBC
+
+
+.MoreLiterals: ld b,(hl) : NEXT_HL
+ scf : exa : jr nc,.noUpdatemoar
+
+ ld a,(hl) : or #F0 : exa
+ ld a,(hl) : NEXT_HL : or #0F
+ rrca : rrca : rrca : rrca
+
+.noUpdatemoar ;sub #F0-3 : cp 15+3 : jr z,ManyLiterals
+ inc a : jr z,.ManyLiterals : sub #F0-3+1
+
+.CopyLiterals: ld c,a : ld a,b : ld b,0
+ COPYBC
+ push de : or a : jp p,.CASE0xx ;: jr CASE1xx
+
+ cp %11000000 : jr c,.CASE10x
+
+.CASE11x cp %11100000 : jr c,.CASE110
+
+ ; "111": repeated offset
+.CASE111: ld de,ix : jr .MatchLen
+
+
+.Literals0011: jr nz,.MoreLiterals
+
+ ; if "LL" of the byte token is equal to 0,
+ ; there are no literals to copy
+.NoLiterals: or (hl) : NEXT_HL
+ push de : jp m,.CASE1xx
+
+ ; short (5 or 9 bit long) offsets
+.CASE0xx ld d,#FF : cp %01000000 : jr c,.CASE00x
+
+ ; "01x": the case of the 9-bit offset
+.CASE01x: cp %01100000 : rl d
+
+.ReadOffsetE ld e,(hl) : NEXT_HL
+
+.SaveOffset: LD ix,de
+
+.MatchLen: inc a : and %00000111 : jr z,.LongerMatch : inc a
+
+.CopyMatch: ld c,a
+;.useC
+ ex (sp),hl ; BC = len, DE = offset, HL = dest, SP ->[dest,src]
+ ADD_OFFSET ; BC = len, DE = dest, HL = dest-offset, SP->[src]
+ COPY1
+ COPYBC
+.popSrc pop hl
+
+ ; compressed data stream contains records
+ ; each record begins with the byte token "XYZ|LL|MMM"
+.ReadToken: ld a,(hl) : and %00011000 : jp pe,.Literals0011 ; process the cases 00 and 11 separately
+
+ rrca : rrca : rrca
+
+ ld c,a : ld a,(hl) ; token is re-read for further processing
+.NEXTHLuseBC NEXT_HL
+ COPYBC
+
+ ; the token and literals are followed by the offset
+ push de : or a : jp p,.CASE0xx
+
+.CASE1xx cp %11000000 : jr nc,.CASE11x
+
+ ; "10x": the case of the 13-bit offset
+.CASE10x: ld c,a : exa : jr nc,.noUpdatecase10x
+
+ ld a,(hl) : or #F0 : exa
+ ld a,(hl) : NEXT_HL : or #0F
+ rrca : rrca : rrca : rrca
+
+.noUpdatecase10x ld d,a : ld a,c
+ cp %10100000 : dec d : rl d : jr .ReadOffsetE
+
+
+
+ ; "110": 16-bit offset
+.CASE110: ld d,(hl) : NEXT_HL : jr .ReadOffsetE
+
+
+
+
+ ; "00x": the case of the 5-bit offset
+.CASE00x: ld c,a : exa : jr nc,.noUpdatecase00x
+
+ ld a,(hl) : or #F0 : exa
+ ld a,(hl) : NEXT_HL : or #0F
+ rrca : rrca : rrca : rrca
+
+.noUpdatecase00x ld e,a : ld a,c
+ cp %00100000 : rl e : jp .SaveOffset
+
+
+.LongerMatch: scf : exa : jr nc,.noUpdatelongermatch
+
+ ld a,(hl) : or #F0 : exa
+ ld a,(hl) : NEXT_HL : or #0F
+ rrca : rrca : rrca : rrca
+
+.noUpdatelongermatch sub #F0-9 : cp 15+9 : jr c,.CopyMatch
+
+
+.LongMatch: add (hl) : NEXT_HL : jr c,.VeryLongMatch
+
+ ld c,a
+.useC ex (sp),hl
+ ADD_OFFSET
+ COPY1
+
+ ; this is an unrolled equivalent of LDIR
+ xor a : sub c
+ and 32-1 : add a
+ ld (.jrOffset),a : jr nz,$+2
+.jrOffset EQU $-1
+.fastLDIR repeat 32
+ COPY1
+ rend
+ jp pe,.fastLDIR
+ jp .popSrc
+
+.VeryLongMatch: ld c,(hl) : NEXT_HL
+ ld b,(hl) : NEXT_HL : jr nz,.useC
+ pop de : ret
+
+mend
+
+
+
+
+
diff --git a/tools/rasm/documentation_EN.pdf b/tools/rasm/documentation_EN.pdf
new file mode 100644
index 0000000..2cc0326
--- /dev/null
+++ b/tools/rasm/documentation_EN.pdf
Binary files differ
diff --git a/tools/rasm/documentation_FR.pdf b/tools/rasm/documentation_FR.pdf
new file mode 100644
index 0000000..04924d9
--- /dev/null
+++ b/tools/rasm/documentation_FR.pdf
Binary files differ
diff --git a/tools/rasm/exomizer.h b/tools/rasm/exomizer.h
index 1f3c7ca..4f0f7e3 100644
--- a/tools/rasm/exomizer.h
+++ b/tools/rasm/exomizer.h
@@ -4861,7 +4861,6 @@ unsigned char *Exomizer_crunch(unsigned char *input_data, int input_len, int *re
int argc=1;
char **argv=NULL;
char flags_arr[32];
- int decrunch_mode = 0;
int backwards_mode = 0;
int reverse_mode = 0;
int c, infilec;
diff --git a/tools/rasm/lz4.h b/tools/rasm/lz4.h
index f34bae4..863fd54 100644
--- a/tools/rasm/lz4.h
+++ b/tools/rasm/lz4.h
@@ -600,14 +600,14 @@ LZ4LIB_API LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") int LZ4
* Basic Types
**************************************/
#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
- typedef uint8_t BYTE;
+ typedef uint8_t U8;
typedef uint16_t U16;
typedef uint32_t U32;
typedef int32_t S32;
typedef uint64_t U64;
typedef uintptr_t uptrval;
#else
- typedef unsigned char BYTE;
+ typedef unsigned char U8;
typedef unsigned short U16;
typedef unsigned int U32;
typedef signed int S32;
@@ -626,7 +626,7 @@ LZ4LIB_API LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") int LZ4
**************************************/
static unsigned LZ4_isLittleEndian(void)
{
- const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */
+ const union { U32 u; U8 c[4]; } one = { 1 }; /* don't use static : performance detrimental */
return one.c[0];
}
@@ -689,7 +689,7 @@ static U16 LZ4_readLE16(const void* memPtr)
if (LZ4_isLittleEndian()) {
return LZ4_read16(memPtr);
} else {
- const BYTE* p = (const BYTE*)memPtr;
+ const U8* p = (const U8*)memPtr;
return (U16)((U16)p[0] + (p[1]<<8));
}
}
@@ -699,9 +699,9 @@ static void LZ4_writeLE16(void* memPtr, U16 value)
if (LZ4_isLittleEndian()) {
LZ4_write16(memPtr, value);
} else {
- BYTE* p = (BYTE*)memPtr;
- p[0] = (BYTE) value;
- p[1] = (BYTE)(value>>8);
+ U8* p = (U8*)memPtr;
+ p[0] = (U8) value;
+ p[1] = (U8)(value>>8);
}
}
@@ -713,9 +713,9 @@ static void LZ4_copy8(void* dst, const void* src)
/* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */
static void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
{
- BYTE* d = (BYTE*)dstPtr;
- const BYTE* s = (const BYTE*)srcPtr;
- BYTE* const e = (BYTE*)dstEnd;
+ U8* d = (U8*)dstPtr;
+ const U8* s = (const U8*)srcPtr;
+ U8* const e = (U8*)dstEnd;
do { LZ4_copy8(d,s); d+=8; s+=8; } while (d<e);
}
@@ -812,9 +812,9 @@ static unsigned LZ4_NbCommonBytes (register reg_t val)
}
#define STEPSIZE sizeof(reg_t)
-static unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
+static unsigned LZ4_count(const U8* pIn, const U8* pMatch, const U8* pInLimit)
{
- const BYTE* const pStart = pIn;
+ const U8* const pStart = pIn;
while (likely(pIn<pInLimit-(STEPSIZE-1))) {
reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);
@@ -892,30 +892,30 @@ FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableTy
return LZ4_hash4(LZ4_read32(p), tableType);
}
-static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase)
+static void LZ4_putPositionOnHash(const U8* p, U32 h, void* tableBase, tableType_t const tableType, const U8* srcBase)
{
switch (tableType)
{
- case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; }
+ case byPtr: { const U8** hashTable = (const U8**)tableBase; hashTable[h] = p; return; }
case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; }
case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; }
}
}
-FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)
+FORCE_INLINE void LZ4_putPosition(const U8* p, void* tableBase, tableType_t tableType, const U8* srcBase)
{
U32 const h = LZ4_hashPosition(p, tableType);
LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase);
}
-static const BYTE* LZ4_getPositionOnHash(U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase)
+static const U8* LZ4_getPositionOnHash(U32 h, void* tableBase, tableType_t tableType, const U8* srcBase)
{
- if (tableType == byPtr) { const BYTE** hashTable = (const BYTE**) tableBase; return hashTable[h]; }
+ if (tableType == byPtr) { const U8** hashTable = (const U8**) tableBase; return hashTable[h]; }
if (tableType == byU32) { const U32* const hashTable = (U32*) tableBase; return hashTable[h] + srcBase; }
{ const U16* const hashTable = (U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */
}
-FORCE_INLINE const BYTE* LZ4_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)
+FORCE_INLINE const U8* LZ4_getPosition(const U8* p, void* tableBase, tableType_t tableType, const U8* srcBase)
{
U32 const h = LZ4_hashPosition(p, tableType);
return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase);
@@ -936,20 +936,20 @@ FORCE_INLINE int LZ4_compress_generic(
const dictIssue_directive dictIssue,
const U32 acceleration)
{
- const BYTE* ip = (const BYTE*) source;
- const BYTE* base;
- const BYTE* lowLimit;
- const BYTE* const lowRefLimit = ip - cctx->dictSize;
- const BYTE* const dictionary = cctx->dictionary;
- const BYTE* const dictEnd = dictionary + cctx->dictSize;
- const ptrdiff_t dictDelta = dictEnd - (const BYTE*)source;
- const BYTE* anchor = (const BYTE*) source;
- const BYTE* const iend = ip + inputSize;
- const BYTE* const mflimit = iend - MFLIMIT;
- const BYTE* const matchlimit = iend - LASTLITERALS;
-
- BYTE* op = (BYTE*) dest;
- BYTE* const olimit = op + maxOutputSize;
+ const U8* ip = (const U8*) source;
+ const U8* base;
+ const U8* lowLimit;
+ const U8* const lowRefLimit = ip - cctx->dictSize;
+ const U8* const dictionary = cctx->dictionary;
+ const U8* const dictEnd = dictionary + cctx->dictSize;
+ const ptrdiff_t dictDelta = dictEnd - (const U8*)source;
+ const U8* anchor = (const U8*) source;
+ const U8* const iend = ip + inputSize;
+ const U8* const mflimit = iend - MFLIMIT;
+ const U8* const matchlimit = iend - LASTLITERALS;
+
+ U8* op = (U8*) dest;
+ U8* const olimit = op + maxOutputSize;
U32 forwardH;
@@ -959,16 +959,16 @@ FORCE_INLINE int LZ4_compress_generic(
{
case noDict:
default:
- base = (const BYTE*)source;
- lowLimit = (const BYTE*)source;
+ base = (const U8*)source;
+ lowLimit = (const U8*)source;
break;
case withPrefix64k:
- base = (const BYTE*)source - cctx->currentOffset;
- lowLimit = (const BYTE*)source - cctx->dictSize;
+ base = (const U8*)source - cctx->currentOffset;
+ lowLimit = (const U8*)source - cctx->dictSize;
break;
case usingExtDict:
- base = (const BYTE*)source - cctx->currentOffset;
- lowLimit = (const BYTE*)source;
+ base = (const U8*)source - cctx->currentOffset;
+ lowLimit = (const U8*)source;
break;
}
if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */
@@ -981,11 +981,11 @@ FORCE_INLINE int LZ4_compress_generic(
/* Main Loop */
for ( ; ; ) {
ptrdiff_t refDelta = 0;
- const BYTE* match;
- BYTE* token;
+ const U8* match;
+ U8* token;
/* Find a match */
- { const BYTE* forwardIp = ip;
+ { const U8* forwardIp = ip;
unsigned step = 1;
unsigned searchMatchNb = acceleration << LZ4_skipTrigger;
do {
@@ -998,12 +998,12 @@ FORCE_INLINE int LZ4_compress_generic(
match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType, base);
if (dict==usingExtDict) {
- if (match < (const BYTE*)source) {
+ if (match < (const U8*)source) {
refDelta = dictDelta;
lowLimit = dictionary;
} else {
refDelta = 0;
- lowLimit = (const BYTE*)source;
+ lowLimit = (const U8*)source;
} }
forwardH = LZ4_hashPosition(forwardIp, tableType);
LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType, base);
@@ -1026,9 +1026,9 @@ FORCE_INLINE int LZ4_compress_generic(
int len = (int)litLength-RUN_MASK;
*token = (RUN_MASK<<ML_BITS);
for(; len >= 255 ; len-=255) *op++ = 255;
- *op++ = (BYTE)len;
+ *op++ = (U8)len;
}
- else *token = (BYTE)(litLength<<ML_BITS);
+ else *token = (U8)(litLength<<ML_BITS);
/* Copy Literals */
LZ4_wildCopy(op, anchor, op+litLength);
@@ -1043,14 +1043,14 @@ _next_match:
{ unsigned matchCode;
if ((dict==usingExtDict) && (lowLimit==dictionary)) {
- const BYTE* limit;
+ const U8* limit;
match += refDelta;
limit = ip + (dictEnd-match);
if (limit > matchlimit) limit = matchlimit;
matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, limit);
ip += MINMATCH + matchCode;
if (ip==limit) {
- unsigned const more = LZ4_count(ip, (const BYTE*)source, matchlimit);
+ unsigned const more = LZ4_count(ip, (const U8*)source, matchlimit);
matchCode += more;
ip += more;
}
@@ -1068,9 +1068,9 @@ _next_match:
LZ4_write32(op, 0xFFFFFFFF);
while (matchCode >= 4*255) op+=4, LZ4_write32(op, 0xFFFFFFFF), matchCode -= 4*255;
op += matchCode / 255;
- *op++ = (BYTE)(matchCode % 255);
+ *op++ = (U8)(matchCode % 255);
} else
- *token += (BYTE)(matchCode);
+ *token += (U8)(matchCode);
}
anchor = ip;
@@ -1084,12 +1084,12 @@ _next_match:
/* Test next position */
match = LZ4_getPosition(ip, cctx->hashTable, tableType, base);
if (dict==usingExtDict) {
- if (match < (const BYTE*)source) {
+ if (match < (const U8*)source) {
refDelta = dictDelta;
lowLimit = dictionary;
} else {
refDelta = 0;
- lowLimit = (const BYTE*)source;
+ lowLimit = (const U8*)source;
} }
LZ4_putPosition(ip, cctx->hashTable, tableType, base);
if ( ((dictIssue==dictSmall) ? (match>=lowRefLimit) : 1)
@@ -1105,15 +1105,15 @@ _last_literals:
/* Encode Last Literals */
{ size_t const lastRun = (size_t)(iend - anchor);
if ( (outputLimited) && /* Check output buffer overflow */
- ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize) )
+ ((op - (U8*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize) )
return 0;
if (lastRun >= RUN_MASK) {
size_t accumulator = lastRun - RUN_MASK;
*op++ = RUN_MASK << ML_BITS;
for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
- *op++ = (BYTE) accumulator;
+ *op++ = (U8) accumulator;
} else {
- *op++ = (BYTE)(lastRun<<ML_BITS);
+ *op++ = (U8)(lastRun<<ML_BITS);
}
memcpy(op, anchor, lastRun);
op += lastRun;
@@ -1194,19 +1194,19 @@ static int LZ4_compress_destSize_generic(
const int targetDstSize,
const tableType_t tableType)
{
- const BYTE* ip = (const BYTE*) src;
- const BYTE* base = (const BYTE*) src;
- const BYTE* lowLimit = (const BYTE*) src;
- const BYTE* anchor = ip;
- const BYTE* const iend = ip + *srcSizePtr;
- const BYTE* const mflimit = iend - MFLIMIT;
- const BYTE* const matchlimit = iend - LASTLITERALS;
+ const U8* ip = (const U8*) src;
+ const U8* base = (const U8*) src;
+ const U8* lowLimit = (const U8*) src;
+ const U8* anchor = ip;
+ const U8* const iend = ip + *srcSizePtr;
+ const U8* const mflimit = iend - MFLIMIT;
+ const U8* const matchlimit = iend - LASTLITERALS;
- BYTE* op = (BYTE*) dst;
- BYTE* const oend = op + targetDstSize;
- BYTE* const oMaxLit = op + targetDstSize - 2 /* offset */ - 8 /* because 8+MINMATCH==MFLIMIT */ - 1 /* token */;
- BYTE* const oMaxMatch = op + targetDstSize - (LASTLITERALS + 1 /* token */);
- BYTE* const oMaxSeq = oMaxLit - 1 /* token */;
+ U8* op = (U8*) dst;
+ U8* const oend = op + targetDstSize;
+ U8* const oMaxLit = op + targetDstSize - 2 /* offset */ - 8 /* because 8+MINMATCH==MFLIMIT */ - 1 /* token */;
+ U8* const oMaxMatch = op + targetDstSize - (LASTLITERALS + 1 /* token */);
+ U8* const oMaxSeq = oMaxLit - 1 /* token */;
U32 forwardH;
@@ -1224,11 +1224,11 @@ static int LZ4_compress_destSize_generic(
/* Main Loop */
for ( ; ; ) {
- const BYTE* match;
- BYTE* token;
+ const U8* match;
+ U8* token;
/* Find a match */
- { const BYTE* forwardIp = ip;
+ { const U8* forwardIp = ip;
unsigned step = 1;
unsigned searchMatchNb = 1 << LZ4_skipTrigger;
@@ -1263,9 +1263,9 @@ static int LZ4_compress_destSize_generic(
unsigned len = litLength - RUN_MASK;
*token=(RUN_MASK<<ML_BITS);
for(; len >= 255 ; len-=255) *op++ = 255;
- *op++ = (BYTE)len;
+ *op++ = (U8)len;
}
- else *token = (BYTE)(litLength<<ML_BITS);
+ else *token = (U8)(litLength<<ML_BITS);
/* Copy Literals */
LZ4_wildCopy(op, anchor, op+litLength);
@@ -1289,9 +1289,9 @@ _next_match:
*token += ML_MASK;
matchLength -= ML_MASK;
while (matchLength >= 255) { matchLength-=255; *op++ = 255; }
- *op++ = (BYTE)matchLength;
+ *op++ = (U8)matchLength;
}
- else *token += (BYTE)(matchLength);
+ else *token += (U8)(matchLength);
}
anchor = ip;
@@ -1328,9 +1328,9 @@ _last_literals:
size_t accumulator = lastRunSize - RUN_MASK;
*op++ = RUN_MASK << ML_BITS;
for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
- *op++ = (BYTE) accumulator;
+ *op++ = (U8) accumulator;
} else {
- *op++ = (BYTE)(lastRunSize<<ML_BITS);
+ *op++ = (U8)(lastRunSize<<ML_BITS);
}
memcpy(op, anchor, lastRunSize);
op += lastRunSize;
@@ -1404,9 +1404,9 @@ int LZ4_freeStream (LZ4_stream_t* LZ4_stream)
int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize)
{
LZ4_stream_t_internal* dict = &LZ4_dict->internal_donotuse;
- const BYTE* p = (const BYTE*)dictionary;
- const BYTE* const dictEnd = p + dictSize;
- const BYTE* base;
+ const U8* p = (const U8*)dictionary;
+ const U8* const dictEnd = p + dictSize;
+ const U8* base;
if ((dict->initCheck) || (dict->currentOffset > 1 GB)) /* Uninitialized structure, or reuse overflow */
LZ4_resetStream(LZ4_dict);
@@ -1433,13 +1433,13 @@ int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize)
}
-static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const BYTE* src)
+static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const U8* src)
{
if ((LZ4_dict->currentOffset > 0x80000000) ||
((uptrval)LZ4_dict->currentOffset > (uptrval)src)) { /* address space overflow */
/* rescale hash table */
U32 const delta = LZ4_dict->currentOffset - 64 KB;
- const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize;
+ const U8* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize;
int i;
for (i=0; i<LZ4_HASH_SIZE_U32; i++) {
if (LZ4_dict->hashTable[i] < delta) LZ4_dict->hashTable[i]=0;
@@ -1455,16 +1455,16 @@ static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const BYTE* src)
int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
{
LZ4_stream_t_internal* streamPtr = &LZ4_stream->internal_donotuse;
- const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
+ const U8* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
- const BYTE* smallest = (const BYTE*) source;
+ const U8* smallest = (const U8*) source;
if (streamPtr->initCheck) return 0; /* Uninitialized structure detected */
if ((streamPtr->dictSize>0) && (smallest>dictEnd)) smallest = dictEnd;
LZ4_renormDictT(streamPtr, smallest);
if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;
/* Check overlapping input/dictionary space */
- { const BYTE* sourceEnd = (const BYTE*) source + inputSize;
+ { const U8* sourceEnd = (const U8*) source + inputSize;
if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd)) {
streamPtr->dictSize = (U32)(dictEnd - sourceEnd);
if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB;
@@ -1474,7 +1474,7 @@ int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, ch
}
/* prefix mode : source data follows dictionary */
- if (dictEnd == (const BYTE*)source) {
+ if (dictEnd == (const U8*)source) {
int result;
if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, dictSmall, acceleration);
@@ -1491,7 +1491,7 @@ int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, ch
result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, dictSmall, acceleration);
else
result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, noDictIssue, acceleration);
- streamPtr->dictionary = (const BYTE*)source;
+ streamPtr->dictionary = (const U8*)source;
streamPtr->dictSize = (U32)inputSize;
streamPtr->currentOffset += (U32)inputSize;
return result;
@@ -1504,15 +1504,15 @@ int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char*
{
LZ4_stream_t_internal* streamPtr = &LZ4_dict->internal_donotuse;
int result;
- const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
+ const U8* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
- const BYTE* smallest = dictEnd;
- if (smallest > (const BYTE*) source) smallest = (const BYTE*) source;
+ const U8* smallest = dictEnd;
+ if (smallest > (const U8*) source) smallest = (const U8*) source;
LZ4_renormDictT(streamPtr, smallest);
result = LZ4_compress_generic(streamPtr, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1);
- streamPtr->dictionary = (const BYTE*)source;
+ streamPtr->dictionary = (const U8*)source;
streamPtr->dictSize = (U32)inputSize;
streamPtr->currentOffset += (U32)inputSize;
@@ -1530,14 +1530,14 @@ int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char*
int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)
{
LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse;
- const BYTE* const previousDictEnd = dict->dictionary + dict->dictSize;
+ const U8* const previousDictEnd = dict->dictionary + dict->dictSize;
if ((U32)dictSize > 64 KB) dictSize = 64 KB; /* useless to define a dictionary > 64 KB */
if ((U32)dictSize > dict->dictSize) dictSize = dict->dictSize;
memmove(safeBuffer, previousDictEnd - dictSize, dictSize);
- dict->dictionary = (const BYTE*)safeBuffer;
+ dict->dictionary = (const U8*)safeBuffer;
dict->dictSize = (U32)dictSize;
return dictSize;
@@ -1564,22 +1564,22 @@ FORCE_INLINE int LZ4_decompress_generic(
int partialDecoding, /* full, partial */
int targetOutputSize, /* only used if partialDecoding==partial */
int dict, /* noDict, withPrefix64k, usingExtDict */
- const BYTE* const lowPrefix, /* == dest when no prefix */
- const BYTE* const dictStart, /* only if dict==usingExtDict */
+ const U8* const lowPrefix, /* == dest when no prefix */
+ const U8* const dictStart, /* only if dict==usingExtDict */
const size_t dictSize /* note : = 0 if noDict */
)
{
/* Local Variables */
- const BYTE* ip = (const BYTE*) source;
- const BYTE* const iend = ip + inputSize;
+ const U8* ip = (const U8*) source;
+ const U8* const iend = ip + inputSize;
- BYTE* op = (BYTE*) dest;
- BYTE* const oend = op + outputSize;
- BYTE* cpy;
- BYTE* oexit = op + targetOutputSize;
- const BYTE* const lowLimit = lowPrefix - dictSize;
+ U8* op = (U8*) dest;
+ U8* const oend = op + outputSize;
+ U8* cpy;
+ U8* oexit = op + targetOutputSize;
+ const U8* const lowLimit = lowPrefix - dictSize;
- const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;
+ const U8* const dictEnd = (const U8*)dictStart + dictSize;
const unsigned dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4};
const int dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3};
@@ -1595,7 +1595,7 @@ FORCE_INLINE int LZ4_decompress_generic(
/* Main Loop : decode sequences */
while (1) {
size_t length;
- const BYTE* match;
+ const U8* match;
size_t offset;
/* get literal length */
@@ -1664,8 +1664,8 @@ FORCE_INLINE int LZ4_decompress_generic(
memcpy(op, dictEnd - copySize, copySize);
op += copySize;
if (restSize > (size_t)(op-lowPrefix)) { /* overlap copy */
- BYTE* const endOfMatch = op + restSize;
- const BYTE* copyFrom = lowPrefix;
+ U8* const endOfMatch = op + restSize;
+ const U8* copyFrom = lowPrefix;
while (op < endOfMatch) *op++ = *copyFrom++;
} else {
memcpy(op, lowPrefix, restSize);
@@ -1689,7 +1689,7 @@ FORCE_INLINE int LZ4_decompress_generic(
op += 8;
if (unlikely(cpy>oend-12)) {
- BYTE* const oCopyLimit = oend-(WILDCOPYLENGTH-1);
+ U8* const oCopyLimit = oend-(WILDCOPYLENGTH-1);
if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals (uncompressed) */
if (op < oCopyLimit) {
LZ4_wildCopy(op, match, oCopyLimit);
@@ -1718,17 +1718,17 @@ _output_error:
int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize)
{
- return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, full, 0, noDict, (BYTE*)dest, NULL, 0);
+ return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, full, 0, noDict, (U8*)dest, NULL, 0);
}
int LZ4_decompress_safe_partial(const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize)
{
- return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, partial, targetOutputSize, noDict, (BYTE*)dest, NULL, 0);
+ return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, partial, targetOutputSize, noDict, (U8*)dest, NULL, 0);
}
int LZ4_decompress_fast(const char* source, char* dest, int originalSize)
{
- return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)(dest - 64 KB), NULL, 64 KB);
+ return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (U8*)(dest - 64 KB), NULL, 64 KB);
}
@@ -1762,7 +1762,7 @@ int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dicti
{
LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;
lz4sd->prefixSize = (size_t) dictSize;
- lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize;
+ lz4sd->prefixEnd = (const U8*) dictionary + dictSize;
lz4sd->externalDict = NULL;
lz4sd->extDictSize = 0;
return 1;
@@ -1780,7 +1780,7 @@ int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const ch
LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;
int result;
- if (lz4sd->prefixEnd == (BYTE*)dest) {
+ if (lz4sd->prefixEnd == (U8*)dest) {
result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
endOnInputSize, full, 0,
usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
@@ -1792,10 +1792,10 @@ int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const ch
lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
endOnInputSize, full, 0,
- usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
+ usingExtDict, (U8*)dest, lz4sd->externalDict, lz4sd->extDictSize);
if (result <= 0) return result;
lz4sd->prefixSize = result;
- lz4sd->prefixEnd = (BYTE*)dest + result;
+ lz4sd->prefixEnd = (U8*)dest + result;
}
return result;
@@ -1806,7 +1806,7 @@ int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const ch
LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;
int result;
- if (lz4sd->prefixEnd == (BYTE*)dest) {
+ if (lz4sd->prefixEnd == (U8*)dest) {
result = LZ4_decompress_generic(source, dest, 0, originalSize,
endOnOutputSize, full, 0,
usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
@@ -1818,10 +1818,10 @@ int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const ch
lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
result = LZ4_decompress_generic(source, dest, 0, originalSize,
endOnOutputSize, full, 0,
- usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
+ usingExtDict, (U8*)dest, lz4sd->externalDict, lz4sd->extDictSize);
if (result <= 0) return result;
lz4sd->prefixSize = originalSize;
- lz4sd->prefixEnd = (BYTE*)dest + originalSize;
+ lz4sd->prefixEnd = (U8*)dest + originalSize;
}
return result;
@@ -1838,13 +1838,13 @@ Advanced decoding functions :
FORCE_INLINE int LZ4_decompress_usingDict_generic(const char* source, char* dest, int compressedSize, int maxOutputSize, int safe, const char* dictStart, int dictSize)
{
if (dictSize==0)
- return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest, NULL, 0);
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (U8*)dest, NULL, 0);
if (dictStart+dictSize == dest) {
if (dictSize >= (int)(64 KB - 1))
- return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k, (BYTE*)dest-64 KB, NULL, 0);
- return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0);
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k, (U8*)dest-64 KB, NULL, 0);
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (U8*)dest-dictSize, NULL, 0);
}
- return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict, (U8*)dest, (const U8*)dictStart, dictSize);
}
int LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
@@ -1860,7 +1860,7 @@ int LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSi
/* debug function */
int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
{
- return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, (U8*)dest, (const U8*)dictStart, dictSize);
}
@@ -1889,7 +1889,7 @@ int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize,
int LZ4_sizeofStreamState() { return LZ4_STREAMSIZE; }
-static void LZ4_init(LZ4_stream_t* lz4ds, BYTE* base)
+static void LZ4_init(LZ4_stream_t* lz4ds, U8* base)
{
MEM_INIT(lz4ds, 0, sizeof(LZ4_stream_t));
lz4ds->internal_donotuse.bufferStart = base;
@@ -1898,14 +1898,14 @@ static void LZ4_init(LZ4_stream_t* lz4ds, BYTE* base)
int LZ4_resetStreamState(void* state, char* inputBuffer)
{
if ((((uptrval)state) & 3) != 0) return 1; /* Error : pointer is not aligned on 4-bytes boundary */
- LZ4_init((LZ4_stream_t*)state, (BYTE*)inputBuffer);
+ LZ4_init((LZ4_stream_t*)state, (U8*)inputBuffer);
return 0;
}
void* LZ4_create (char* inputBuffer)
{
LZ4_stream_t* lz4ds = (LZ4_stream_t*)ALLOCATOR(8, sizeof(LZ4_stream_t));
- LZ4_init (lz4ds, (BYTE*)inputBuffer);
+ LZ4_init (lz4ds, (U8*)inputBuffer);
return lz4ds;
}
@@ -1920,12 +1920,12 @@ char* LZ4_slideInputBuffer (void* LZ4_Data)
int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize)
{
- return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB);
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, withPrefix64k, (U8*)dest - 64 KB, NULL, 64 KB);
}
int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize)
{
- return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB);
+ return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (U8*)dest - 64 KB, NULL, 64 KB);
}
#endif /* LZ4_COMMONDEFS_ONLY */
@@ -2294,20 +2294,20 @@ static U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr)
***************************************/
FORCE_INLINE int LZ4HC_BinTree_InsertAndGetAllMatches (
LZ4HC_CCtx_internal* ctx,
- const BYTE* const ip,
- const BYTE* const iHighLimit,
+ const U8* const ip,
+ const U8* const iHighLimit,
size_t best_mlen,
LZ4HC_match_t* matches,
int* matchNum)
{
U16* const chainTable = ctx->chainTable;
U32* const HashTable = ctx->hashTable;
- const BYTE* const base = ctx->base;
+ const U8* const base = ctx->base;
const U32 dictLimit = ctx->dictLimit;
const U32 current = (U32)(ip - base);
const U32 lowLimit = (ctx->lowLimit + MAX_DISTANCE > current) ? ctx->lowLimit : current - (MAX_DISTANCE - 1);
- const BYTE* const dictBase = ctx->dictBase;
- const BYTE* match;
+ const U8* const dictBase = ctx->dictBase;
+ const U8* match;
int nbAttempts = ctx->searchNum;
int mnum = 0;
U16 *ptr0, *ptr1, delta0, delta1;
@@ -2332,7 +2332,7 @@ FORCE_INLINE int LZ4HC_BinTree_InsertAndGetAllMatches (
match = base + matchIndex;
matchLength = LZ4_count(ip, match, iHighLimit);
} else {
- const BYTE* vLimit = ip + (dictLimit - matchIndex);
+ const U8* vLimit = ip + (dictLimit - matchIndex);
match = dictBase + matchIndex;
if (vLimit > iHighLimit) vLimit = iHighLimit;
matchLength = LZ4_count(ip, match, vLimit);
@@ -2382,9 +2382,9 @@ FORCE_INLINE int LZ4HC_BinTree_InsertAndGetAllMatches (
}
-FORCE_INLINE void LZ4HC_updateBinTree(LZ4HC_CCtx_internal* ctx, const BYTE* const ip, const BYTE* const iHighLimit)
+FORCE_INLINE void LZ4HC_updateBinTree(LZ4HC_CCtx_internal* ctx, const U8* const ip, const U8* const iHighLimit)
{
- const BYTE* const base = ctx->base;
+ const U8* const base = ctx->base;
const U32 target = (U32)(ip - base);
U32 idx = ctx->nextToUpdate;
while(idx < target)
@@ -2395,7 +2395,7 @@ FORCE_INLINE void LZ4HC_updateBinTree(LZ4HC_CCtx_internal* ctx, const BYTE* cons
/** Tree updater, providing best match */
FORCE_INLINE int LZ4HC_BinTree_GetAllMatches (
LZ4HC_CCtx_internal* ctx,
- const BYTE* const ip, const BYTE* const iHighLimit,
+ const U8* const ip, const U8* const iHighLimit,
size_t best_mlen, LZ4HC_match_t* matches, const int fullUpdate)
{
int mnum = 0;
@@ -2416,7 +2416,7 @@ FORCE_INLINE int LZ4HC_BinTree_GetAllMatches (
opt[pos].price = (int)cost; \
}
-FORCE_INLINE int LZ4HC_encodeSequence ( const BYTE** ip, BYTE** op, const BYTE** anchor, int matchLength, const BYTE* const match, limitedOutput_directive limit, BYTE* oend);
+FORCE_INLINE int LZ4HC_encodeSequence ( const U8** ip, U8** op, const U8** anchor, int matchLength, const U8* const match, limitedOutput_directive limit, U8* oend);
static int LZ4HC_compress_optimal (
LZ4HC_CCtx_internal* ctx,
@@ -2432,13 +2432,13 @@ static int LZ4HC_compress_optimal (
LZ4HC_optimal_t opt[LZ4_OPT_NUM + 1]; /* this uses a bit too much stack memory to my taste ... */
LZ4HC_match_t matches[LZ4_OPT_NUM + 1];
- const BYTE* ip = (const BYTE*) source;
- const BYTE* anchor = ip;
- const BYTE* const iend = ip + inputSize;
- const BYTE* const mflimit = iend - MFLIMIT;
- const BYTE* const matchlimit = (iend - LASTLITERALS);
- BYTE* op = (BYTE*) dest;
- BYTE* const oend = op + maxOutputSize;
+ const U8* ip = (const U8*) source;
+ const U8* anchor = ip;
+ const U8* const iend = ip + inputSize;
+ const U8* const mflimit = iend - MFLIMIT;
+ const U8* const matchlimit = (iend - LASTLITERALS);
+ U8* op = (U8*) dest;
+ U8* const oend = op + maxOutputSize;
/* init */
if (sufficient_len >= LZ4_OPT_NUM) sufficient_len = LZ4_OPT_NUM-1;
@@ -2479,7 +2479,7 @@ static int LZ4HC_compress_optimal (
/* check further positions */
opt[0].mlen = opt[1].mlen = 1;
for (cur = 1; cur <= last_pos; cur++) {
- const BYTE* const curPtr = ip + cur;
+ const U8* const curPtr = ip + cur;
/* establish baseline price if cur is literal */
{ size_t price, litlen;
@@ -2567,8 +2567,8 @@ encode: /* cur, last_pos, best_mlen, best_off must be set */
/* Encode Last Literals */
{ int lastRun = (int)(iend - anchor);
if ((limit) && (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) return 0; /* Check output limit */
- if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; }
- else *op++ = (BYTE)(lastRun<<ML_BITS);
+ if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (U8) lastRun; }
+ else *op++ = (U8)(lastRun<<ML_BITS);
memcpy(op, anchor, iend - anchor);
op += iend-anchor;
}
@@ -2636,7 +2636,7 @@ encode: /* cur, last_pos, best_mlen, best_off must be set */
/**************************************
* HC Compression
**************************************/
-static void LZ4HC_init (LZ4HC_CCtx_internal* hc4, const BYTE* start)
+static void LZ4HC_init (LZ4HC_CCtx_internal* hc4, const U8* start)
{
MEM_INIT((void*)hc4->hashTable, 0, sizeof(hc4->hashTable));
MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable));
@@ -2650,11 +2650,11 @@ static void LZ4HC_init (LZ4HC_CCtx_internal* hc4, const BYTE* start)
/* Update chains up to ip (excluded) */
-FORCE_INLINE void LZ4HC_Insert (LZ4HC_CCtx_internal* hc4, const BYTE* ip)
+FORCE_INLINE void LZ4HC_Insert (LZ4HC_CCtx_internal* hc4, const U8* ip)
{
U16* const chainTable = hc4->chainTable;
U32* const hashTable = hc4->hashTable;
- const BYTE* const base = hc4->base;
+ const U8* const base = hc4->base;
U32 const target = (U32)(ip - base);
U32 idx = hc4->nextToUpdate;
@@ -2672,14 +2672,14 @@ FORCE_INLINE void LZ4HC_Insert (LZ4HC_CCtx_internal* hc4, const BYTE* ip)
FORCE_INLINE int LZ4HC_InsertAndFindBestMatch (LZ4HC_CCtx_internal* hc4, /* Index table will be updated */
- const BYTE* ip, const BYTE* const iLimit,
- const BYTE** matchpos,
+ const U8* ip, const U8* const iLimit,
+ const U8** matchpos,
const int maxNbAttempts)
{
U16* const chainTable = hc4->chainTable;
U32* const HashTable = hc4->hashTable;
- const BYTE* const base = hc4->base;
- const BYTE* const dictBase = hc4->dictBase;
+ const U8* const base = hc4->base;
+ const U8* const dictBase = hc4->dictBase;
const U32 dictLimit = hc4->dictLimit;
const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1);
U32 matchIndex;
@@ -2693,7 +2693,7 @@ FORCE_INLINE int LZ4HC_InsertAndFindBestMatch (LZ4HC_CCtx_internal* hc4, /* In
while ((matchIndex>=lowLimit) && (nbAttempts)) {
nbAttempts--;
if (matchIndex >= dictLimit) {
- const BYTE* const match = base + matchIndex;
+ const U8* const match = base + matchIndex;
if (*(match+ml) == *(ip+ml)
&& (LZ4_read32(match) == LZ4_read32(ip)))
{
@@ -2701,10 +2701,10 @@ FORCE_INLINE int LZ4HC_InsertAndFindBestMatch (LZ4HC_CCtx_internal* hc4, /* In
if (mlt > ml) { ml = mlt; *matchpos = match; }
}
} else {
- const BYTE* const match = dictBase + matchIndex;
+ const U8* const match = dictBase + matchIndex;
if (LZ4_read32(match) == LZ4_read32(ip)) {
size_t mlt;
- const BYTE* vLimit = ip + (dictLimit - matchIndex);
+ const U8* vLimit = ip + (dictLimit - matchIndex);
if (vLimit > iLimit) vLimit = iLimit;
mlt = LZ4_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;
if ((ip+mlt == vLimit) && (vLimit < iLimit))
@@ -2721,21 +2721,21 @@ FORCE_INLINE int LZ4HC_InsertAndFindBestMatch (LZ4HC_CCtx_internal* hc4, /* In
FORCE_INLINE int LZ4HC_InsertAndGetWiderMatch (
LZ4HC_CCtx_internal* hc4,
- const BYTE* const ip,
- const BYTE* const iLowLimit,
- const BYTE* const iHighLimit,
+ const U8* const ip,
+ const U8* const iLowLimit,
+ const U8* const iHighLimit,
int longest,
- const BYTE** matchpos,
- const BYTE** startpos,
+ const U8** matchpos,
+ const U8** startpos,
const int maxNbAttempts)
{
U16* const chainTable = hc4->chainTable;
U32* const HashTable = hc4->hashTable;
- const BYTE* const base = hc4->base;
+ const U8* const base = hc4->base;
const U32 dictLimit = hc4->dictLimit;
- const BYTE* const lowPrefixPtr = base + dictLimit;
+ const U8* const lowPrefixPtr = base + dictLimit;
const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1);
- const BYTE* const dictBase = hc4->dictBase;
+ const U8* const dictBase = hc4->dictBase;
U32 matchIndex;
int nbAttempts = maxNbAttempts;
int delta = (int)(ip-iLowLimit);
@@ -2748,7 +2748,7 @@ FORCE_INLINE int LZ4HC_InsertAndGetWiderMatch (
while ((matchIndex>=lowLimit) && (nbAttempts)) {
nbAttempts--;
if (matchIndex >= dictLimit) {
- const BYTE* matchPtr = base + matchIndex;
+ const U8* matchPtr = base + matchIndex;
if (*(iLowLimit + longest) == *(matchPtr - delta + longest)) {
if (LZ4_read32(matchPtr) == LZ4_read32(ip)) {
int mlt = MINMATCH + LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit);
@@ -2767,11 +2767,11 @@ FORCE_INLINE int LZ4HC_InsertAndGetWiderMatch (
*startpos = ip+back;
} } }
} else {
- const BYTE* const matchPtr = dictBase + matchIndex;
+ const U8* const matchPtr = dictBase + matchIndex;
if (LZ4_read32(matchPtr) == LZ4_read32(ip)) {
size_t mlt;
int back=0;
- const BYTE* vLimit = ip + (dictLimit - matchIndex);
+ const U8* vLimit = ip + (dictLimit - matchIndex);
if (vLimit > iHighLimit) vLimit = iHighLimit;
mlt = LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;
if ((ip+mlt == vLimit) && (vLimit < iHighLimit))
@@ -2798,10 +2798,10 @@ static unsigned debug = 0;
/* LZ4HC_encodeSequence() :
* @return : 0 if ok,
* 1 if buffer issue detected */
-FORCE_INLINE int LZ4HC_encodeSequence ( const BYTE** ip, BYTE** op, const BYTE** anchor, int matchLength, const BYTE* const match, limitedOutput_directive limit, BYTE* oend)
+FORCE_INLINE int LZ4HC_encodeSequence ( const U8** ip, U8** op, const U8** anchor, int matchLength, const U8* const match, limitedOutput_directive limit, U8* oend)
{
size_t length;
- BYTE* token;
+ U8* token;
#if LZ4HC_DEBUG
if (debug) printf("literal : %u -- match : %u -- offset : %u\n", (U32)(*ip - *anchor), (U32)matchLength, (U32)(*ip-match));
@@ -2815,9 +2815,9 @@ FORCE_INLINE int LZ4HC_encodeSequence ( const BYTE** ip, BYTE** op, const BYTE**
size_t len = length - RUN_MASK;
*token = (RUN_MASK << ML_BITS);
for(; len >= 255 ; len -= 255) *(*op)++ = 255;
- *(*op)++ = (BYTE)len;
+ *(*op)++ = (U8)len;
} else {
- *token = (BYTE)(length << ML_BITS);
+ *token = (U8)(length << ML_BITS);
}
/* Copy Literals */
@@ -2835,9 +2835,9 @@ FORCE_INLINE int LZ4HC_encodeSequence ( const BYTE** ip, BYTE** op, const BYTE**
length -= ML_MASK;
for(; length >= 510 ; length -= 510) { *(*op)++ = 255; *(*op)++ = 255; }
if (length >= 255) { length -= 255; *(*op)++ = 255; }
- *(*op)++ = (BYTE)length;
+ *(*op)++ = (U8)length;
} else {
- *token += (BYTE)(length);
+ *token += (U8)(length);
}
/* Prepare next loop */
@@ -2862,24 +2862,24 @@ static int LZ4HC_compress_hashChain (
{
const int inputSize = *srcSizePtr;
- const BYTE* ip = (const BYTE*) source;
- const BYTE* anchor = ip;
- const BYTE* const iend = ip + inputSize;
- const BYTE* const mflimit = iend - MFLIMIT;
- const BYTE* const matchlimit = (iend - LASTLITERALS);
+ const U8* ip = (const U8*) source;
+ const U8* anchor = ip;
+ const U8* const iend = ip + inputSize;
+ const U8* const mflimit = iend - MFLIMIT;
+ const U8* const matchlimit = (iend - LASTLITERALS);
- BYTE* optr = (BYTE*) dest;
- BYTE* op = (BYTE*) dest;
- BYTE* oend = op + maxOutputSize;
+ U8* optr = (U8*) dest;
+ U8* op = (U8*) dest;
+ U8* oend = op + maxOutputSize;
int ml, ml2, ml3, ml0;
- const BYTE* ref = NULL;
- const BYTE* start2 = NULL;
- const BYTE* ref2 = NULL;
- const BYTE* start3 = NULL;
- const BYTE* ref3 = NULL;
- const BYTE* start0;
- const BYTE* ref0;
+ const U8* ref = NULL;
+ const U8* start2 = NULL;
+ const U8* ref2 = NULL;
+ const U8* start3 = NULL;
+ const U8* ref3 = NULL;
+ const U8* start0;
+ const U8* ref0;
/* init */
*srcSizePtr = 0;
@@ -3049,9 +3049,9 @@ _last_literals:
size_t accumulator = lastRunSize - RUN_MASK;
*op++ = (RUN_MASK << ML_BITS);
for(; accumulator >= 255 ; accumulator -= 255) *op++ = 255;
- *op++ = (BYTE) accumulator;
+ *op++ = (U8) accumulator;
} else {
- *op++ = (BYTE)(lastRunSize << ML_BITS);
+ *op++ = (U8)(lastRunSize << ML_BITS);
}
memcpy(op, anchor, lastRunSize);
op += lastRunSize;
@@ -3113,7 +3113,7 @@ int LZ4_compress_HC_extStateHC (void* state, const char* src, char* dst, int src
{
LZ4HC_CCtx_internal* const ctx = &((LZ4_streamHC_t*)state)->internal_donotuse;
if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0; /* Error : state is not aligned for pointers (32 or 64 bits) */
- LZ4HC_init (ctx, (const BYTE*)src);
+ LZ4HC_init (ctx, (const U8*)src);
if (dstCapacity < LZ4_compressBound(srcSize))
return LZ4HC_compress_generic (ctx, src, dst, &srcSize, dstCapacity, compressionLevel, limitedOutput);
else
@@ -3141,7 +3141,7 @@ int LZ4_compress_HC(const char* src, char* dst, int srcSize, int dstCapacity, in
int LZ4_compress_HC_destSize(void* LZ4HC_Data, const char* source, char* dest, int* sourceSizePtr, int targetDestSize, int cLevel)
{
LZ4HC_CCtx_internal* const ctx = &((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse;
- LZ4HC_init(ctx, (const BYTE*) source);
+ LZ4HC_init(ctx, (const U8*) source);
return LZ4HC_compress_generic(ctx, source, dest, sourceSizePtr, targetDestSize, cLevel, limitedDestSize);
}
@@ -3172,8 +3172,8 @@ int LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, const char* dictionary, int
dictionary += dictSize - 64 KB;
dictSize = 64 KB;
}
- LZ4HC_init (ctxPtr, (const BYTE*)dictionary);
- ctxPtr->end = (const BYTE*)dictionary + dictSize;
+ LZ4HC_init (ctxPtr, (const U8*)dictionary);
+ ctxPtr->end = (const U8*)dictionary + dictSize;
if (ctxPtr->compressionLevel >= LZ4HC_CLEVEL_OPT_MIN)
LZ4HC_updateBinTree(ctxPtr, ctxPtr->end - MFLIMIT, ctxPtr->end - LASTLITERALS);
else
@@ -3184,7 +3184,7 @@ int LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, const char* dictionary, int
/* compression */
-static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBlock)
+static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const U8* newBlock)
{
if (ctxPtr->compressionLevel >= LZ4HC_CLEVEL_OPT_MIN)
LZ4HC_updateBinTree(ctxPtr, ctxPtr->end - MFLIMIT, ctxPtr->end - LASTLITERALS);
@@ -3207,7 +3207,7 @@ static int LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr,
{
LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse;
/* auto-init if forgotten */
- if (ctxPtr->base == NULL) LZ4HC_init (ctxPtr, (const BYTE*) src);
+ if (ctxPtr->base == NULL) LZ4HC_init (ctxPtr, (const U8*) src);
/* Check overflow */
if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB) {
@@ -3217,13 +3217,13 @@ static int LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr,
}
/* Check if blocks follow each other */
- if ((const BYTE*)src != ctxPtr->end) LZ4HC_setExternalDict(ctxPtr, (const BYTE*)src);
+ if ((const U8*)src != ctxPtr->end) LZ4HC_setExternalDict(ctxPtr, (const U8*)src);
/* Check overlapping input/dictionary space */
- { const BYTE* sourceEnd = (const BYTE*) src + *srcSizePtr;
- const BYTE* const dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;
- const BYTE* const dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit;
- if ((sourceEnd > dictBegin) && ((const BYTE*)src < dictEnd)) {
+ { const U8* sourceEnd = (const U8*) src + *srcSizePtr;
+ const U8* const dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;
+ const U8* const dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit;
+ if ((sourceEnd > dictBegin) && ((const U8*)src < dictEnd)) {
if (sourceEnd > dictEnd) sourceEnd = dictEnd;
ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);
if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit;
@@ -3244,7 +3244,7 @@ int LZ4_compress_HC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* src,
int LZ4_compress_HC_continue_destSize (LZ4_streamHC_t* LZ4_streamHCPtr, const char* src, char* dst, int* srcSizePtr, int targetDestSize)
{
LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse;
- if (ctxPtr->compressionLevel >= LZ4HC_CLEVEL_OPT_MIN) LZ4HC_init(ctxPtr, (const BYTE*)src); /* not compatible with btopt implementation */
+ if (ctxPtr->compressionLevel >= LZ4HC_CLEVEL_OPT_MIN) LZ4HC_init(ctxPtr, (const U8*)src); /* not compatible with btopt implementation */
return LZ4_compressHC_continue_generic(LZ4_streamHCPtr, src, dst, srcSizePtr, targetDestSize, limitedDestSize);
}
@@ -3261,7 +3261,7 @@ int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictS
if (dictSize > prefixSize) dictSize = prefixSize;
memmove(safeBuffer, streamPtr->end - dictSize, dictSize);
{ U32 const endIndex = (U32)(streamPtr->end - streamPtr->base);
- streamPtr->end = (const BYTE*)safeBuffer + dictSize;
+ streamPtr->end = (const U8*)safeBuffer + dictSize;
streamPtr->base = streamPtr->end - endIndex;
streamPtr->dictLimit = endIndex - dictSize;
streamPtr->lowLimit = endIndex - dictSize;
@@ -3295,8 +3295,8 @@ int LZ4_resetStreamStateHC(void* state, char* inputBuffer)
{
LZ4HC_CCtx_internal *ctx = &((LZ4_streamHC_t*)state)->internal_donotuse;
if ((((size_t)state) & (sizeof(void*)-1)) != 0) return 1; /* Error : pointer is not aligned for pointer (32 or 64 bits) */
- LZ4HC_init(ctx, (const BYTE*)inputBuffer);
- ctx->inputBuffer = (BYTE*)inputBuffer;
+ LZ4HC_init(ctx, (const U8*)inputBuffer);
+ ctx->inputBuffer = (U8*)inputBuffer;
return 0;
}
@@ -3304,8 +3304,8 @@ void* LZ4_createHC (char* inputBuffer)
{
LZ4_streamHC_t* hc4 = (LZ4_streamHC_t*)ALLOCATOR(1, sizeof(LZ4_streamHC_t));
if (hc4 == NULL) return NULL; /* not enough memory */
- LZ4HC_init (&hc4->internal_donotuse, (const BYTE*)inputBuffer);
- hc4->internal_donotuse.inputBuffer = (BYTE*)inputBuffer;
+ LZ4HC_init (&hc4->internal_donotuse, (const U8*)inputBuffer);
+ hc4->internal_donotuse.inputBuffer = (U8*)inputBuffer;
return hc4;
}
diff --git a/tools/rasm/lzsa-master/src/dictionary.c b/tools/rasm/lzsa-master/src/dictionary.c
new file mode 100644
index 0000000..fbc4f52
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/dictionary.c
@@ -0,0 +1,101 @@
+/*
+ * dictionary.c - dictionary implementation
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "format.h"
+#include "lib.h"
+
+/**
+ * Load dictionary contents
+ *
+ * @param pszDictionaryFilename name of dictionary file, or NULL for none
+ * @param ppDictionaryData pointer to returned dictionary contents, or NULL for none
+ * @param pDictionaryDataSize pointer to returned size of dictionary contents, or 0
+ *
+ * @return LZSA_OK for success, or an error value from lzsa_status_t
+ */
+int lzsa_dictionary_load(const char *pszDictionaryFilename, void **ppDictionaryData, int *pDictionaryDataSize) {
+ unsigned char *pDictionaryData = NULL;
+ int nDictionaryDataSize = 0;
+
+ if (pszDictionaryFilename) {
+ pDictionaryData = (unsigned char *)malloc(BLOCK_SIZE);
+ if (!pDictionaryData) {
+ return LZSA_ERROR_MEMORY;
+ }
+
+ FILE *pDictionaryFile = fopen(pszDictionaryFilename, "rb");
+ if (!pDictionaryFile) {
+ free(pDictionaryData);
+ pDictionaryData = NULL;
+ return LZSA_ERROR_DICTIONARY;
+ }
+
+ fseek(pDictionaryFile, 0, SEEK_END);
+#ifdef _WIN32
+ __int64 nDictionaryFileSize = _ftelli64(pDictionaryFile);
+#else
+ off_t nDictionaryFileSize = ftello(pDictionaryFile);
+#endif
+ if (nDictionaryFileSize > BLOCK_SIZE) {
+ /* Use the last BLOCK_SIZE bytes of the dictionary */
+ fseek(pDictionaryFile, -BLOCK_SIZE, SEEK_END);
+ }
+ else {
+ fseek(pDictionaryFile, 0, SEEK_SET);
+ }
+
+ nDictionaryDataSize = (int)fread(pDictionaryData, 1, BLOCK_SIZE, pDictionaryFile);
+ if (nDictionaryDataSize < 0)
+ nDictionaryDataSize = 0;
+
+ fclose(pDictionaryFile);
+ pDictionaryFile = NULL;
+ }
+
+ *ppDictionaryData = pDictionaryData;
+ *pDictionaryDataSize = nDictionaryDataSize;
+ return LZSA_OK;
+}
+
+/**
+ * Free dictionary contents
+ *
+ * @param ppDictionaryData pointer to pointer to dictionary contents
+ */
+void lzsa_dictionary_free(void **ppDictionaryData) {
+ if (*ppDictionaryData) {
+ free(*ppDictionaryData);
+ *ppDictionaryData = NULL;
+ }
+}
diff --git a/tools/rasm/lzsa-master/src/dictionary.h b/tools/rasm/lzsa-master/src/dictionary.h
new file mode 100644
index 0000000..a363564
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/dictionary.h
@@ -0,0 +1,64 @@
+/*
+ * dictionary.h - dictionary definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#ifndef _DICTIONARY_H
+#define _DICTIONARY_H
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Load dictionary contents
+ *
+ * @param pszDictionaryFilename name of dictionary file, or NULL for none
+ * @param ppDictionaryData pointer to returned dictionary contents, or NULL for none
+ * @param pDictionaryDataSize pointer to returned size of dictionary contents, or 0
+ *
+ * @return LZSA_OK for success, or an error value from lzsa_status_t
+ */
+int lzsa_dictionary_load(const char *pszDictionaryFilename, void **ppDictionaryData, int *pDictionaryDataSize);
+
+/**
+ * Free dictionary contents
+ *
+ * @param ppDictionaryData pointer to pointer to dictionary contents
+ */
+void lzsa_dictionary_free(void **ppDictionaryData);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DICTIONARY_H */
diff --git a/tools/rasm/lzsa-master/src/expand_block_v1.c b/tools/rasm/lzsa-master/src/expand_block_v1.c
new file mode 100644
index 0000000..c248fb3
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/expand_block_v1.c
@@ -0,0 +1,224 @@
+/*
+ * expand_block_v1.c - LZSA1 block decompressor implementation
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "format.h"
+#include "expand_block_v1.h"
+
+#ifdef _MSC_VER
+#define FORCE_INLINE __forceinline
+#else /* _MSC_VER */
+#define FORCE_INLINE __attribute__((always_inline))
+#endif /* _MSC_VER */
+
+static inline FORCE_INLINE int lzsa_build_literals_len_v1(const unsigned char **ppInBlock, const unsigned char *pInBlockEnd, unsigned int *nLiterals) {
+ unsigned int nByte;
+ const unsigned char *pInBlock = *ppInBlock;
+
+ if (pInBlock < pInBlockEnd) {
+ nByte = *pInBlock++;
+ (*nLiterals) += nByte;
+
+ if (nByte == 250) {
+ if (pInBlock < pInBlockEnd) {
+ (*nLiterals) = 256 + ((unsigned int)*pInBlock++);
+ }
+ else {
+ return -1;
+ }
+ }
+ else if (nByte == 249) {
+ if ((pInBlock + 1) < pInBlockEnd) {
+ (*nLiterals) = ((unsigned int)*pInBlock++);
+ (*nLiterals) |= (((unsigned int)*pInBlock++) << 8);
+ }
+ else {
+ return -1;
+ }
+ }
+
+ *ppInBlock = pInBlock;
+ return 0;
+ }
+ else {
+ return -1;
+ }
+}
+
+static inline FORCE_INLINE int lzsa_build_match_len_v1(const unsigned char **ppInBlock, const unsigned char *pInBlockEnd, unsigned int *nMatchLen) {
+ unsigned int nByte;
+ const unsigned char *pInBlock = *ppInBlock;
+
+ if (pInBlock < pInBlockEnd) {
+ nByte = *pInBlock++;
+ (*nMatchLen) += nByte;
+
+ if (nByte == 239) {
+ if (pInBlock < pInBlockEnd) {
+ (*nMatchLen) = 256 + ((unsigned int)*pInBlock++);
+ }
+ else {
+ return -1;
+ }
+ }
+ else if (nByte == 238) {
+ if ((pInBlock + 1) < pInBlockEnd) {
+ (*nMatchLen) = ((unsigned int)*pInBlock++);
+ (*nMatchLen) |= (((unsigned int)*pInBlock++) << 8);
+ }
+ else {
+ return -1;
+ }
+ }
+
+ *ppInBlock = pInBlock;
+ return 0;
+ }
+ else {
+ return -1;
+ }
+}
+
+/**
+ * Decompress one LZSA1 data block
+ *
+ * @param pInBlock pointer to compressed data
+ * @param nBlockSize size of compressed data, in bytes
+ * @param pOutData pointer to output decompression buffer (previously decompressed bytes + room for decompressing this block)
+ * @param nOutDataOffset starting index of where to store decompressed bytes in output buffer (and size of previously decompressed bytes)
+ * @param nBlockMaxSize total size of output decompression buffer, in bytes
+ *
+ * @return size of decompressed data in bytes, or -1 for error
+ */
+int lzsa_decompressor_expand_block_v1(const unsigned char *pInBlock, int nBlockSize, unsigned char *pOutData, int nOutDataOffset, int nBlockMaxSize) {
+ const unsigned char *pInBlockEnd = pInBlock + nBlockSize;
+ unsigned char *pCurOutData = pOutData + nOutDataOffset;
+ const unsigned char *pOutDataEnd = pCurOutData + nBlockMaxSize;
+ const unsigned char *pOutDataFastEnd = pOutDataEnd - 18;
+
+ while (pInBlock < pInBlockEnd) {
+ const unsigned char token = *pInBlock++;
+ unsigned int nLiterals = (unsigned int)((token & 0x70) >> 4);
+
+ if (nLiterals != LITERALS_RUN_LEN_V1 && (pInBlock + 8) <= pInBlockEnd && pCurOutData < pOutDataFastEnd) {
+ memcpy(pCurOutData, pInBlock, 8);
+ pInBlock += nLiterals;
+ pCurOutData += nLiterals;
+ }
+ else {
+ if (nLiterals == LITERALS_RUN_LEN_V1) {
+ if (lzsa_build_literals_len_v1(&pInBlock, pInBlockEnd, &nLiterals))
+ return -1;
+ }
+
+ if (nLiterals != 0) {
+ if ((pInBlock + nLiterals) <= pInBlockEnd &&
+ (pCurOutData + nLiterals) <= pOutDataEnd) {
+ memcpy(pCurOutData, pInBlock, nLiterals);
+ pInBlock += nLiterals;
+ pCurOutData += nLiterals;
+ }
+ else {
+ return -1;
+ }
+ }
+ }
+
+ if ((pInBlock + 1) < pInBlockEnd) { /* The last token in the block does not include match information */
+ unsigned int nMatchOffset;
+
+ nMatchOffset = ((unsigned int)(*pInBlock++)) ^ 0xff;
+ if (token & 0x80) {
+ nMatchOffset |= (((unsigned int)(*pInBlock++)) << 8) ^ 0xff00;
+ }
+ nMatchOffset++;
+
+ const unsigned char *pSrc = pCurOutData - nMatchOffset;
+ if (pSrc >= pOutData) {
+ unsigned int nMatchLen = (unsigned int)(token & 0x0f);
+ if (nMatchLen != MATCH_RUN_LEN_V1 && nMatchOffset >= 8 && pCurOutData < pOutDataFastEnd && (pSrc + 18) <= pOutDataEnd) {
+ memcpy(pCurOutData, pSrc, 8);
+ memcpy(pCurOutData + 8, pSrc + 8, 8);
+ memcpy(pCurOutData + 16, pSrc + 16, 2);
+ pCurOutData += (MIN_MATCH_SIZE_V1 + nMatchLen);
+ }
+ else {
+ nMatchLen += MIN_MATCH_SIZE_V1;
+ if (nMatchLen == (MATCH_RUN_LEN_V1 + MIN_MATCH_SIZE_V1)) {
+ if (lzsa_build_match_len_v1(&pInBlock, pInBlockEnd, &nMatchLen))
+ return -1;
+ if (nMatchLen == 0)
+ break;
+ }
+
+ if ((pSrc + nMatchLen) <= pOutDataEnd) {
+ if ((pCurOutData + nMatchLen) <= pOutDataEnd) {
+ /* Do a deterministic, left to right byte copy instead of memcpy() so as to handle overlaps */
+
+ if (nMatchOffset >= 16 && (pCurOutData + nMatchLen) < (pOutDataFastEnd - 15)) {
+ const unsigned char *pCopySrc = pSrc;
+ unsigned char *pCopyDst = pCurOutData;
+ const unsigned char *pCopyEndDst = pCurOutData + nMatchLen;
+
+ do {
+ memcpy(pCopyDst, pCopySrc, 16);
+ pCopySrc += 16;
+ pCopyDst += 16;
+ } while (pCopyDst < pCopyEndDst);
+
+ pCurOutData += nMatchLen;
+ }
+ else {
+ while (nMatchLen) {
+ *pCurOutData++ = *pSrc++;
+ nMatchLen--;
+ }
+ }
+ }
+ else {
+ return -1;
+ }
+ }
+ else {
+ return -1;
+ }
+ }
+ }
+ else {
+ return -1;
+ }
+ }
+ }
+
+ return (int)(pCurOutData - (pOutData + nOutDataOffset));
+}
diff --git a/tools/rasm/lzsa-master/src/expand_block_v1.h b/tools/rasm/lzsa-master/src/expand_block_v1.h
new file mode 100644
index 0000000..a1d5651
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/expand_block_v1.h
@@ -0,0 +1,49 @@
+/*
+ * expand_block_v1.h - LZSA1 block decompressor definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#ifndef _EXPAND_BLOCK_V1_H
+#define _EXPAND_BLOCK_V1_H
+
+/**
+ * Decompress one LZSA1 data block
+ *
+ * @param pInBlock pointer to compressed data
+ * @param nBlockSize size of compressed data, in bytes
+ * @param pOutData pointer to output decompression buffer (previously decompressed bytes + room for decompressing this block)
+ * @param nOutDataOffset starting index of where to store decompressed bytes in output buffer (and size of previously decompressed bytes)
+ * @param nBlockMaxSize total size of output decompression buffer, in bytes
+ *
+ * @return size of decompressed data in bytes, or -1 for error
+ */
+int lzsa_decompressor_expand_block_v1(const unsigned char *pInBlock, int nBlockSize, unsigned char *pOutData, int nOutDataOffset, int nBlockMaxSize);
+
+#endif /* _EXPAND_BLOCK_V1_H */
diff --git a/tools/rasm/lzsa-master/src/expand_block_v2.c b/tools/rasm/lzsa-master/src/expand_block_v2.c
new file mode 100644
index 0000000..e024b4c
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/expand_block_v2.c
@@ -0,0 +1,253 @@
+/*
+ * expand_block_v2.c - LZSA2 block decompressor implementation
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "format.h"
+#include "expand_block_v2.h"
+
+#ifdef _MSC_VER
+#define FORCE_INLINE __forceinline
+#else /* _MSC_VER */
+#define FORCE_INLINE __attribute__((always_inline))
+#endif /* _MSC_VER */
+
+static inline FORCE_INLINE unsigned int lzsa_get_nibble_v2(const unsigned char **ppInBlock, const unsigned char *pInBlockEnd, int *nCurNibbles, unsigned char *nibbles, unsigned int *nValue) {
+ if ((*nCurNibbles ^= 1) != 0) {
+ const unsigned char *pInBlock = *ppInBlock;
+ if (pInBlock < pInBlockEnd) {
+ (*nibbles) = *pInBlock++;
+ *ppInBlock = pInBlock;
+ (*nValue) = ((unsigned int)((*nibbles) & 0xf0)) >> 4;
+ return 0;
+ }
+ else {
+ return -1;
+ }
+ }
+
+ (*nValue) = (unsigned int)((*nibbles) & 0x0f);
+ return 0;
+}
+
+static inline FORCE_INLINE int lzsa_build_len_v2(const unsigned char **ppInBlock, const unsigned char *pInBlockEnd, int *nCurNibbles, unsigned char *nibbles, unsigned int *nLength) {
+ unsigned int nValue;
+
+ if (!lzsa_get_nibble_v2(ppInBlock, pInBlockEnd, nCurNibbles, nibbles, &nValue)) {
+ (*nLength) += nValue;
+
+ if (nValue == 15) {
+ const unsigned char *pInBlock = *ppInBlock;
+
+ if (pInBlock < pInBlockEnd) {
+ (*nLength) += ((unsigned int)*pInBlock++);
+
+ if ((*nLength) == 257) {
+ if ((pInBlock + 1) < pInBlockEnd) {
+ (*nLength) = ((unsigned int)*pInBlock++);
+ (*nLength) |= (((unsigned int)*pInBlock++) << 8);
+ }
+ else {
+ return -1;
+ }
+ }
+ else if ((*nLength) == 256) {
+ (*nLength) = 0;
+ }
+ }
+ else {
+ return -1;
+ }
+
+ *ppInBlock = pInBlock;
+ }
+
+ return 0;
+ }
+ else {
+ return -1;
+ }
+}
+
+/**
+ * Decompress one LZSA2 data block
+ *
+ * @param pInBlock pointer to compressed data
+ * @param nBlockSize size of compressed data, in bytes
+ * @param pOutData pointer to output decompression buffer (previously decompressed bytes + room for decompressing this block)
+ * @param nOutDataOffset starting index of where to store decompressed bytes in output buffer (and size of previously decompressed bytes)
+ * @param nBlockMaxSize total size of output decompression buffer, in bytes
+ *
+ * @return size of decompressed data in bytes, or -1 for error
+ */
+int lzsa_decompressor_expand_block_v2(const unsigned char *pInBlock, int nBlockSize, unsigned char *pOutData, int nOutDataOffset, int nBlockMaxSize) {
+ const unsigned char *pInBlockEnd = pInBlock + nBlockSize;
+ unsigned char *pCurOutData = pOutData + nOutDataOffset;
+ const unsigned char *pOutDataEnd = pCurOutData + nBlockMaxSize;
+ const unsigned char *pOutDataFastEnd = pOutDataEnd - 20;
+ int nCurNibbles = 0;
+ unsigned char nibbles;
+ int nMatchOffset = 0;
+
+ while (pInBlock < pInBlockEnd) {
+ const unsigned char token = *pInBlock++;
+ unsigned int nLiterals = (unsigned int)((token & 0x18) >> 3);
+
+ if (nLiterals != LITERALS_RUN_LEN_V2 && (pInBlock + 4) <= pInBlockEnd && pCurOutData < pOutDataFastEnd) {
+ memcpy(pCurOutData, pInBlock, 4);
+ pInBlock += nLiterals;
+ pCurOutData += nLiterals;
+ }
+ else {
+ if (nLiterals == LITERALS_RUN_LEN_V2) {
+ if (lzsa_build_len_v2(&pInBlock, pInBlockEnd, &nCurNibbles, &nibbles, &nLiterals))
+ return -1;
+ }
+
+ if (nLiterals != 0) {
+ if ((pInBlock + nLiterals) <= pInBlockEnd &&
+ (pCurOutData + nLiterals) <= pOutDataEnd) {
+ memcpy(pCurOutData, pInBlock, nLiterals);
+ pInBlock += nLiterals;
+ pCurOutData += nLiterals;
+ }
+ else {
+ return -1;
+ }
+ }
+ }
+
+ if (pInBlock < pInBlockEnd) { /* The last token in the block does not include match information */
+ unsigned char nOffsetMode = token & 0xc0;
+ unsigned int nValue;
+
+ switch (nOffsetMode) {
+ case 0x00:
+ /* 5 bit offset */
+ if (lzsa_get_nibble_v2(&pInBlock, pInBlockEnd, &nCurNibbles, &nibbles, &nValue))
+ return -1;
+ nMatchOffset = nValue << 1;
+ nMatchOffset |= ((token & 0x20) >> 5);
+ nMatchOffset ^= 0x1e;
+ nMatchOffset++;
+ break;
+
+ case 0x40:
+ /* 9 bit offset */
+ nMatchOffset = (unsigned int)(*pInBlock++);
+ nMatchOffset |= (((unsigned int)(token & 0x20)) << 3);
+ nMatchOffset ^= 0x0ff;
+ nMatchOffset++;
+ break;
+
+ case 0x80:
+ /* 13 bit offset */
+ if (lzsa_get_nibble_v2(&pInBlock, pInBlockEnd, &nCurNibbles, &nibbles, &nValue))
+ return -1;
+ nMatchOffset = (unsigned int)(*pInBlock++);
+ nMatchOffset |= (nValue << 9);
+ nMatchOffset |= (((unsigned int)(token & 0x20)) << 3);
+ nMatchOffset ^= 0x1eff;
+ nMatchOffset += (512 + 1);
+ break;
+
+ default:
+ /* Check if this is a 16 bit offset or a rep-match */
+ if ((token & 0x20) == 0) {
+ /* 16 bit offset */
+ nMatchOffset = (((unsigned int)(*pInBlock++)) << 8);
+ if (pInBlock >= pInBlockEnd) return -1;
+ nMatchOffset |= (unsigned int)(*pInBlock++);
+ nMatchOffset ^= 0xffff;
+ nMatchOffset++;
+ }
+ break;
+ }
+
+ const unsigned char *pSrc = pCurOutData - nMatchOffset;
+ if (pSrc >= pOutData) {
+ unsigned int nMatchLen = (unsigned int)(token & 0x07);
+ if (nMatchLen != MATCH_RUN_LEN_V2 && nMatchOffset >= 8 && pCurOutData < pOutDataFastEnd && (pSrc + 10) <= pOutDataEnd) {
+ memcpy(pCurOutData, pSrc, 8);
+ memcpy(pCurOutData + 8, pSrc + 8, 2);
+ pCurOutData += (MIN_MATCH_SIZE_V2 + nMatchLen);
+ }
+ else {
+ nMatchLen += MIN_MATCH_SIZE_V2;
+ if (nMatchLen == (MATCH_RUN_LEN_V2 + MIN_MATCH_SIZE_V2)) {
+ if (lzsa_build_len_v2(&pInBlock, pInBlockEnd, &nCurNibbles, &nibbles, &nMatchLen))
+ return -1;
+ if (nMatchLen == 0)
+ break;
+ }
+
+ if ((pSrc + nMatchLen) <= pOutDataEnd) {
+ if ((pCurOutData + nMatchLen) <= pOutDataEnd) {
+ /* Do a deterministic, left to right byte copy instead of memcpy() so as to handle overlaps */
+
+ if (nMatchOffset >= 16 && (pCurOutData + nMatchLen) < (pOutDataFastEnd - 15)) {
+ const unsigned char *pCopySrc = pSrc;
+ unsigned char *pCopyDst = pCurOutData;
+ const unsigned char *pCopyEndDst = pCurOutData + nMatchLen;
+
+ do {
+ memcpy(pCopyDst, pCopySrc, 16);
+ pCopySrc += 16;
+ pCopyDst += 16;
+ } while (pCopyDst < pCopyEndDst);
+
+ pCurOutData += nMatchLen;
+ }
+ else {
+ while (nMatchLen) {
+ *pCurOutData++ = *pSrc++;
+ nMatchLen--;
+ }
+ }
+ }
+ else {
+ return -1;
+ }
+ }
+ else {
+ return -1;
+ }
+ }
+ }
+ else {
+ return -1;
+ }
+ }
+ }
+
+ return (int)(pCurOutData - (pOutData + nOutDataOffset));
+}
diff --git a/tools/rasm/lzsa-master/src/expand_block_v2.h b/tools/rasm/lzsa-master/src/expand_block_v2.h
new file mode 100644
index 0000000..f612f7a
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/expand_block_v2.h
@@ -0,0 +1,49 @@
+/*
+ * expand_block_v2.h - LZSA2 block decompressor definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#ifndef _EXPAND_BLOCK_V2_H
+#define _EXPAND_BLOCK_V2_H
+
+/**
+ * Decompress one LZSA2 data block
+ *
+ * @param pInBlock pointer to compressed data
+ * @param nBlockSize size of compressed data, in bytes
+ * @param pOutData pointer to output decompression buffer (previously decompressed bytes + room for decompressing this block)
+ * @param nOutDataOffset starting index of where to store decompressed bytes in output buffer (and size of previously decompressed bytes)
+ * @param nBlockMaxSize total size of output decompression buffer, in bytes
+ *
+ * @return size of decompressed data in bytes, or -1 for error
+ */
+int lzsa_decompressor_expand_block_v2(const unsigned char *pInBlock, int nBlockSize, unsigned char *pOutData, int nOutDataOffset, int nBlockMaxSize);
+
+#endif /* _EXPAND_BLOCK_V2_H */
diff --git a/tools/rasm/lzsa-master/src/expand_context.c b/tools/rasm/lzsa-master/src/expand_context.c
new file mode 100644
index 0000000..b02620d
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/expand_context.c
@@ -0,0 +1,76 @@
+/*
+ * expand_context.h - decompressor context definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "expand_context.h"
+#include "expand_block_v1.h"
+#include "expand_block_v2.h"
+#include "lib.h"
+
+/**
+ * Decompress one data block
+ *
+ * @param pInBlock pointer to compressed data
+ * @param nBlockSize size of compressed data, in bytes
+ * @param pOutData pointer to output decompression buffer (previously decompressed bytes + room for decompressing this block)
+ * @param nOutDataOffset starting index of where to store decompressed bytes in output buffer (and size of previously decompressed bytes)
+ * @param nBlockMaxSize total size of output decompression buffer, in bytes
+ * @param nFormatVersion version of format to use (1-2)
+ * @param nFlags compression flags (LZSA_FLAG_xxx)
+ *
+ * @return size of decompressed data in bytes, or -1 for error
+ */
+int lzsa_decompressor_expand_block(unsigned char *pInBlock, int nBlockSize, unsigned char *pOutData, int nOutDataOffset, int nBlockMaxSize, const int nFormatVersion, const int nFlags) {
+ int nDecompressedSize;
+
+ if (nFlags & LZSA_FLAG_RAW_BACKWARD) {
+ lzsa_reverse_buffer(pInBlock, nBlockSize);
+ }
+
+ if (nFormatVersion == 1)
+ nDecompressedSize = lzsa_decompressor_expand_block_v1(pInBlock, nBlockSize, pOutData, nOutDataOffset, nBlockMaxSize);
+ else if (nFormatVersion == 2)
+ nDecompressedSize = lzsa_decompressor_expand_block_v2(pInBlock, nBlockSize, pOutData, nOutDataOffset, nBlockMaxSize);
+ else
+ nDecompressedSize = -1;
+
+ if (nDecompressedSize != -1 && (nFlags & LZSA_FLAG_RAW_BACKWARD)) {
+ lzsa_reverse_buffer(pOutData + nOutDataOffset, nDecompressedSize);
+ }
+
+ if (nFlags & LZSA_FLAG_RAW_BACKWARD) {
+ lzsa_reverse_buffer(pInBlock, nBlockSize);
+ }
+
+ return nDecompressedSize;
+}
diff --git a/tools/rasm/lzsa-master/src/expand_context.h b/tools/rasm/lzsa-master/src/expand_context.h
new file mode 100644
index 0000000..698e039
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/expand_context.h
@@ -0,0 +1,61 @@
+/*
+ * expand_context.h - decompressor context definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#ifndef _EXPAND_CONTEXT_H
+#define _EXPAND_CONTEXT_H
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Decompress one data block
+ *
+ * @param pInBlock pointer to compressed data
+ * @param nBlockSize size of compressed data, in bytes
+ * @param pOutData pointer to output decompression buffer (previously decompressed bytes + room for decompressing this block)
+ * @param nOutDataOffset starting index of where to store decompressed bytes in output buffer (and size of previously decompressed bytes)
+ * @param nBlockMaxSize total size of output decompression buffer, in bytes
+ * @param nFormatVersion version of format to use (1-2)
+ * @param nFlags compression flags (LZSA_FLAG_xxx)
+ *
+ * @return size of decompressed data in bytes, or -1 for error
+ */
+int lzsa_decompressor_expand_block(unsigned char *pInBlock, int nBlockSize, unsigned char *pOutData, int nOutDataOffset, int nBlockMaxSize, const int nFormatVersion, const int nFlags);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _EXPAND_CONTEXT_H */
diff --git a/tools/rasm/lzsa-master/src/expand_inmem.c b/tools/rasm/lzsa-master/src/expand_inmem.c
new file mode 100644
index 0000000..050bdbc
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/expand_inmem.c
@@ -0,0 +1,163 @@
+/*
+ * expand_inmem.c - in-memory decompression implementation
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "expand_inmem.h"
+#include "lib.h"
+#include "frame.h"
+
+#define BLOCK_SIZE 65536
+
+/**
+ * Get maximum decompressed size of compressed data
+ *
+ * @param pFileData compressed data
+ * @param nFileSize compressed size in bytes
+ *
+ * @return maximum decompressed size
+ */
+size_t lzsa_get_max_decompressed_size_inmem(const unsigned char *pFileData, size_t nFileSize) {
+ const unsigned char *pCurFileData = pFileData;
+ const unsigned char *pEndFileData = pCurFileData + nFileSize;
+ int nFormatVersion = 0;
+ size_t nMaxDecompressedSize = 0;
+ const int nHeaderSize = lzsa_get_header_size();
+
+ /* Check header */
+ if ((pCurFileData + nHeaderSize) > pEndFileData ||
+ lzsa_decode_header(pCurFileData, nHeaderSize, &nFormatVersion) != 0)
+ return -1;
+
+ pCurFileData += nHeaderSize;
+
+ while (pCurFileData < pEndFileData) {
+ unsigned int nBlockDataSize = 0;
+ int nIsUncompressed = 0;
+ const int nFrameSize = lzsa_get_frame_size();
+
+ /* Decode frame header */
+ if ((pCurFileData + nFrameSize) > pEndFileData ||
+ lzsa_decode_frame(pCurFileData, nFrameSize, &nBlockDataSize, &nIsUncompressed) != 0)
+ return -1;
+ pCurFileData += nFrameSize;
+
+ if (!nBlockDataSize)
+ break;
+
+ /* Add one potentially full block to the decompressed size */
+ nMaxDecompressedSize += BLOCK_SIZE;
+
+ if ((pCurFileData + nBlockDataSize) > pEndFileData)
+ return -1;
+
+ pCurFileData += nBlockDataSize;
+ }
+
+ return nMaxDecompressedSize;
+}
+
+/**
+ * Decompress data in memory
+ *
+ * @param pFileData compressed data
+ * @param pOutBuffer buffer for decompressed data
+ * @param nFileSize compressed size in bytes
+ * @param nMaxOutBufferSize maximum capacity of decompression buffer
+ * @param nFlags compression flags (LZSA_FLAG_xxx)
+ * @param pFormatVersion pointer to format version, updated if this function is successful
+ *
+ * @return actual decompressed size, or -1 for error
+ */
+size_t lzsa_decompress_inmem(unsigned char *pFileData, unsigned char *pOutBuffer, size_t nFileSize, size_t nMaxOutBufferSize, const unsigned int nFlags, int *pFormatVersion) {
+ unsigned char *pCurFileData = pFileData;
+ const unsigned char *pEndFileData = pCurFileData + nFileSize;
+ unsigned char *pCurOutBuffer = pOutBuffer;
+ const unsigned char *pEndOutBuffer = pCurOutBuffer + nMaxOutBufferSize;
+ int nPreviousBlockSize;
+ const int nHeaderSize = lzsa_get_header_size();
+
+ if (nFlags & LZSA_FLAG_RAW_BLOCK) {
+ return (size_t)lzsa_decompressor_expand_block(pFileData, (int)nFileSize, pOutBuffer, 0, (int)nMaxOutBufferSize, *pFormatVersion, nFlags);
+ }
+
+ /* Check header */
+ if ((pCurFileData + nHeaderSize) > pEndFileData ||
+ lzsa_decode_header(pCurFileData, nHeaderSize, pFormatVersion) != 0)
+ return -1;
+
+ pCurFileData += nHeaderSize;
+ nPreviousBlockSize = 0;
+
+ while (pCurFileData < pEndFileData) {
+ unsigned int nBlockDataSize = 0;
+ int nIsUncompressed = 0;
+ const int nFrameSize = lzsa_get_frame_size();
+
+ /* Decode frame header */
+ if ((pCurFileData + nFrameSize) > pEndFileData ||
+ lzsa_decode_frame(pCurFileData, nFrameSize, &nBlockDataSize, &nIsUncompressed) != 0)
+ return -1;
+ pCurFileData += nFrameSize;
+
+ if (!nBlockDataSize)
+ break;
+
+ if (!nIsUncompressed) {
+ int nDecompressedSize;
+
+ /* Decompress block */
+ if ((pCurFileData + nBlockDataSize) > pEndFileData)
+ return -1;
+
+ nDecompressedSize = lzsa_decompressor_expand_block(pCurFileData, nBlockDataSize, pCurOutBuffer - nPreviousBlockSize, nPreviousBlockSize, (int)(pEndOutBuffer - pCurOutBuffer + nPreviousBlockSize), *pFormatVersion, nFlags);
+ if (nDecompressedSize < 0)
+ return -1;
+
+ pCurOutBuffer += nDecompressedSize;
+ nPreviousBlockSize = nDecompressedSize;
+ }
+ else {
+ /* Copy uncompressed block */
+ if ((pCurFileData + nBlockDataSize) > pEndFileData)
+ return -1;
+ if ((pCurOutBuffer + nBlockDataSize) > pEndOutBuffer)
+ return -1;
+ memcpy(pCurOutBuffer, pCurFileData, nBlockDataSize);
+ pCurOutBuffer += nBlockDataSize;
+ }
+
+ pCurFileData += nBlockDataSize;
+ }
+
+ return (int)(pCurOutBuffer - pOutBuffer);
+}
diff --git a/tools/rasm/lzsa-master/src/expand_inmem.h b/tools/rasm/lzsa-master/src/expand_inmem.h
new file mode 100644
index 0000000..b52ee68
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/expand_inmem.h
@@ -0,0 +1,70 @@
+/*
+ * expand_inmem.h - in-memory decompression definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#ifndef _EXPAND_INMEM_H
+#define _EXPAND_INMEM_H
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Get maximum decompressed size of compressed data
+ *
+ * @param pFileData compressed data
+ * @param nFileSize compressed size in bytes
+ *
+ * @return maximum decompressed size
+ */
+size_t lzsa_get_max_decompressed_size_inmem(const unsigned char *pFileData, size_t nFileSize);
+
+/**
+ * Decompress data in memory
+ *
+ * @param pFileData compressed data
+ * @param pOutBuffer buffer for decompressed data
+ * @param nFileSize compressed size in bytes
+ * @param nMaxOutBufferSize maximum capacity of decompression buffer
+ * @param nFlags compression flags (LZSA_FLAG_xxx)
+ * @param pFormatVersion pointer to format version, updated if this function is successful
+ *
+ * @return actual decompressed size, or -1 for error
+ */
+size_t lzsa_decompress_inmem(unsigned char *pFileData, unsigned char *pOutBuffer, size_t nFileSize, size_t nMaxOutBufferSize, const unsigned int nFlags, int *pFormatVersion);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _EXPAND_INMEM_H */
diff --git a/tools/rasm/lzsa-master/src/expand_streaming.c b/tools/rasm/lzsa-master/src/expand_streaming.c
new file mode 100644
index 0000000..b241c68
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/expand_streaming.c
@@ -0,0 +1,236 @@
+/*
+ * expand_streaming.c - streaming decompression definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include "expand_streaming.h"
+#include "format.h"
+#include "frame.h"
+#include "lib.h"
+
+/*-------------- File API -------------- */
+
+/**
+ * Decompress file
+ *
+ * @param pszInFilename name of input(compressed) file to decompress
+ * @param pszOutFilename name of output(decompressed) file to generate
+ * @param pszDictionaryFilename name of dictionary file, or NULL for none
+ * @param nFlags compression flags (LZSA_FLAG_RAW_BLOCK to decompress a raw block, or 0)
+ * @param nFormatVersion default version of format to use (1-2). This is used when decompressing a raw block, otherwise the version is extracted from the source file
+ * @param pOriginalSize pointer to returned output(decompressed) size, updated when this function is successful
+ * @param pCompressedSize pointer to returned input(compressed) size, updated when this function is successful
+ *
+ * @return LZSA_OK for success, or an error value from lzsa_status_t
+ */
+lzsa_status_t lzsa_decompress_file(const char *pszInFilename, const char *pszOutFilename, const char *pszDictionaryFilename, const unsigned int nFlags, int nFormatVersion,
+ long long *pOriginalSize, long long *pCompressedSize) {
+ lzsa_stream_t inStream, outStream;
+ void *pDictionaryData = NULL;
+ int nDictionaryDataSize = 0;
+ lzsa_status_t nStatus;
+
+ if (lzsa_filestream_open(&inStream, pszInFilename, "rb") < 0) {
+ return LZSA_ERROR_SRC;
+ }
+
+ if (lzsa_filestream_open(&outStream, pszOutFilename, "wb") < 0) {
+ inStream.close(&inStream);
+ return LZSA_ERROR_DST;
+ }
+
+ nStatus = lzsa_dictionary_load(pszDictionaryFilename, &pDictionaryData, &nDictionaryDataSize);
+ if (nStatus) {
+ outStream.close(&outStream);
+ inStream.close(&inStream);
+ return nStatus;
+ }
+
+ nStatus = lzsa_decompress_stream(&inStream, &outStream, pDictionaryData, nDictionaryDataSize, nFlags, nFormatVersion, pOriginalSize, pCompressedSize);
+
+ lzsa_dictionary_free(&pDictionaryData);
+ outStream.close(&outStream);
+ inStream.close(&inStream);
+
+ return nStatus;
+}
+
+/*-------------- Streaming API -------------- */
+
+/**
+ * Decompress stream
+ *
+ * @param pInStream input(compressed) stream to decompress
+ * @param pOutStream output(decompressed) stream to write to
+ * @param pDictionaryData dictionary contents, or NULL for none
+ * @param nDictionaryDataSize size of dictionary contents, or 0
+ * @param nFlags compression flags (LZSA_FLAG_RAW_BLOCK to decompress a raw block, or 0)
+ * @param nFormatVersion default version of format to use (1-2). This is used when decompressing a raw block, otherwise the version is extracted from the source file
+ * @param pOriginalSize pointer to returned output(decompressed) size, updated when this function is successful
+ * @param pCompressedSize pointer to returned input(compressed) size, updated when this function is successful
+ *
+ * @return LZSA_OK for success, or an error value from lzsa_status_t
+ */
+lzsa_status_t lzsa_decompress_stream(lzsa_stream_t *pInStream, lzsa_stream_t *pOutStream, const void *pDictionaryData, int nDictionaryDataSize, const unsigned int nFlags, int nFormatVersion,
+ long long *pOriginalSize, long long *pCompressedSize) {
+ long long nOriginalSize = 0LL, nCompressedSize = 0LL;
+ unsigned char cFrameData[16];
+ unsigned char *pInBlock;
+ unsigned char *pOutData;
+
+ if ((nFlags & LZSA_FLAG_RAW_BLOCK) == 0) {
+ const int nHeaderSize = lzsa_get_header_size();
+
+ memset(cFrameData, 0, 16);
+ if (pInStream->read(pInStream, cFrameData, nHeaderSize) != nHeaderSize) {
+ return LZSA_ERROR_SRC;
+ }
+
+ if (lzsa_decode_header(cFrameData, nHeaderSize, &nFormatVersion) < 0) {
+ return LZSA_ERROR_FORMAT;
+ }
+
+ nCompressedSize += (long long)nHeaderSize;
+ }
+
+ pInBlock = (unsigned char*)malloc(BLOCK_SIZE);
+ if (!pInBlock) {
+ return LZSA_ERROR_MEMORY;
+ }
+
+ pOutData = (unsigned char*)malloc(BLOCK_SIZE * 2);
+ if (!pOutData) {
+ free(pInBlock);
+ pInBlock = NULL;
+
+ return LZSA_ERROR_MEMORY;
+ }
+
+ int nDecompressionError = 0;
+ int nPrevDecompressedSize = 0;
+ int nNumBlocks = 0;
+
+ while (!pInStream->eof(pInStream) && !nDecompressionError) {
+ unsigned int nBlockSize = 0;
+ int nIsUncompressed = 0;
+
+ if (nPrevDecompressedSize != 0) {
+ memcpy(pOutData + BLOCK_SIZE - nPrevDecompressedSize, pOutData + BLOCK_SIZE, nPrevDecompressedSize);
+ }
+ else if (nDictionaryDataSize && pDictionaryData) {
+ nPrevDecompressedSize = nDictionaryDataSize;
+ memcpy(pOutData + BLOCK_SIZE - nPrevDecompressedSize, pDictionaryData, nPrevDecompressedSize);
+ }
+
+ if ((nFlags & LZSA_FLAG_RAW_BLOCK) == 0) {
+ const int nFrameSize = lzsa_get_frame_size();
+
+ memset(cFrameData, 0, 16);
+ if (pInStream->read(pInStream, cFrameData, nFrameSize) == nFrameSize) {
+ if (lzsa_decode_frame(cFrameData, nFrameSize, &nBlockSize, &nIsUncompressed) < 0) {
+ nDecompressionError = LZSA_ERROR_FORMAT;
+ nBlockSize = 0;
+ }
+
+ nCompressedSize += (long long)nFrameSize;
+ }
+ else {
+ nDecompressionError = LZSA_ERROR_SRC;
+ nBlockSize = 0;
+ }
+ }
+ else {
+ if (!nNumBlocks)
+ nBlockSize = BLOCK_SIZE;
+ else
+ nBlockSize = 0;
+ }
+
+ if (nBlockSize != 0) {
+ int nDecompressedSize = 0;
+
+ if ((int)nBlockSize > BLOCK_SIZE) {
+ nDecompressionError = LZSA_ERROR_FORMAT;
+ break;
+ }
+ size_t nReadBytes = pInStream->read(pInStream, pInBlock, nBlockSize);
+ if (nFlags & LZSA_FLAG_RAW_BLOCK) {
+ nBlockSize = (unsigned int)nReadBytes;
+ }
+
+ if (nReadBytes == nBlockSize) {
+ nCompressedSize += (long long)nReadBytes;
+
+ if (nIsUncompressed) {
+ memcpy(pOutData + BLOCK_SIZE, pInBlock, nBlockSize);
+ nDecompressedSize = nBlockSize;
+ }
+ else {
+ nDecompressedSize = lzsa_decompressor_expand_block(pInBlock, nBlockSize, pOutData, BLOCK_SIZE, BLOCK_SIZE, nFormatVersion, nFlags);
+ if (nDecompressedSize < 0) {
+ nDecompressionError = LZSA_ERROR_DECOMPRESSION;
+ break;
+ }
+ }
+
+ if (nDecompressedSize != 0) {
+ nOriginalSize += (long long)nDecompressedSize;
+
+ if (pOutStream->write(pOutStream, pOutData + BLOCK_SIZE, nDecompressedSize) != nDecompressedSize)
+ nDecompressionError = LZSA_ERROR_DST;
+ nPrevDecompressedSize = nDecompressedSize;
+ nDecompressedSize = 0;
+ }
+ }
+ else {
+ break;
+ }
+
+ nNumBlocks++;
+ }
+ else {
+ break;
+ }
+ }
+
+ free(pOutData);
+ pOutData = NULL;
+
+ free(pInBlock);
+ pInBlock = NULL;
+
+ *pOriginalSize = nOriginalSize;
+ *pCompressedSize = nCompressedSize;
+ return nDecompressionError;
+}
+
diff --git a/tools/rasm/lzsa-master/src/expand_streaming.h b/tools/rasm/lzsa-master/src/expand_streaming.h
new file mode 100644
index 0000000..30dd88d
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/expand_streaming.h
@@ -0,0 +1,86 @@
+/*
+ * expand_streaming.h - streaming decompression definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#ifndef _EXPAND_STREAMING_H
+#define _EXPAND_STREAMING_H
+
+#include "stream.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declaration */
+typedef enum _lzsa_status_t lzsa_status_t;
+
+/*-------------- File API -------------- */
+
+/**
+ * Decompress file
+ *
+ * @param pszInFilename name of input(compressed) file to decompress
+ * @param pszOutFilename name of output(decompressed) file to generate
+ * @param pszDictionaryFilename name of dictionary file, or NULL for none
+ * @param nFlags compression flags (LZSA_FLAG_RAW_BLOCK to decompress a raw block, or 0)
+ * @param nFormatVersion default version of format to use (1-2). This is used when decompressing a raw block, otherwise the version is extracted from the source file
+ * @param pOriginalSize pointer to returned output(decompressed) size, updated when this function is successful
+ * @param pCompressedSize pointer to returned input(compressed) size, updated when this function is successful
+ *
+ * @return LZSA_OK for success, or an error value from lzsa_status_t
+ */
+lzsa_status_t lzsa_decompress_file(const char *pszInFilename, const char *pszOutFilename, const char *pszDictionaryFilename, const unsigned int nFlags, int nFormatVersion,
+ long long *pOriginalSize, long long *pCompressedSize);
+
+/*-------------- Streaming API -------------- */
+
+/**
+ * Decompress stream
+ *
+ * @param pInStream input(compressed) stream to decompress
+ * @param pOutStream output(decompressed) stream to write to
+ * @param pDictionaryData dictionary contents, or NULL for none
+ * @param nDictionaryDataSize size of dictionary contents, or 0
+ * @param nFlags compression flags (LZSA_FLAG_RAW_BLOCK to decompress a raw block, or 0)
+ * @param nFormatVersion default version of format to use (1-2). This is used when decompressing a raw block, otherwise the version is extracted from the source file
+ * @param pOriginalSize pointer to returned output(decompressed) size, updated when this function is successful
+ * @param pCompressedSize pointer to returned input(compressed) size, updated when this function is successful
+ *
+ * @return LZSA_OK for success, or an error value from lzsa_status_t
+ */
+lzsa_status_t lzsa_decompress_stream(lzsa_stream_t *pInStream, lzsa_stream_t *pOutStream, const void *pDictionaryData, int nDictionaryDataSize, const unsigned int nFlags, int nFormatVersion,
+ long long *pOriginalSize, long long *pCompressedSize);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _EXPAND_STREAMING_H */
diff --git a/tools/rasm/lzsa-master/src/format.h b/tools/rasm/lzsa-master/src/format.h
new file mode 100755
index 0000000..ace4f15
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/format.h
@@ -0,0 +1,51 @@
+/*
+ * format.h - byte stream format definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#ifndef _FORMAT_H
+#define _FORMAT_H
+
+#define MIN_OFFSET 1
+#define MAX_OFFSET 0xffff
+
+#define MAX_VARLEN 0xffff
+
+#define BLOCK_SIZE 65536
+
+#define MIN_MATCH_SIZE_V1 3
+#define LITERALS_RUN_LEN_V1 7
+#define MATCH_RUN_LEN_V1 15
+
+#define MIN_MATCH_SIZE_V2 2
+#define LITERALS_RUN_LEN_V2 3
+#define MATCH_RUN_LEN_V2 7
+
+#endif /* _FORMAT_H */
diff --git a/tools/rasm/lzsa-master/src/frame.c b/tools/rasm/lzsa-master/src/frame.c
new file mode 100644
index 0000000..f1d6be2
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/frame.c
@@ -0,0 +1,189 @@
+/*
+ * frame.c - frame implementation
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "frame.h"
+
+#define LZSA_ID_0 0x7b
+#define LZSA_ID_1 0x9e
+
+/**
+ * Get compressed file header size
+ *
+ * @return file header size
+ */
+int lzsa_get_header_size(void) {
+ return 3;
+}
+
+/**
+ * Get compressed frame header size
+ *
+ * @return frame header size
+ */
+int lzsa_get_frame_size(void) {
+ return 3;
+}
+
+/**
+ * Encode file header
+ *
+ * @param pFrameData encoding buffer
+ * @param nMaxFrameDataSize max encoding buffer size, in bytes
+ *
+ * @return number of encoded bytes, or -1 for failure
+ */
+int lzsa_encode_header(unsigned char *pFrameData, const int nMaxFrameDataSize, int nFormatVersion) {
+ if (nMaxFrameDataSize >= 3 && (nFormatVersion == 1 || nFormatVersion == 2)) {
+ pFrameData[0] = LZSA_ID_0; /* Magic number */
+ pFrameData[1] = LZSA_ID_1;
+ pFrameData[2] = (nFormatVersion == 2) ? 0x20 : 0; /* Format version 1 */
+
+ return 3;
+ }
+ else {
+ return -1;
+ }
+}
+
+/**
+ * Encode compressed block frame header
+ *
+ * @param pFrameData encoding buffer
+ * @param nMaxFrameDataSize max encoding buffer size, in bytes
+ * @param nBlockDataSize compressed block's data size, in bytes
+ *
+ * @return number of encoded bytes, or -1 for failure
+ */
+int lzsa_encode_compressed_block_frame(unsigned char *pFrameData, const int nMaxFrameDataSize, const int nBlockDataSize) {
+ if (nMaxFrameDataSize >= 3 && nBlockDataSize <= 0x7fffff) {
+ pFrameData[0] = nBlockDataSize & 0xff;
+ pFrameData[1] = (nBlockDataSize >> 8) & 0xff;
+ pFrameData[2] = (nBlockDataSize >> 16) & 0x7f;
+
+ return 3;
+ }
+ else {
+ return -1;
+ }
+}
+
+/**
+ * Encode uncompressed block frame header
+ *
+ * @param pFrameData encoding buffer
+ * @param nMaxFrameDataSize max encoding buffer size, in bytes
+ * @param nBlockDataSize uncompressed block's data size, in bytes
+ *
+ * @return number of encoded bytes, or -1 for failure
+ */
+int lzsa_encode_uncompressed_block_frame(unsigned char *pFrameData, const int nMaxFrameDataSize, const int nBlockDataSize) {
+ if (nMaxFrameDataSize >= 3 && nBlockDataSize <= 0x7fffff) {
+ pFrameData[0] = nBlockDataSize & 0xff;
+ pFrameData[1] = (nBlockDataSize >> 8) & 0xff;
+ pFrameData[2] = ((nBlockDataSize >> 16) & 0x7f) | 0x80; /* Uncompressed block */
+
+ return 3;
+ }
+ else {
+ return -1;
+ }
+}
+
+/**
+ * Encode terminal frame header
+ *
+ * @param pFrameData encoding buffer
+ * @param nMaxFrameDataSize max encoding buffer size, in bytes
+ *
+ * @return number of encoded bytes, or -1 for failure
+ */
+int lzsa_encode_footer_frame(unsigned char *pFrameData, const int nMaxFrameDataSize) {
+ if (nMaxFrameDataSize >= 3) {
+ pFrameData[0] = 0x00; /* EOD frame */
+ pFrameData[1] = 0x00;
+ pFrameData[2] = 0x00;
+
+ return 3;
+ }
+ else {
+ return -1;
+ }
+}
+
+/**
+ * Decode file header
+ *
+ * @param pFrameData data bytes
+ * @param nFrameDataSize number of bytes to decode
+ *
+ * @return 0 for success, or -1 for failure
+ */
+int lzsa_decode_header(const unsigned char *pFrameData, const int nFrameDataSize, int *nFormatVersion) {
+ if (nFrameDataSize != 3 ||
+ pFrameData[0] != LZSA_ID_0 ||
+ pFrameData[1] != LZSA_ID_1 ||
+ (pFrameData[2] & 0x1f) != 0 ||
+ ((pFrameData[2] & 0xe0) != 0x00 && (pFrameData[2] & 0xe0) != 0x20)) {
+ return -1;
+ }
+ else {
+ *nFormatVersion = (pFrameData[2] & 0xe0) ? 2 : 1;
+ return 0;
+ }
+}
+
+/**
+ * Decode frame header
+ *
+ * @param pFrameData data bytes
+ * @param nFrameDataSize number of bytes to decode
+ * @param nBlockSize pointer to block size, updated if this function succeeds (set to 0 if this is the terminal frame)
+ * @param nIsUncompressed pointer to compressed block flag, updated if this function succeeds
+ *
+ * @return 0 for success, or -1 for failure
+ */
+int lzsa_decode_frame(const unsigned char *pFrameData, const int nFrameDataSize, unsigned int *nBlockSize, int *nIsUncompressed) {
+ if (nFrameDataSize == 3) {
+ *nBlockSize = ((unsigned int)pFrameData[0]) |
+ (((unsigned int)pFrameData[1]) << 8) |
+ (((unsigned int)pFrameData[2]) << 16);
+
+ *nIsUncompressed = ((*nBlockSize & 0x800000) != 0) ? 1 : 0;
+ *nBlockSize &= 0x7fffff;
+ return 0;
+ }
+ else {
+ return -1;
+ }
+}
diff --git a/tools/rasm/lzsa-master/src/frame.h b/tools/rasm/lzsa-master/src/frame.h
new file mode 100644
index 0000000..7b5db99
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/frame.h
@@ -0,0 +1,122 @@
+/*
+ * frame.h - frame definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#ifndef _FRAME_H
+#define _FRAME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Get compressed file header size
+ *
+ * @return file header size
+ */
+int lzsa_get_header_size(void);
+
+/**
+ * Get compressed frame header size
+ *
+ * @return frame header size
+ */
+int lzsa_get_frame_size(void);
+
+/**
+ * Encode file header
+ *
+ * @param pFrameData encoding buffer
+ * @param nMaxFrameDataSize max encoding buffer size, in bytes
+ *
+ * @return number of encoded bytes, or -1 for failure
+ */
+int lzsa_encode_header(unsigned char *pFrameData, const int nMaxFrameDataSize, int nFormatVersion);
+
+/**
+ * Encode compressed block frame header
+ *
+ * @param pFrameData encoding buffer
+ * @param nMaxFrameDataSize max encoding buffer size, in bytes
+ * @param nBlockDataSize compressed block's data size, in bytes
+ *
+ * @return number of encoded bytes, or -1 for failure
+ */
+int lzsa_encode_compressed_block_frame(unsigned char *pFrameData, const int nMaxFrameDataSize, const int nBlockDataSize);
+
+/**
+ * Encode uncompressed block frame header
+ *
+ * @param pFrameData encoding buffer
+ * @param nMaxFrameDataSize max encoding buffer size, in bytes
+ * @param nBlockDataSize uncompressed block's data size, in bytes
+ *
+ * @return number of encoded bytes, or -1 for failure
+ */
+int lzsa_encode_uncompressed_block_frame(unsigned char *pFrameData, const int nMaxFrameDataSize, const int nBlockDataSize);
+
+/**
+ * Encode terminal frame header
+ *
+ * @param pFrameData encoding buffer
+ * @param nMaxFrameDataSize max encoding buffer size, in bytes
+ *
+ * @return number of encoded bytes, or -1 for failure
+ */
+int lzsa_encode_footer_frame(unsigned char *pFrameData, const int nMaxFrameDataSize);
+
+/**
+ * Decode file header
+ *
+ * @param pFrameData data bytes
+ * @param nFrameDataSize number of bytes to decode
+ *
+ * @return 0 for success, or -1 for failure
+ */
+int lzsa_decode_header(const unsigned char *pFrameData, const int nFrameDataSize, int *nFormatVersion);
+
+/**
+ * Decode frame header
+ *
+ * @param pFrameData data bytes
+ * @param nFrameDataSize number of bytes to decode
+ * @param nBlockSize pointer to block size, updated if this function succeeds (set to 0 if this is the terminal frame)
+ * @param nIsUncompressed pointer to compressed block flag, updated if this function succeeds
+ *
+ * @return 0 for success, or -1 for failure
+ */
+int lzsa_decode_frame(const unsigned char *pFrameData, const int nFrameDataSize, unsigned int *nBlockSize, int *nIsUncompressed);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FRAME_H */
diff --git a/tools/rasm/lzsa-master/src/lib.h b/tools/rasm/lzsa-master/src/lib.h
new file mode 100755
index 0000000..2520b13
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/lib.h
@@ -0,0 +1,95 @@
+/*
+ * lib.h - LZSA library definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#ifndef _LIB_H
+#define _LIB_H
+
+#include "stream.h"
+#include "dictionary.h"
+#include "frame.h"
+#include "format.h"
+#include "shrink_context.h"
+#include "shrink_streaming.h"
+#include "shrink_inmem.h"
+#include "expand_context.h"
+#include "expand_streaming.h"
+#include "expand_inmem.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** High level status for compression and decompression */
+typedef enum _lzsa_status_t {
+ LZSA_OK = 0, /**< Success */
+ LZSA_ERROR_SRC, /**< Error reading input */
+ LZSA_ERROR_DST, /**< Error reading output */
+ LZSA_ERROR_DICTIONARY, /**< Error reading dictionary */
+ LZSA_ERROR_MEMORY, /**< Out of memory */
+
+ /* Compression-specific status codes */
+ LZSA_ERROR_COMPRESSION, /**< Internal compression error */
+ LZSA_ERROR_RAW_TOOLARGE, /**< Input is too large to be compressed to a raw block */
+ LZSA_ERROR_RAW_UNCOMPRESSED, /**< Input is incompressible and raw blocks don't support uncompressed data */
+
+ /* Decompression-specific status codes */
+ LZSA_ERROR_FORMAT, /**< Invalid input format or magic number when decompressing */
+ LZSA_ERROR_DECOMPRESSION /**< Internal decompression error */
+} lzsa_status_t;
+
+/* Compression flags */
+#define LZSA_FLAG_FAVOR_RATIO (1<<0) /**< 1 to compress with the best ratio, 0 to trade some compression ratio for extra decompression speed */
+#define LZSA_FLAG_RAW_BLOCK (1<<1) /**< 1 to emit raw block */
+#define LZSA_FLAG_RAW_BACKWARD (1<<2) /**< 1 to compress or decompress raw block backward */
+
+/**
+ * Reverse bytes in the specified buffer
+ *
+ * @param pBuffer pointer to buffer whose contents are to be reversed
+ * @param nBufferSize size of buffer in bytes
+ */
+static inline void lzsa_reverse_buffer(unsigned char *pBuffer, const int nBufferSize) {
+ int nMidPoint = nBufferSize / 2;
+ int i, j;
+
+ for (i = 0, j = nBufferSize - 1; i < nMidPoint; i++, j--) {
+ unsigned char c = pBuffer[i];
+ pBuffer[i] = pBuffer[j];
+ pBuffer[j] = c;
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIB_H */
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/.gitignore b/tools/rasm/lzsa-master/src/libdivsufsort/.gitignore
new file mode 100644
index 0000000..a0a0666
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/.gitignore
@@ -0,0 +1,32 @@
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# CMake files/directories
+build/
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/CHANGELOG.md b/tools/rasm/lzsa-master/src/libdivsufsort/CHANGELOG.md
new file mode 100644
index 0000000..fe9d004
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/CHANGELOG.md
@@ -0,0 +1,21 @@
+# libdivsufsort Change Log
+
+See full changelog at: https://github.com/y-256/libdivsufsort/commits
+
+## [2.0.1] - 2010-11-11
+### Fixed
+* Wrong variable used in `divbwt` function
+* Enclose some string variables with double quotation marks in include/CMakeLists.txt
+* Fix typo in include/CMakeLists.txt
+
+## 2.0.0 - 2008-08-23
+### Changed
+* Switch the build system to [CMake](http://www.cmake.org/)
+* Improve the performance of the suffix-sorting algorithm
+
+### Added
+* OpenMP support
+* 64-bit version of divsufsort
+
+[Unreleased]: https://github.com/y-256/libdivsufsort/compare/2.0.1...HEAD
+[2.0.1]: https://github.com/y-256/libdivsufsort/compare/2.0.0...2.0.1
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/CMakeLists.txt b/tools/rasm/lzsa-master/src/libdivsufsort/CMakeLists.txt
new file mode 100644
index 0000000..7859943
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/CMakeLists.txt
@@ -0,0 +1,99 @@
+### cmake file for building libdivsufsort Package ###
+cmake_minimum_required(VERSION 2.4.4)
+set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
+include(AppendCompilerFlags)
+
+## Project information ##
+project(libdivsufsort C)
+set(PROJECT_VENDOR "Yuta Mori")
+set(PROJECT_CONTACT "yuta.256@gmail.com")
+set(PROJECT_URL "https://github.com/y-256/libdivsufsort")
+set(PROJECT_DESCRIPTION "A lightweight suffix sorting library")
+include(VERSION.cmake)
+
+## CPack configuration ##
+set(CPACK_GENERATOR "TGZ;TBZ2;ZIP")
+set(CPACK_SOURCE_GENERATOR "TGZ;TBZ2;ZIP")
+include(ProjectCPack)
+
+## Project options ##
+option(BUILD_SHARED_LIBS "Set to OFF to build static libraries" ON)
+option(BUILD_EXAMPLES "Build examples" ON)
+option(BUILD_DIVSUFSORT64 "Build libdivsufsort64" OFF)
+option(USE_OPENMP "Use OpenMP for parallelization" OFF)
+option(WITH_LFS "Enable Large File Support" ON)
+
+## Installation directories ##
+set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32 or 64)")
+
+set(CMAKE_INSTALL_RUNTIMEDIR "" CACHE PATH "Specify the output directory for dll runtimes (default is bin)")
+if(NOT CMAKE_INSTALL_RUNTIMEDIR)
+ set(CMAKE_INSTALL_RUNTIMEDIR "${CMAKE_INSTALL_PREFIX}/bin")
+endif(NOT CMAKE_INSTALL_RUNTIMEDIR)
+
+set(CMAKE_INSTALL_LIBDIR "" CACHE PATH "Specify the output directory for libraries (default is lib)")
+if(NOT CMAKE_INSTALL_LIBDIR)
+ set(CMAKE_INSTALL_LIBDIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}")
+endif(NOT CMAKE_INSTALL_LIBDIR)
+
+set(CMAKE_INSTALL_INCLUDEDIR "" CACHE PATH "Specify the output directory for header files (default is include)")
+if(NOT CMAKE_INSTALL_INCLUDEDIR)
+ set(CMAKE_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/include")
+endif(NOT CMAKE_INSTALL_INCLUDEDIR)
+
+set(CMAKE_INSTALL_PKGCONFIGDIR "" CACHE PATH "Specify the output directory for pkgconfig files (default is lib/pkgconfig)")
+if(NOT CMAKE_INSTALL_PKGCONFIGDIR)
+ set(CMAKE_INSTALL_PKGCONFIGDIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+endif(NOT CMAKE_INSTALL_PKGCONFIGDIR)
+
+## Build type ##
+if(NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE "Release")
+elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
+ set(CMAKE_VERBOSE_MAKEFILE ON)
+endif(NOT CMAKE_BUILD_TYPE)
+
+## Compiler options ##
+if(MSVC)
+ append_c_compiler_flags("/W4" "VC" CMAKE_C_FLAGS)
+ append_c_compiler_flags("/Oi;/Ot;/Ox;/Oy" "VC" CMAKE_C_FLAGS_RELEASE)
+ if(USE_OPENMP)
+ append_c_compiler_flags("/openmp" "VC" CMAKE_C_FLAGS)
+ endif(USE_OPENMP)
+elseif(BORLAND)
+ append_c_compiler_flags("-w" "BCC" CMAKE_C_FLAGS)
+ append_c_compiler_flags("-Oi;-Og;-Os;-Ov;-Ox" "BCC" CMAKE_C_FLAGS_RELEASE)
+else(MSVC)
+ if(CMAKE_COMPILER_IS_GNUCC)
+ append_c_compiler_flags("-Wall" "GCC" CMAKE_C_FLAGS)
+ append_c_compiler_flags("-fomit-frame-pointer" "GCC" CMAKE_C_FLAGS_RELEASE)
+ if(USE_OPENMP)
+ append_c_compiler_flags("-fopenmp" "GCC" CMAKE_C_FLAGS)
+ endif(USE_OPENMP)
+ else(CMAKE_COMPILER_IS_GNUCC)
+ append_c_compiler_flags("-Wall" "UNKNOWN" CMAKE_C_FLAGS)
+ append_c_compiler_flags("-fomit-frame-pointer" "UNKNOWN" CMAKE_C_FLAGS_RELEASE)
+ if(USE_OPENMP)
+ append_c_compiler_flags("-fopenmp;-openmp;-omp" "UNKNOWN" CMAKE_C_FLAGS)
+ endif(USE_OPENMP)
+ endif(CMAKE_COMPILER_IS_GNUCC)
+endif(MSVC)
+
+## Add definitions ##
+add_definitions(-DHAVE_CONFIG_H=1 -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS)
+
+## Add subdirectories ##
+add_subdirectory(pkgconfig)
+add_subdirectory(include)
+add_subdirectory(lib)
+if(BUILD_EXAMPLES)
+ add_subdirectory(examples)
+endif(BUILD_EXAMPLES)
+
+## Add 'uninstall' target ##
+CONFIGURE_FILE(
+ "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/cmake_uninstall.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/CMakeModules/cmake_uninstall.cmake"
+ IMMEDIATE @ONLY)
+ADD_CUSTOM_TARGET(uninstall
+ "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/CMakeModules/cmake_uninstall.cmake")
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/AppendCompilerFlags.cmake b/tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/AppendCompilerFlags.cmake
new file mode 100644
index 0000000..58d3f99
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/AppendCompilerFlags.cmake
@@ -0,0 +1,38 @@
+include(CheckCSourceCompiles)
+include(CheckCXXSourceCompiles)
+
+macro(append_c_compiler_flags _flags _name _result)
+ set(SAFE_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
+ string(REGEX REPLACE "[-+/ ]" "_" cname "${_name}")
+ string(TOUPPER "${cname}" cname)
+ foreach(flag ${_flags})
+ string(REGEX REPLACE "^[-+/ ]+(.*)[-+/ ]*$" "\\1" flagname "${flag}")
+ string(REGEX REPLACE "[-+/ ]" "_" flagname "${flagname}")
+ string(TOUPPER "${flagname}" flagname)
+ set(have_flag "HAVE_${cname}_${flagname}")
+ set(CMAKE_REQUIRED_FLAGS "${flag}")
+ check_c_source_compiles("int main() { return 0; }" ${have_flag})
+ if(${have_flag})
+ set(${_result} "${${_result}} ${flag}")
+ endif(${have_flag})
+ endforeach(flag)
+ set(CMAKE_REQUIRED_FLAGS ${SAFE_CMAKE_REQUIRED_FLAGS})
+endmacro(append_c_compiler_flags)
+
+macro(append_cxx_compiler_flags _flags _name _result)
+ set(SAFE_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
+ string(REGEX REPLACE "[-+/ ]" "_" cname "${_name}")
+ string(TOUPPER "${cname}" cname)
+ foreach(flag ${_flags})
+ string(REGEX REPLACE "^[-+/ ]+(.*)[-+/ ]*$" "\\1" flagname "${flag}")
+ string(REGEX REPLACE "[-+/ ]" "_" flagname "${flagname}")
+ string(TOUPPER "${flagname}" flagname)
+ set(have_flag "HAVE_${cname}_${flagname}")
+ set(CMAKE_REQUIRED_FLAGS "${flag}")
+ check_cxx_source_compiles("int main() { return 0; }" ${have_flag})
+ if(${have_flag})
+ set(${_result} "${${_result}} ${flag}")
+ endif(${have_flag})
+ endforeach(flag)
+ set(CMAKE_REQUIRED_FLAGS ${SAFE_CMAKE_REQUIRED_FLAGS})
+endmacro(append_cxx_compiler_flags)
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/CheckFunctionKeywords.cmake b/tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/CheckFunctionKeywords.cmake
new file mode 100644
index 0000000..44601fd
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/CheckFunctionKeywords.cmake
@@ -0,0 +1,15 @@
+include(CheckCSourceCompiles)
+
+macro(check_function_keywords _wordlist)
+ set(${_result} "")
+ foreach(flag ${_wordlist})
+ string(REGEX REPLACE "[-+/ ()]" "_" flagname "${flag}")
+ string(TOUPPER "${flagname}" flagname)
+ set(have_flag "HAVE_${flagname}")
+ check_c_source_compiles("${flag} void func(); void func() { } int main() { func(); return 0; }" ${have_flag})
+ if(${have_flag} AND NOT ${_result})
+ set(${_result} "${flag}")
+# break()
+ endif(${have_flag} AND NOT ${_result})
+ endforeach(flag)
+endmacro(check_function_keywords)
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/CheckLFS.cmake b/tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/CheckLFS.cmake
new file mode 100644
index 0000000..e2b0099
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/CheckLFS.cmake
@@ -0,0 +1,109 @@
+## Checks for large file support ##
+include(CheckIncludeFile)
+include(CheckSymbolExists)
+include(CheckTypeSize)
+
+macro(check_lfs _isenable)
+ set(LFS_OFF_T "")
+ set(LFS_FOPEN "")
+ set(LFS_FSEEK "")
+ set(LFS_FTELL "")
+ set(LFS_PRID "")
+
+ if(${_isenable})
+ set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
+ set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+ -D_LARGEFILE_SOURCE -D_LARGE_FILES -D_FILE_OFFSET_BITS=64
+ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS)
+
+ check_include_file("sys/types.h" HAVE_SYS_TYPES_H)
+ check_include_file("inttypes.h" HAVE_INTTYPES_H)
+ check_include_file("stddef.h" HAVE_STDDEF_H)
+ check_include_file("stdint.h" HAVE_STDINT_H)
+
+ # LFS type1: 8 <= sizeof(off_t), fseeko, ftello
+ check_type_size("off_t" SIZEOF_OFF_T)
+ if(SIZEOF_OFF_T GREATER 7)
+ check_symbol_exists("fseeko" "stdio.h" HAVE_FSEEKO)
+ check_symbol_exists("ftello" "stdio.h" HAVE_FTELLO)
+ if(HAVE_FSEEKO AND HAVE_FTELLO)
+ set(LFS_OFF_T "off_t")
+ set(LFS_FOPEN "fopen")
+ set(LFS_FSEEK "fseeko")
+ set(LFS_FTELL "ftello")
+ check_symbol_exists("PRIdMAX" "inttypes.h" HAVE_PRIDMAX)
+ if(HAVE_PRIDMAX)
+ set(LFS_PRID "PRIdMAX")
+ else(HAVE_PRIDMAX)
+ check_type_size("long" SIZEOF_LONG)
+ check_type_size("int" SIZEOF_INT)
+ if(SIZEOF_OFF_T GREATER SIZEOF_LONG)
+ set(LFS_PRID "\"lld\"")
+ elseif(SIZEOF_LONG GREATER SIZEOF_INT)
+ set(LFS_PRID "\"ld\"")
+ else(SIZEOF_OFF_T GREATER SIZEOF_LONG)
+ set(LFS_PRID "\"d\"")
+ endif(SIZEOF_OFF_T GREATER SIZEOF_LONG)
+ endif(HAVE_PRIDMAX)
+ endif(HAVE_FSEEKO AND HAVE_FTELLO)
+ endif(SIZEOF_OFF_T GREATER 7)
+
+ # LFS type2: 8 <= sizeof(off64_t), fopen64, fseeko64, ftello64
+ if(NOT LFS_OFF_T)
+ check_type_size("off64_t" SIZEOF_OFF64_T)
+ if(SIZEOF_OFF64_T GREATER 7)
+ check_symbol_exists("fopen64" "stdio.h" HAVE_FOPEN64)
+ check_symbol_exists("fseeko64" "stdio.h" HAVE_FSEEKO64)
+ check_symbol_exists("ftello64" "stdio.h" HAVE_FTELLO64)
+ if(HAVE_FOPEN64 AND HAVE_FSEEKO64 AND HAVE_FTELLO64)
+ set(LFS_OFF_T "off64_t")
+ set(LFS_FOPEN "fopen64")
+ set(LFS_FSEEK "fseeko64")
+ set(LFS_FTELL "ftello64")
+ check_symbol_exists("PRIdMAX" "inttypes.h" HAVE_PRIDMAX)
+ if(HAVE_PRIDMAX)
+ set(LFS_PRID "PRIdMAX")
+ else(HAVE_PRIDMAX)
+ check_type_size("long" SIZEOF_LONG)
+ check_type_size("int" SIZEOF_INT)
+ if(SIZEOF_OFF64_T GREATER SIZEOF_LONG)
+ set(LFS_PRID "\"lld\"")
+ elseif(SIZEOF_LONG GREATER SIZEOF_INT)
+ set(LFS_PRID "\"ld\"")
+ else(SIZEOF_OFF64_T GREATER SIZEOF_LONG)
+ set(LFS_PRID "\"d\"")
+ endif(SIZEOF_OFF64_T GREATER SIZEOF_LONG)
+ endif(HAVE_PRIDMAX)
+ endif(HAVE_FOPEN64 AND HAVE_FSEEKO64 AND HAVE_FTELLO64)
+ endif(SIZEOF_OFF64_T GREATER 7)
+ endif(NOT LFS_OFF_T)
+
+ # LFS type3: 8 <= sizeof(__int64), _fseeki64, _ftelli64
+ if(NOT LFS_OFF_T)
+ check_type_size("__int64" SIZEOF___INT64)
+ if(SIZEOF___INT64 GREATER 7)
+ check_symbol_exists("_fseeki64" "stdio.h" HAVE__FSEEKI64)
+ check_symbol_exists("_ftelli64" "stdio.h" HAVE__FTELLI64)
+ if(HAVE__FSEEKI64 AND HAVE__FTELLI64)
+ set(LFS_OFF_T "__int64")
+ set(LFS_FOPEN "fopen")
+ set(LFS_FSEEK "_fseeki64")
+ set(LFS_FTELL "_ftelli64")
+ set(LFS_PRID "\"I64d\"")
+ endif(HAVE__FSEEKI64 AND HAVE__FTELLI64)
+ endif(SIZEOF___INT64 GREATER 7)
+ endif(NOT LFS_OFF_T)
+
+ set(CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
+ endif(${_isenable})
+
+ if(NOT LFS_OFF_T)
+ ## not found
+ set(LFS_OFF_T "long")
+ set(LFS_FOPEN "fopen")
+ set(LFS_FSEEK "fseek")
+ set(LFS_FTELL "ftell")
+ set(LFS_PRID "\"ld\"")
+ endif(NOT LFS_OFF_T)
+
+endmacro(check_lfs)
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/ProjectCPack.cmake b/tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/ProjectCPack.cmake
new file mode 100644
index 0000000..7c105f9
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/ProjectCPack.cmake
@@ -0,0 +1,38 @@
+# If the cmake version includes cpack, use it
+IF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
+ SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_DESCRIPTION}")
+ SET(CPACK_PACKAGE_VENDOR "${PROJECT_VENDOR}")
+ SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
+ SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
+ SET(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
+ SET(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
+ SET(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
+# SET(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME} ${PROJECT_VERSION}")
+ SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION_FULL}")
+
+ IF(NOT DEFINED CPACK_SYSTEM_NAME)
+ SET(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
+ ENDIF(NOT DEFINED CPACK_SYSTEM_NAME)
+
+ IF(${CPACK_SYSTEM_NAME} MATCHES Windows)
+ IF(CMAKE_CL_64)
+ SET(CPACK_SYSTEM_NAME win64-${CMAKE_SYSTEM_PROCESSOR})
+ ELSE(CMAKE_CL_64)
+ SET(CPACK_SYSTEM_NAME win32-${CMAKE_SYSTEM_PROCESSOR})
+ ENDIF(CMAKE_CL_64)
+ ENDIF(${CPACK_SYSTEM_NAME} MATCHES Windows)
+
+ IF(NOT DEFINED CPACK_PACKAGE_FILE_NAME)
+ SET(CPACK_PACKAGE_FILE_NAME "${CPACK_SOURCE_PACKAGE_FILE_NAME}-${CPACK_SYSTEM_NAME}")
+ ENDIF(NOT DEFINED CPACK_PACKAGE_FILE_NAME)
+
+ SET(CPACK_PACKAGE_CONTACT "${PROJECT_CONTACT}")
+ IF(UNIX)
+ SET(CPACK_STRIP_FILES "")
+ SET(CPACK_SOURCE_STRIP_FILES "")
+# SET(CPACK_PACKAGE_EXECUTABLES "ccmake" "CMake")
+ ENDIF(UNIX)
+ SET(CPACK_SOURCE_IGNORE_FILES "/CVS/" "/build/" "/\\\\.build/" "/\\\\.svn/" "~$")
+ # include CPack model once all variables are set
+ INCLUDE(CPack)
+ENDIF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/cmake_uninstall.cmake.in b/tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/cmake_uninstall.cmake.in
new file mode 100644
index 0000000..8366a83
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/CMakeModules/cmake_uninstall.cmake.in
@@ -0,0 +1,36 @@
+IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+ MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
+ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+
+FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
+STRING(REGEX REPLACE "\n" ";" files "${files}")
+
+SET(NUM 0)
+FOREACH(file ${files})
+ IF(EXISTS "$ENV{DESTDIR}${file}")
+ MESSAGE(STATUS "Looking for \"$ENV{DESTDIR}${file}\" - found")
+ SET(UNINSTALL_CHECK_${NUM} 1)
+ ELSE(EXISTS "$ENV{DESTDIR}${file}")
+ MESSAGE(STATUS "Looking for \"$ENV{DESTDIR}${file}\" - not found")
+ SET(UNINSTALL_CHECK_${NUM} 0)
+ ENDIF(EXISTS "$ENV{DESTDIR}${file}")
+ MATH(EXPR NUM "1 + ${NUM}")
+ENDFOREACH(file)
+
+SET(NUM 0)
+FOREACH(file ${files})
+ IF(${UNINSTALL_CHECK_${NUM}})
+ MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
+ EXEC_PROGRAM(
+ "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
+ OUTPUT_VARIABLE rm_out
+ RETURN_VALUE rm_retval
+ )
+ IF(NOT "${rm_retval}" STREQUAL 0)
+ MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
+ ENDIF(NOT "${rm_retval}" STREQUAL 0)
+ ENDIF(${UNINSTALL_CHECK_${NUM}})
+ MATH(EXPR NUM "1 + ${NUM}")
+ENDFOREACH(file)
+
+FILE(REMOVE "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/LICENSE b/tools/rasm/lzsa-master/src/libdivsufsort/LICENSE
new file mode 100644
index 0000000..249efa4
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2003 Yuta Mori All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), 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/tools/rasm/lzsa-master/src/libdivsufsort/README.md b/tools/rasm/lzsa-master/src/libdivsufsort/README.md
new file mode 100644
index 0000000..381a188
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/README.md
@@ -0,0 +1,140 @@
+# libdivsufsort
+
+libdivsufsort is a software library that implements a lightweight suffix array construction algorithm.
+
+## News
+* 2015-03-21: The project has moved from [Google Code](http://code.google.com/p/libdivsufsort/) to [GitHub](https://github.com/y-256/libdivsufsort)
+
+## Introduction
+This library provides a simple and an efficient C API to construct a suffix array and a Burrows-Wheeler transformed string from a given string over a constant-size alphabet.
+The algorithm runs in O(n log n) worst-case time using only 5n+O(1) bytes of memory space, where n is the length of
+the string.
+
+## Build requirements
+* An ANSI C Compiler (e.g. GNU GCC)
+* [CMake](http://www.cmake.org/ "CMake") version 2.4.2 or newer
+* CMake-supported build tool
+
+## Building on GNU/Linux
+1. Get the source code from GitHub. You can either
+ * use git to clone the repository
+ ```
+ git clone https://github.com/y-256/libdivsufsort.git
+ ```
+ * or download a [zip file](../../archive/master.zip) directly
+2. Create a `build` directory in the package source directory.
+```shell
+$ cd libdivsufsort
+$ mkdir build
+$ cd build
+```
+3. Configure the package for your system.
+If you want to install to a different location, change the -DCMAKE_INSTALL_PREFIX option.
+```shell
+$ cmake -DCMAKE_BUILD_TYPE="Release" \
+-DCMAKE_INSTALL_PREFIX="/usr/local" ..
+```
+4. Compile the package.
+```shell
+$ make
+```
+5. (Optional) Install the library and header files.
+```shell
+$ sudo make install
+```
+
+## API
+```c
+/* Data types */
+typedef int32_t saint_t;
+typedef int32_t saidx_t;
+typedef uint8_t sauchar_t;
+
+/*
+ * Constructs the suffix array of a given string.
+ * @param T[0..n-1] The input string.
+ * @param SA[0..n-1] The output array or suffixes.
+ * @param n The length of the given string.
+ * @return 0 if no error occurred, -1 or -2 otherwise.
+ */
+saint_t
+divsufsort(const sauchar_t *T, saidx_t *SA, saidx_t n);
+
+/*
+ * Constructs the burrows-wheeler transformed string of a given string.
+ * @param T[0..n-1] The input string.
+ * @param U[0..n-1] The output string. (can be T)
+ * @param A[0..n-1] The temporary array. (can be NULL)
+ * @param n The length of the given string.
+ * @return The primary index if no error occurred, -1 or -2 otherwise.
+ */
+saidx_t
+divbwt(const sauchar_t *T, sauchar_t *U, saidx_t *A, saidx_t n);
+```
+
+## Example Usage
+```c
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <divsufsort.h>
+
+int main() {
+ // intput data
+ char *Text = "abracadabra";
+ int n = strlen(Text);
+ int i, j;
+
+ // allocate
+ int *SA = (int *)malloc(n * sizeof(int));
+
+ // sort
+ divsufsort((unsigned char *)Text, SA, n);
+
+ // output
+ for(i = 0; i < n; ++i) {
+ printf("SA[%2d] = %2d: ", i, SA[i]);
+ for(j = SA[i]; j < n; ++j) {
+ printf("%c", Text[j]);
+ }
+ printf("$\n");
+ }
+
+ // deallocate
+ free(SA);
+
+ return 0;
+}
+```
+See the [examples](examples) directory for a few other examples.
+
+## Benchmarks
+See [Benchmarks](https://github.com/y-256/libdivsufsort/blob/wiki/SACA_Benchmarks.md) page for details.
+
+## License
+libdivsufsort is released under the [MIT license](LICENSE "MIT license").
+> The MIT License (MIT)
+>
+> Copyright (c) 2003 Yuta Mori All rights reserved.
+>
+> Permission is hereby granted, free of charge, to any person obtaining a copy
+> of this software and associated documentation files (the "Software"), 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.
+
+## Author
+* Yuta Mori
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/VERSION.cmake b/tools/rasm/lzsa-master/src/libdivsufsort/VERSION.cmake
new file mode 100644
index 0000000..3f11ac1
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/VERSION.cmake
@@ -0,0 +1,23 @@
+set(PROJECT_VERSION_MAJOR "2")
+set(PROJECT_VERSION_MINOR "0")
+set(PROJECT_VERSION_PATCH "2")
+set(PROJECT_VERSION_EXTRA "-1")
+set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
+set(PROJECT_VERSION_FULL "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${PROJECT_VERSION_EXTRA}")
+
+set(LIBRARY_VERSION "3.0.1")
+set(LIBRARY_SOVERSION "3")
+
+## Git revision number ##
+if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git")
+ execute_process(COMMAND git describe --tags HEAD
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ OUTPUT_VARIABLE GIT_DESCRIBE_TAGS ERROR_QUIET)
+ if(GIT_DESCRIBE_TAGS)
+ string(REGEX REPLACE "^v(.*)" "\\1" GIT_REVISION "${GIT_DESCRIBE_TAGS}")
+ string(STRIP "${GIT_REVISION}" GIT_REVISION)
+ if(GIT_REVISION)
+ set(PROJECT_VERSION_FULL "${GIT_REVISION}")
+ endif(GIT_REVISION)
+ endif(GIT_DESCRIBE_TAGS)
+endif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git")
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/examples/CMakeLists.txt b/tools/rasm/lzsa-master/src/libdivsufsort/examples/CMakeLists.txt
new file mode 100644
index 0000000..e801c81
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/examples/CMakeLists.txt
@@ -0,0 +1,11 @@
+## Add definitions ##
+add_definitions(-D_LARGEFILE_SOURCE -D_LARGE_FILES -D_FILE_OFFSET_BITS=64)
+
+## Targets ##
+include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../include"
+ "${CMAKE_CURRENT_BINARY_DIR}/../include")
+link_directories("${CMAKE_CURRENT_BINARY_DIR}/../lib")
+foreach(src suftest mksary sasearch bwt unbwt)
+ add_executable(${src} ${src}.c)
+ target_link_libraries(${src} divsufsort)
+endforeach(src)
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/examples/bwt.c b/tools/rasm/lzsa-master/src/libdivsufsort/examples/bwt.c
new file mode 100644
index 0000000..5a362d0
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/examples/bwt.c
@@ -0,0 +1,220 @@
+/*
+ * bwt.c for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+#if HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_IO_H && HAVE_FCNTL_H
+# include <io.h>
+# include <fcntl.h>
+#endif
+#include <time.h>
+#include <divsufsort.h>
+#include "lfs.h"
+
+
+static
+size_t
+write_int(FILE *fp, saidx_t n) {
+ unsigned char c[4];
+ c[0] = (unsigned char)((n >> 0) & 0xff), c[1] = (unsigned char)((n >> 8) & 0xff),
+ c[2] = (unsigned char)((n >> 16) & 0xff), c[3] = (unsigned char)((n >> 24) & 0xff);
+ return fwrite(c, sizeof(unsigned char), 4, fp);
+}
+
+static
+void
+print_help(const char *progname, int status) {
+ fprintf(stderr,
+ "bwt, a burrows-wheeler transform program, version %s.\n",
+ divsufsort_version());
+ fprintf(stderr, "usage: %s [-b num] INFILE OUTFILE\n", progname);
+ fprintf(stderr, " -b num set block size to num MiB [1..512] (default: 32)\n\n");
+ exit(status);
+}
+
+int
+main(int argc, const char *argv[]) {
+ FILE *fp, *ofp;
+ const char *fname, *ofname;
+ sauchar_t *T;
+ saidx_t *SA;
+ LFS_OFF_T n;
+ size_t m;
+ saidx_t pidx;
+ clock_t start,finish;
+ saint_t i, blocksize = 32, needclose = 3;
+
+ /* Check arguments. */
+ if((argc == 1) ||
+ (strcmp(argv[1], "-h") == 0) ||
+ (strcmp(argv[1], "--help") == 0)) { print_help(argv[0], EXIT_SUCCESS); }
+ if((argc != 3) && (argc != 5)) { print_help(argv[0], EXIT_FAILURE); }
+ i = 1;
+ if(argc == 5) {
+ if(strcmp(argv[i], "-b") != 0) { print_help(argv[0], EXIT_FAILURE); }
+ blocksize = atoi(argv[i + 1]);
+ if(blocksize < 0) { blocksize = 1; }
+ else if(512 < blocksize) { blocksize = 512; }
+ i += 2;
+ }
+ blocksize <<= 20;
+
+ /* Open a file for reading. */
+ if(strcmp(argv[i], "-") != 0) {
+#if HAVE_FOPEN_S
+ if(fopen_s(&fp, fname = argv[i], "rb") != 0) {
+#else
+ if((fp = LFS_FOPEN(fname = argv[i], "rb")) == NULL) {
+#endif
+ fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+#if HAVE__SETMODE && HAVE__FILENO
+ if(_setmode(_fileno(stdin), _O_BINARY) == -1) {
+ fprintf(stderr, "%s: Cannot set mode: ", argv[0]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+#endif
+ fp = stdin;
+ fname = "stdin";
+ needclose ^= 1;
+ }
+ i += 1;
+
+ /* Open a file for writing. */
+ if(strcmp(argv[i], "-") != 0) {
+#if HAVE_FOPEN_S
+ if(fopen_s(&ofp, ofname = argv[i], "wb") != 0) {
+#else
+ if((ofp = LFS_FOPEN(ofname = argv[i], "wb")) == NULL) {
+#endif
+ fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], ofname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+#if HAVE__SETMODE && HAVE__FILENO
+ if(_setmode(_fileno(stdout), _O_BINARY) == -1) {
+ fprintf(stderr, "%s: Cannot set mode: ", argv[0]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+#endif
+ ofp = stdout;
+ ofname = "stdout";
+ needclose ^= 2;
+ }
+
+ /* Get the file size. */
+ if(LFS_FSEEK(fp, 0, SEEK_END) == 0) {
+ n = LFS_FTELL(fp);
+ rewind(fp);
+ if(n < 0) {
+ fprintf(stderr, "%s: Cannot ftell `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ if(0x20000000L < n) { n = 0x20000000L; }
+ if((blocksize == 0) || (n < blocksize)) { blocksize = (saidx_t)n; }
+ } else if(blocksize == 0) { blocksize = 32 << 20; }
+
+ /* Allocate 5blocksize bytes of memory. */
+ T = (sauchar_t *)malloc(blocksize * sizeof(sauchar_t));
+ SA = (saidx_t *)malloc(blocksize * sizeof(saidx_t));
+ if((T == NULL) || (SA == NULL)) {
+ fprintf(stderr, "%s: Cannot allocate memory.\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Write the blocksize. */
+ if(write_int(ofp, blocksize) != 4) {
+ fprintf(stderr, "%s: Cannot write to `%s': ", argv[0], ofname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ fprintf(stderr, " BWT (blocksize %" PRIdSAINT_T ") ... ", blocksize);
+ start = clock();
+ for(n = 0; 0 < (m = fread(T, sizeof(sauchar_t), blocksize, fp)); n += m) {
+ /* Burrows-Wheeler Transform. */
+ pidx = divbwt(T, T, SA, m);
+ if(pidx < 0) {
+ fprintf(stderr, "%s (bw_transform): %s.\n",
+ argv[0],
+ (pidx == -1) ? "Invalid arguments" : "Cannot allocate memory");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Write the bwted data. */
+ if((write_int(ofp, pidx) != 4) ||
+ (fwrite(T, sizeof(sauchar_t), m, ofp) != m)) {
+ fprintf(stderr, "%s: Cannot write to `%s': ", argv[0], ofname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ }
+ if(ferror(fp)) {
+ fprintf(stderr, "%s: Cannot read from `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ finish = clock();
+ fprintf(stderr, "%" PRIdOFF_T " bytes: %.4f sec\n",
+ n, (double)(finish - start) / (double)CLOCKS_PER_SEC);
+
+ /* Close files */
+ if(needclose & 1) { fclose(fp); }
+ if(needclose & 2) { fclose(ofp); }
+
+ /* Deallocate memory. */
+ free(SA);
+ free(T);
+
+ return 0;
+}
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/examples/mksary.c b/tools/rasm/lzsa-master/src/libdivsufsort/examples/mksary.c
new file mode 100644
index 0000000..b48177c
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/examples/mksary.c
@@ -0,0 +1,193 @@
+/*
+ * mksary.c for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+#if HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_IO_H && HAVE_FCNTL_H
+# include <io.h>
+# include <fcntl.h>
+#endif
+#include <time.h>
+#include <divsufsort.h>
+#include "lfs.h"
+
+
+static
+void
+print_help(const char *progname, int status) {
+ fprintf(stderr,
+ "mksary, a simple suffix array builder, version %s.\n",
+ divsufsort_version());
+ fprintf(stderr, "usage: %s INFILE OUTFILE\n\n", progname);
+ exit(status);
+}
+
+int
+main(int argc, const char *argv[]) {
+ FILE *fp, *ofp;
+ const char *fname, *ofname;
+ sauchar_t *T;
+ saidx_t *SA;
+ LFS_OFF_T n;
+ clock_t start, finish;
+ saint_t needclose = 3;
+
+ /* Check arguments. */
+ if((argc == 1) ||
+ (strcmp(argv[1], "-h") == 0) ||
+ (strcmp(argv[1], "--help") == 0)) { print_help(argv[0], EXIT_SUCCESS); }
+ if(argc != 3) { print_help(argv[0], EXIT_FAILURE); }
+
+ /* Open a file for reading. */
+ if(strcmp(argv[1], "-") != 0) {
+#if HAVE_FOPEN_S
+ if(fopen_s(&fp, fname = argv[1], "rb") != 0) {
+#else
+ if((fp = LFS_FOPEN(fname = argv[1], "rb")) == NULL) {
+#endif
+ fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+#if HAVE__SETMODE && HAVE__FILENO
+ if(_setmode(_fileno(stdin), _O_BINARY) == -1) {
+ fprintf(stderr, "%s: Cannot set mode: ", argv[0]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+#endif
+ fp = stdin;
+ fname = "stdin";
+ needclose ^= 1;
+ }
+
+ /* Open a file for writing. */
+ if(strcmp(argv[2], "-") != 0) {
+#if HAVE_FOPEN_S
+ if(fopen_s(&ofp, ofname = argv[2], "wb") != 0) {
+#else
+ if((ofp = LFS_FOPEN(ofname = argv[2], "wb")) == NULL) {
+#endif
+ fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], ofname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+#if HAVE__SETMODE && HAVE__FILENO
+ if(_setmode(_fileno(stdout), _O_BINARY) == -1) {
+ fprintf(stderr, "%s: Cannot set mode: ", argv[0]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+#endif
+ ofp = stdout;
+ ofname = "stdout";
+ needclose ^= 2;
+ }
+
+ /* Get the file size. */
+ if(LFS_FSEEK(fp, 0, SEEK_END) == 0) {
+ n = LFS_FTELL(fp);
+ rewind(fp);
+ if(n < 0) {
+ fprintf(stderr, "%s: Cannot ftell `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ if(0x7fffffff <= n) {
+ fprintf(stderr, "%s: Input file `%s' is too big.\n", argv[0], fname);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ fprintf(stderr, "%s: Cannot fseek `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Allocate 5blocksize bytes of memory. */
+ T = (sauchar_t *)malloc((size_t)n * sizeof(sauchar_t));
+ SA = (saidx_t *)malloc((size_t)n * sizeof(saidx_t));
+ if((T == NULL) || (SA == NULL)) {
+ fprintf(stderr, "%s: Cannot allocate memory.\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Read n bytes of data. */
+ if(fread(T, sizeof(sauchar_t), (size_t)n, fp) != (size_t)n) {
+ fprintf(stderr, "%s: %s `%s': ",
+ argv[0],
+ (ferror(fp) || !feof(fp)) ? "Cannot read from" : "Unexpected EOF in",
+ fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ if(needclose & 1) { fclose(fp); }
+
+ /* Construct the suffix array. */
+ fprintf(stderr, "%s: %" PRIdOFF_T " bytes ... ", fname, n);
+ start = clock();
+ if(divsufsort(T, SA, (saidx_t)n) != 0) {
+ fprintf(stderr, "%s: Cannot allocate memory.\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ finish = clock();
+ fprintf(stderr, "%.4f sec\n", (double)(finish - start) / (double)CLOCKS_PER_SEC);
+
+ /* Write the suffix array. */
+ if(fwrite(SA, sizeof(saidx_t), (size_t)n, ofp) != (size_t)n) {
+ fprintf(stderr, "%s: Cannot write to `%s': ", argv[0], ofname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ if(needclose & 2) { fclose(ofp); }
+
+ /* Deallocate memory. */
+ free(SA);
+ free(T);
+
+ return 0;
+}
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/examples/sasearch.c b/tools/rasm/lzsa-master/src/libdivsufsort/examples/sasearch.c
new file mode 100644
index 0000000..7e5ca4f
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/examples/sasearch.c
@@ -0,0 +1,165 @@
+/*
+ * sasearch.c for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+#if HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_IO_H && HAVE_FCNTL_H
+# include <io.h>
+# include <fcntl.h>
+#endif
+#include <divsufsort.h>
+#include "lfs.h"
+
+
+static
+void
+print_help(const char *progname, int status) {
+ fprintf(stderr,
+ "sasearch, a simple SA-based full-text search tool, version %s\n",
+ divsufsort_version());
+ fprintf(stderr, "usage: %s PATTERN FILE SAFILE\n\n", progname);
+ exit(status);
+}
+
+int
+main(int argc, const char *argv[]) {
+ FILE *fp;
+ const char *P;
+ sauchar_t *T;
+ saidx_t *SA;
+ LFS_OFF_T n;
+ size_t Psize;
+ saidx_t i, size, left;
+
+ if((argc == 1) ||
+ (strcmp(argv[1], "-h") == 0) ||
+ (strcmp(argv[1], "--help") == 0)) { print_help(argv[0], EXIT_SUCCESS); }
+ if(argc != 4) { print_help(argv[0], EXIT_FAILURE); }
+
+ P = argv[1];
+ Psize = strlen(P);
+
+ /* Open a file for reading. */
+#if HAVE_FOPEN_S
+ if(fopen_s(&fp, argv[2], "rb") != 0) {
+#else
+ if((fp = LFS_FOPEN(argv[2], "rb")) == NULL) {
+#endif
+ fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], argv[2]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Get the file size. */
+ if(LFS_FSEEK(fp, 0, SEEK_END) == 0) {
+ n = LFS_FTELL(fp);
+ rewind(fp);
+ if(n < 0) {
+ fprintf(stderr, "%s: Cannot ftell `%s': ", argv[0], argv[2]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ fprintf(stderr, "%s: Cannot fseek `%s': ", argv[0], argv[2]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Allocate 5n bytes of memory. */
+ T = (sauchar_t *)malloc((size_t)n * sizeof(sauchar_t));
+ SA = (saidx_t *)malloc((size_t)n * sizeof(saidx_t));
+ if((T == NULL) || (SA == NULL)) {
+ fprintf(stderr, "%s: Cannot allocate memory.\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Read n bytes of data. */
+ if(fread(T, sizeof(sauchar_t), (size_t)n, fp) != (size_t)n) {
+ fprintf(stderr, "%s: %s `%s': ",
+ argv[0],
+ (ferror(fp) || !feof(fp)) ? "Cannot read from" : "Unexpected EOF in",
+ argv[2]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ fclose(fp);
+
+ /* Open the SA file for reading. */
+#if HAVE_FOPEN_S
+ if(fopen_s(&fp, argv[3], "rb") != 0) {
+#else
+ if((fp = LFS_FOPEN(argv[3], "rb")) == NULL) {
+#endif
+ fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], argv[3]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Read n * sizeof(saidx_t) bytes of data. */
+ if(fread(SA, sizeof(saidx_t), (size_t)n, fp) != (size_t)n) {
+ fprintf(stderr, "%s: %s `%s': ",
+ argv[0],
+ (ferror(fp) || !feof(fp)) ? "Cannot read from" : "Unexpected EOF in",
+ argv[3]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ fclose(fp);
+
+ /* Search and print */
+ size = sa_search(T, (saidx_t)n,
+ (const sauchar_t *)P, (saidx_t)Psize,
+ SA, (saidx_t)n, &left);
+ for(i = 0; i < size; ++i) {
+ fprintf(stdout, "%" PRIdSAIDX_T "\n", SA[left + i]);
+ }
+
+ /* Deallocate memory. */
+ free(SA);
+ free(T);
+
+ return 0;
+}
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/examples/suftest.c b/tools/rasm/lzsa-master/src/libdivsufsort/examples/suftest.c
new file mode 100644
index 0000000..71892ac
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/examples/suftest.c
@@ -0,0 +1,164 @@
+/*
+ * suftest.c for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+#if HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_IO_H && HAVE_FCNTL_H
+# include <io.h>
+# include <fcntl.h>
+#endif
+#include <time.h>
+#include <divsufsort.h>
+#include "lfs.h"
+
+
+static
+void
+print_help(const char *progname, int status) {
+ fprintf(stderr,
+ "suftest, a suffixsort tester, version %s.\n",
+ divsufsort_version());
+ fprintf(stderr, "usage: %s FILE\n\n", progname);
+ exit(status);
+}
+
+int
+main(int argc, const char *argv[]) {
+ FILE *fp;
+ const char *fname;
+ sauchar_t *T;
+ saidx_t *SA;
+ LFS_OFF_T n;
+ clock_t start, finish;
+ saint_t needclose = 1;
+
+ /* Check arguments. */
+ if((argc == 1) ||
+ (strcmp(argv[1], "-h") == 0) ||
+ (strcmp(argv[1], "--help") == 0)) { print_help(argv[0], EXIT_SUCCESS); }
+ if(argc != 2) { print_help(argv[0], EXIT_FAILURE); }
+
+ /* Open a file for reading. */
+ if(strcmp(argv[1], "-") != 0) {
+#if HAVE_FOPEN_S
+ if(fopen_s(&fp, fname = argv[1], "rb") != 0) {
+#else
+ if((fp = LFS_FOPEN(fname = argv[1], "rb")) == NULL) {
+#endif
+ fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+#if HAVE__SETMODE && HAVE__FILENO
+ if(_setmode(_fileno(stdin), _O_BINARY) == -1) {
+ fprintf(stderr, "%s: Cannot set mode: ", argv[0]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+#endif
+ fp = stdin;
+ fname = "stdin";
+ needclose = 0;
+ }
+
+ /* Get the file size. */
+ if(LFS_FSEEK(fp, 0, SEEK_END) == 0) {
+ n = LFS_FTELL(fp);
+ rewind(fp);
+ if(n < 0) {
+ fprintf(stderr, "%s: Cannot ftell `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ if(0x7fffffff <= n) {
+ fprintf(stderr, "%s: Input file `%s' is too big.\n", argv[0], fname);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ fprintf(stderr, "%s: Cannot fseek `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Allocate 5n bytes of memory. */
+ T = (sauchar_t *)malloc((size_t)n * sizeof(sauchar_t));
+ SA = (saidx_t *)malloc((size_t)n * sizeof(saidx_t));
+ if((T == NULL) || (SA == NULL)) {
+ fprintf(stderr, "%s: Cannot allocate memory.\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Read n bytes of data. */
+ if(fread(T, sizeof(sauchar_t), (size_t)n, fp) != (size_t)n) {
+ fprintf(stderr, "%s: %s `%s': ",
+ argv[0],
+ (ferror(fp) || !feof(fp)) ? "Cannot read from" : "Unexpected EOF in",
+ argv[1]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ if(needclose & 1) { fclose(fp); }
+
+ /* Construct the suffix array. */
+ fprintf(stderr, "%s: %" PRIdOFF_T " bytes ... ", fname, n);
+ start = clock();
+ if(divsufsort(T, SA, (saidx_t)n) != 0) {
+ fprintf(stderr, "%s: Cannot allocate memory.\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ finish = clock();
+ fprintf(stderr, "%.4f sec\n", (double)(finish - start) / (double)CLOCKS_PER_SEC);
+
+ /* Check the suffix array. */
+ if(sufcheck(T, SA, (saidx_t)n, 1) != 0) { exit(EXIT_FAILURE); }
+
+ /* Deallocate memory. */
+ free(SA);
+ free(T);
+
+ return 0;
+}
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/examples/unbwt.c b/tools/rasm/lzsa-master/src/libdivsufsort/examples/unbwt.c
new file mode 100644
index 0000000..c0f19e9
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/examples/unbwt.c
@@ -0,0 +1,207 @@
+/*
+ * unbwt.c for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+#if HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_IO_H && HAVE_FCNTL_H
+# include <io.h>
+# include <fcntl.h>
+#endif
+#include <time.h>
+#include <divsufsort.h>
+#include "lfs.h"
+
+
+static
+size_t
+read_int(FILE *fp, saidx_t *n) {
+ unsigned char c[4];
+ size_t m = fread(c, sizeof(unsigned char), 4, fp);
+ if(m == 4) {
+ *n = (c[0] << 0) | (c[1] << 8) |
+ (c[2] << 16) | (c[3] << 24);
+ }
+ return m;
+}
+
+static
+void
+print_help(const char *progname, int status) {
+ fprintf(stderr,
+ "unbwt, an inverse burrows-wheeler transform program, version %s.\n",
+ divsufsort_version());
+ fprintf(stderr, "usage: %s INFILE OUTFILE\n\n", progname);
+ exit(status);
+}
+
+int
+main(int argc, const char *argv[]) {
+ FILE *fp, *ofp;
+ const char *fname, *ofname;
+ sauchar_t *T;
+ saidx_t *A;
+ LFS_OFF_T n;
+ size_t m;
+ saidx_t pidx;
+ clock_t start, finish;
+ saint_t err, blocksize, needclose = 3;
+
+ /* Check arguments. */
+ if((argc == 1) ||
+ (strcmp(argv[1], "-h") == 0) ||
+ (strcmp(argv[1], "--help") == 0)) { print_help(argv[0], EXIT_SUCCESS); }
+ if(argc != 3) { print_help(argv[0], EXIT_FAILURE); }
+
+ /* Open a file for reading. */
+ if(strcmp(argv[1], "-") != 0) {
+#if HAVE_FOPEN_S
+ if(fopen_s(&fp, fname = argv[1], "rb") != 0) {
+#else
+ if((fp = LFS_FOPEN(fname = argv[1], "rb")) == NULL) {
+#endif
+ fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+#if HAVE__SETMODE && HAVE__FILENO
+ if(_setmode(_fileno(stdin), _O_BINARY) == -1) {
+ fprintf(stderr, "%s: Cannot set mode: ", argv[0]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+#endif
+ fp = stdin;
+ fname = "stdin";
+ needclose ^= 1;
+ }
+
+ /* Open a file for writing. */
+ if(strcmp(argv[2], "-") != 0) {
+#if HAVE_FOPEN_S
+ if(fopen_s(&ofp, ofname = argv[2], "wb") != 0) {
+#else
+ if((ofp = LFS_FOPEN(ofname = argv[2], "wb")) == NULL) {
+#endif
+ fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], ofname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+#if HAVE__SETMODE && HAVE__FILENO
+ if(_setmode(_fileno(stdout), _O_BINARY) == -1) {
+ fprintf(stderr, "%s: Cannot set mode: ", argv[0]);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+#endif
+ ofp = stdout;
+ ofname = "stdout";
+ needclose ^= 2;
+ }
+
+ /* Read the blocksize. */
+ if(read_int(fp, &blocksize) != 4) {
+ fprintf(stderr, "%s: Cannot read from `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Allocate 5blocksize bytes of memory. */
+ T = (sauchar_t *)malloc(blocksize * sizeof(sauchar_t));
+ A = (saidx_t *)malloc(blocksize * sizeof(saidx_t));
+ if((T == NULL) || (A == NULL)) {
+ fprintf(stderr, "%s: Cannot allocate memory.\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ fprintf(stderr, "UnBWT (blocksize %" PRIdSAINT_T ") ... ", blocksize);
+ start = clock();
+ for(n = 0; (m = read_int(fp, &pidx)) != 0; n += m) {
+ /* Read blocksize bytes of data. */
+ if((m != 4) || ((m = fread(T, sizeof(sauchar_t), blocksize, fp)) == 0)) {
+ fprintf(stderr, "%s: %s `%s': ",
+ argv[0],
+ (ferror(fp) || !feof(fp)) ? "Cannot read from" : "Unexpected EOF in",
+ fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Inverse Burrows-Wheeler Transform. */
+ if((err = inverse_bw_transform(T, T, A, m, pidx)) != 0) {
+ fprintf(stderr, "%s (reverseBWT): %s.\n",
+ argv[0],
+ (err == -1) ? "Invalid data" : "Cannot allocate memory");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Write m bytes of data. */
+ if(fwrite(T, sizeof(sauchar_t), m, ofp) != m) {
+ fprintf(stderr, "%s: Cannot write to `%s': ", argv[0], ofname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ }
+ if(ferror(fp)) {
+ fprintf(stderr, "%s: Cannot read from `%s': ", argv[0], fname);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ finish = clock();
+ fprintf(stderr, "%" PRIdOFF_T " bytes: %.4f sec\n",
+ n, (double)(finish - start) / (double)CLOCKS_PER_SEC);
+
+ /* Close files */
+ if(needclose & 1) { fclose(fp); }
+ if(needclose & 2) { fclose(ofp); }
+
+ /* Deallocate memory. */
+ free(A);
+ free(T);
+
+ return 0;
+}
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/include/CMakeLists.txt b/tools/rasm/lzsa-master/src/libdivsufsort/include/CMakeLists.txt
new file mode 100644
index 0000000..37781cc
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/include/CMakeLists.txt
@@ -0,0 +1,162 @@
+include(CheckIncludeFiles)
+include(CheckIncludeFile)
+include(CheckSymbolExists)
+include(CheckTypeSize)
+include(CheckFunctionKeywords)
+include(CheckLFS)
+
+## Checks for header files ##
+check_include_file("inttypes.h" HAVE_INTTYPES_H)
+check_include_file("memory.h" HAVE_MEMORY_H)
+check_include_file("stddef.h" HAVE_STDDEF_H)
+check_include_file("stdint.h" HAVE_STDINT_H)
+check_include_file("stdlib.h" HAVE_STDLIB_H)
+check_include_file("string.h" HAVE_STRING_H)
+check_include_file("strings.h" HAVE_STRINGS_H)
+check_include_file("sys/types.h" HAVE_SYS_TYPES_H)
+if(HAVE_INTTYPES_H)
+ set(INCFILE "#include <inttypes.h>")
+elseif(HAVE_STDINT_H)
+ set(INCFILE "#include <stdint.h>")
+else(HAVE_INTTYPES_H)
+ set(INCFILE "")
+endif(HAVE_INTTYPES_H)
+
+## create configuration files from .cmake file ##
+if(BUILD_EXAMPLES)
+ ## Checks for WinIO ##
+ if(WIN32)
+ check_include_file("io.h" HAVE_IO_H)
+ check_include_file("fcntl.h" HAVE_FCNTL_H)
+ check_symbol_exists("_setmode" "io.h;fcntl.h" HAVE__SETMODE)
+ if(NOT HAVE__SETMODE)
+ check_symbol_exists("setmode" "io.h;fcntl.h" HAVE_SETMODE)
+ endif(NOT HAVE__SETMODE)
+ check_symbol_exists("_fileno" "stdio.h" HAVE__FILENO)
+ check_symbol_exists("fopen_s" "stdio.h" HAVE_FOPEN_S)
+ check_symbol_exists("_O_BINARY" "fcntl.h" HAVE__O_BINARY)
+ endif(WIN32)
+
+ ## Checks for large file support ##
+ check_lfs(WITH_LFS)
+ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/lfs.h.cmake" "${CMAKE_CURRENT_BINARY_DIR}/lfs.h" @ONLY)
+endif(BUILD_EXAMPLES)
+
+## generate config.h ##
+check_function_keywords("inline;__inline;__inline__;__declspec(dllexport);__declspec(dllimport)")
+if(HAVE_INLINE)
+ set(INLINE "inline")
+elseif(HAVE___INLINE)
+ set(INLINE "__inline")
+elseif(HAVE___INLINE__)
+ set(INLINE "__inline__")
+else(HAVE_INLINE)
+ set(INLINE "")
+endif(HAVE_INLINE)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake" "${CMAKE_CURRENT_BINARY_DIR}/config.h")
+
+## Checks for types ##
+# sauchar_t (8bit)
+check_type_size("uint8_t" UINT8_T)
+if(HAVE_UINT8_T)
+ set(SAUCHAR_TYPE "uint8_t")
+else(HAVE_UINT8_T)
+ check_type_size("unsigned char" SIZEOF_UNSIGNED_CHAR)
+ if("${SIZEOF_UNSIGNED_CHAR}" STREQUAL "1")
+ set(SAUCHAR_TYPE "unsigned char")
+ else("${SIZEOF_UNSIGNED_CHAR}" STREQUAL "1")
+ message(FATAL_ERROR "Cannot find unsigned 8-bit integer type")
+ endif("${SIZEOF_UNSIGNED_CHAR}" STREQUAL "1")
+endif(HAVE_UINT8_T)
+# saint_t (32bit)
+check_type_size("int32_t" INT32_T)
+if(HAVE_INT32_T)
+ set(SAINT32_TYPE "int32_t")
+ check_symbol_exists("PRId32" "inttypes.h" HAVE_PRID32)
+ if(HAVE_PRID32)
+ set(SAINT32_PRId "PRId32")
+ else(HAVE_PRID32)
+ set(SAINT32_PRId "\"d\"")
+ endif(HAVE_PRID32)
+else(HAVE_INT32_T)
+ check_type_size("int" SIZEOF_INT)
+ check_type_size("long" SIZEOF_LONG)
+ check_type_size("short" SIZEOF_SHORT)
+ check_type_size("__int32" SIZEOF___INT32)
+ if("${SIZEOF_INT}" STREQUAL "4")
+ set(SAINT32_TYPE "int")
+ set(SAINT32_PRId "\"d\"")
+ elseif("${SIZEOF_LONG}" STREQUAL "4")
+ set(SAINT32_TYPE "long")
+ set(SAINT32_PRId "\"ld\"")
+ elseif("${SIZEOF_SHORT}" STREQUAL "4")
+ set(SAINT32_TYPE "short")
+ set(SAINT32_PRId "\"d\"")
+ elseif("${SIZEOF___INT32}" STREQUAL "4")
+ set(SAINT32_TYPE "__int32")
+ set(SAINT32_PRId "\"d\"")
+ else("${SIZEOF_INT}" STREQUAL "4")
+ message(FATAL_ERROR "Cannot find 32-bit integer type")
+ endif("${SIZEOF_INT}" STREQUAL "4")
+endif(HAVE_INT32_T)
+# saint64_t (64bit)
+if(BUILD_DIVSUFSORT64)
+ check_type_size("int64_t" INT64_T)
+ if(HAVE_INT64_T)
+ set(SAINT64_TYPE "int64_t")
+ check_symbol_exists("PRId64" "inttypes.h" HAVE_PRID64)
+ if(HAVE_PRID64)
+ set(SAINT64_PRId "PRId64")
+ else(HAVE_PRID64)
+ set(SAINT64_PRId "\"lld\"")
+ endif(HAVE_PRID64)
+ else(HAVE_INT64_T)
+ check_type_size("int" SIZEOF_INT)
+ check_type_size("long" SIZEOF_LONG)
+ check_type_size("long long" SIZEOF_LONG_LONG)
+ check_type_size("__int64" SIZEOF___INT64)
+ if("${SIZEOF_INT}" STREQUAL "8")
+ set(SAINT64_TYPE "int")
+ set(SAINT64_PRId "\"d\"")
+ elseif("${SIZEOF_LONG}" STREQUAL "8")
+ set(SAINT64_TYPE "long")
+ set(SAINT64_PRId "\"ld\"")
+ elseif("${SIZEOF_LONG_LONG}" STREQUAL "8")
+ set(SAINT64_TYPE "long long")
+ set(SAINT64_PRId "\"lld\"")
+ elseif("${SIZEOF___INT64}" STREQUAL "8")
+ set(SAINT64_TYPE "__int64")
+ set(SAINT64_PRId "\"I64d\"")
+ else("${SIZEOF_INT}" STREQUAL "8")
+ message(SEND_ERROR "Cannot find 64-bit integer type")
+ set(BUILD_DIVSUFSORT64 OFF)
+ endif("${SIZEOF_INT}" STREQUAL "8")
+ endif(HAVE_INT64_T)
+endif(BUILD_DIVSUFSORT64)
+
+## generate divsufsort.h ##
+set(DIVSUFSORT_IMPORT "")
+set(DIVSUFSORT_EXPORT "")
+if(BUILD_SHARED_LIBS)
+ if(HAVE___DECLSPEC_DLLIMPORT_)
+ set(DIVSUFSORT_IMPORT "__declspec(dllimport)")
+ endif(HAVE___DECLSPEC_DLLIMPORT_)
+ if(HAVE___DECLSPEC_DLLEXPORT_)
+ set(DIVSUFSORT_EXPORT "__declspec(dllexport)")
+ endif(HAVE___DECLSPEC_DLLEXPORT_)
+endif(BUILD_SHARED_LIBS)
+set(W64BIT "")
+set(SAINDEX_TYPE "${SAINT32_TYPE}")
+set(SAINDEX_PRId "${SAINT32_PRId}")
+set(SAINT_PRId "${SAINT32_PRId}")
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/divsufsort.h.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/divsufsort.h" @ONLY)
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/divsufsort.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+if(BUILD_DIVSUFSORT64)
+ set(W64BIT "64")
+ set(SAINDEX_TYPE "${SAINT64_TYPE}")
+ set(SAINDEX_PRId "${SAINT64_PRId}")
+ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/divsufsort.h.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/divsufsort64.h" @ONLY)
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/divsufsort64.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+endif(BUILD_DIVSUFSORT64)
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/include/config.h.cmake b/tools/rasm/lzsa-master/src/libdivsufsort/include/config.h.cmake
new file mode 100644
index 0000000..6a1cf47
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/include/config.h.cmake
@@ -0,0 +1,81 @@
+/*
+ * config.h for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#ifndef _CONFIG_H
+#define _CONFIG_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/** Define to the version of this package. **/
+#cmakedefine PROJECT_VERSION_FULL "${PROJECT_VERSION_FULL}"
+
+/** Define to 1 if you have the header files. **/
+#cmakedefine HAVE_INTTYPES_H 1
+#cmakedefine HAVE_STDDEF_H 1
+#cmakedefine HAVE_STDINT_H 1
+#cmakedefine HAVE_STDLIB_H 1
+#cmakedefine HAVE_STRING_H 1
+#cmakedefine HAVE_STRINGS_H 1
+#cmakedefine HAVE_MEMORY_H 1
+#cmakedefine HAVE_SYS_TYPES_H 1
+
+/** for WinIO **/
+#cmakedefine HAVE_IO_H 1
+#cmakedefine HAVE_FCNTL_H 1
+#cmakedefine HAVE__SETMODE 1
+#cmakedefine HAVE_SETMODE 1
+#cmakedefine HAVE__FILENO 1
+#cmakedefine HAVE_FOPEN_S 1
+#cmakedefine HAVE__O_BINARY 1
+#ifndef HAVE__SETMODE
+# if HAVE_SETMODE
+# define _setmode setmode
+# define HAVE__SETMODE 1
+# endif
+# if HAVE__SETMODE && !HAVE__O_BINARY
+# define _O_BINARY 0
+# define HAVE__O_BINARY 1
+# endif
+#endif
+
+/** for inline **/
+#ifndef INLINE
+# define INLINE @INLINE@
+#endif
+
+/** for VC++ warning **/
+#ifdef _MSC_VER
+#pragma warning(disable: 4127)
+#endif
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* _CONFIG_H */
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/include/divsufsort.h b/tools/rasm/lzsa-master/src/libdivsufsort/include/divsufsort.h
new file mode 100755
index 0000000..7ebb412
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/include/divsufsort.h
@@ -0,0 +1,189 @@
+/*
+ * divsufsort.h for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#ifndef _DIVSUFSORT_H
+#define _DIVSUFSORT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define DIVSUFSORT_API
+
+/*- Datatypes -*/
+#ifndef SAUCHAR_T
+#define SAUCHAR_T
+typedef unsigned char sauchar_t;
+#endif /* SAUCHAR_T */
+#ifndef SAINT_T
+#define SAINT_T
+typedef int saint_t;
+#endif /* SAINT_T */
+#ifndef SAIDX_T
+#define SAIDX_T
+typedef int saidx_t;
+#endif /* SAIDX_T */
+#ifndef PRIdSAIDX_T
+#define PRIdSAIDX_T "d"
+#endif
+
+/*- divsufsort context */
+typedef struct _divsufsort_ctx_t {
+ saidx_t *bucket_A;
+ saidx_t *bucket_B;
+} divsufsort_ctx_t;
+
+/*- Prototypes -*/
+
+/**
+ * Initialize suffix array context
+ *
+ * @return 0 for success, or non-zero in case of an error
+ */
+int divsufsort_init(divsufsort_ctx_t *ctx);
+
+/**
+ * Destroy suffix array context
+ *
+ * @param ctx suffix array context to destroy
+ */
+void divsufsort_destroy(divsufsort_ctx_t *ctx);
+
+/**
+ * Constructs the suffix array of a given string.
+ * @param ctx suffix array context
+ * @param T[0..n-1] The input string.
+ * @param SA[0..n-1] The output array of suffixes.
+ * @param n The length of the given string.
+ * @return 0 if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saint_t divsufsort_build_array(divsufsort_ctx_t *ctx, const sauchar_t *T, saidx_t *SA, saidx_t n);
+
+#if 0
+/**
+ * Constructs the burrows-wheeler transformed string of a given string.
+ * @param T[0..n-1] The input string.
+ * @param U[0..n-1] The output string. (can be T)
+ * @param A[0..n-1] The temporary array. (can be NULL)
+ * @param n The length of the given string.
+ * @return The primary index if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saidx_t
+divbwt(const sauchar_t *T, sauchar_t *U, saidx_t *A, saidx_t n);
+
+/**
+ * Returns the version of the divsufsort library.
+ * @return The version number string.
+ */
+DIVSUFSORT_API
+const char *
+divsufsort_version(void);
+
+
+/**
+ * Constructs the burrows-wheeler transformed string of a given string and suffix array.
+ * @param T[0..n-1] The input string.
+ * @param U[0..n-1] The output string. (can be T)
+ * @param SA[0..n-1] The suffix array. (can be NULL)
+ * @param n The length of the given string.
+ * @param idx The output primary index.
+ * @return 0 if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saint_t
+bw_transform(const sauchar_t *T, sauchar_t *U,
+ saidx_t *SA /* can NULL */,
+ saidx_t n, saidx_t *idx);
+
+/**
+ * Inverse BW-transforms a given BWTed string.
+ * @param T[0..n-1] The input string.
+ * @param U[0..n-1] The output string. (can be T)
+ * @param A[0..n-1] The temporary array. (can be NULL)
+ * @param n The length of the given string.
+ * @param idx The primary index.
+ * @return 0 if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saint_t
+inverse_bw_transform(const sauchar_t *T, sauchar_t *U,
+ saidx_t *A /* can NULL */,
+ saidx_t n, saidx_t idx);
+
+/**
+ * Checks the correctness of a given suffix array.
+ * @param T[0..n-1] The input string.
+ * @param SA[0..n-1] The input suffix array.
+ * @param n The length of the given string.
+ * @param verbose The verbose mode.
+ * @return 0 if no error occurred.
+ */
+DIVSUFSORT_API
+saint_t
+sufcheck(const sauchar_t *T, const saidx_t *SA, saidx_t n, saint_t verbose);
+
+/**
+ * Search for the pattern P in the string T.
+ * @param T[0..Tsize-1] The input string.
+ * @param Tsize The length of the given string.
+ * @param P[0..Psize-1] The input pattern string.
+ * @param Psize The length of the given pattern string.
+ * @param SA[0..SAsize-1] The input suffix array.
+ * @param SAsize The length of the given suffix array.
+ * @param idx The output index.
+ * @return The count of matches if no error occurred, -1 otherwise.
+ */
+DIVSUFSORT_API
+saidx_t
+sa_search(const sauchar_t *T, saidx_t Tsize,
+ const sauchar_t *P, saidx_t Psize,
+ const saidx_t *SA, saidx_t SAsize,
+ saidx_t *left);
+
+/**
+ * Search for the character c in the string T.
+ * @param T[0..Tsize-1] The input string.
+ * @param Tsize The length of the given string.
+ * @param SA[0..SAsize-1] The input suffix array.
+ * @param SAsize The length of the given suffix array.
+ * @param c The input character.
+ * @param idx The output index.
+ * @return The count of matches if no error occurred, -1 otherwise.
+ */
+DIVSUFSORT_API
+saidx_t
+sa_simplesearch(const sauchar_t *T, saidx_t Tsize,
+ const saidx_t *SA, saidx_t SAsize,
+ saint_t c, saidx_t *left);
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* _DIVSUFSORT_H */
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/include/divsufsort.h.cmake b/tools/rasm/lzsa-master/src/libdivsufsort/include/divsufsort.h.cmake
new file mode 100644
index 0000000..bcaba7c
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/include/divsufsort.h.cmake
@@ -0,0 +1,180 @@
+/*
+ * divsufsort@W64BIT@.h for libdivsufsort@W64BIT@
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#ifndef _DIVSUFSORT@W64BIT@_H
+#define _DIVSUFSORT@W64BIT@_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+@INCFILE@
+
+#ifndef DIVSUFSORT_API
+# ifdef DIVSUFSORT_BUILD_DLL
+# define DIVSUFSORT_API @DIVSUFSORT_EXPORT@
+# else
+# define DIVSUFSORT_API @DIVSUFSORT_IMPORT@
+# endif
+#endif
+
+/*- Datatypes -*/
+#ifndef SAUCHAR_T
+#define SAUCHAR_T
+typedef @SAUCHAR_TYPE@ sauchar_t;
+#endif /* SAUCHAR_T */
+#ifndef SAINT_T
+#define SAINT_T
+typedef @SAINT32_TYPE@ saint_t;
+#endif /* SAINT_T */
+#ifndef SAIDX@W64BIT@_T
+#define SAIDX@W64BIT@_T
+typedef @SAINDEX_TYPE@ saidx@W64BIT@_t;
+#endif /* SAIDX@W64BIT@_T */
+#ifndef PRIdSAINT_T
+#define PRIdSAINT_T @SAINT_PRId@
+#endif /* PRIdSAINT_T */
+#ifndef PRIdSAIDX@W64BIT@_T
+#define PRIdSAIDX@W64BIT@_T @SAINDEX_PRId@
+#endif /* PRIdSAIDX@W64BIT@_T */
+
+
+/*- Prototypes -*/
+
+/**
+ * Constructs the suffix array of a given string.
+ * @param T[0..n-1] The input string.
+ * @param SA[0..n-1] The output array of suffixes.
+ * @param n The length of the given string.
+ * @return 0 if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saint_t
+divsufsort@W64BIT@(const sauchar_t *T, saidx@W64BIT@_t *SA, saidx@W64BIT@_t n);
+
+/**
+ * Constructs the burrows-wheeler transformed string of a given string.
+ * @param T[0..n-1] The input string.
+ * @param U[0..n-1] The output string. (can be T)
+ * @param A[0..n-1] The temporary array. (can be NULL)
+ * @param n The length of the given string.
+ * @return The primary index if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saidx@W64BIT@_t
+divbwt@W64BIT@(const sauchar_t *T, sauchar_t *U, saidx@W64BIT@_t *A, saidx@W64BIT@_t n);
+
+/**
+ * Returns the version of the divsufsort library.
+ * @return The version number string.
+ */
+DIVSUFSORT_API
+const char *
+divsufsort@W64BIT@_version(void);
+
+
+/**
+ * Constructs the burrows-wheeler transformed string of a given string and suffix array.
+ * @param T[0..n-1] The input string.
+ * @param U[0..n-1] The output string. (can be T)
+ * @param SA[0..n-1] The suffix array. (can be NULL)
+ * @param n The length of the given string.
+ * @param idx The output primary index.
+ * @return 0 if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saint_t
+bw_transform@W64BIT@(const sauchar_t *T, sauchar_t *U,
+ saidx@W64BIT@_t *SA /* can NULL */,
+ saidx@W64BIT@_t n, saidx@W64BIT@_t *idx);
+
+/**
+ * Inverse BW-transforms a given BWTed string.
+ * @param T[0..n-1] The input string.
+ * @param U[0..n-1] The output string. (can be T)
+ * @param A[0..n-1] The temporary array. (can be NULL)
+ * @param n The length of the given string.
+ * @param idx The primary index.
+ * @return 0 if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saint_t
+inverse_bw_transform@W64BIT@(const sauchar_t *T, sauchar_t *U,
+ saidx@W64BIT@_t *A /* can NULL */,
+ saidx@W64BIT@_t n, saidx@W64BIT@_t idx);
+
+/**
+ * Checks the correctness of a given suffix array.
+ * @param T[0..n-1] The input string.
+ * @param SA[0..n-1] The input suffix array.
+ * @param n The length of the given string.
+ * @param verbose The verbose mode.
+ * @return 0 if no error occurred.
+ */
+DIVSUFSORT_API
+saint_t
+sufcheck@W64BIT@(const sauchar_t *T, const saidx@W64BIT@_t *SA, saidx@W64BIT@_t n, saint_t verbose);
+
+/**
+ * Search for the pattern P in the string T.
+ * @param T[0..Tsize-1] The input string.
+ * @param Tsize The length of the given string.
+ * @param P[0..Psize-1] The input pattern string.
+ * @param Psize The length of the given pattern string.
+ * @param SA[0..SAsize-1] The input suffix array.
+ * @param SAsize The length of the given suffix array.
+ * @param idx The output index.
+ * @return The count of matches if no error occurred, -1 otherwise.
+ */
+DIVSUFSORT_API
+saidx@W64BIT@_t
+sa_search@W64BIT@(const sauchar_t *T, saidx@W64BIT@_t Tsize,
+ const sauchar_t *P, saidx@W64BIT@_t Psize,
+ const saidx@W64BIT@_t *SA, saidx@W64BIT@_t SAsize,
+ saidx@W64BIT@_t *left);
+
+/**
+ * Search for the character c in the string T.
+ * @param T[0..Tsize-1] The input string.
+ * @param Tsize The length of the given string.
+ * @param SA[0..SAsize-1] The input suffix array.
+ * @param SAsize The length of the given suffix array.
+ * @param c The input character.
+ * @param idx The output index.
+ * @return The count of matches if no error occurred, -1 otherwise.
+ */
+DIVSUFSORT_API
+saidx@W64BIT@_t
+sa_simplesearch@W64BIT@(const sauchar_t *T, saidx@W64BIT@_t Tsize,
+ const saidx@W64BIT@_t *SA, saidx@W64BIT@_t SAsize,
+ saint_t c, saidx@W64BIT@_t *left);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* _DIVSUFSORT@W64BIT@_H */
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/include/divsufsort_config.h b/tools/rasm/lzsa-master/src/libdivsufsort/include/divsufsort_config.h
new file mode 100644
index 0000000..4054a8a
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/include/divsufsort_config.h
@@ -0,0 +1,9 @@
+#define HAVE_STRING_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_STDINT_H 1
+#define INLINE inline
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4244 )
+#endif /* _MSC_VER */
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/include/divsufsort_private.h b/tools/rasm/lzsa-master/src/libdivsufsort/include/divsufsort_private.h
new file mode 100644
index 0000000..b4d97ad
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/include/divsufsort_private.h
@@ -0,0 +1,205 @@
+/*
+ * divsufsort_private.h for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#ifndef _DIVSUFSORT_PRIVATE_H
+#define _DIVSUFSORT_PRIVATE_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "divsufsort_config.h"
+#include <assert.h>
+#include <stdio.h>
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+#if HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#endif
+#if defined(BUILD_DIVSUFSORT64)
+# include "divsufsort64.h"
+# ifndef SAIDX_T
+# define SAIDX_T
+# define saidx_t saidx64_t
+# endif /* SAIDX_T */
+# ifndef PRIdSAIDX_T
+# define PRIdSAIDX_T PRIdSAIDX64_T
+# endif /* PRIdSAIDX_T */
+# define divsufsort divsufsort64
+# define divbwt divbwt64
+# define divsufsort_version divsufsort64_version
+# define bw_transform bw_transform64
+# define inverse_bw_transform inverse_bw_transform64
+# define sufcheck sufcheck64
+# define sa_search sa_search64
+# define sa_simplesearch sa_simplesearch64
+# define sssort sssort64
+# define trsort trsort64
+#else
+# include "divsufsort.h"
+#endif
+
+
+/*- Constants -*/
+#if !defined(UINT8_MAX)
+# define UINT8_MAX (255)
+#endif /* UINT8_MAX */
+#if defined(ALPHABET_SIZE) && (ALPHABET_SIZE < 1)
+# undef ALPHABET_SIZE
+#endif
+#if !defined(ALPHABET_SIZE)
+# define ALPHABET_SIZE (UINT8_MAX + 1)
+#endif
+/* for divsufsort.c */
+#define BUCKET_A_SIZE (ALPHABET_SIZE)
+#define BUCKET_B_SIZE (ALPHABET_SIZE * ALPHABET_SIZE)
+/* for sssort.c */
+#if defined(SS_INSERTIONSORT_THRESHOLD)
+# if SS_INSERTIONSORT_THRESHOLD < 1
+# undef SS_INSERTIONSORT_THRESHOLD
+# define SS_INSERTIONSORT_THRESHOLD (1)
+# endif
+#else
+# define SS_INSERTIONSORT_THRESHOLD (8)
+#endif
+#if defined(SS_BLOCKSIZE)
+# if SS_BLOCKSIZE < 0
+# undef SS_BLOCKSIZE
+# define SS_BLOCKSIZE (0)
+# elif 32768 <= SS_BLOCKSIZE
+# undef SS_BLOCKSIZE
+# define SS_BLOCKSIZE (32767)
+# endif
+#else
+# define SS_BLOCKSIZE (1024)
+#endif
+/* minstacksize = log(SS_BLOCKSIZE) / log(3) * 2 */
+#if SS_BLOCKSIZE == 0
+# if defined(BUILD_DIVSUFSORT64)
+# define SS_MISORT_STACKSIZE (96)
+# else
+# define SS_MISORT_STACKSIZE (64)
+# endif
+#elif SS_BLOCKSIZE <= 4096
+# define SS_MISORT_STACKSIZE (16)
+#else
+# define SS_MISORT_STACKSIZE (24)
+#endif
+#if defined(BUILD_DIVSUFSORT64)
+# define SS_SMERGE_STACKSIZE (64)
+#else
+# define SS_SMERGE_STACKSIZE (32)
+#endif
+/* for trsort.c */
+#define TR_INSERTIONSORT_THRESHOLD (8)
+#if defined(BUILD_DIVSUFSORT64)
+# define TR_STACKSIZE (96)
+#else
+# define TR_STACKSIZE (64)
+#endif
+
+
+/*- Macros -*/
+#ifndef SWAP
+# define SWAP(_a, _b) do { t = (_a); (_a) = (_b); (_b) = t; } while(0)
+#endif /* SWAP */
+#ifndef MIN
+# define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b))
+#endif /* MIN */
+#ifndef MAX
+# define MAX(_a, _b) (((_a) > (_b)) ? (_a) : (_b))
+#endif /* MAX */
+#define STACK_PUSH(_a, _b, _c, _d)\
+ do {\
+ assert(ssize < STACK_SIZE);\
+ stack[ssize].a = (_a), stack[ssize].b = (_b),\
+ stack[ssize].c = (_c), stack[ssize++].d = (_d);\
+ } while(0)
+#define STACK_PUSH5(_a, _b, _c, _d, _e)\
+ do {\
+ assert(ssize < STACK_SIZE);\
+ stack[ssize].a = (_a), stack[ssize].b = (_b),\
+ stack[ssize].c = (_c), stack[ssize].d = (_d), stack[ssize++].e = (_e);\
+ } while(0)
+#define STACK_POP(_a, _b, _c, _d)\
+ do {\
+ assert(0 <= ssize);\
+ if(ssize == 0) { return; }\
+ (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\
+ (_c) = stack[ssize].c, (_d) = stack[ssize].d;\
+ } while(0)
+#define STACK_POP5(_a, _b, _c, _d, _e)\
+ do {\
+ assert(0 <= ssize);\
+ if(ssize == 0) { return; }\
+ (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\
+ (_c) = stack[ssize].c, (_d) = stack[ssize].d, (_e) = stack[ssize].e;\
+ } while(0)
+/* for divsufsort.c */
+#define BUCKET_A(_c0) bucket_A[(_c0)]
+#if ALPHABET_SIZE == 256
+#define BUCKET_B(_c0, _c1) (bucket_B[((_c1) << 8) | (_c0)])
+#define BUCKET_BSTAR(_c0, _c1) (bucket_B[((_c0) << 8) | (_c1)])
+#else
+#define BUCKET_B(_c0, _c1) (bucket_B[(_c1) * ALPHABET_SIZE + (_c0)])
+#define BUCKET_BSTAR(_c0, _c1) (bucket_B[(_c0) * ALPHABET_SIZE + (_c1)])
+#endif
+
+
+/*- Private Prototypes -*/
+/* sssort.c */
+void
+sssort(const sauchar_t *Td, const saidx_t *PA,
+ saidx_t *first, saidx_t *last,
+ saidx_t *buf, saidx_t bufsize,
+ saidx_t depth, saidx_t n, saint_t lastsuffix);
+/* trsort.c */
+void
+trsort(saidx_t *ISA, saidx_t *SA, saidx_t n, saidx_t depth);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* _DIVSUFSORT_PRIVATE_H */
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/include/lfs.h.cmake b/tools/rasm/lzsa-master/src/libdivsufsort/include/lfs.h.cmake
new file mode 100644
index 0000000..d5b84a8
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/include/lfs.h.cmake
@@ -0,0 +1,56 @@
+/*
+ * lfs.h for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), 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.
+ */
+
+#ifndef _LFS_H
+#define _LFS_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef __STRICT_ANSI__
+# define LFS_OFF_T @LFS_OFF_T@
+# define LFS_FOPEN @LFS_FOPEN@
+# define LFS_FTELL @LFS_FTELL@
+# define LFS_FSEEK @LFS_FSEEK@
+# define LFS_PRId @LFS_PRID@
+#else
+# define LFS_OFF_T long
+# define LFS_FOPEN fopen
+# define LFS_FTELL ftell
+# define LFS_FSEEK fseek
+# define LFS_PRId "ld"
+#endif
+#ifndef PRIdOFF_T
+# define PRIdOFF_T LFS_PRId
+#endif
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* _LFS_H */
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/pkgconfig/CMakeLists.txt b/tools/rasm/lzsa-master/src/libdivsufsort/pkgconfig/CMakeLists.txt
new file mode 100644
index 0000000..ee7063c
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/pkgconfig/CMakeLists.txt
@@ -0,0 +1,9 @@
+## generate libdivsufsort.pc ##
+set(W64BIT "")
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/libdivsufsort.pc.cmake" "${CMAKE_CURRENT_BINARY_DIR}/libdivsufsort.pc" @ONLY)
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libdivsufsort.pc" DESTINATION ${CMAKE_INSTALL_PKGCONFIGDIR})
+if(BUILD_DIVSUFSORT64)
+ set(W64BIT "64")
+ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/libdivsufsort.pc.cmake" "${CMAKE_CURRENT_BINARY_DIR}/libdivsufsort64.pc" @ONLY)
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libdivsufsort64.pc" DESTINATION ${CMAKE_INSTALL_PKGCONFIGDIR})
+endif(BUILD_DIVSUFSORT64)
diff --git a/tools/rasm/lzsa-master/src/libdivsufsort/pkgconfig/libdivsufsort.pc.cmake b/tools/rasm/lzsa-master/src/libdivsufsort/pkgconfig/libdivsufsort.pc.cmake
new file mode 100644
index 0000000..6419d1e
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/libdivsufsort/pkgconfig/libdivsufsort.pc.cmake
@@ -0,0 +1,11 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=${prefix}
+libdir=@CMAKE_INSTALL_LIBDIR@
+includedir=@CMAKE_INSTALL_INCLUDEDIR@
+
+Name: @PROJECT_NAME@@W64BIT@
+Description: @PROJECT_DESCRIPTION@
+Version: @PROJECT_VERSION_FULL@
+URL: @PROJECT_URL@
+Libs: -L${libdir} -ldivsufsort@W64BIT@
+Cflags: -I${includedir}
diff --git a/tools/rasm/lzsa-master/src/lzsa.c b/tools/rasm/lzsa-master/src/lzsa.c
new file mode 100755
index 0000000..96a460a
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/lzsa.c
@@ -0,0 +1,1109 @@
+/*
+ * lzsa.c - command line compression utility for the LZSA format
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _WIN32
+#include <windows.h>
+#include <sys/timeb.h>
+#else
+#include <sys/time.h>
+#endif
+#include "lib.h"
+
+#define OPT_VERBOSE 1
+#define OPT_RAW 2
+#define OPT_FAVOR_RATIO 4
+#define OPT_RAW_BACKWARD 8
+#define OPT_STATS 16
+
+#define TOOL_VERSION "1.3.5"
+
+/*---------------------------------------------------------------------------*/
+
+#ifdef _WIN32
+LARGE_INTEGER hpc_frequency;
+BOOL hpc_available = FALSE;
+#endif
+
+static void do_init_time() {
+#ifdef _WIN32
+ hpc_frequency.QuadPart = 0;
+ hpc_available = QueryPerformanceFrequency(&hpc_frequency);
+#endif
+}
+
+static long long do_get_time() {
+ long long nTime;
+
+#ifdef _WIN32
+ if (hpc_available) {
+ LARGE_INTEGER nCurTime;
+
+ /* Use HPC hardware for best precision */
+ QueryPerformanceCounter(&nCurTime);
+ nTime = (long long)(nCurTime.QuadPart * 1000000LL / hpc_frequency.QuadPart);
+ }
+ else {
+ struct _timeb tb;
+ _ftime(&tb);
+
+ nTime = ((long long)tb.time * 1000LL + (long long)tb.millitm) * 1000LL;
+ }
+#else
+ struct timeval tm;
+ gettimeofday(&tm, NULL);
+
+ nTime = (long long)tm.tv_sec * 1000000LL + (long long)tm.tv_usec;
+#endif
+ return nTime;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void compression_progress(long long nOriginalSize, long long nCompressedSize) {
+ if (nOriginalSize >= 1024 * 1024) {
+ fprintf(stdout, "\r%lld => %lld (%g %%) \b\b\b\b\b", nOriginalSize, nCompressedSize, (double)(nCompressedSize * 100.0 / nOriginalSize));
+ fflush(stdout);
+ }
+}
+
+static int do_compress(const char *pszInFilename, const char *pszOutFilename, const char *pszDictionaryFilename, const unsigned int nOptions, const int nMinMatchSize, const int nFormatVersion) {
+ long long nStartTime = 0LL, nEndTime = 0LL;
+ long long nOriginalSize = 0LL, nCompressedSize = 0LL;
+ int nCommandCount = 0, nSafeDist = 0;
+ int nFlags;
+ lzsa_status_t nStatus;
+ lzsa_stats stats;
+
+ nFlags = 0;
+ if (nOptions & OPT_FAVOR_RATIO)
+ nFlags |= LZSA_FLAG_FAVOR_RATIO;
+ if (nOptions & OPT_RAW)
+ nFlags |= LZSA_FLAG_RAW_BLOCK;
+ if (nOptions & OPT_RAW_BACKWARD)
+ nFlags |= LZSA_FLAG_RAW_BACKWARD;
+
+ if (nOptions & OPT_VERBOSE) {
+ nStartTime = do_get_time();
+ }
+
+ nStatus = lzsa_compress_file(pszInFilename, pszOutFilename, pszDictionaryFilename, nFlags, nMinMatchSize, nFormatVersion, compression_progress, &nOriginalSize, &nCompressedSize, &nCommandCount, &nSafeDist, &stats);
+
+ if ((nOptions & OPT_VERBOSE)) {
+ nEndTime = do_get_time();
+ }
+
+ switch (nStatus) {
+ case LZSA_ERROR_SRC: fprintf(stderr, "error reading '%s'\n", pszInFilename); break;
+ case LZSA_ERROR_DST: fprintf(stderr, "error writing '%s'\n", pszOutFilename); break;
+ case LZSA_ERROR_DICTIONARY: fprintf(stderr, "error reading dictionary '%s'\n", pszDictionaryFilename); break;
+ case LZSA_ERROR_MEMORY: fprintf(stderr, "out of memory\n"); break;
+ case LZSA_ERROR_COMPRESSION: fprintf(stderr, "internal compression error\n"); break;
+ case LZSA_ERROR_RAW_TOOLARGE: fprintf(stderr, "error: raw blocks can only be used with files <= 64 Kb\n"); break;
+ case LZSA_ERROR_RAW_UNCOMPRESSED: fprintf(stderr, "error: incompressible data needs to be <= 64 Kb in raw blocks\n"); break;
+ case LZSA_OK: break;
+ default: fprintf(stderr, "unknown compression error %d\n", nStatus); break;
+ }
+
+ if (nStatus)
+ return 100;
+
+ if ((nOptions & OPT_VERBOSE)) {
+ double fDelta = ((double)(nEndTime - nStartTime)) / 1000000.0;
+ double fSpeed = ((double)nOriginalSize / 1048576.0) / fDelta;
+ fprintf(stdout, "\rCompressed '%s' in %g seconds, %.02g Mb/s, %d tokens (%g bytes/token), %lld into %lld bytes ==> %g %%\n",
+ pszInFilename, fDelta, fSpeed, nCommandCount, (double)nOriginalSize / (double)nCommandCount,
+ nOriginalSize, nCompressedSize, (double)(nCompressedSize * 100.0 / nOriginalSize));
+ if (nOptions & OPT_RAW) {
+ fprintf(stdout, "Safe distance: %d (0x%X)\n", nSafeDist, nSafeDist);
+ }
+ }
+
+ if (nOptions & OPT_STATS) {
+ if (stats.literals_divisor > 0)
+ fprintf(stdout, "Literals: min: %d avg: %d max: %d count: %d\n", stats.min_literals, stats.total_literals / stats.literals_divisor, stats.max_literals, stats.literals_divisor);
+ else
+ fprintf(stdout, "Literals: none\n");
+ if (stats.match_divisor > 0) {
+ fprintf(stdout, "Offsets: min: %d avg: %d max: %d reps: %d count: %d\n", stats.min_offset, stats.total_offsets / stats.match_divisor, stats.max_offset, stats.num_rep_offsets, stats.match_divisor);
+ fprintf(stdout, "Match lens: min: %d avg: %d max: %d count: %d\n", stats.min_match_len, stats.total_match_lens / stats.match_divisor, stats.max_match_len, stats.match_divisor);
+ }
+ else {
+ fprintf(stdout, "Offsets: none\n");
+ fprintf(stdout, "Match lens: none\n");
+ }
+ if (stats.rle1_divisor > 0) {
+ fprintf(stdout, "RLE1 lens: min: %d avg: %d max: %d count: %d\n", stats.min_rle1_len, stats.total_rle1_lens / stats.rle1_divisor, stats.max_rle1_len, stats.rle1_divisor);
+ }
+ else {
+ fprintf(stdout, "RLE1 lens: none\n");
+ }
+ if (stats.rle2_divisor > 0) {
+ fprintf(stdout, "RLE2 lens: min: %d avg: %d max: %d count: %d\n", stats.min_rle2_len, stats.total_rle2_lens / stats.rle2_divisor, stats.max_rle2_len, stats.rle2_divisor);
+ }
+ else {
+ fprintf(stdout, "RLE2 lens: none\n");
+ }
+ }
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static int do_decompress(const char *pszInFilename, const char *pszOutFilename, const char *pszDictionaryFilename, const unsigned int nOptions, int nFormatVersion) {
+ long long nStartTime = 0LL, nEndTime = 0LL;
+ long long nOriginalSize = 0LL, nCompressedSize = 0LL;
+ lzsa_status_t nStatus;
+ int nFlags;
+
+ nFlags = 0;
+ if (nOptions & OPT_RAW)
+ nFlags |= LZSA_FLAG_RAW_BLOCK;
+ if (nOptions & OPT_RAW_BACKWARD)
+ nFlags |= LZSA_FLAG_RAW_BACKWARD;
+
+ if (nOptions & OPT_VERBOSE) {
+ nStartTime = do_get_time();
+ }
+
+ nStatus = lzsa_decompress_file(pszInFilename, pszOutFilename, pszDictionaryFilename, nFlags, nFormatVersion, &nOriginalSize, &nCompressedSize);
+
+ switch (nStatus) {
+ case LZSA_ERROR_SRC: fprintf(stderr, "error reading '%s'\n", pszInFilename); break;
+ case LZSA_ERROR_DST: fprintf(stderr, "error writing '%s'\n", pszOutFilename); break;
+ case LZSA_ERROR_DICTIONARY: fprintf(stderr, "error reading dictionary '%s'\n", pszDictionaryFilename); break;
+ case LZSA_ERROR_MEMORY: fprintf(stderr, "out of memory\n"); break;
+ case LZSA_ERROR_DECOMPRESSION: fprintf(stderr, "internal decompression error\n"); break;
+ case LZSA_ERROR_FORMAT: fprintf(stderr, "invalid magic number or format version in input file\n"); break;
+ case LZSA_OK: break;
+ default: fprintf(stderr, "unknown decompression error %d\n", nStatus); break;
+ }
+
+ if (nStatus) {
+ fprintf(stderr, "decompression error for '%s'\n", pszInFilename);
+ return 100;
+ }
+ else {
+ if (nOptions & OPT_VERBOSE) {
+ nEndTime = do_get_time();
+ double fDelta = ((double)(nEndTime - nStartTime)) / 1000000.0;
+ double fSpeed = ((double)nOriginalSize / 1048576.0) / fDelta;
+ fprintf(stdout, "Decompressed '%s' in %g seconds, %g Mb/s\n",
+ pszInFilename, fDelta, fSpeed);
+ }
+
+ return 0;
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct {
+ FILE *f;
+ void *pCompareDataBuf;
+ size_t nCompareDataSize;
+} compare_stream_t;
+
+void comparestream_close(lzsa_stream_t *stream) {
+ if (stream->obj) {
+ compare_stream_t *pCompareStream = (compare_stream_t *)stream->obj;
+ if (pCompareStream->pCompareDataBuf) {
+ free(pCompareStream->pCompareDataBuf);
+ pCompareStream->pCompareDataBuf = NULL;
+ }
+
+ fclose(pCompareStream->f);
+ free(pCompareStream);
+
+ stream->obj = NULL;
+ stream->read = NULL;
+ stream->write = NULL;
+ stream->eof = NULL;
+ stream->close = NULL;
+ }
+}
+
+size_t comparestream_read(lzsa_stream_t *stream, void *ptr, size_t size) {
+ return 0;
+}
+
+size_t comparestream_write(lzsa_stream_t *stream, void *ptr, size_t size) {
+ compare_stream_t *pCompareStream = (compare_stream_t *)stream->obj;
+
+ if (!pCompareStream->pCompareDataBuf || pCompareStream->nCompareDataSize < size) {
+ pCompareStream->nCompareDataSize = size;
+ pCompareStream->pCompareDataBuf = realloc(pCompareStream->pCompareDataBuf, pCompareStream->nCompareDataSize);
+ if (!pCompareStream->pCompareDataBuf)
+ return 0;
+ }
+
+ size_t nReadBytes = fread(pCompareStream->pCompareDataBuf, 1, size, pCompareStream->f);
+ if (nReadBytes != size) {
+ return 0;
+ }
+
+ if (memcmp(ptr, pCompareStream->pCompareDataBuf, size)) {
+ return 0;
+ }
+
+ return size;
+}
+
+int comparestream_eof(lzsa_stream_t *stream) {
+ compare_stream_t *pCompareStream = (compare_stream_t *)stream->obj;
+ return feof(pCompareStream->f);
+}
+
+int comparestream_open(lzsa_stream_t *stream, const char *pszCompareFilename, const char *pszMode) {
+ compare_stream_t *pCompareStream;
+
+ pCompareStream = (compare_stream_t*)malloc(sizeof(compare_stream_t));
+ if (!pCompareStream)
+ return -1;
+
+ pCompareStream->pCompareDataBuf = NULL;
+ pCompareStream->nCompareDataSize = 0;
+ pCompareStream->f = (FILE*)fopen(pszCompareFilename, pszMode);
+
+ if (pCompareStream->f) {
+ stream->obj = pCompareStream;
+ stream->read = comparestream_read;
+ stream->write = comparestream_write;
+ stream->eof = comparestream_eof;
+ stream->close = comparestream_close;
+ return 0;
+ }
+ else {
+ free(pCompareStream);
+ return -1;
+ }
+}
+
+static int do_compare(const char *pszInFilename, const char *pszOutFilename, const char *pszDictionaryFilename, const unsigned int nOptions, int nFormatVersion) {
+ lzsa_stream_t inStream, compareStream;
+ long long nStartTime = 0LL, nEndTime = 0LL;
+ long long nOriginalSize = 0LL;
+ long long nCompressedSize = 0LL;
+ void *pDictionaryData = NULL;
+ int nDictionaryDataSize = 0;
+ lzsa_status_t nStatus;
+ int nFlags;
+
+ if (lzsa_filestream_open(&inStream, pszInFilename, "rb") < 0) {
+ fprintf(stderr, "error opening compressed input file\n");
+ return 100;
+ }
+
+ if (comparestream_open(&compareStream, pszOutFilename, "rb") < 0) {
+ fprintf(stderr, "error opening original uncompressed file\n");
+ inStream.close(&inStream);
+ return 100;
+ }
+
+ nStatus = lzsa_dictionary_load(pszDictionaryFilename, &pDictionaryData, &nDictionaryDataSize);
+ if (nStatus) {
+ compareStream.close(&compareStream);
+ inStream.close(&inStream);
+ fprintf(stderr, "error reading dictionary '%s'\n", pszDictionaryFilename);
+ return 100;
+ }
+
+ nFlags = 0;
+ if (nOptions & OPT_RAW)
+ nFlags |= LZSA_FLAG_RAW_BLOCK;
+ if (nOptions & OPT_RAW_BACKWARD)
+ nFlags |= LZSA_FLAG_RAW_BACKWARD;
+
+ if (nOptions & OPT_VERBOSE) {
+ nStartTime = do_get_time();
+ }
+
+ nStatus = lzsa_decompress_stream(&inStream, &compareStream, pDictionaryData, nDictionaryDataSize, nFlags, nFormatVersion, &nOriginalSize, &nCompressedSize);
+
+ switch (nStatus) {
+ case LZSA_ERROR_SRC: fprintf(stderr, "error reading '%s'\n", pszInFilename); break;
+ case LZSA_ERROR_DST: fprintf(stderr, "error comparing compressed file '%s' with original '%s'\n", pszInFilename, pszOutFilename); break;
+ case LZSA_ERROR_MEMORY: fprintf(stderr, "out of memory\n"); break;
+ case LZSA_ERROR_DECOMPRESSION: fprintf(stderr, "internal decompression error\n"); break;
+ case LZSA_ERROR_FORMAT: fprintf(stderr, "invalid magic number or format version in input file\n"); break;
+ case LZSA_OK: break;
+ default: fprintf(stderr, "unknown decompression error %d\n", nStatus); break;
+ }
+
+ lzsa_dictionary_free(&pDictionaryData);
+ compareStream.close(&compareStream);
+ inStream.close(&inStream);
+
+ if (nStatus) {
+ return 100;
+ }
+ else {
+ if (nOptions & OPT_VERBOSE) {
+ nEndTime = do_get_time();
+ double fDelta = ((double)(nEndTime - nStartTime)) / 1000000.0;
+ double fSpeed = ((double)nOriginalSize / 1048576.0) / fDelta;
+ fprintf(stdout, "Compared '%s' in %g seconds, %g Mb/s\n",
+ pszInFilename, fDelta, fSpeed);
+ }
+
+ return 0;
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void generate_compressible_data(unsigned char *pBuffer, size_t nBufferSize, int nMinMatchSize, unsigned int nSeed, int nNumLiteralValues, float fMatchProbability) {
+ size_t nIndex = 0;
+ int nMatchProbability = (int)(fMatchProbability * 1023.0f);
+
+ srand(nSeed);
+
+ if (nIndex >= nBufferSize) return;
+ pBuffer[nIndex++] = rand() % nNumLiteralValues;
+
+ while (nIndex < nBufferSize) {
+ if ((rand() & 1023) >= nMatchProbability) {
+ size_t nLiteralCount = rand() & 127;
+ if (nLiteralCount > (nBufferSize - nIndex))
+ nLiteralCount = nBufferSize - nIndex;
+
+ while (nLiteralCount--)
+ pBuffer[nIndex++] = rand() % nNumLiteralValues;
+ }
+ else {
+ size_t nMatchLength = nMinMatchSize + (rand() & 1023);
+ size_t nMatchOffset;
+
+ if (nMatchLength > (nBufferSize - nIndex))
+ nMatchLength = nBufferSize - nIndex;
+ if (nMatchLength > nIndex)
+ nMatchLength = nIndex;
+
+ if (nMatchLength < nIndex)
+ nMatchOffset = rand() % (nIndex - nMatchLength);
+ else
+ nMatchOffset = 0;
+
+ while (nMatchLength--) {
+ pBuffer[nIndex] = pBuffer[nIndex - nMatchOffset];
+ nIndex++;
+ }
+ }
+ }
+}
+
+static void xor_data(unsigned char *pBuffer, size_t nBufferSize, unsigned int nSeed, float fXorProbability) {
+ size_t nIndex = 0;
+ int nXorProbability = (int)(fXorProbability * 1023.0f);
+
+ srand(nSeed);
+
+ if (nIndex >= nBufferSize) return;
+
+ while (nIndex < nBufferSize) {
+ if ((rand() & 1023) < nXorProbability) {
+ pBuffer[nIndex] ^= 0xff;
+ }
+ nIndex++;
+ }
+}
+
+static int do_self_test(const unsigned int nOptions, const int nMinMatchSize, int nFormatVersion) {
+ unsigned char *pGeneratedData;
+ unsigned char *pCompressedData;
+ unsigned char *pTmpCompressedData;
+ unsigned char *pTmpDecompressedData;
+ size_t nGeneratedDataSize;
+ size_t nMaxCompressedDataSize;
+ unsigned int nSeed = 123;
+ int nFlags;
+ int i;
+
+ nFlags = 0;
+ if (nOptions & OPT_FAVOR_RATIO)
+ nFlags |= LZSA_FLAG_FAVOR_RATIO;
+ if (nOptions & OPT_RAW)
+ nFlags |= LZSA_FLAG_RAW_BLOCK;
+ if (nOptions & OPT_RAW_BACKWARD)
+ nFlags |= LZSA_FLAG_RAW_BACKWARD;
+
+ pGeneratedData = (unsigned char*)malloc(4 * BLOCK_SIZE);
+ if (!pGeneratedData) {
+ fprintf(stderr, "out of memory, %d bytes needed\n", 4 * BLOCK_SIZE);
+ return 100;
+ }
+
+ nMaxCompressedDataSize = lzsa_get_max_compressed_size_inmem(4 * BLOCK_SIZE);
+ pCompressedData = (unsigned char*)malloc(nMaxCompressedDataSize);
+ if (!pCompressedData) {
+ free(pGeneratedData);
+ pGeneratedData = NULL;
+
+ fprintf(stderr, "out of memory, %zd bytes needed\n", nMaxCompressedDataSize);
+ return 100;
+ }
+
+ pTmpCompressedData = (unsigned char*)malloc(nMaxCompressedDataSize);
+ if (!pTmpCompressedData) {
+ free(pCompressedData);
+ pCompressedData = NULL;
+ free(pGeneratedData);
+ pGeneratedData = NULL;
+
+ fprintf(stderr, "out of memory, %zd bytes needed\n", nMaxCompressedDataSize);
+ return 100;
+ }
+
+ pTmpDecompressedData = (unsigned char*)malloc(4 * BLOCK_SIZE);
+ if (!pTmpDecompressedData) {
+ free(pTmpCompressedData);
+ pTmpCompressedData = NULL;
+ free(pCompressedData);
+ pCompressedData = NULL;
+ free(pGeneratedData);
+ pGeneratedData = NULL;
+
+ fprintf(stderr, "out of memory, %d bytes needed\n", 4 * BLOCK_SIZE);
+ return 100;
+ }
+
+ memset(pGeneratedData, 0, 4 * BLOCK_SIZE);
+ memset(pCompressedData, 0, nMaxCompressedDataSize);
+ memset(pTmpCompressedData, 0, nMaxCompressedDataSize);
+
+ /* Test compressing with a too small buffer to do anything, expect to fail cleanly */
+ for (i = 0; i < 12; i++) {
+ generate_compressible_data(pGeneratedData, i, nMinMatchSize, nSeed, 256, 0.5f);
+ lzsa_compress_inmem(pGeneratedData, pCompressedData, i, i, nFlags, nMinMatchSize, nFormatVersion);
+ }
+
+ size_t nDataSizeStep = 128;
+ float fProbabilitySizeStep = 0.0005f;
+
+ for (nGeneratedDataSize = 1024; nGeneratedDataSize <= ((size_t)((nOptions & OPT_RAW) ? BLOCK_SIZE : (4 * BLOCK_SIZE))); nGeneratedDataSize += nDataSizeStep) {
+ float fMatchProbability;
+
+ fprintf(stdout, "size %zd", nGeneratedDataSize);
+ for (fMatchProbability = 0; fMatchProbability <= 0.995f; fMatchProbability += fProbabilitySizeStep) {
+ int nNumLiteralValues[12] = { 1, 2, 3, 15, 30, 56, 96, 137, 178, 191, 255, 256 };
+ float fXorProbability;
+
+ fputc('.', stdout);
+ fflush(stdout);
+
+ for (i = 0; i < 12; i++) {
+ /* Generate data to compress */
+ generate_compressible_data(pGeneratedData, nGeneratedDataSize, nMinMatchSize, nSeed, nNumLiteralValues[i], fMatchProbability);
+
+ /* Try to compress it, expected to succeed */
+ size_t nActualCompressedSize = lzsa_compress_inmem(pGeneratedData, pCompressedData, nGeneratedDataSize, lzsa_get_max_compressed_size_inmem(nGeneratedDataSize),
+ nFlags, nMinMatchSize, nFormatVersion);
+ if (nActualCompressedSize == -1 || (int)nActualCompressedSize < (lzsa_get_header_size() + lzsa_get_frame_size() + lzsa_get_frame_size() /* footer */)) {
+ free(pTmpDecompressedData);
+ pTmpDecompressedData = NULL;
+ free(pTmpCompressedData);
+ pTmpCompressedData = NULL;
+ free(pCompressedData);
+ pCompressedData = NULL;
+ free(pGeneratedData);
+ pGeneratedData = NULL;
+
+ fprintf(stderr, "\nself-test: error compressing size %zd, seed %d, match probability %f, literals range %d\n", nGeneratedDataSize, nSeed, fMatchProbability, nNumLiteralValues[i]);
+ return 100;
+ }
+
+ /* Try to decompress it, expected to succeed */
+ size_t nActualDecompressedSize;
+ int nDecFormatVersion = nFormatVersion;
+ nActualDecompressedSize = lzsa_decompress_inmem(pCompressedData, pTmpDecompressedData, nActualCompressedSize, nGeneratedDataSize, nFlags, &nDecFormatVersion);
+ if (nActualDecompressedSize == -1) {
+ free(pTmpDecompressedData);
+ pTmpDecompressedData = NULL;
+ free(pTmpCompressedData);
+ pTmpCompressedData = NULL;
+ free(pCompressedData);
+ pCompressedData = NULL;
+ free(pGeneratedData);
+ pGeneratedData = NULL;
+
+ fprintf(stderr, "\nself-test: error decompressing size %zd, seed %d, match probability %f, literals range %d\n", nGeneratedDataSize, nSeed, fMatchProbability, nNumLiteralValues[i]);
+ return 100;
+ }
+
+ if (memcmp(pGeneratedData, pTmpDecompressedData, nGeneratedDataSize)) {
+ free(pTmpDecompressedData);
+ pTmpDecompressedData = NULL;
+ free(pTmpCompressedData);
+ pTmpCompressedData = NULL;
+ free(pCompressedData);
+ pCompressedData = NULL;
+ free(pGeneratedData);
+ pGeneratedData = NULL;
+
+ fprintf(stderr, "\nself-test: error comparing decompressed and original data, size %zd, seed %d, match probability %f, literals range %d\n", nGeneratedDataSize, nSeed, fMatchProbability, nNumLiteralValues[i]);
+ return 100;
+ }
+
+ /* Try to decompress corrupted data, expected to fail cleanly, without crashing or corrupting memory outside the output buffer */
+ for (fXorProbability = 0.05f; fXorProbability <= 0.5f; fXorProbability += 0.05f) {
+ memcpy(pTmpCompressedData, pCompressedData, nActualCompressedSize);
+ xor_data(pTmpCompressedData + lzsa_get_header_size() + lzsa_get_frame_size(), nActualCompressedSize - lzsa_get_header_size() - lzsa_get_frame_size() - lzsa_get_frame_size() /* footer */, nSeed, fXorProbability);
+ nDecFormatVersion = nFormatVersion;
+ lzsa_decompress_inmem(pTmpCompressedData, pGeneratedData, nActualCompressedSize, nGeneratedDataSize, nFlags, &nDecFormatVersion);
+ }
+ }
+
+ nSeed++;
+ }
+
+ fputc(10, stdout);
+ fflush(stdout);
+
+ nDataSizeStep <<= 1;
+ if (nDataSizeStep > (128 * 4096))
+ nDataSizeStep = 128 * 4096;
+ fProbabilitySizeStep *= 1.25;
+ if (fProbabilitySizeStep > (0.0005f * 4096))
+ fProbabilitySizeStep = 0.0005f * 4096;
+ }
+
+ free(pTmpDecompressedData);
+ pTmpDecompressedData = NULL;
+
+ free(pTmpCompressedData);
+ pTmpCompressedData = NULL;
+
+ free(pCompressedData);
+ pCompressedData = NULL;
+
+ free(pGeneratedData);
+ pGeneratedData = NULL;
+
+ fprintf(stdout, "All tests passed.\n");
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static int do_compr_benchmark(const char *pszInFilename, const char *pszOutFilename, const char *pszDictionaryFilename, const unsigned int nOptions, const int nMinMatchSize, int nFormatVersion) {
+ size_t nFileSize, nMaxCompressedSize;
+ unsigned char *pFileData;
+ unsigned char *pCompressedData;
+ int nFlags;
+ int i;
+
+ nFlags = 0;
+ if (nOptions & OPT_FAVOR_RATIO)
+ nFlags |= LZSA_FLAG_FAVOR_RATIO;
+ if (nOptions & OPT_RAW)
+ nFlags |= LZSA_FLAG_RAW_BLOCK;
+ if (nOptions & OPT_RAW_BACKWARD)
+ nFlags |= LZSA_FLAG_RAW_BACKWARD;
+
+ if (pszDictionaryFilename) {
+ fprintf(stderr, "in-memory benchmarking does not support dictionaries\n");
+ return 100;
+ }
+
+ /* Read the whole original file in memory */
+
+ FILE *f_in = fopen(pszInFilename, "rb");
+ if (!f_in) {
+ fprintf(stderr, "error opening '%s' for reading\n", pszInFilename);
+ return 100;
+ }
+
+ fseek(f_in, 0, SEEK_END);
+ nFileSize = (size_t)ftell(f_in);
+ fseek(f_in, 0, SEEK_SET);
+
+ pFileData = (unsigned char*)malloc(nFileSize);
+ if (!pFileData) {
+ fclose(f_in);
+ fprintf(stderr, "out of memory for reading '%s', %zd bytes needed\n", pszInFilename, nFileSize);
+ return 100;
+ }
+
+ if (fread(pFileData, 1, nFileSize, f_in) != nFileSize) {
+ free(pFileData);
+ fclose(f_in);
+ fprintf(stderr, "I/O error while reading '%s'\n", pszInFilename);
+ return 100;
+ }
+
+ fclose(f_in);
+
+ /* Allocate max compressed size */
+
+ nMaxCompressedSize = lzsa_get_max_compressed_size_inmem(nFileSize);
+
+ pCompressedData = (unsigned char*)malloc(nMaxCompressedSize + 2048);
+ if (!pCompressedData) {
+ free(pFileData);
+ fprintf(stderr, "out of memory for compressing '%s', %zd bytes needed\n", pszInFilename, nMaxCompressedSize);
+ return 100;
+ }
+
+ memset(pCompressedData + 1024, 0, nMaxCompressedSize);
+
+ long long nBestCompTime = -1;
+
+ size_t nActualCompressedSize = 0;
+ size_t nRightGuardPos = nMaxCompressedSize;
+
+ for (i = 0; i < 5; i++) {
+ unsigned char nGuard = 0x33 + i;
+ int j;
+
+ /* Write guard bytes around the output buffer, to help check for writes outside of it by the compressor */
+ memset(pCompressedData, nGuard, 1024);
+ memset(pCompressedData + 1024 + nRightGuardPos, nGuard, 1024);
+
+ long long t0 = do_get_time();
+ nActualCompressedSize = lzsa_compress_inmem(pFileData, pCompressedData + 1024, nFileSize, nRightGuardPos, nFlags, nMinMatchSize, nFormatVersion);
+ long long t1 = do_get_time();
+ if (nActualCompressedSize == -1) {
+ free(pCompressedData);
+ free(pFileData);
+ fprintf(stderr, "compression error\n");
+ return 100;
+ }
+
+ long long nCurDecTime = t1 - t0;
+ if (nBestCompTime == -1 || nBestCompTime > nCurDecTime)
+ nBestCompTime = nCurDecTime;
+
+ /* Check guard bytes before the output buffer */
+ for (j = 0; j < 1024; j++) {
+ if (pCompressedData[j] != nGuard) {
+ free(pCompressedData);
+ free(pFileData);
+ fprintf(stderr, "error, wrote outside of output buffer at %d!\n", j - 1024);
+ return 100;
+ }
+ }
+
+ /* Check guard bytes after the output buffer */
+ for (j = 0; j < 1024; j++) {
+ if (pCompressedData[1024 + nRightGuardPos + j] != nGuard) {
+ free(pCompressedData);
+ free(pFileData);
+ fprintf(stderr, "error, wrote outside of output buffer at %d!\n", j);
+ return 100;
+ }
+ }
+
+ nRightGuardPos = nActualCompressedSize;
+ }
+
+ if (pszOutFilename) {
+ FILE *f_out;
+
+ /* Write whole compressed file out */
+
+ f_out = fopen(pszOutFilename, "wb");
+ if (f_out) {
+ fwrite(pCompressedData + 1024, 1, nActualCompressedSize, f_out);
+ fclose(f_out);
+ }
+ }
+
+ free(pCompressedData);
+ free(pFileData);
+
+ fprintf(stdout, "compressed size: %zd bytes\n", nActualCompressedSize);
+ fprintf(stdout, "compression time: %lld microseconds (%g Mb/s)\n", nBestCompTime, ((double)nActualCompressedSize / 1024.0) / ((double)nBestCompTime / 1000.0));
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static int do_dec_benchmark(const char *pszInFilename, const char *pszOutFilename, const char *pszDictionaryFilename, const unsigned int nOptions, int nFormatVersion) {
+ size_t nFileSize, nMaxDecompressedSize;
+ unsigned char *pFileData;
+ unsigned char *pDecompressedData;
+ int nFlags;
+ int i;
+
+ nFlags = 0;
+ if (nOptions & OPT_RAW)
+ nFlags |= LZSA_FLAG_RAW_BLOCK;
+ if (nOptions & OPT_RAW_BACKWARD)
+ nFlags |= LZSA_FLAG_RAW_BACKWARD;
+
+ if (pszDictionaryFilename) {
+ fprintf(stderr, "in-memory benchmarking does not support dictionaries\n");
+ return 100;
+ }
+
+ /* Read the whole compressed file in memory */
+
+ FILE *f_in = fopen(pszInFilename, "rb");
+ if (!f_in) {
+ fprintf(stderr, "error opening '%s' for reading\n", pszInFilename);
+ return 100;
+ }
+
+ fseek(f_in, 0, SEEK_END);
+ nFileSize = (size_t)ftell(f_in);
+ fseek(f_in, 0, SEEK_SET);
+
+ pFileData = (unsigned char*)malloc(nFileSize);
+ if (!pFileData) {
+ fclose(f_in);
+ fprintf(stderr, "out of memory for reading '%s', %zd bytes needed\n", pszInFilename, nFileSize);
+ return 100;
+ }
+
+ if (fread(pFileData, 1, nFileSize, f_in) != nFileSize) {
+ free(pFileData);
+ fclose(f_in);
+ fprintf(stderr, "I/O error while reading '%s'\n", pszInFilename);
+ return 100;
+ }
+
+ fclose(f_in);
+
+ /* Allocate max decompressed size */
+
+ if (nOptions & OPT_RAW)
+ nMaxDecompressedSize = 65536;
+ else
+ nMaxDecompressedSize = lzsa_get_max_decompressed_size_inmem(pFileData, nFileSize);
+ if (nMaxDecompressedSize == -1) {
+ free(pFileData);
+ fprintf(stderr, "invalid compressed format for file '%s'\n", pszInFilename);
+ return 100;
+ }
+
+ pDecompressedData = (unsigned char*)malloc(nMaxDecompressedSize);
+ if (!pDecompressedData) {
+ free(pFileData);
+ fprintf(stderr, "out of memory for decompressing '%s', %zd bytes needed\n", pszInFilename, nMaxDecompressedSize);
+ return 100;
+ }
+
+ memset(pDecompressedData, 0, nMaxDecompressedSize);
+
+ long long nBestDecTime = -1;
+
+ size_t nActualDecompressedSize = 0;
+ for (i = 0; i < 50; i++) {
+ long long t0 = do_get_time();
+ nActualDecompressedSize = lzsa_decompress_inmem(pFileData, pDecompressedData, nFileSize, nMaxDecompressedSize, nFlags, &nFormatVersion);
+ long long t1 = do_get_time();
+ if (nActualDecompressedSize == -1) {
+ free(pDecompressedData);
+ free(pFileData);
+ fprintf(stderr, "decompression error\n");
+ return 100;
+ }
+
+ long long nCurDecTime = t1 - t0;
+ if (nBestDecTime == -1 || nBestDecTime > nCurDecTime)
+ nBestDecTime = nCurDecTime;
+ }
+
+ if (pszOutFilename) {
+ FILE *f_out;
+
+ /* Write whole decompressed file out */
+
+ f_out = fopen(pszOutFilename, "wb");
+ if (f_out) {
+ fwrite(pDecompressedData, 1, nActualDecompressedSize, f_out);
+ fclose(f_out);
+ }
+ }
+
+ free(pDecompressedData);
+ free(pFileData);
+
+ fprintf(stdout, "format: LZSA%d\n", nFormatVersion);
+ fprintf(stdout, "decompressed size: %zd bytes\n", nActualDecompressedSize);
+ fprintf(stdout, "decompression time: %lld microseconds (%g Mb/s)\n", nBestDecTime, ((double)nActualDecompressedSize / 1024.0) / ((double)nBestDecTime / 1000.0));
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+int main(int argc, char **argv) {
+ int i;
+ const char *pszInFilename = NULL;
+ const char *pszOutFilename = NULL;
+ const char *pszDictionaryFilename = NULL;
+ int nArgsError = 0;
+ int nCommandDefined = 0;
+ int nVerifyCompression = 0;
+ int nMinMatchDefined = 0;
+ int nFormatVersionDefined = 0;
+ char cCommand = 'z';
+ int nMinMatchSize = 0;
+ unsigned int nOptions = OPT_FAVOR_RATIO;
+ int nFormatVersion = 1;
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-d")) {
+ if (!nCommandDefined) {
+ nCommandDefined = 1;
+ cCommand = 'd';
+ }
+ else
+ nArgsError = 1;
+ }
+ else if (!strcmp(argv[i], "-z")) {
+ if (!nCommandDefined) {
+ nCommandDefined = 1;
+ cCommand = 'z';
+ }
+ else
+ nArgsError = 1;
+ }
+ else if (!strcmp(argv[i], "-c")) {
+ if (!nVerifyCompression) {
+ nVerifyCompression = 1;
+ }
+ else
+ nArgsError = 1;
+ }
+ else if (!strcmp(argv[i], "-cbench")) {
+ if (!nCommandDefined) {
+ nCommandDefined = 1;
+ cCommand = 'B';
+ }
+ else
+ nArgsError = 1;
+ }
+ else if (!strcmp(argv[i], "-dbench")) {
+ if (!nCommandDefined) {
+ nCommandDefined = 1;
+ cCommand = 'b';
+ }
+ else
+ nArgsError = 1;
+ }
+ else if (!strcmp(argv[i], "-test")) {
+ if (!nCommandDefined) {
+ nCommandDefined = 1;
+ cCommand = 't';
+ }
+ else
+ nArgsError = 1;
+ }
+ else if (!strcmp(argv[i], "-D")) {
+ if (!pszDictionaryFilename && (i + 1) < argc) {
+ pszDictionaryFilename = argv[i + 1];
+ i++;
+ }
+ else
+ nArgsError = 1;
+ }
+ else if (!strncmp(argv[i], "-D", 2)) {
+ if (!pszDictionaryFilename) {
+ pszDictionaryFilename = argv[i] + 2;
+ }
+ else
+ nArgsError = 1;
+ }
+ else if (!strcmp(argv[i], "-m")) {
+ if (!nMinMatchDefined && (i + 1) < argc) {
+ char *pEnd = NULL;
+ nMinMatchSize = (int)strtol(argv[i + 1], &pEnd, 10);
+ if (pEnd && pEnd != argv[i + 1] && (nMinMatchSize >= 2 && nMinMatchSize <= 5)) {
+ i++;
+ nMinMatchDefined = 1;
+ nOptions &= (~OPT_FAVOR_RATIO);
+ }
+ else {
+ nArgsError = 1;
+ }
+ }
+ else
+ nArgsError = 1;
+ }
+ else if (!strncmp(argv[i], "-m", 2)) {
+ if (!nMinMatchDefined) {
+ char *pEnd = NULL;
+ nMinMatchSize = (int)strtol(argv[i] + 2, &pEnd, 10);
+ if (pEnd && pEnd != (argv[i]+2) && (nMinMatchSize >= 2 && nMinMatchSize <= 5)) {
+ nMinMatchDefined = 1;
+ nOptions &= (~OPT_FAVOR_RATIO);
+ }
+ else {
+ nArgsError = 1;
+ }
+ }
+ else
+ nArgsError = 1;
+ }
+ else if (!strcmp(argv[i], "--prefer-ratio")) {
+ if (!nMinMatchDefined) {
+ nMinMatchSize = 0;
+ nMinMatchDefined = 1;
+ }
+ else
+ nArgsError = 1;
+ }
+ else if (!strcmp(argv[i], "--prefer-speed")) {
+ if (!nMinMatchDefined) {
+ nMinMatchSize = 3;
+ nOptions &= (~OPT_FAVOR_RATIO);
+ nMinMatchDefined = 1;
+ }
+ else
+ nArgsError = 1;
+ }
+ else if (!strcmp(argv[i], "-f")) {
+ if (!nFormatVersionDefined && (i + 1) < argc) {
+ char *pEnd = NULL;
+ nFormatVersion = (int)strtol(argv[i + 1], &pEnd, 10);
+ if (pEnd && pEnd != argv[i + 1] && (nFormatVersion >= 1 && nFormatVersion <= 2)) {
+ i++;
+ nFormatVersionDefined = 1;
+ }
+ else {
+ nArgsError = 1;
+ }
+ }
+ else
+ nArgsError = 1;
+ }
+ else if (!strncmp(argv[i], "-f", 2)) {
+ if (!nFormatVersionDefined) {
+ char *pEnd = NULL;
+ nFormatVersion = (int)strtol(argv[i] + 2, &pEnd, 10);
+ if (pEnd && pEnd != (argv[i] + 2) && (nFormatVersion >= 1 && nFormatVersion <= 2)) {
+ nFormatVersionDefined = 1;
+ }
+ else {
+ nArgsError = 1;
+ }
+ }
+ else
+ nArgsError = 1;
+ }
+ else if (!strcmp(argv[i], "-v")) {
+ if ((nOptions & OPT_VERBOSE) == 0) {
+ nOptions |= OPT_VERBOSE;
+ }
+ else
+ nArgsError = 1;
+ }
+ else if (!strcmp(argv[i], "-r")) {
+ if ((nOptions & OPT_RAW) == 0) {
+ nOptions |= OPT_RAW;
+ }
+ else
+ nArgsError = 1;
+ }
+ else if (!strcmp(argv[i], "-b")) {
+ if ((nOptions & OPT_RAW_BACKWARD) == 0) {
+ nOptions |= OPT_RAW_BACKWARD;
+ }
+ else
+ nArgsError = 1;
+ }
+ else if (!strcmp(argv[i], "-stats")) {
+ if ((nOptions & OPT_STATS) == 0) {
+ nOptions |= OPT_STATS;
+ }
+ else
+ nArgsError = 1;
+ }
+ else {
+ if (!pszInFilename)
+ pszInFilename = argv[i];
+ else {
+ if (!pszOutFilename)
+ pszOutFilename = argv[i];
+ else
+ nArgsError = 1;
+ }
+ }
+ }
+
+ if (!nArgsError && (nOptions & OPT_RAW_BACKWARD) && !(nOptions & OPT_RAW)) {
+ fprintf(stderr, "error: -b (compress backwards) requires -r (raw block format)\n");
+ return 100;
+ }
+
+ if (!nArgsError && cCommand == 't') {
+ return do_self_test(nOptions, nMinMatchSize, nFormatVersion);
+ }
+
+ if (nArgsError || !pszInFilename || !pszOutFilename) {
+ fprintf(stderr, "lzsa command-line tool v" TOOL_VERSION " by Emmanuel Marty and spke\n");
+ fprintf(stderr, "usage: %s [-c] [-d] [-v] [-r] <infile> <outfile>\n", argv[0]);
+ fprintf(stderr, " -c: check resulting stream after compressing\n");
+ fprintf(stderr, " -d: decompress (default: compress)\n");
+ fprintf(stderr, " -cbench: benchmark in-memory compression\n");
+ fprintf(stderr, " -dbench: benchmark in-memory decompression\n");
+ fprintf(stderr, " -test: run automated self-tests\n");
+ fprintf(stderr, " -stats: show compressed data stats\n");
+ fprintf(stderr, " -v: be verbose\n");
+ fprintf(stderr, " -f <value>: LZSA compression format (1-2)\n");
+ fprintf(stderr, " -r: raw block format (max. 64 Kb files)\n");
+ fprintf(stderr, " -b: compress backward (requires -r and a backward decompressor)\n");
+ fprintf(stderr, " -D <filename>: use dictionary file\n");
+ fprintf(stderr, " -m <value>: minimum match size (3-5) (default: 3)\n");
+ fprintf(stderr, " --prefer-ratio: favor compression ratio (default)\n");
+ fprintf(stderr, " --prefer-speed: favor decompression speed (same as -m3)\n");
+ return 100;
+ }
+
+ do_init_time();
+
+ if (cCommand == 'z') {
+ int nResult = do_compress(pszInFilename, pszOutFilename, pszDictionaryFilename, nOptions, nMinMatchSize, nFormatVersion);
+ if (nResult == 0 && nVerifyCompression) {
+ return do_compare(pszOutFilename, pszInFilename, pszDictionaryFilename, nOptions, nFormatVersion);
+ } else {
+ return nResult;
+ }
+ }
+ else if (cCommand == 'd') {
+ return do_decompress(pszInFilename, pszOutFilename, pszDictionaryFilename, nOptions, nFormatVersion);
+ }
+ else if (cCommand == 'B') {
+ return do_compr_benchmark(pszInFilename, pszOutFilename, pszDictionaryFilename, nOptions, nMinMatchSize, nFormatVersion);
+ }
+ else if (cCommand == 'b') {
+ return do_dec_benchmark(pszInFilename, pszOutFilename, pszDictionaryFilename, nOptions, nFormatVersion);
+ }
+ else {
+ return 100;
+ }
+}
diff --git a/tools/rasm/lzsa-master/src/matchfinder.c b/tools/rasm/lzsa-master/src/matchfinder.c
new file mode 100644
index 0000000..3de2cfa
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/matchfinder.c
@@ -0,0 +1,361 @@
+/*
+ * matchfinder.c - LZ match finder implementation
+ *
+ * The following copying information applies to this specific source code file:
+ *
+ * Written in 2019 by Emmanuel Marty <marty.emmanuel@gmail.com>
+ * Portions written in 2014-2015 by Eric Biggers <ebiggers3@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all copyright
+ * and related and neighboring rights to this software to the public domain
+ * worldwide via the Creative Commons Zero 1.0 Universal Public Domain
+ * Dedication (the "CC0").
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the CC0 for more details.
+ *
+ * You should have received a copy of the CC0 along with this software; if not
+ * see <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "matchfinder.h"
+#include "format.h"
+#include "lib.h"
+
+/**
+ * Hash index into TAG_BITS
+ *
+ * @param nIndex index value
+ *
+ * @return hash
+ */
+static inline int lzsa_get_index_tag(unsigned int nIndex) {
+ return (int)(((unsigned long long)nIndex * 11400714819323198485ULL) >> (64ULL - TAG_BITS));
+}
+
+/**
+ * Parse input data, build suffix array and overlaid data structures to speed up match finding
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param nInWindowSize total input size in bytes (previously compressed bytes + bytes to compress)
+ *
+ * @return 0 for success, non-zero for failure
+ */
+int lzsa_build_suffix_array(lzsa_compressor *pCompressor, const unsigned char *pInWindow, const int nInWindowSize) {
+ unsigned int *intervals = pCompressor->intervals;
+
+ /* Build suffix array from input data */
+ if (divsufsort_build_array(&pCompressor->divsufsort_context, pInWindow, (saidx_t*)intervals, nInWindowSize) != 0) {
+ return 100;
+ }
+
+ int *PLCP = (int*)pCompressor->pos_data; /* Use temporarily */
+ int *Phi = PLCP;
+ int nCurLen = 0;
+ int i, r;
+
+ /* Compute the permuted LCP first (Kärkkäinen method) */
+ Phi[intervals[0]] = -1;
+ for (i = 1; i < nInWindowSize; i++)
+ Phi[intervals[i]] = intervals[i - 1];
+ for (i = 0; i < nInWindowSize; i++) {
+ if (Phi[i] == -1) {
+ PLCP[i] = 0;
+ continue;
+ }
+ int nMaxLen = (i > Phi[i]) ? (nInWindowSize - i) : (nInWindowSize - Phi[i]);
+ while (nCurLen < nMaxLen && pInWindow[i + nCurLen] == pInWindow[Phi[i] + nCurLen]) nCurLen++;
+ PLCP[i] = nCurLen;
+ if (nCurLen > 0)
+ nCurLen--;
+ }
+
+ /* Rotate permuted LCP into the LCP. This has better cache locality than the direct Kasai LCP method. This also
+ * saves us from having to build the inverse suffix array index, as the LCP is calculated without it using this method,
+ * and the interval builder below doesn't need it either. */
+ intervals[0] &= POS_MASK;
+ int nMinMatchSize = pCompressor->min_match_size;
+
+ if (pCompressor->format_version >= 2) {
+ for (i = 1; i < nInWindowSize; i++) {
+ int nIndex = (int)(intervals[i] & POS_MASK);
+ int nLen = PLCP[nIndex];
+ if (nLen < nMinMatchSize)
+ nLen = 0;
+ if (nLen > LCP_MAX)
+ nLen = LCP_MAX;
+ int nTaggedLen = 0;
+ if (nLen)
+ nTaggedLen = (nLen << TAG_BITS) | (lzsa_get_index_tag((unsigned int)nIndex) & ((1 << TAG_BITS) - 1));
+ intervals[i] = ((unsigned int)nIndex) | (((unsigned int)nTaggedLen) << LCP_SHIFT);
+ }
+ }
+ else {
+ for (i = 1; i < nInWindowSize; i++) {
+ int nIndex = (int)(intervals[i] & POS_MASK);
+ int nLen = PLCP[nIndex];
+ if (nLen < nMinMatchSize)
+ nLen = 0;
+ if (nLen > LCP_AND_TAG_MAX)
+ nLen = LCP_AND_TAG_MAX;
+ intervals[i] = ((unsigned int)nIndex) | (((unsigned int)nLen) << LCP_SHIFT);
+ }
+ }
+
+ /**
+ * Build intervals for finding matches
+ *
+ * Methodology and code fragment taken from wimlib (CC0 license):
+ * https://wimlib.net/git/?p=wimlib;a=blob_plain;f=src/lcpit_matchfinder.c;h=a2d6a1e0cd95200d1f3a5464d8359d5736b14cbe;hb=HEAD
+ */
+ unsigned int * const SA_and_LCP = intervals;
+ unsigned int *pos_data = pCompressor->pos_data;
+ unsigned int next_interval_idx;
+ unsigned int *top = pCompressor->open_intervals;
+ unsigned int prev_pos = SA_and_LCP[0] & POS_MASK;
+
+ *top = 0;
+ intervals[0] = 0;
+ next_interval_idx = 1;
+
+ for (r = 1; r < nInWindowSize; r++) {
+ const unsigned int next_pos = SA_and_LCP[r] & POS_MASK;
+ const unsigned int next_lcp = SA_and_LCP[r] & LCP_MASK;
+ const unsigned int top_lcp = *top & LCP_MASK;
+
+ if (next_lcp == top_lcp) {
+ /* Continuing the deepest open interval */
+ pos_data[prev_pos] = *top;
+ }
+ else if (next_lcp > top_lcp) {
+ /* Opening a new interval */
+ *++top = next_lcp | next_interval_idx++;
+ pos_data[prev_pos] = *top;
+ }
+ else {
+ /* Closing the deepest open interval */
+ pos_data[prev_pos] = *top;
+ for (;;) {
+ const unsigned int closed_interval_idx = *top-- & POS_MASK;
+ const unsigned int superinterval_lcp = *top & LCP_MASK;
+
+ if (next_lcp == superinterval_lcp) {
+ /* Continuing the superinterval */
+ intervals[closed_interval_idx] = *top;
+ break;
+ }
+ else if (next_lcp > superinterval_lcp) {
+ /* Creating a new interval that is a
+ * superinterval of the one being
+ * closed, but still a subinterval of
+ * its superinterval */
+ *++top = next_lcp | next_interval_idx++;
+ intervals[closed_interval_idx] = *top;
+ break;
+ }
+ else {
+ /* Also closing the superinterval */
+ intervals[closed_interval_idx] = *top;
+ }
+ }
+ }
+ prev_pos = next_pos;
+ }
+
+ /* Close any still-open intervals. */
+ pos_data[prev_pos] = *top;
+ for (; top > pCompressor->open_intervals; top--)
+ intervals[*top & POS_MASK] = *(top - 1);
+
+ /* Success */
+ return 0;
+}
+
+/**
+ * Find matches at the specified offset in the input window
+ *
+ * @param pCompressor compression context
+ * @param nOffset offset to find matches at, in the input window
+ * @param pMatches pointer to returned matches
+ * @param nMaxMatches maximum number of matches to return (0 for none)
+ * @param nInWindowSize total input size in bytes (previously compressed bytes + bytes to compress)
+ *
+ * @return number of matches
+ */
+int lzsa_find_matches_at(lzsa_compressor *pCompressor, const int nOffset, lzsa_match *pMatches, const int nMaxMatches, const int nInWindowSize) {
+ unsigned int *intervals = pCompressor->intervals;
+ unsigned int *pos_data = pCompressor->pos_data;
+ unsigned int ref;
+ unsigned int super_ref;
+ unsigned int match_pos;
+ lzsa_match *matchptr;
+ int nPrevOffset = 0;
+
+ /**
+ * Find matches using intervals
+ *
+ * Taken from wimlib (CC0 license):
+ * https://wimlib.net/git/?p=wimlib;a=blob_plain;f=src/lcpit_matchfinder.c;h=a2d6a1e0cd95200d1f3a5464d8359d5736b14cbe;hb=HEAD
+ */
+
+ /* Get the deepest lcp-interval containing the current suffix. */
+ ref = pos_data[nOffset];
+
+ pos_data[nOffset] = 0;
+
+ /* Ascend until we reach a visited interval, the root, or a child of the
+ * root. Link unvisited intervals to the current suffix as we go. */
+ while ((super_ref = intervals[ref & POS_MASK]) & LCP_MASK) {
+ intervals[ref & POS_MASK] = nOffset | VISITED_FLAG;
+ ref = super_ref;
+ }
+
+ if (super_ref == 0) {
+ /* In this case, the current interval may be any of:
+ * (1) the root;
+ * (2) an unvisited child of the root */
+
+ if (ref != 0) /* Not the root? */
+ intervals[ref & POS_MASK] = nOffset | VISITED_FLAG;
+ return 0;
+ }
+
+ /* Ascend indirectly via pos_data[] links. */
+ match_pos = super_ref & EXCL_VISITED_MASK;
+ matchptr = pMatches;
+
+ if (pCompressor->format_version >= 2 && nInWindowSize < 65536) {
+ if ((matchptr - pMatches) < nMaxMatches) {
+ int nMatchOffset = (int)(nOffset - match_pos);
+
+ if (nMatchOffset <= MAX_OFFSET) {
+ matchptr->length = (unsigned short)(ref >> (LCP_SHIFT + TAG_BITS));
+ matchptr->offset = (unsigned short)nMatchOffset;
+ matchptr++;
+
+ nPrevOffset = nMatchOffset;
+ }
+ }
+ }
+
+ for (;;) {
+ if ((super_ref = pos_data[match_pos]) > ref) {
+ match_pos = intervals[super_ref & POS_MASK] & EXCL_VISITED_MASK;
+
+ if (pCompressor->format_version >= 2 && nInWindowSize < 65536) {
+ if ((matchptr - pMatches) < nMaxMatches) {
+ int nMatchOffset = (int)(nOffset - match_pos);
+
+ if (nMatchOffset <= MAX_OFFSET && nMatchOffset != nPrevOffset) {
+ matchptr->length = ((unsigned short)(ref >> (LCP_SHIFT + TAG_BITS))) | 0x8000;
+ matchptr->offset = (unsigned short)nMatchOffset;
+ matchptr++;
+
+ nPrevOffset = nMatchOffset;
+ }
+ }
+ }
+ }
+
+ while ((super_ref = pos_data[match_pos]) > ref)
+ match_pos = intervals[super_ref & POS_MASK] & EXCL_VISITED_MASK;
+ intervals[ref & POS_MASK] = nOffset | VISITED_FLAG;
+ pos_data[match_pos] = ref;
+
+ if ((matchptr - pMatches) < nMaxMatches) {
+ int nMatchOffset = (int)(nOffset - match_pos);
+
+ if (nMatchOffset <= MAX_OFFSET && nMatchOffset != nPrevOffset) {
+ if (pCompressor->format_version >= 2) {
+ matchptr->length = (unsigned short)(ref >> (LCP_SHIFT + TAG_BITS));
+ }
+ else {
+ matchptr->length = (unsigned short)(ref >> LCP_SHIFT);
+ }
+ matchptr->offset = (unsigned short)nMatchOffset;
+ matchptr++;
+ }
+ }
+
+ if (super_ref == 0)
+ break;
+ ref = super_ref;
+ match_pos = intervals[ref & POS_MASK] & EXCL_VISITED_MASK;
+
+ if (pCompressor->format_version >= 2 && nInWindowSize < 65536) {
+ if ((matchptr - pMatches) < nMaxMatches) {
+ int nMatchOffset = (int)(nOffset - match_pos);
+
+ if (nMatchOffset <= MAX_OFFSET && nMatchOffset != nPrevOffset) {
+ matchptr->length = ((unsigned short)(ref >> (LCP_SHIFT + TAG_BITS))) | 0x8000;
+ matchptr->offset = (unsigned short)nMatchOffset;
+
+ if ((matchptr->length & 0x7fff) > 2) {
+ matchptr++;
+
+ nPrevOffset = nMatchOffset;
+ }
+ }
+ }
+ }
+ }
+
+ return (int)(matchptr - pMatches);
+}
+
+/**
+ * Skip previously compressed bytes
+ *
+ * @param pCompressor compression context
+ * @param nStartOffset current offset in input window (typically 0)
+ * @param nEndOffset offset to skip to in input window (typically the number of previously compressed bytes)
+ */
+void lzsa_skip_matches(lzsa_compressor *pCompressor, const int nStartOffset, const int nEndOffset) {
+ lzsa_match match;
+ int i;
+
+ /* Skipping still requires scanning for matches, as this also performs a lazy update of the intervals. However,
+ * we don't store the matches. */
+ for (i = nStartOffset; i < nEndOffset; i++) {
+ lzsa_find_matches_at(pCompressor, i, &match, 0, 0);
+ }
+}
+
+/**
+ * Find all matches for the data to be compressed
+ *
+ * @param pCompressor compression context
+ * @param nMatchesPerOffset maximum number of matches to store for each offset
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ */
+void lzsa_find_all_matches(lzsa_compressor *pCompressor, const int nMatchesPerOffset, const int nStartOffset, const int nEndOffset) {
+ lzsa_match *pMatch = pCompressor->match;
+ int i;
+
+ for (i = nStartOffset; i < nEndOffset; i++) {
+ int nMatches = lzsa_find_matches_at(pCompressor, i, pMatch, nMatchesPerOffset, nEndOffset - nStartOffset);
+
+ while (nMatches < nMatchesPerOffset) {
+ pMatch[nMatches].length = 0;
+ pMatch[nMatches].offset = 0;
+ nMatches++;
+ }
+
+ pMatch += nMatchesPerOffset;
+ }
+}
diff --git a/tools/rasm/lzsa-master/src/matchfinder.h b/tools/rasm/lzsa-master/src/matchfinder.h
new file mode 100644
index 0000000..cc3b5ab
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/matchfinder.h
@@ -0,0 +1,91 @@
+/*
+ * matchfinder.h - LZ match finder definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#ifndef _MATCHFINDER_H
+#define _MATCHFINDER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declarations */
+typedef struct _lzsa_match lzsa_match;
+typedef struct _lzsa_compressor lzsa_compressor;
+
+/**
+ * Parse input data, build suffix array and overlaid data structures to speed up match finding
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param nInWindowSize total input size in bytes (previously compressed bytes + bytes to compress)
+ *
+ * @return 0 for success, non-zero for failure
+ */
+int lzsa_build_suffix_array(lzsa_compressor *pCompressor, const unsigned char *pInWindow, const int nInWindowSize);
+
+/**
+ * Find matches at the specified offset in the input window
+ *
+ * @param pCompressor compression context
+ * @param nOffset offset to find matches at, in the input window
+ * @param pMatches pointer to returned matches
+ * @param nMaxMatches maximum number of matches to return (0 for none)
+ * @param nInWindowSize total input size in bytes (previously compressed bytes + bytes to compress)
+ *
+ * @return number of matches
+ */
+int lzsa_find_matches_at(lzsa_compressor *pCompressor, const int nOffset, lzsa_match *pMatches, const int nMaxMatches, const int nInWindowSize);
+
+/**
+ * Skip previously compressed bytes
+ *
+ * @param pCompressor compression context
+ * @param nStartOffset current offset in input window (typically 0)
+ * @param nEndOffset offset to skip to in input window (typically the number of previously compressed bytes)
+ */
+void lzsa_skip_matches(lzsa_compressor *pCompressor, const int nStartOffset, const int nEndOffset);
+
+/**
+ * Find all matches for the data to be compressed
+ *
+ * @param pCompressor compression context
+ * @param nMatchesPerOffset maximum number of matches to store for each offset
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ */
+void lzsa_find_all_matches(lzsa_compressor *pCompressor, const int nMatchesPerOffset, const int nStartOffset, const int nEndOffset);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MATCHFINDER_H */
diff --git a/tools/rasm/lzsa-master/src/shrink_block_v1.c b/tools/rasm/lzsa-master/src/shrink_block_v1.c
new file mode 100644
index 0000000..32c5c38
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/shrink_block_v1.c
@@ -0,0 +1,710 @@
+/*
+ * shrink_block_v1.c - LZSA1 block compressor implementation
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "lib.h"
+#include "shrink_block_v1.h"
+#include "format.h"
+
+/**
+ * Get the number of extra bits required to represent a literals length
+ *
+ * @param nLength literals length
+ *
+ * @return number of extra bits required
+ */
+static inline int lzsa_get_literals_varlen_size_v1(const int nLength) {
+ if (nLength < LITERALS_RUN_LEN_V1) {
+ return 0;
+ }
+ else {
+ if (nLength < 256)
+ return 8;
+ else {
+ if (nLength < 512)
+ return 16;
+ else
+ return 24;
+ }
+ }
+}
+
+/**
+ * Write extra literals length bytes to output (compressed) buffer. The caller must first check that there is enough
+ * room to write the bytes.
+ *
+ * @param pOutData pointer to output buffer
+ * @param nOutOffset current write index into output buffer
+ * @param nLength literals length
+ */
+static inline int lzsa_write_literals_varlen_v1(unsigned char *pOutData, int nOutOffset, int nLength) {
+ if (nLength >= LITERALS_RUN_LEN_V1) {
+ if (nLength < 256)
+ pOutData[nOutOffset++] = nLength - LITERALS_RUN_LEN_V1;
+ else {
+ if (nLength < 512) {
+ pOutData[nOutOffset++] = 250;
+ pOutData[nOutOffset++] = nLength - 256;
+ }
+ else {
+ pOutData[nOutOffset++] = 249;
+ pOutData[nOutOffset++] = nLength & 0xff;
+ pOutData[nOutOffset++] = (nLength >> 8) & 0xff;
+ }
+ }
+ }
+
+ return nOutOffset;
+}
+
+/**
+ * Get the number of extra bits required to represent an encoded match length
+ *
+ * @param nLength encoded match length (actual match length - MIN_MATCH_SIZE_V1)
+ *
+ * @return number of extra bits required
+ */
+static inline int lzsa_get_match_varlen_size_v1(const int nLength) {
+ if (nLength < MATCH_RUN_LEN_V1) {
+ return 0;
+ }
+ else {
+ if ((nLength + MIN_MATCH_SIZE_V1) < 256)
+ return 8;
+ else {
+ if ((nLength + MIN_MATCH_SIZE_V1) < 512)
+ return 16;
+ else
+ return 24;
+ }
+ }
+}
+
+/**
+ * Write extra encoded match length bytes to output (compressed) buffer. The caller must first check that there is enough
+ * room to write the bytes.
+ *
+ * @param pOutData pointer to output buffer
+ * @param nOutOffset current write index into output buffer
+ * @param nLength encoded match length (actual match length - MIN_MATCH_SIZE_V1)
+ */
+static inline int lzsa_write_match_varlen_v1(unsigned char *pOutData, int nOutOffset, int nLength) {
+ if (nLength >= MATCH_RUN_LEN_V1) {
+ if ((nLength + MIN_MATCH_SIZE_V1) < 256)
+ pOutData[nOutOffset++] = nLength - MATCH_RUN_LEN_V1;
+ else {
+ if ((nLength + MIN_MATCH_SIZE_V1) < 512) {
+ pOutData[nOutOffset++] = 239;
+ pOutData[nOutOffset++] = nLength + MIN_MATCH_SIZE_V1 - 256;
+ }
+ else {
+ pOutData[nOutOffset++] = 238;
+ pOutData[nOutOffset++] = (nLength + MIN_MATCH_SIZE_V1) & 0xff;
+ pOutData[nOutOffset++] = ((nLength + MIN_MATCH_SIZE_V1) >> 8) & 0xff;
+ }
+ }
+ }
+
+ return nOutOffset;
+}
+
+/**
+ * Get offset encoding cost in bits
+ *
+ * @param nMatchOffset offset to get cost of
+ *
+ * @return cost in bits
+ */
+static inline int lzsa_get_offset_cost_v1(const unsigned int nMatchOffset) {
+ return (nMatchOffset <= 256) ? 8 : 16;
+}
+
+/**
+ * Attempt to pick optimal matches using a forward arrivals parser, so as to produce the smallest possible output that decompresses to the same input
+ *
+ * @param pCompressor compression context
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ */
+static void lzsa_optimize_forward_v1(lzsa_compressor *pCompressor, lzsa_match *pBestMatch, const int nStartOffset, const int nEndOffset, const int nReduce) {
+ lzsa_arrival *arrival = pCompressor->arrival - (nStartOffset << ARRIVALS_PER_POSITION_SHIFT);
+ const int nMinMatchSize = pCompressor->min_match_size;
+ const int nFavorRatio = (pCompressor->flags & LZSA_FLAG_FAVOR_RATIO) ? 1 : 0;
+ const int nModeSwitchPenalty = nFavorRatio ? 0 : MODESWITCH_PENALTY;
+ const int nDisableScore = nReduce ? 0 : (2 * BLOCK_SIZE);
+ int i, j, n;
+
+ if ((nEndOffset - nStartOffset) > BLOCK_SIZE) return;
+
+ memset(arrival + (nStartOffset << ARRIVALS_PER_POSITION_SHIFT), 0, sizeof(lzsa_arrival) * ((nEndOffset - nStartOffset + 1) << ARRIVALS_PER_POSITION_SHIFT));
+
+ arrival[nStartOffset << ARRIVALS_PER_POSITION_SHIFT].from_slot = -1;
+
+ for (i = nStartOffset; i != nEndOffset; i++) {
+ lzsa_arrival* cur_arrival = &arrival[i << ARRIVALS_PER_POSITION_SHIFT];
+ int m;
+
+ for (j = 0; j < NARRIVALS_PER_POSITION_V1 && cur_arrival[j].from_slot; j++) {
+ int nPrevCost = cur_arrival[j].cost;
+ int nCodingChoiceCost = nPrevCost + 8 /* literal */;
+ int nScore = cur_arrival[j].score + 1;
+ int nNumLiterals = cur_arrival[j].num_literals + 1;
+
+ if (nNumLiterals == LITERALS_RUN_LEN_V1 || nNumLiterals == 256 || nNumLiterals == 512) {
+ nCodingChoiceCost += 8;
+ }
+
+ if (nNumLiterals == 1)
+ nCodingChoiceCost += nModeSwitchPenalty;
+
+ lzsa_arrival *pDestSlots = &arrival[(i + 1) << ARRIVALS_PER_POSITION_SHIFT];
+ for (n = 0; n < NARRIVALS_PER_POSITION_V1 /* we only need the literals + short match cost + long match cost cases */; n++) {
+ lzsa_arrival *pDestArrival = &pDestSlots[n];
+
+ if (pDestArrival->from_slot == 0 ||
+ nCodingChoiceCost < pDestArrival->cost ||
+ (nCodingChoiceCost == pDestArrival->cost && nScore < (pDestArrival->score + nDisableScore))) {
+ memmove(&arrival[((i + 1) << ARRIVALS_PER_POSITION_SHIFT) + n + 1],
+ &arrival[((i + 1) << ARRIVALS_PER_POSITION_SHIFT) + n],
+ sizeof(lzsa_arrival) * (NARRIVALS_PER_POSITION_V1 - n - 1));
+
+ pDestArrival->cost = nCodingChoiceCost;
+ pDestArrival->from_pos = i;
+ pDestArrival->from_slot = j + 1;
+ pDestArrival->match_len = 0;
+ pDestArrival->num_literals = nNumLiterals;
+ pDestArrival->score = nScore;
+ pDestArrival->rep_offset = cur_arrival[j].rep_offset;
+ break;
+ }
+ }
+ }
+
+ const lzsa_match *match = pCompressor->match + ((i - nStartOffset) << MATCHES_PER_INDEX_SHIFT_V1);
+ int nNumArrivalsForThisPos = j;
+
+ for (m = 0; m < NMATCHES_PER_INDEX_V1 && match[m].length; m++) {
+ int nMatchLen = match[m].length;
+ int nMatchOffsetCost = lzsa_get_offset_cost_v1(match[m].offset);
+ int nStartingMatchLen, k;
+
+ if ((i + nMatchLen) > nEndOffset)
+ nMatchLen = nEndOffset - i;
+
+ if (nMatchLen >= LEAVE_ALONE_MATCH_SIZE)
+ nStartingMatchLen = nMatchLen;
+ else
+ nStartingMatchLen = nMinMatchSize;
+ for (k = nStartingMatchLen; k <= nMatchLen; k++) {
+ int nMatchLenCost = lzsa_get_match_varlen_size_v1(k - MIN_MATCH_SIZE_V1);
+
+ lzsa_arrival *pDestSlots = &arrival[(i + k) << ARRIVALS_PER_POSITION_SHIFT];
+
+ for (j = 0; j < nNumArrivalsForThisPos; j++) {
+ int nPrevCost = cur_arrival[j].cost;
+ int nCodingChoiceCost = nPrevCost + 8 /* token */ /* the actual cost of the literals themselves accumulates up the chain */ + nMatchOffsetCost + nMatchLenCost;
+ int exists = 0;
+
+ if (!cur_arrival[j].num_literals)
+ nCodingChoiceCost += nModeSwitchPenalty;
+
+ for (n = 0;
+ n < NARRIVALS_PER_POSITION_V1 && pDestSlots[n].from_slot && pDestSlots[n].cost <= nCodingChoiceCost;
+ n++) {
+ if (lzsa_get_offset_cost_v1(pDestSlots[n].rep_offset) == nMatchOffsetCost) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (!exists) {
+ int nScore = cur_arrival[j].score + 5;
+
+ for (n = 0; n < NARRIVALS_PER_POSITION_V1 /* we only need the literals + short match cost + long match cost cases */; n++) {
+ lzsa_arrival *pDestArrival = &pDestSlots[n];
+
+ if (pDestArrival->from_slot == 0 ||
+ nCodingChoiceCost < pDestArrival->cost ||
+ (nCodingChoiceCost == pDestArrival->cost && nScore < (pDestArrival->score + nDisableScore))) {
+ memmove(&pDestSlots[n + 1],
+ &pDestSlots[n],
+ sizeof(lzsa_arrival) * (NARRIVALS_PER_POSITION_V1 - n - 1));
+
+ pDestArrival->cost = nCodingChoiceCost;
+ pDestArrival->from_pos = i;
+ pDestArrival->from_slot = j + 1;
+ pDestArrival->match_len = k;
+ pDestArrival->num_literals = 0;
+ pDestArrival->score = nScore;
+ pDestArrival->rep_offset = match[m].offset;
+ j = NARRIVALS_PER_POSITION_V1;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ lzsa_arrival *end_arrival = &arrival[(i << ARRIVALS_PER_POSITION_SHIFT) + 0];
+
+ while (end_arrival->from_slot > 0 && end_arrival->from_pos >= 0) {
+ if (end_arrival->from_pos >= nEndOffset) return;
+ pBestMatch[end_arrival->from_pos].length = end_arrival->match_len;
+ if (end_arrival->match_len)
+ pBestMatch[end_arrival->from_pos].offset = end_arrival->rep_offset;
+ else
+ pBestMatch[end_arrival->from_pos].offset = 0;
+
+ end_arrival = &arrival[(end_arrival->from_pos << ARRIVALS_PER_POSITION_SHIFT) + (end_arrival->from_slot - 1)];
+ }
+}
+
+/**
+ * Attempt to minimize the number of commands issued in the compressed data block, in order to speed up decompression without
+ * impacting the compression ratio
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param pBestMatch optimal matches to emit
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ *
+ * @return non-zero if the number of tokens was reduced, 0 if it wasn't
+ */
+static int lzsa_optimize_command_count_v1(lzsa_compressor *pCompressor, const unsigned char *pInWindow, lzsa_match *pBestMatch, const int nStartOffset, const int nEndOffset) {
+ int i;
+ int nNumLiterals = 0;
+ int nDidReduce = 0;
+
+ for (i = nStartOffset; i < nEndOffset; ) {
+ lzsa_match *pMatch = pBestMatch + i;
+
+ if (pMatch->length == 0 &&
+ (i + 1) < nEndOffset &&
+ pBestMatch[i + 1].length >= MIN_MATCH_SIZE_V1 &&
+ pBestMatch[i + 1].length < MAX_VARLEN &&
+ pBestMatch[i + 1].offset &&
+ i >= pBestMatch[i + 1].offset &&
+ (i + pBestMatch[i + 1].length + 1) <= nEndOffset &&
+ !memcmp(pInWindow + i - (pBestMatch[i + 1].offset), pInWindow + i, pBestMatch[i + 1].length + 1)) {
+ int nCurLenSize = lzsa_get_match_varlen_size_v1(pBestMatch[i + 1].length - MIN_MATCH_SIZE_V1);
+ int nReducedLenSize = lzsa_get_match_varlen_size_v1(pBestMatch[i + 1].length + 1 - MIN_MATCH_SIZE_V1);
+
+ if ((nReducedLenSize - nCurLenSize) <= 8) {
+ /* Merge */
+ pBestMatch[i].length = pBestMatch[i + 1].length + 1;
+ pBestMatch[i].offset = pBestMatch[i + 1].offset;
+ pBestMatch[i + 1].length = 0;
+ pBestMatch[i + 1].offset = 0;
+ nDidReduce = 1;
+ continue;
+ }
+ }
+
+ if (pMatch->length >= MIN_MATCH_SIZE_V1) {
+ if (pMatch->length <= 9 /* Don't waste time considering large matches, they will always win over literals */ &&
+ (i + pMatch->length) < nEndOffset /* Don't consider the last token in the block, we can only reduce a match inbetween other tokens */) {
+ int nNextIndex = i + pMatch->length;
+ int nNextLiterals = 0;
+
+ while (nNextIndex < nEndOffset && pBestMatch[nNextIndex].length < MIN_MATCH_SIZE_V1) {
+ nNextLiterals++;
+ nNextIndex++;
+ }
+
+ /* This command is a match, is followed by 'nNextLiterals' literals and then by another match, or the end of the input. Calculate this command's current cost (excluding 'nNumLiterals' bytes) */
+ if ((8 /* token */ + lzsa_get_literals_varlen_size_v1(nNumLiterals) + ((pMatch->offset <= 256) ? 8 : 16) /* match offset */ + lzsa_get_match_varlen_size_v1(pMatch->length - MIN_MATCH_SIZE_V1) +
+ 8 /* token */ + lzsa_get_literals_varlen_size_v1(nNextLiterals)) >=
+ (8 /* token */ + (pMatch->length << 3) + lzsa_get_literals_varlen_size_v1(nNumLiterals + pMatch->length + nNextLiterals))) {
+ /* Reduce */
+ int nMatchLen = pMatch->length;
+ int j;
+
+ for (j = 0; j < nMatchLen; j++) {
+ pBestMatch[i + j].length = 0;
+ }
+
+ nDidReduce = 1;
+ continue;
+ }
+ }
+
+ if ((i + pMatch->length) <= nEndOffset && pMatch->offset > 0 && pMatch->length >= MIN_MATCH_SIZE_V1 &&
+ pBestMatch[i + pMatch->length].offset > 0 &&
+ pBestMatch[i + pMatch->length].length >= MIN_MATCH_SIZE_V1 &&
+ (pMatch->length + pBestMatch[i + pMatch->length].length) >= LEAVE_ALONE_MATCH_SIZE &&
+ (pMatch->length + pBestMatch[i + pMatch->length].length) <= MAX_VARLEN &&
+ (i + pMatch->length) > pMatch->offset &&
+ (i + pMatch->length) > pBestMatch[i + pMatch->length].offset &&
+ (i + pMatch->length + pBestMatch[i + pMatch->length].length) <= nEndOffset &&
+ !memcmp(pInWindow + i - pMatch->offset + pMatch->length,
+ pInWindow + i + pMatch->length - pBestMatch[i + pMatch->length].offset,
+ pBestMatch[i + pMatch->length].length)) {
+
+ int nCurPartialSize = lzsa_get_match_varlen_size_v1(pMatch->length - MIN_MATCH_SIZE_V1);
+ nCurPartialSize += 8 /* token */ + lzsa_get_literals_varlen_size_v1(0) + ((pBestMatch[i + pMatch->length].offset <= 256) ? 8 : 16) /* match offset */ + lzsa_get_match_varlen_size_v1(pBestMatch[i + pMatch->length].length - MIN_MATCH_SIZE_V1);
+
+ int nReducedPartialSize = lzsa_get_match_varlen_size_v1(pMatch->length + pBestMatch[i + pMatch->length].length - MIN_MATCH_SIZE_V1);
+
+ if (nCurPartialSize >= nReducedPartialSize) {
+ int nMatchLen = pMatch->length;
+
+ /* Join */
+
+ pMatch->length += pBestMatch[i + nMatchLen].length;
+ pBestMatch[i + nMatchLen].offset = 0;
+ pBestMatch[i + nMatchLen].length = -1;
+ continue;
+ }
+ }
+
+ i += pMatch->length;
+ nNumLiterals = 0;
+ }
+ else {
+ nNumLiterals++;
+ i++;
+ }
+ }
+
+ return nDidReduce;
+}
+
+/**
+ * Get compressed data block size
+ *
+ * @param pCompressor compression context
+ * @param pBestMatch optimal matches to emit
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ *
+ * @return size of compressed data that will be written to output buffer
+ */
+static int lzsa_get_compressed_size_v1(lzsa_compressor *pCompressor, lzsa_match *pBestMatch, const int nStartOffset, const int nEndOffset) {
+ int i;
+ int nNumLiterals = 0;
+ int nCompressedSize = 0;
+
+ for (i = nStartOffset; i < nEndOffset; ) {
+ const lzsa_match *pMatch = pBestMatch + i;
+
+ if (pMatch->length >= MIN_MATCH_SIZE_V1) {
+ int nMatchOffset = pMatch->offset;
+ int nMatchLen = pMatch->length;
+ int nEncodedMatchLen = nMatchLen - MIN_MATCH_SIZE_V1;
+ int nTokenLongOffset = (nMatchOffset <= 256) ? 0x00 : 0x80;
+ int nCommandSize = 8 /* token */ + lzsa_get_literals_varlen_size_v1(nNumLiterals) + (nNumLiterals << 3) + (nTokenLongOffset ? 16 : 8) /* match offset */ + lzsa_get_match_varlen_size_v1(nEncodedMatchLen);
+
+ nCompressedSize += nCommandSize;
+ nNumLiterals = 0;
+ i += nMatchLen;
+ }
+ else {
+ nNumLiterals++;
+ i++;
+ }
+ }
+
+ {
+ int nCommandSize = 8 /* token */ + lzsa_get_literals_varlen_size_v1(nNumLiterals) + (nNumLiterals << 3);
+
+ nCompressedSize += nCommandSize;
+ nNumLiterals = 0;
+ }
+
+ if (pCompressor->flags & LZSA_FLAG_RAW_BLOCK) {
+ nCompressedSize += 8 * 4;
+ }
+
+ return nCompressedSize;
+}
+
+/**
+ * Emit block of compressed data
+ *
+ * @param pCompressor compression context
+ * @param pBestMatch optimal matches to emit
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ * @param pOutData pointer to output buffer
+ * @param nMaxOutDataSize maximum size of output buffer, in bytes
+ *
+ * @return size of compressed data in output buffer, or -1 if the data is uncompressible
+ */
+static int lzsa_write_block_v1(lzsa_compressor *pCompressor, lzsa_match *pBestMatch, const unsigned char *pInWindow, const int nStartOffset, const int nEndOffset, unsigned char *pOutData, const int nMaxOutDataSize) {
+ int i;
+ int nNumLiterals = 0;
+ int nInFirstLiteralOffset = 0;
+ int nOutOffset = 0;
+
+ for (i = nStartOffset; i < nEndOffset; ) {
+ const lzsa_match *pMatch = pBestMatch + i;
+
+ if (pMatch->length >= MIN_MATCH_SIZE_V1) {
+ int nMatchOffset = pMatch->offset;
+ int nMatchLen = pMatch->length;
+ int nEncodedMatchLen = nMatchLen - MIN_MATCH_SIZE_V1;
+ int nTokenLiteralsLen = (nNumLiterals >= LITERALS_RUN_LEN_V1) ? LITERALS_RUN_LEN_V1 : nNumLiterals;
+ int nTokenMatchLen = (nEncodedMatchLen >= MATCH_RUN_LEN_V1) ? MATCH_RUN_LEN_V1 : nEncodedMatchLen;
+ int nTokenLongOffset = (nMatchOffset <= 256) ? 0x00 : 0x80;
+ int nCommandSize = 8 /* token */ + lzsa_get_literals_varlen_size_v1(nNumLiterals) + (nNumLiterals << 3) + (nTokenLongOffset ? 16 : 8) /* match offset */ + lzsa_get_match_varlen_size_v1(nEncodedMatchLen);
+
+ if ((nOutOffset + (nCommandSize >> 3)) > nMaxOutDataSize)
+ return -1;
+ if (nMatchOffset < MIN_OFFSET || nMatchOffset > MAX_OFFSET)
+ return -1;
+
+ pOutData[nOutOffset++] = nTokenLongOffset | (nTokenLiteralsLen << 4) | nTokenMatchLen;
+ nOutOffset = lzsa_write_literals_varlen_v1(pOutData, nOutOffset, nNumLiterals);
+
+ if (nNumLiterals < pCompressor->stats.min_literals || pCompressor->stats.min_literals == -1)
+ pCompressor->stats.min_literals = nNumLiterals;
+ if (nNumLiterals > pCompressor->stats.max_literals)
+ pCompressor->stats.max_literals = nNumLiterals;
+ pCompressor->stats.total_literals += nNumLiterals;
+ pCompressor->stats.literals_divisor++;
+
+ if (nNumLiterals != 0) {
+ memcpy(pOutData + nOutOffset, pInWindow + nInFirstLiteralOffset, nNumLiterals);
+ nOutOffset += nNumLiterals;
+ nNumLiterals = 0;
+ }
+
+ pOutData[nOutOffset++] = (-nMatchOffset) & 0xff;
+ if (nTokenLongOffset) {
+ pOutData[nOutOffset++] = (-nMatchOffset) >> 8;
+ }
+ nOutOffset = lzsa_write_match_varlen_v1(pOutData, nOutOffset, nEncodedMatchLen);
+
+ if (nMatchOffset < pCompressor->stats.min_offset || pCompressor->stats.min_offset == -1)
+ pCompressor->stats.min_offset = nMatchOffset;
+ if (nMatchOffset > pCompressor->stats.max_offset)
+ pCompressor->stats.max_offset = nMatchOffset;
+ pCompressor->stats.total_offsets += nMatchOffset;
+
+ if (nMatchLen < pCompressor->stats.min_match_len || pCompressor->stats.min_match_len == -1)
+ pCompressor->stats.min_match_len = nMatchLen;
+ if (nMatchLen > pCompressor->stats.max_match_len)
+ pCompressor->stats.max_match_len = nMatchLen;
+ pCompressor->stats.total_match_lens += nMatchLen;
+ pCompressor->stats.match_divisor++;
+
+ if (nMatchOffset == 1) {
+ if (nMatchLen < pCompressor->stats.min_rle1_len || pCompressor->stats.min_rle1_len == -1)
+ pCompressor->stats.min_rle1_len = nMatchLen;
+ if (nMatchLen > pCompressor->stats.max_rle1_len)
+ pCompressor->stats.max_rle1_len = nMatchLen;
+ pCompressor->stats.total_rle1_lens += nMatchLen;
+ pCompressor->stats.rle1_divisor++;
+ }
+ else if (nMatchOffset == 2) {
+ if (nMatchLen < pCompressor->stats.min_rle2_len || pCompressor->stats.min_rle2_len == -1)
+ pCompressor->stats.min_rle2_len = nMatchLen;
+ if (nMatchLen > pCompressor->stats.max_rle2_len)
+ pCompressor->stats.max_rle2_len = nMatchLen;
+ pCompressor->stats.total_rle2_lens += nMatchLen;
+ pCompressor->stats.rle2_divisor++;
+ }
+
+ i += nMatchLen;
+
+ if (pCompressor->flags & LZSA_FLAG_RAW_BLOCK) {
+ int nCurSafeDist = (i - nStartOffset) - nOutOffset;
+ if (nCurSafeDist >= 0 && pCompressor->safe_dist < nCurSafeDist)
+ pCompressor->safe_dist = nCurSafeDist;
+ }
+
+ pCompressor->num_commands++;
+ }
+ else {
+ if (nNumLiterals == 0)
+ nInFirstLiteralOffset = i;
+ nNumLiterals++;
+ i++;
+ }
+ }
+
+ {
+ int nTokenLiteralsLen = (nNumLiterals >= LITERALS_RUN_LEN_V1) ? LITERALS_RUN_LEN_V1 : nNumLiterals;
+ int nCommandSize = 8 /* token */ + lzsa_get_literals_varlen_size_v1(nNumLiterals) + (nNumLiterals << 3);
+
+ if ((nOutOffset + (nCommandSize >> 3)) > nMaxOutDataSize)
+ return -1;
+
+ if (pCompressor->flags & LZSA_FLAG_RAW_BLOCK)
+ pOutData[nOutOffset++] = (nTokenLiteralsLen << 4) | 0x0f;
+ else
+ pOutData[nOutOffset++] = (nTokenLiteralsLen << 4) | 0x00;
+ nOutOffset = lzsa_write_literals_varlen_v1(pOutData, nOutOffset, nNumLiterals);
+
+ if (nNumLiterals < pCompressor->stats.min_literals || pCompressor->stats.min_literals == -1)
+ pCompressor->stats.min_literals = nNumLiterals;
+ if (nNumLiterals > pCompressor->stats.max_literals)
+ pCompressor->stats.max_literals = nNumLiterals;
+ pCompressor->stats.total_literals += nNumLiterals;
+ pCompressor->stats.literals_divisor++;
+
+ if (nNumLiterals != 0) {
+ memcpy(pOutData + nOutOffset, pInWindow + nInFirstLiteralOffset, nNumLiterals);
+ nOutOffset += nNumLiterals;
+ nNumLiterals = 0;
+ }
+
+ if (pCompressor->flags & LZSA_FLAG_RAW_BLOCK) {
+ int nCurSafeDist = (i - nStartOffset) - nOutOffset;
+ if (nCurSafeDist >= 0 && pCompressor->safe_dist < nCurSafeDist)
+ pCompressor->safe_dist = nCurSafeDist;
+ }
+
+ pCompressor->num_commands++;
+ }
+
+ if (pCompressor->flags & LZSA_FLAG_RAW_BLOCK) {
+ /* Emit EOD marker for raw block */
+
+ if ((nOutOffset + 4) > nMaxOutDataSize)
+ return -1;
+
+ pOutData[nOutOffset++] = 0;
+ pOutData[nOutOffset++] = 238;
+ pOutData[nOutOffset++] = 0;
+ pOutData[nOutOffset++] = 0;
+ }
+
+ return nOutOffset;
+}
+
+/**
+ * Emit raw block of uncompressible data
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ * @param pOutData pointer to output buffer
+ * @param nMaxOutDataSize maximum size of output buffer, in bytes
+ *
+ * @return size of compressed data in output buffer, or -1 if the data is uncompressible
+ */
+static int lzsa_write_raw_uncompressed_block_v1(lzsa_compressor *pCompressor, const unsigned char *pInWindow, const int nStartOffset, const int nEndOffset, unsigned char *pOutData, const int nMaxOutDataSize) {
+ int nNumLiterals = nEndOffset - nStartOffset;
+ int nTokenLiteralsLen = (nNumLiterals >= LITERALS_RUN_LEN_V1) ? LITERALS_RUN_LEN_V1 : nNumLiterals;
+ int nOutOffset = 0;
+
+ int nCommandSize = 8 /* token */ + lzsa_get_literals_varlen_size_v1(nNumLiterals) + (nNumLiterals << 3) + 4;
+ if ((nOutOffset + (nCommandSize >> 3)) > nMaxOutDataSize)
+ return -1;
+
+ pCompressor->num_commands = 0;
+ pOutData[nOutOffset++] = (nTokenLiteralsLen << 4) | 0x0f;
+
+ nOutOffset = lzsa_write_literals_varlen_v1(pOutData, nOutOffset, nNumLiterals);
+
+ if (nNumLiterals != 0) {
+ memcpy(pOutData + nOutOffset, pInWindow + nStartOffset, nNumLiterals);
+ nOutOffset += nNumLiterals;
+ nNumLiterals = 0;
+ }
+
+ pCompressor->num_commands++;
+
+ /* Emit EOD marker for raw block */
+
+ pOutData[nOutOffset++] = 0;
+ pOutData[nOutOffset++] = 238;
+ pOutData[nOutOffset++] = 0;
+ pOutData[nOutOffset++] = 0;
+
+ return nOutOffset;
+}
+
+/**
+ * Select the most optimal matches, reduce the token count if possible, and then emit a block of compressed LZSA1 data
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param nPreviousBlockSize number of previously compressed bytes (or 0 for none)
+ * @param nInDataSize number of input bytes to compress
+ * @param pOutData pointer to output buffer
+ * @param nMaxOutDataSize maximum size of output buffer, in bytes
+ *
+ * @return size of compressed data in output buffer, or -1 if the data is uncompressible
+ */
+int lzsa_optimize_and_write_block_v1(lzsa_compressor *pCompressor, const unsigned char *pInWindow, const int nPreviousBlockSize, const int nInDataSize, unsigned char *pOutData, const int nMaxOutDataSize) {
+ int nResult, nBaseCompressedSize;
+
+ /* Compress optimally without breaking ties in favor of less tokens */
+
+ memset(pCompressor->best_match, 0, BLOCK_SIZE * sizeof(lzsa_match));
+ lzsa_optimize_forward_v1(pCompressor, pCompressor->best_match - nPreviousBlockSize, nPreviousBlockSize, nPreviousBlockSize + nInDataSize, 0 /* reduce */);
+
+ int nDidReduce;
+ int nPasses = 0;
+ do {
+ nDidReduce = lzsa_optimize_command_count_v1(pCompressor, pInWindow, pCompressor->best_match - nPreviousBlockSize, nPreviousBlockSize, nPreviousBlockSize + nInDataSize);
+ nPasses++;
+ } while (nDidReduce && nPasses < 20);
+
+ nBaseCompressedSize = lzsa_get_compressed_size_v1(pCompressor, pCompressor->best_match - nPreviousBlockSize, nPreviousBlockSize, nPreviousBlockSize + nInDataSize);
+ lzsa_match *pBestMatch = pCompressor->best_match - nPreviousBlockSize;
+
+ if (nBaseCompressedSize > 0 && nInDataSize < 65536) {
+ int nReducedCompressedSize;
+
+ /* Compress optimally and do break ties in favor of less tokens */
+ memset(pCompressor->improved_match, 0, BLOCK_SIZE * sizeof(lzsa_match));
+ lzsa_optimize_forward_v1(pCompressor, pCompressor->improved_match - nPreviousBlockSize, nPreviousBlockSize, nPreviousBlockSize + nInDataSize, 1 /* reduce */);
+
+ nPasses = 0;
+ do {
+ nDidReduce = lzsa_optimize_command_count_v1(pCompressor, pInWindow, pCompressor->improved_match - nPreviousBlockSize, nPreviousBlockSize, nPreviousBlockSize + nInDataSize);
+ nPasses++;
+ } while (nDidReduce && nPasses < 20);
+
+ nReducedCompressedSize = lzsa_get_compressed_size_v1(pCompressor, pCompressor->improved_match - nPreviousBlockSize, nPreviousBlockSize, nPreviousBlockSize + nInDataSize);
+ if (nReducedCompressedSize > 0 && nReducedCompressedSize <= nBaseCompressedSize) {
+ /* Pick the parse with the reduced number of tokens as it didn't negatively affect the size */
+ pBestMatch = pCompressor->improved_match - nPreviousBlockSize;
+ }
+ }
+
+ nResult = lzsa_write_block_v1(pCompressor, pBestMatch, pInWindow, nPreviousBlockSize, nPreviousBlockSize + nInDataSize, pOutData, nMaxOutDataSize);
+ if (nResult < 0 && pCompressor->flags & LZSA_FLAG_RAW_BLOCK) {
+ nResult = lzsa_write_raw_uncompressed_block_v1(pCompressor, pInWindow, nPreviousBlockSize, nPreviousBlockSize + nInDataSize, pOutData, nMaxOutDataSize);
+ }
+
+ return nResult;
+}
diff --git a/tools/rasm/lzsa-master/src/shrink_block_v1.h b/tools/rasm/lzsa-master/src/shrink_block_v1.h
new file mode 100644
index 0000000..cc89cde
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/shrink_block_v1.h
@@ -0,0 +1,53 @@
+/*
+ * shrink_block_v1.h - LZSA1 block compressor definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#ifndef _SHRINK_BLOCK_V1_H
+#define _SHRINK_BLOCK_V1_H
+
+/* Forward declarations */
+typedef struct _lzsa_compressor lzsa_compressor;
+
+/**
+ * Select the most optimal matches, reduce the token count if possible, and then emit a block of compressed LZSA1 data
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param nPreviousBlockSize number of previously compressed bytes (or 0 for none)
+ * @param nInDataSize number of input bytes to compress
+ * @param pOutData pointer to output buffer
+ * @param nMaxOutDataSize maximum size of output buffer, in bytes
+ *
+ * @return size of compressed data in output buffer, or -1 if the data is uncompressible
+ */
+int lzsa_optimize_and_write_block_v1(lzsa_compressor *pCompressor, const unsigned char *pInWindow, const int nPreviousBlockSize, const int nInDataSize, unsigned char *pOutData, const int nMaxOutDataSize);
+
+#endif /* _SHRINK_BLOCK_V1_H */
diff --git a/tools/rasm/lzsa-master/src/shrink_block_v2.c b/tools/rasm/lzsa-master/src/shrink_block_v2.c
new file mode 100644
index 0000000..0aba0c0
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/shrink_block_v2.c
@@ -0,0 +1,1371 @@
+/*
+ * shrink_block_v2.c - LZSA2 block compressor implementation
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "lib.h"
+#include "shrink_block_v2.h"
+#include "format.h"
+
+/**
+ * Write 4-bit nibble to output (compressed) buffer
+ *
+ * @param pOutData pointer to output buffer
+ * @param nOutOffset current write index into output buffer
+ * @param nMaxOutDataSize maximum size of output buffer, in bytes
+ * @param nCurNibbleOffset write index into output buffer, of current byte being filled with nibbles
+ * @param nNibbleValue value to write (0..15)
+ */
+static int lzsa_write_nibble_v2(unsigned char *pOutData, int nOutOffset, const int nMaxOutDataSize, int *nCurNibbleOffset, int nNibbleValue) {
+ if (nOutOffset < 0) return -1;
+
+ if ((*nCurNibbleOffset) == -1) {
+ if (nOutOffset >= nMaxOutDataSize) return -1;
+ (*nCurNibbleOffset) = nOutOffset;
+ pOutData[nOutOffset++] = nNibbleValue << 4;
+ }
+ else {
+ pOutData[*nCurNibbleOffset] = (pOutData[*nCurNibbleOffset]) | (nNibbleValue & 0x0f);
+ (*nCurNibbleOffset) = -1;
+ }
+
+ return nOutOffset;
+}
+
+/**
+ * Get the number of extra bits required to represent a literals length
+ *
+ * @param nLength literals length
+ *
+ * @return number of extra bits required
+ */
+static inline int lzsa_get_literals_varlen_size_v2(const int nLength) {
+ if (nLength < LITERALS_RUN_LEN_V2) {
+ return 0;
+ }
+ else {
+ if (nLength < (LITERALS_RUN_LEN_V2 + 15)) {
+ return 4;
+ }
+ else {
+ if (nLength < 256)
+ return 4+8;
+ else {
+ return 4+24;
+ }
+ }
+ }
+}
+
+/**
+ * Write extra literals length bytes to output (compressed) buffer. The caller must first check that there is enough
+ * room to write the bytes.
+ *
+ * @param pOutData pointer to output buffer
+ * @param nOutOffset current write index into output buffer
+ * @param nMaxOutDataSize maximum size of output buffer, in bytes
+ * @param nCurNibbleOffset write index into output buffer, of current byte being filled with nibbles
+ * @param nLength literals length
+ */
+static inline int lzsa_write_literals_varlen_v2(unsigned char *pOutData, int nOutOffset, const int nMaxOutDataSize, int *nCurNibbleOffset, int nLength) {
+ if (nLength >= LITERALS_RUN_LEN_V2) {
+ if (nLength < (LITERALS_RUN_LEN_V2 + 15)) {
+ nOutOffset = lzsa_write_nibble_v2(pOutData, nOutOffset, nMaxOutDataSize, nCurNibbleOffset, nLength - LITERALS_RUN_LEN_V2);
+ }
+ else {
+ nOutOffset = lzsa_write_nibble_v2(pOutData, nOutOffset, nMaxOutDataSize, nCurNibbleOffset, 15);
+ if (nOutOffset < 0) return -1;
+
+ if (nLength < 256)
+ pOutData[nOutOffset++] = nLength - 18;
+ else {
+ pOutData[nOutOffset++] = 239;
+ pOutData[nOutOffset++] = nLength & 0xff;
+ pOutData[nOutOffset++] = (nLength >> 8) & 0xff;
+ }
+ }
+ }
+
+ return nOutOffset;
+}
+
+/**
+ * Get the number of extra bits required to represent an encoded match length
+ *
+ * @param nLength encoded match length (actual match length - MIN_MATCH_SIZE_V2)
+ *
+ * @return number of extra bits required
+ */
+static inline int lzsa_get_match_varlen_size_v2(const int nLength) {
+ if (nLength < MATCH_RUN_LEN_V2) {
+ return 0;
+ }
+ else {
+ if (nLength < (MATCH_RUN_LEN_V2 + 15))
+ return 4;
+ else {
+ if ((nLength + MIN_MATCH_SIZE_V2) < 256)
+ return 4+8;
+ else {
+ return 4 + 24;
+ }
+ }
+ }
+}
+
+/**
+ * Write extra encoded match length bytes to output (compressed) buffer. The caller must first check that there is enough
+ * room to write the bytes.
+ *
+ * @param pOutData pointer to output buffer
+ * @param nOutOffset current write index into output buffer
+ * @param nMaxOutDataSize maximum size of output buffer, in bytes
+ * @param nCurNibbleOffset write index into output buffer, of current byte being filled with nibbles
+ * @param nLength encoded match length (actual match length - MIN_MATCH_SIZE_V2)
+ */
+static inline int lzsa_write_match_varlen_v2(unsigned char *pOutData, int nOutOffset, const int nMaxOutDataSize, int *nCurNibbleOffset, int nLength) {
+ if (nLength >= MATCH_RUN_LEN_V2) {
+ if (nLength < (MATCH_RUN_LEN_V2 + 15)) {
+ nOutOffset = lzsa_write_nibble_v2(pOutData, nOutOffset, nMaxOutDataSize, nCurNibbleOffset, nLength - MATCH_RUN_LEN_V2);
+ }
+ else {
+ nOutOffset = lzsa_write_nibble_v2(pOutData, nOutOffset, nMaxOutDataSize, nCurNibbleOffset, 15);
+ if (nOutOffset < 0) return -1;
+
+ if ((nLength + MIN_MATCH_SIZE_V2) < 256)
+ pOutData[nOutOffset++] = nLength + MIN_MATCH_SIZE_V2 - 24;
+ else {
+ pOutData[nOutOffset++] = 233;
+ pOutData[nOutOffset++] = (nLength + MIN_MATCH_SIZE_V2) & 0xff;
+ pOutData[nOutOffset++] = ((nLength + MIN_MATCH_SIZE_V2) >> 8) & 0xff;
+ }
+ }
+ }
+
+ return nOutOffset;
+}
+
+/**
+ * Insert forward rep candidate
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param i input data window position whose matches are being considered
+ * @param nMatchOffset match offset to use as rep candidate
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ * @param nDepth current insertion depth
+ */
+static void lzsa_insert_forward_match_v2(lzsa_compressor *pCompressor, const unsigned char *pInWindow, const int i, const int nMatchOffset, const int nStartOffset, const int nEndOffset, int nDepth) {
+ lzsa_arrival *arrival = pCompressor->arrival + ((i - nStartOffset) << ARRIVALS_PER_POSITION_SHIFT);
+ const int *rle_end = (int*)pCompressor->intervals /* reuse */;
+ lzsa_match* visited = ((lzsa_match*)pCompressor->pos_data) - nStartOffset /* reuse */;
+ int j;
+
+ for (j = 0; j < NARRIVALS_PER_POSITION_V2_BIG && arrival[j].from_slot; j++) {
+ int nRepOffset = arrival[j].rep_offset;
+
+ if (nMatchOffset != nRepOffset && nRepOffset && arrival[j].rep_len >= MIN_MATCH_SIZE_V2) {
+ int nRepPos = arrival[j].rep_pos;
+ int nRepLen = arrival[j].rep_len;
+
+ if (nRepPos > nMatchOffset &&
+ (nRepPos + nRepLen) <= nEndOffset &&
+ pCompressor->match[((nRepPos - nStartOffset) << MATCHES_PER_INDEX_SHIFT_V2) + NMATCHES_PER_INDEX_V2 - 1].length == 0) {
+
+ if (visited[nRepPos].offset != nMatchOffset || visited[nRepPos].length > nRepLen) {
+ visited[nRepPos].offset = nMatchOffset;
+ visited[nRepPos].length = nRepLen;
+
+ if (pInWindow[nRepPos] == pInWindow[nRepPos - nMatchOffset]) {
+ int nLen0 = rle_end[nRepPos - nMatchOffset] - (nRepPos - nMatchOffset);
+ int nLen1 = rle_end[nRepPos] - (nRepPos);
+ int nMinLen = (nLen0 < nLen1) ? nLen0 : nLen1;
+
+ if (nMinLen >= nRepLen || !memcmp(pInWindow + nRepPos + nMinLen, pInWindow + nRepPos + nMinLen - nMatchOffset, nRepLen - nMinLen)) {
+ visited[nRepPos].length = 0;
+
+ lzsa_match* fwd_match = pCompressor->match + ((nRepPos - nStartOffset) << MATCHES_PER_INDEX_SHIFT_V2);
+ int r;
+
+ for (r = 0; r < NMATCHES_PER_INDEX_V2 && fwd_match[r].length >= MIN_MATCH_SIZE_V2; r++) {
+ if (fwd_match[r].offset == nMatchOffset) {
+ r = NMATCHES_PER_INDEX_V2;
+ break;
+ }
+ }
+
+ if (r < NMATCHES_PER_INDEX_V2) {
+ int nMaxRepLen = nEndOffset - nRepPos;
+ if (nMaxRepLen > LCP_MAX)
+ nMaxRepLen = LCP_MAX;
+ int nCurRepLen = (nMinLen > nRepLen) ? nMinLen : nRepLen;
+ if (nCurRepLen > nMaxRepLen)
+ nCurRepLen = nMaxRepLen;
+ const unsigned char* pInWindowMax = pInWindow + nRepPos + nMaxRepLen;
+ const unsigned char* pInWindowAtRepPos = pInWindow + nRepPos + nCurRepLen;
+ while ((pInWindowAtRepPos + 8) < pInWindowMax && !memcmp(pInWindowAtRepPos, pInWindowAtRepPos - nMatchOffset, 8))
+ pInWindowAtRepPos += 8;
+ while ((pInWindowAtRepPos + 4) < pInWindowMax && !memcmp(pInWindowAtRepPos, pInWindowAtRepPos - nMatchOffset, 4))
+ pInWindowAtRepPos += 4;
+ while (pInWindowAtRepPos < pInWindowMax && pInWindowAtRepPos[0] == pInWindowAtRepPos[-nMatchOffset])
+ pInWindowAtRepPos++;
+
+ nCurRepLen = (int)(pInWindowAtRepPos - (pInWindow + nRepPos));
+ fwd_match[r].offset = nMatchOffset;
+ fwd_match[r].length = nCurRepLen;
+
+ if (nDepth < 9)
+ lzsa_insert_forward_match_v2(pCompressor, pInWindow, nRepPos, nMatchOffset, nStartOffset, nEndOffset, nDepth + 1);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Attempt to pick optimal matches using a forward arrivals parser, so as to produce the smallest possible output that decompresses to the same input
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param pBestMatch pointer to buffer for outputting optimal matches
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ * @param nReduce non-zero to reduce the number of tokens when the path costs are equal, zero not to
+ * @param nInsertForwardReps non-zero to insert forward repmatch candidates, zero to use the previously inserted candidates
+ * @param nArrivalsPerPosition number of arrivals to record per input buffer position
+ */
+static void lzsa_optimize_forward_v2(lzsa_compressor *pCompressor, const unsigned char *pInWindow, lzsa_match *pBestMatch, const int nStartOffset, const int nEndOffset, const int nReduce, const int nInsertForwardReps, const int nArrivalsPerPosition) {
+ lzsa_arrival *arrival = pCompressor->arrival - (nStartOffset << ARRIVALS_PER_POSITION_SHIFT);
+ const int *rle_end = (int*)pCompressor->intervals /* reuse */;
+ lzsa_match *visited = ((lzsa_match*)pCompressor->pos_data) - nStartOffset /* reuse */;
+ char *nRepLenHandledMask = pCompressor->rep_handled_mask;
+ const int nModeSwitchPenalty = (pCompressor->flags & LZSA_FLAG_FAVOR_RATIO) ? 0 : MODESWITCH_PENALTY;
+ const int nMinMatchSize = pCompressor->min_match_size;
+ const int nDisableScore = nReduce ? 0 : (2 * BLOCK_SIZE);
+ const int nMaxRepInsertedLen = nReduce ? LEAVE_ALONE_MATCH_SIZE : 0;
+ const int nLeaveAloneMatchSize = (nArrivalsPerPosition == NARRIVALS_PER_POSITION_V2_SMALL) ? LEAVE_ALONE_MATCH_SIZE_SMALL : LEAVE_ALONE_MATCH_SIZE;
+ int i, j, n;
+
+ if ((nEndOffset - nStartOffset) > BLOCK_SIZE) return;
+
+ memset(arrival + (nStartOffset << ARRIVALS_PER_POSITION_SHIFT), 0, sizeof(lzsa_arrival) * ((nEndOffset - nStartOffset + 1) << ARRIVALS_PER_POSITION_SHIFT));
+
+ for (i = (nStartOffset << ARRIVALS_PER_POSITION_SHIFT); i != ((nEndOffset + 1) << ARRIVALS_PER_POSITION_SHIFT); i++) {
+ arrival[i].cost = 0x40000000;
+ }
+
+ arrival[nStartOffset << ARRIVALS_PER_POSITION_SHIFT].from_slot = -1;
+
+ if (nInsertForwardReps) {
+ memset(visited + nStartOffset, 0, (nEndOffset - nStartOffset) * sizeof(lzsa_match));
+ }
+
+ for (i = nStartOffset; i != nEndOffset; i++) {
+ lzsa_arrival *cur_arrival = &arrival[i << ARRIVALS_PER_POSITION_SHIFT];
+ int m;
+
+ for (j = 0; j < nArrivalsPerPosition && cur_arrival[j].from_slot; j++) {
+ const int nPrevCost = cur_arrival[j].cost & 0x3fffffff;
+ int nCodingChoiceCost = nPrevCost + 8 /* literal */;
+ int nNumLiterals = cur_arrival[j].num_literals + 1;
+
+ if (nNumLiterals == LITERALS_RUN_LEN_V2) {
+ nCodingChoiceCost += 4;
+ }
+ else if (nNumLiterals == (LITERALS_RUN_LEN_V2 + 15)) {
+ nCodingChoiceCost += 8;
+ }
+ else if (nNumLiterals == 256) {
+ nCodingChoiceCost += 16;
+ }
+
+ if (nNumLiterals == 1)
+ nCodingChoiceCost += nModeSwitchPenalty;
+
+ lzsa_arrival *pDestSlots = &cur_arrival[1 << ARRIVALS_PER_POSITION_SHIFT];
+ if (nCodingChoiceCost <= pDestSlots[nArrivalsPerPosition - 1].cost) {
+ int nRepOffset = cur_arrival[j].rep_offset;
+ int exists = 0;
+
+ for (n = 0;
+ n < nArrivalsPerPosition && pDestSlots[n].cost < nCodingChoiceCost;
+ n++) {
+ if (pDestSlots[n].rep_offset == nRepOffset) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (!exists) {
+ int nScore = cur_arrival[j].score + 1;
+
+ for (;
+ n < nArrivalsPerPosition && pDestSlots[n].cost == nCodingChoiceCost && nScore >= (pDestSlots[n].score + nDisableScore);
+ n++) {
+ if (pDestSlots[n].rep_offset == nRepOffset) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (!exists) {
+ if (n < nArrivalsPerPosition) {
+ int nn;
+
+ for (nn = n;
+ nn < nArrivalsPerPosition && pDestSlots[nn].cost == nCodingChoiceCost;
+ nn++) {
+ if (pDestSlots[nn].rep_offset == nRepOffset) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (!exists) {
+ int z;
+
+ for (z = n; z < nArrivalsPerPosition - 1 && pDestSlots[z].from_slot; z++) {
+ if (pDestSlots[z].rep_offset == nRepOffset)
+ break;
+ }
+
+ memmove(&pDestSlots[n + 1],
+ &pDestSlots[n],
+ sizeof(lzsa_arrival) * (z - n));
+
+ lzsa_arrival* pDestArrival = &pDestSlots[n];
+ pDestArrival->cost = nCodingChoiceCost;
+ pDestArrival->from_pos = i;
+ pDestArrival->from_slot = j + 1;
+ pDestArrival->match_len = 0;
+ pDestArrival->num_literals = nNumLiterals;
+ pDestArrival->score = nScore;
+ pDestArrival->rep_offset = nRepOffset;
+ pDestArrival->rep_pos = cur_arrival[j].rep_pos;
+ pDestArrival->rep_len = cur_arrival[j].rep_len;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ lzsa_match *match = pCompressor->match + ((i - nStartOffset) << MATCHES_PER_INDEX_SHIFT_V2);
+ int nNumArrivalsForThisPos = j, nMinOverallRepLen = 0, nMaxOverallRepLen = 0;
+
+ int nRepLenForArrival[NARRIVALS_PER_POSITION_V2_BIG];
+ memset(nRepLenForArrival, 0, nArrivalsPerPosition * sizeof(int));
+
+ int nMaxRepLenForPos = nEndOffset - i;
+ if (nMaxRepLenForPos > LCP_MAX)
+ nMaxRepLenForPos = LCP_MAX;
+ const unsigned char* pInWindowStart = pInWindow + i;
+ const unsigned char* pInWindowMax = pInWindowStart + nMaxRepLenForPos;
+
+ for (j = 0; j < nNumArrivalsForThisPos && (i + MIN_MATCH_SIZE_V2) <= nEndOffset; j++) {
+ int nRepOffset = cur_arrival[j].rep_offset;
+
+ if (nRepOffset) {
+ if (i > nRepOffset) {
+ if (pInWindow[i] == pInWindow[i - nRepOffset]) {
+ const unsigned char* pInWindowAtPos;
+
+ int nLen0 = rle_end[i - nRepOffset] - (i - nRepOffset);
+ int nLen1 = rle_end[i] - (i);
+ int nMinLen = (nLen0 < nLen1) ? nLen0 : nLen1;
+
+ if (nMinLen > nMaxRepLenForPos)
+ nMinLen = nMaxRepLenForPos;
+ pInWindowAtPos = pInWindowStart + nMinLen;
+
+ while ((pInWindowAtPos + 8) < pInWindowMax && !memcmp(pInWindowAtPos - nRepOffset, pInWindowAtPos, 8))
+ pInWindowAtPos += 8;
+ while ((pInWindowAtPos + 4) < pInWindowMax && !memcmp(pInWindowAtPos - nRepOffset, pInWindowAtPos, 4))
+ pInWindowAtPos += 4;
+ while (pInWindowAtPos < pInWindowMax && pInWindowAtPos[-nRepOffset] == pInWindowAtPos[0])
+ pInWindowAtPos++;
+ nRepLenForArrival[j] = (int)(pInWindowAtPos - pInWindowStart);
+
+ if (nMaxOverallRepLen < nRepLenForArrival[j])
+ nMaxOverallRepLen = nRepLenForArrival[j];
+ }
+ }
+ }
+ }
+
+ if (!nReduce) {
+ memset(nRepLenHandledMask, 0, nArrivalsPerPosition * ((LCP_MAX + 1) / 8) * sizeof(char));
+ }
+
+ for (m = 0; m < NMATCHES_PER_INDEX_V2 && match[m].length; m++) {
+ int nMatchLen = match[m].length & 0x7fff;
+ int nMatchOffset = match[m].offset;
+ int nScorePenalty = 3 + ((match[m].length & 0x8000) >> 15);
+ int nNoRepmatchOffsetCost = (nMatchOffset <= 32) ? 4 : ((nMatchOffset <= 512) ? 8 : ((nMatchOffset <= (8192 + 512)) ? 12 : 16));
+ int nStartingMatchLen, k;
+
+ if ((i + nMatchLen) > nEndOffset)
+ nMatchLen = nEndOffset - i;
+
+ if (nInsertForwardReps)
+ lzsa_insert_forward_match_v2(pCompressor, pInWindow, i, nMatchOffset, nStartOffset, nEndOffset, 0);
+
+ int nNonRepMatchArrivalIdx = -1;
+ for (j = 0; j < nNumArrivalsForThisPos; j++) {
+ int nRepOffset = cur_arrival[j].rep_offset;
+
+ if (nMatchOffset != nRepOffset) {
+ nNonRepMatchArrivalIdx = j;
+ break;
+ }
+ }
+
+ int nMatchLenCost;
+ if (nMatchLen >= nLeaveAloneMatchSize) {
+ nStartingMatchLen = nMatchLen;
+ nMatchLenCost = 4 + 24 + 8 /* token */;
+ }
+ else {
+ nStartingMatchLen = nMinMatchSize;
+ nMatchLenCost = 0 + 8 /* token */;
+ }
+
+ for (k = nStartingMatchLen; k <= nMatchLen; k++) {
+ if (k == (MATCH_RUN_LEN_V2 + MIN_MATCH_SIZE_V2)) {
+ nMatchLenCost = 4 + 8 /* token */;
+ }
+ else {
+ if (k == (MATCH_RUN_LEN_V2 + 15 + MIN_MATCH_SIZE_V2))
+ nMatchLenCost = 4 + 8 + 8 /* token */;
+ else {
+ if (k == 256)
+ nMatchLenCost = 4 + 24 + 8 /* token */;
+ }
+ }
+
+ lzsa_arrival *pDestSlots = &cur_arrival[k << ARRIVALS_PER_POSITION_SHIFT];
+
+ /* Insert non-repmatch candidate */
+
+ if (nNonRepMatchArrivalIdx >= 0) {
+ const int nPrevCost = cur_arrival[nNonRepMatchArrivalIdx].cost & 0x3fffffff;
+ int nCodingChoiceCost = nPrevCost /* the actual cost of the literals themselves accumulates up the chain */ + nMatchLenCost + nNoRepmatchOffsetCost;
+
+ if (!cur_arrival[nNonRepMatchArrivalIdx].num_literals)
+ nCodingChoiceCost += nModeSwitchPenalty;
+
+ int nScore = cur_arrival[nNonRepMatchArrivalIdx].score + nScorePenalty;
+ if (nCodingChoiceCost < pDestSlots[nArrivalsPerPosition - 2].cost ||
+ (nCodingChoiceCost == pDestSlots[nArrivalsPerPosition - 2].cost && nScore < (pDestSlots[nArrivalsPerPosition - 2].score + nDisableScore))) {
+ int exists = 0;
+
+ for (n = 0;
+ n < nArrivalsPerPosition && pDestSlots[n].cost < nCodingChoiceCost;
+ n++) {
+ if (pDestSlots[n].rep_offset == nMatchOffset) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (!exists) {
+ for (;
+ n < nArrivalsPerPosition && pDestSlots[n].cost == nCodingChoiceCost && nScore >= (pDestSlots[n].score + nDisableScore);
+ n++) {
+ if (pDestSlots[n].rep_offset == nMatchOffset) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (!exists) {
+ if (n < nArrivalsPerPosition - 1) {
+ int nn;
+
+ for (nn = n;
+ nn < nArrivalsPerPosition && pDestSlots[nn].cost == nCodingChoiceCost;
+ nn++) {
+ if (pDestSlots[nn].rep_offset == nMatchOffset &&
+ (!nInsertForwardReps || pDestSlots[nn].rep_pos >= i ||
+ pDestSlots[nArrivalsPerPosition - 1].from_slot)) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (!exists) {
+ int z;
+
+ for (z = n; z < nArrivalsPerPosition - 1 && pDestSlots[z].from_slot; z++) {
+ if (pDestSlots[z].rep_offset == nMatchOffset)
+ break;
+ }
+
+ if (z == (nArrivalsPerPosition - 1) && pDestSlots[z].from_slot && pDestSlots[z].match_len < MIN_MATCH_SIZE_V2)
+ z--;
+
+ memmove(&pDestSlots[n + 1],
+ &pDestSlots[n],
+ sizeof(lzsa_arrival) * (z - n));
+
+ lzsa_arrival* pDestArrival = &pDestSlots[n];
+ pDestArrival->cost = nCodingChoiceCost;
+ pDestArrival->from_pos = i;
+ pDestArrival->from_slot = nNonRepMatchArrivalIdx + 1;
+ pDestArrival->match_len = k;
+ pDestArrival->num_literals = 0;
+ pDestArrival->score = nScore;
+ pDestArrival->rep_offset = nMatchOffset;
+ pDestArrival->rep_pos = i;
+ pDestArrival->rep_len = k;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Insert repmatch candidates */
+
+ if (k > nMinOverallRepLen && k <= nMaxOverallRepLen) {
+ for (j = 0; j < nNumArrivalsForThisPos; j++) {
+ int nMaskOffset = (j << 7) + (k >> 3);
+ if (nRepLenForArrival[j] >= k && (nReduce || !(nRepLenHandledMask[nMaskOffset] & (1 << (k & 7))))) {
+ const int nPrevCost = cur_arrival[j].cost & 0x3fffffff;
+ int nRepCodingChoiceCost = nPrevCost /* the actual cost of the literals themselves accumulates up the chain */ + nMatchLenCost;
+ int nScore = cur_arrival[j].score + 2;
+
+ if (nRepCodingChoiceCost < pDestSlots[nArrivalsPerPosition - 1].cost ||
+ (nRepCodingChoiceCost == pDestSlots[nArrivalsPerPosition - 1].cost && nScore < (pDestSlots[nArrivalsPerPosition - 1].score + nDisableScore))) {
+ int nRepOffset = cur_arrival[j].rep_offset;
+ int exists = 0;
+
+ for (n = 0;
+ n < nArrivalsPerPosition && pDestSlots[n].cost < nRepCodingChoiceCost;
+ n++) {
+ if (pDestSlots[n].rep_offset == nRepOffset) {
+ exists = 1;
+ if (!nReduce)
+ nRepLenHandledMask[nMaskOffset] |= 1 << (k & 7);
+ break;
+ }
+ }
+
+ if (!exists) {
+ for (;
+ n < nArrivalsPerPosition && pDestSlots[n].cost == nRepCodingChoiceCost && nScore >= (pDestSlots[n].score + nDisableScore);
+ n++) {
+ if (pDestSlots[n].rep_offset == nRepOffset) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (!exists) {
+ if (n < nArrivalsPerPosition) {
+ int nn;
+
+ for (nn = n;
+ nn < nArrivalsPerPosition && pDestSlots[nn].cost == nRepCodingChoiceCost;
+ nn++) {
+ if (pDestSlots[nn].rep_offset == nRepOffset) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (!exists) {
+ int z;
+
+ for (z = n; z < nArrivalsPerPosition - 1 && pDestSlots[z].from_slot; z++) {
+ if (pDestSlots[z].rep_offset == nRepOffset)
+ break;
+ }
+
+ memmove(&pDestSlots[n + 1],
+ &pDestSlots[n],
+ sizeof(lzsa_arrival) * (z - n));
+
+ lzsa_arrival* pDestArrival = &pDestSlots[n];
+ pDestArrival->cost = nRepCodingChoiceCost;
+ pDestArrival->from_pos = i;
+ pDestArrival->from_slot = j + 1;
+ pDestArrival->match_len = k;
+ pDestArrival->num_literals = 0;
+ pDestArrival->score = nScore;
+ pDestArrival->rep_offset = nRepOffset;
+ pDestArrival->rep_pos = i;
+ pDestArrival->rep_len = k;
+ }
+ }
+ }
+ }
+ }
+ else {
+ break;
+ }
+ }
+ }
+
+ if (k < nMaxRepInsertedLen)
+ nMinOverallRepLen = k;
+ }
+ }
+
+ if (nMatchLen >= LCP_MAX && ((m + 1) >= NMATCHES_PER_INDEX_V2 || match[m + 1].length < LCP_MAX))
+ break;
+ }
+ }
+
+ lzsa_arrival *end_arrival = &arrival[(i << ARRIVALS_PER_POSITION_SHIFT) + 0];
+
+ while (end_arrival->from_slot > 0 && end_arrival->from_pos >= 0) {
+ if (end_arrival->from_pos >= nEndOffset) return;
+ pBestMatch[end_arrival->from_pos].length = end_arrival->match_len;
+ if (end_arrival->match_len)
+ pBestMatch[end_arrival->from_pos].offset = end_arrival->rep_offset;
+ else
+ pBestMatch[end_arrival->from_pos].offset = 0;
+ end_arrival = &arrival[(end_arrival->from_pos << ARRIVALS_PER_POSITION_SHIFT) + (end_arrival->from_slot - 1)];
+ }
+}
+
+/**
+ * Attempt to minimize the number of commands issued in the compressed data block, in order to speed up decompression without
+ * impacting the compression ratio
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param pBestMatch optimal matches to evaluate and update
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ *
+ * @return non-zero if the number of tokens was reduced, 0 if it wasn't
+ */
+static int lzsa_optimize_command_count_v2(lzsa_compressor *pCompressor, const unsigned char *pInWindow, lzsa_match *pBestMatch, const int nStartOffset, const int nEndOffset) {
+ int i;
+ int nNumLiterals = 0;
+ int nPrevRepMatchOffset = 0;
+ int nRepMatchOffset = 0;
+ int nRepMatchLen = 0;
+ int nRepIndex = 0;
+ int nDidReduce = 0;
+
+ for (i = nStartOffset; i < nEndOffset; ) {
+ lzsa_match *pMatch = pBestMatch + i;
+
+ if (pMatch->length == 0 &&
+ (i + 1) < nEndOffset &&
+ pBestMatch[i + 1].length >= MIN_MATCH_SIZE_V2 &&
+ pBestMatch[i + 1].length < MAX_VARLEN &&
+ pBestMatch[i + 1].offset &&
+ i >= pBestMatch[i + 1].offset &&
+ (i + pBestMatch[i + 1].length + 1) <= nEndOffset &&
+ !memcmp(pInWindow + i - (pBestMatch[i + 1].offset), pInWindow + i, pBestMatch[i + 1].length + 1)) {
+ int nCurLenSize = lzsa_get_match_varlen_size_v2(pBestMatch[i + 1].length - MIN_MATCH_SIZE_V2);
+ int nReducedLenSize = lzsa_get_match_varlen_size_v2(pBestMatch[i + 1].length + 1 - MIN_MATCH_SIZE_V2);
+
+ if ((nReducedLenSize - nCurLenSize) <= 8) {
+ /* Merge */
+ pBestMatch[i].length = pBestMatch[i + 1].length + 1;
+ pBestMatch[i].offset = pBestMatch[i + 1].offset;
+ pBestMatch[i + 1].length = 0;
+ pBestMatch[i + 1].offset = 0;
+ nDidReduce = 1;
+ continue;
+ }
+ }
+
+ if (pMatch->length >= MIN_MATCH_SIZE_V2) {
+ if ((i + pMatch->length) < nEndOffset /* Don't consider the last match in the block, we can only reduce a match inbetween other tokens */) {
+ int nNextIndex = i + pMatch->length;
+ int nNextLiterals = 0;
+
+ while (nNextIndex < nEndOffset && pBestMatch[nNextIndex].length < MIN_MATCH_SIZE_V2) {
+ nNextLiterals++;
+ nNextIndex++;
+ }
+
+ if (nNextIndex < nEndOffset && pBestMatch[nNextIndex].length >= MIN_MATCH_SIZE_V2) {
+ /* This command is a match, is followed by 'nNextLiterals' literals and then by another match */
+
+ if (nRepMatchOffset && pMatch->offset != nRepMatchOffset && (pBestMatch[nNextIndex].offset != pMatch->offset || pBestMatch[nNextIndex].offset == nRepMatchOffset ||
+ ((pMatch->offset <= 32) ? 4 : ((pMatch->offset <= 512) ? 8 : ((pMatch->offset <= (8192 + 512)) ? 12 : 16))) >
+ ((pBestMatch[nNextIndex].offset <= 32) ? 4 : ((pBestMatch[nNextIndex].offset <= 512) ? 8 : ((pBestMatch[nNextIndex].offset <= (8192 + 512)) ? 12 : 16))))) {
+ /* Check if we can change the current match's offset to be the same as the previous match's offset, and get an extra repmatch. This will occur when
+ * matching large regions of identical bytes for instance, where there are too many offsets to be considered by the parser, and when not compressing to favor the
+ * ratio (the forward arrivals parser already has this covered). */
+ if (i > nRepMatchOffset &&
+ (i - nRepMatchOffset + pMatch->length) <= nEndOffset &&
+ !memcmp(pInWindow + i - nRepMatchOffset, pInWindow + i - pMatch->offset, pMatch->length)) {
+ pMatch->offset = nRepMatchOffset;
+ nDidReduce = 1;
+ }
+ }
+
+ if (pBestMatch[nNextIndex].offset && pMatch->offset != pBestMatch[nNextIndex].offset && nRepMatchOffset != pBestMatch[nNextIndex].offset) {
+ /* Otherwise, try to gain a match forward as well */
+ if (i > pBestMatch[nNextIndex].offset && (i - pBestMatch[nNextIndex].offset + pMatch->length) <= nEndOffset) {
+ int nMaxLen = 0;
+ while (nMaxLen < pMatch->length && pInWindow[i - pBestMatch[nNextIndex].offset + nMaxLen] == pInWindow[i - pMatch->offset + nMaxLen])
+ nMaxLen++;
+ if (nMaxLen >= pMatch->length) {
+ /* Replace */
+ pMatch->offset = pBestMatch[nNextIndex].offset;
+ nDidReduce = 1;
+ }
+ else if (nMaxLen >= 2 && pMatch->offset != nRepMatchOffset) {
+ int nPartialSizeBefore, nPartialSizeAfter;
+
+ nPartialSizeBefore = lzsa_get_match_varlen_size_v2(pMatch->length - MIN_MATCH_SIZE_V2);
+ nPartialSizeBefore += (pMatch->offset <= 32) ? 4 : ((pMatch->offset <= 512) ? 8 : ((pMatch->offset <= (8192 + 512)) ? 12 : 16));
+ nPartialSizeBefore += lzsa_get_literals_varlen_size_v2(nNextLiterals);
+
+ nPartialSizeAfter = lzsa_get_match_varlen_size_v2(nMaxLen - MIN_MATCH_SIZE_V2);
+ nPartialSizeAfter += lzsa_get_literals_varlen_size_v2(nNextLiterals + (pMatch->length - nMaxLen)) + ((pMatch->length - nMaxLen) << 3);
+
+ if (nPartialSizeAfter < nPartialSizeBefore) {
+ int j;
+
+ /* We gain a repmatch that is shorter than the original match as this is the best we can do, so it is followed by extra literals, but
+ * we have calculated that this is shorter */
+ pMatch->offset = pBestMatch[nNextIndex].offset;
+ for (j = nMaxLen; j < pMatch->length; j++) {
+ pBestMatch[i + j].length = 0;
+ }
+ pMatch->length = nMaxLen;
+ nDidReduce = 1;
+ }
+ }
+ }
+ }
+
+ if (pMatch->length < 9 /* Don't waste time considering large matches, they will always win over literals */) {
+ /* Calculate this command's current cost (excluding 'nNumLiterals' bytes) */
+
+ int nCurCommandSize = 8 /* token */ + lzsa_get_literals_varlen_size_v2(nNumLiterals) + lzsa_get_match_varlen_size_v2(pMatch->length - MIN_MATCH_SIZE_V2);
+ if (pMatch->offset != nRepMatchOffset)
+ nCurCommandSize += (pMatch->offset <= 32) ? 4 : ((pMatch->offset <= 512) ? 8 : ((pMatch->offset <= (8192 + 512)) ? 12 : 16));
+
+ /* Calculate the next command's current cost */
+ int nNextCommandSize = 8 /* token */ + lzsa_get_literals_varlen_size_v2(nNextLiterals) + /* (nNextLiterals << 3) + */ lzsa_get_match_varlen_size_v2(pBestMatch[nNextIndex].length - MIN_MATCH_SIZE_V2);
+ if (pBestMatch[nNextIndex].offset != pMatch->offset)
+ nNextCommandSize += (pBestMatch[nNextIndex].offset <= 32) ? 4 : ((pBestMatch[nNextIndex].offset <= 512) ? 8 : ((pBestMatch[nNextIndex].offset <= (8192 + 512)) ? 12 : 16));
+
+ int nOriginalCombinedCommandSize = nCurCommandSize + nNextCommandSize;
+
+ /* Calculate the cost of replacing this match command by literals + the next command with the cost of encoding these literals (excluding 'nNumLiterals' bytes) */
+ int nReducedCommandSize = (pMatch->length << 3) + 8 /* token */ + lzsa_get_literals_varlen_size_v2(nNumLiterals + pMatch->length + nNextLiterals) + /* (nNextLiterals << 3) + */ lzsa_get_match_varlen_size_v2(pBestMatch[nNextIndex].length - MIN_MATCH_SIZE_V2);
+ if (pBestMatch[nNextIndex].offset != nRepMatchOffset)
+ nReducedCommandSize += (pBestMatch[nNextIndex].offset <= 32) ? 4 : ((pBestMatch[nNextIndex].offset <= 512) ? 8 : ((pBestMatch[nNextIndex].offset <= (8192 + 512)) ? 12 : 16));
+
+ int nReplaceRepOffset = 0;
+ if (nRepMatchOffset && nRepMatchOffset != nPrevRepMatchOffset && nRepMatchLen >= MIN_MATCH_SIZE_V2 && nRepMatchOffset != pBestMatch[nNextIndex].offset && nRepIndex > pBestMatch[nNextIndex].offset &&
+ (nRepIndex - pBestMatch[nNextIndex].offset + nRepMatchLen) <= nEndOffset &&
+ !memcmp(pInWindow + nRepIndex - nRepMatchOffset, pInWindow + nRepIndex - pBestMatch[nNextIndex].offset, nRepMatchLen)) {
+ /* Replacing this match command by literals would let us create a repmatch */
+ nReplaceRepOffset = 1;
+ nReducedCommandSize -= (nRepMatchOffset <= 32) ? 4 : ((nRepMatchOffset <= 512) ? 8 : ((nRepMatchOffset <= (8192 + 512)) ? 12 : 16));
+ }
+
+ if (nOriginalCombinedCommandSize >= nReducedCommandSize) {
+ /* Reduce */
+ int nMatchLen = pMatch->length;
+ int j;
+
+ for (j = 0; j < nMatchLen; j++) {
+ pBestMatch[i + j].length = 0;
+ }
+
+ nDidReduce = 1;
+
+ if (nReplaceRepOffset) {
+ pBestMatch[nRepIndex].offset = pBestMatch[nNextIndex].offset;
+ nRepMatchOffset = pBestMatch[nNextIndex].offset;
+ }
+ continue;
+ }
+ }
+ }
+ }
+
+ if ((i + pMatch->length) <= nEndOffset && pMatch->offset > 0 && pMatch->length >= MIN_MATCH_SIZE_V2 &&
+ pBestMatch[i + pMatch->length].offset > 0 &&
+ pBestMatch[i + pMatch->length].length >= MIN_MATCH_SIZE_V2 &&
+ (pMatch->length + pBestMatch[i + pMatch->length].length) >= LEAVE_ALONE_MATCH_SIZE &&
+ (pMatch->length + pBestMatch[i + pMatch->length].length) <= MAX_VARLEN &&
+ (i + pMatch->length) > pMatch->offset &&
+ (i + pMatch->length) > pBestMatch[i + pMatch->length].offset &&
+ (i + pMatch->length + pBestMatch[i + pMatch->length].length) <= nEndOffset &&
+ !memcmp(pInWindow + i - pMatch->offset + pMatch->length,
+ pInWindow + i + pMatch->length - pBestMatch[i + pMatch->length].offset,
+ pBestMatch[i + pMatch->length].length)) {
+
+ int nNextIndex = i + pMatch->length;
+
+ while (nNextIndex < nEndOffset && pBestMatch[nNextIndex].length < MIN_MATCH_SIZE_V2) {
+ nNextIndex++;
+ }
+
+ int nNextOffset;
+ if (nNextIndex < nEndOffset)
+ nNextOffset = pBestMatch[nNextIndex].offset;
+ else
+ nNextOffset = 0;
+
+ int nCurPartialSize = lzsa_get_match_varlen_size_v2(pMatch->length - MIN_MATCH_SIZE_V2);
+
+ nCurPartialSize += 8 /* token */ + /* lzsa_get_literals_varlen_size_v2(0) + */ lzsa_get_match_varlen_size_v2(pBestMatch[i + pMatch->length].length - MIN_MATCH_SIZE_V2);
+ if (pBestMatch[i + pMatch->length].offset != pMatch->offset)
+ nCurPartialSize += (pBestMatch[i + pMatch->length].offset <= 32) ? 4 : ((pBestMatch[i + pMatch->length].offset <= 512) ? 8 : ((pBestMatch[i + pMatch->length].offset <= (8192 + 512)) ? 12 : 16));
+
+ if (nNextOffset != pBestMatch[i + pMatch->length].offset)
+ nCurPartialSize += (nNextOffset <= 32) ? 4 : ((nNextOffset <= 512) ? 8 : ((nNextOffset <= (8192 + 512)) ? 12 : 16));
+
+ int nReducedPartialSize = lzsa_get_match_varlen_size_v2(pMatch->length + pBestMatch[i + pMatch->length].length - MIN_MATCH_SIZE_V2);
+
+ if (nNextOffset != pMatch->offset)
+ nReducedPartialSize += (nNextOffset <= 32) ? 4 : ((nNextOffset <= 512) ? 8 : ((nNextOffset <= (8192 + 512)) ? 12 : 16));
+
+ if (nCurPartialSize >= nReducedPartialSize) {
+ int nMatchLen = pMatch->length;
+
+ /* Join */
+
+ pMatch->length += pBestMatch[i + nMatchLen].length;
+ pBestMatch[i + nMatchLen].offset = 0;
+ pBestMatch[i + nMatchLen].length = -1;
+ nDidReduce = 1;
+ continue;
+ }
+ }
+
+ nPrevRepMatchOffset = nRepMatchOffset;
+ nRepMatchOffset = pMatch->offset;
+ nRepMatchLen = pMatch->length;
+ nRepIndex = i;
+
+ i += pMatch->length;
+ nNumLiterals = 0;
+ }
+ else {
+ nNumLiterals++;
+ i++;
+ }
+ }
+
+ return nDidReduce;
+}
+
+/**
+ * Get compressed data block size
+ *
+ * @param pCompressor compression context
+ * @param pBestMatch optimal matches to emit
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ *
+ * @return size of compressed data that will be written to output buffer
+ */
+static int lzsa_get_compressed_size_v2(lzsa_compressor *pCompressor, lzsa_match *pBestMatch, const int nStartOffset, const int nEndOffset) {
+ int i;
+ int nNumLiterals = 0;
+ int nRepMatchOffset = 0;
+ int nCompressedSize = 0;
+
+ for (i = nStartOffset; i < nEndOffset; ) {
+ const lzsa_match *pMatch = pBestMatch + i;
+
+ if (pMatch->length >= MIN_MATCH_SIZE_V2) {
+ int nMatchOffset = pMatch->offset;
+ int nMatchLen = pMatch->length;
+ int nEncodedMatchLen = nMatchLen - MIN_MATCH_SIZE_V2;
+ int nOffsetSize;
+
+ if (nMatchOffset == nRepMatchOffset) {
+ nOffsetSize = 0;
+ }
+ else {
+ if (nMatchOffset <= 32) {
+ nOffsetSize = 4;
+ }
+ else if (nMatchOffset <= 512) {
+ nOffsetSize = 8;
+ }
+ else if (nMatchOffset <= (8192 + 512)) {
+ nOffsetSize = 12;
+ }
+ else {
+ nOffsetSize = 16;
+ }
+ }
+
+ int nCommandSize = 8 /* token */ + lzsa_get_literals_varlen_size_v2(nNumLiterals) + (nNumLiterals << 3) + nOffsetSize /* match offset */ + lzsa_get_match_varlen_size_v2(nEncodedMatchLen);
+ nCompressedSize += nCommandSize;
+
+ nNumLiterals = 0;
+ nRepMatchOffset = nMatchOffset;
+ i += nMatchLen;
+ }
+ else {
+ nNumLiterals++;
+ i++;
+ }
+ }
+
+ {
+ int nCommandSize = 8 /* token */ + lzsa_get_literals_varlen_size_v2(nNumLiterals) + (nNumLiterals << 3);
+
+ nCompressedSize += nCommandSize;
+ nNumLiterals = 0;
+ }
+
+ if (pCompressor->flags & LZSA_FLAG_RAW_BLOCK) {
+ nCompressedSize += (8 + 4);
+ }
+
+ return nCompressedSize;
+}
+
+/**
+ * Emit block of compressed data
+ *
+ * @param pCompressor compression context
+ * @param pBestMatch optimal matches to emit
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ * @param pOutData pointer to output buffer
+ * @param nMaxOutDataSize maximum size of output buffer, in bytes
+ *
+ * @return size of compressed data in output buffer, or -1 if the data is uncompressible
+ */
+static int lzsa_write_block_v2(lzsa_compressor *pCompressor, lzsa_match *pBestMatch, const unsigned char *pInWindow, const int nStartOffset, const int nEndOffset, unsigned char *pOutData, const int nMaxOutDataSize) {
+ int i;
+ int nNumLiterals = 0;
+ int nInFirstLiteralOffset = 0;
+ int nOutOffset = 0;
+ int nCurNibbleOffset = -1;
+ int nRepMatchOffset = 0;
+
+ for (i = nStartOffset; i < nEndOffset; ) {
+ const lzsa_match *pMatch = pBestMatch + i;
+
+ if (pMatch->length >= MIN_MATCH_SIZE_V2) {
+ int nMatchOffset = pMatch->offset;
+ int nMatchLen = pMatch->length;
+ int nEncodedMatchLen = nMatchLen - MIN_MATCH_SIZE_V2;
+ int nTokenLiteralsLen = (nNumLiterals >= LITERALS_RUN_LEN_V2) ? LITERALS_RUN_LEN_V2 : nNumLiterals;
+ int nTokenMatchLen = (nEncodedMatchLen >= MATCH_RUN_LEN_V2) ? MATCH_RUN_LEN_V2 : nEncodedMatchLen;
+ int nTokenOffsetMode;
+ int nOffsetSize;
+
+ if (nMatchOffset == nRepMatchOffset) {
+ nTokenOffsetMode = 0xe0;
+ nOffsetSize = 0;
+ }
+ else {
+ if (nMatchOffset <= 32) {
+ nTokenOffsetMode = 0x00 | ((((-nMatchOffset) & 0x01) << 5) ^ 0x20);
+ nOffsetSize = 4;
+ }
+ else if (nMatchOffset <= 512) {
+ nTokenOffsetMode = 0x40 | ((((-nMatchOffset) & 0x100) >> 3) ^ 0x20);
+ nOffsetSize = 8;
+ }
+ else if (nMatchOffset <= (8192 + 512)) {
+ nTokenOffsetMode = 0x80 | ((((-(nMatchOffset - 512)) & 0x0100) >> 3) ^ 0x20);
+ nOffsetSize = 12;
+ }
+ else {
+ nTokenOffsetMode = 0xc0;
+ nOffsetSize = 16;
+ }
+ }
+
+ int nCommandSize = 8 /* token */ + lzsa_get_literals_varlen_size_v2(nNumLiterals) + (nNumLiterals << 3) + nOffsetSize /* match offset */ + lzsa_get_match_varlen_size_v2(nEncodedMatchLen);
+
+ if ((nOutOffset + ((nCommandSize + 7) >> 3)) > nMaxOutDataSize)
+ return -1;
+ if (nMatchOffset < MIN_OFFSET || nMatchOffset > MAX_OFFSET)
+ return -1;
+
+ pOutData[nOutOffset++] = nTokenOffsetMode | (nTokenLiteralsLen << 3) | nTokenMatchLen;
+ nOutOffset = lzsa_write_literals_varlen_v2(pOutData, nOutOffset, nMaxOutDataSize, &nCurNibbleOffset, nNumLiterals);
+ if (nOutOffset < 0) return -1;
+
+ if (nNumLiterals < pCompressor->stats.min_literals || pCompressor->stats.min_literals == -1)
+ pCompressor->stats.min_literals = nNumLiterals;
+ if (nNumLiterals > pCompressor->stats.max_literals)
+ pCompressor->stats.max_literals = nNumLiterals;
+ pCompressor->stats.total_literals += nNumLiterals;
+ pCompressor->stats.literals_divisor++;
+
+ if (nNumLiterals != 0) {
+ memcpy(pOutData + nOutOffset, pInWindow + nInFirstLiteralOffset, nNumLiterals);
+ nOutOffset += nNumLiterals;
+ nNumLiterals = 0;
+ }
+
+ if (nTokenOffsetMode == 0x00 || nTokenOffsetMode == 0x20) {
+ nOutOffset = lzsa_write_nibble_v2(pOutData, nOutOffset, nMaxOutDataSize, &nCurNibbleOffset, ((-nMatchOffset) & 0x1e) >> 1);
+ if (nOutOffset < 0) return -1;
+ }
+ else if (nTokenOffsetMode == 0x40 || nTokenOffsetMode == 0x60) {
+ pOutData[nOutOffset++] = (-nMatchOffset) & 0xff;
+ }
+ else if (nTokenOffsetMode == 0x80 || nTokenOffsetMode == 0xa0) {
+ nOutOffset = lzsa_write_nibble_v2(pOutData, nOutOffset, nMaxOutDataSize, &nCurNibbleOffset, ((-(nMatchOffset - 512)) >> 9) & 0x0f);
+ if (nOutOffset < 0) return -1;
+ pOutData[nOutOffset++] = (-(nMatchOffset - 512)) & 0xff;
+ }
+ else if (nTokenOffsetMode == 0xc0) {
+ pOutData[nOutOffset++] = (-nMatchOffset) >> 8;
+ pOutData[nOutOffset++] = (-nMatchOffset) & 0xff;
+ }
+
+ if (nMatchOffset == nRepMatchOffset)
+ pCompressor->stats.num_rep_offsets++;
+
+ nRepMatchOffset = nMatchOffset;
+
+ nOutOffset = lzsa_write_match_varlen_v2(pOutData, nOutOffset, nMaxOutDataSize, &nCurNibbleOffset, nEncodedMatchLen);
+ if (nOutOffset < 0) return -1;
+
+ if (nMatchOffset < pCompressor->stats.min_offset || pCompressor->stats.min_offset == -1)
+ pCompressor->stats.min_offset = nMatchOffset;
+ if (nMatchOffset > pCompressor->stats.max_offset)
+ pCompressor->stats.max_offset = nMatchOffset;
+ pCompressor->stats.total_offsets += nMatchOffset;
+
+ if (nMatchLen < pCompressor->stats.min_match_len || pCompressor->stats.min_match_len == -1)
+ pCompressor->stats.min_match_len = nMatchLen;
+ if (nMatchLen > pCompressor->stats.max_match_len)
+ pCompressor->stats.max_match_len = nMatchLen;
+ pCompressor->stats.total_match_lens += nMatchLen;
+ pCompressor->stats.match_divisor++;
+
+ if (nMatchOffset == 1) {
+ if (nMatchLen < pCompressor->stats.min_rle1_len || pCompressor->stats.min_rle1_len == -1)
+ pCompressor->stats.min_rle1_len = nMatchLen;
+ if (nMatchLen > pCompressor->stats.max_rle1_len)
+ pCompressor->stats.max_rle1_len = nMatchLen;
+ pCompressor->stats.total_rle1_lens += nMatchLen;
+ pCompressor->stats.rle1_divisor++;
+ }
+ else if (nMatchOffset == 2) {
+ if (nMatchLen < pCompressor->stats.min_rle2_len || pCompressor->stats.min_rle2_len == -1)
+ pCompressor->stats.min_rle2_len = nMatchLen;
+ if (nMatchLen > pCompressor->stats.max_rle2_len)
+ pCompressor->stats.max_rle2_len = nMatchLen;
+ pCompressor->stats.total_rle2_lens += nMatchLen;
+ pCompressor->stats.rle2_divisor++;
+ }
+
+ i += nMatchLen;
+
+ if (pCompressor->flags & LZSA_FLAG_RAW_BLOCK) {
+ int nCurSafeDist = (i - nStartOffset) - nOutOffset;
+ if (nCurSafeDist >= 0 && pCompressor->safe_dist < nCurSafeDist)
+ pCompressor->safe_dist = nCurSafeDist;
+ }
+
+ pCompressor->num_commands++;
+ }
+ else {
+ if (nNumLiterals == 0)
+ nInFirstLiteralOffset = i;
+ nNumLiterals++;
+ i++;
+ }
+ }
+
+ {
+ int nTokenLiteralsLen = (nNumLiterals >= LITERALS_RUN_LEN_V2) ? LITERALS_RUN_LEN_V2 : nNumLiterals;
+ int nCommandSize = 8 /* token */ + lzsa_get_literals_varlen_size_v2(nNumLiterals) + (nNumLiterals << 3);
+
+ if ((nOutOffset + ((nCommandSize + 7) >> 3)) > nMaxOutDataSize)
+ return -1;
+
+ if (pCompressor->flags & LZSA_FLAG_RAW_BLOCK)
+ pOutData[nOutOffset++] = (nTokenLiteralsLen << 3) | 0xe7;
+ else
+ pOutData[nOutOffset++] = (nTokenLiteralsLen << 3) | 0x00;
+ nOutOffset = lzsa_write_literals_varlen_v2(pOutData, nOutOffset, nMaxOutDataSize, &nCurNibbleOffset, nNumLiterals);
+ if (nOutOffset < 0) return -1;
+
+ if (nNumLiterals < pCompressor->stats.min_literals || pCompressor->stats.min_literals == -1)
+ pCompressor->stats.min_literals = nNumLiterals;
+ if (nNumLiterals > pCompressor->stats.max_literals)
+ pCompressor->stats.max_literals = nNumLiterals;
+ pCompressor->stats.total_literals += nNumLiterals;
+ pCompressor->stats.literals_divisor++;
+
+ if (nNumLiterals != 0) {
+ memcpy(pOutData + nOutOffset, pInWindow + nInFirstLiteralOffset, nNumLiterals);
+ nOutOffset += nNumLiterals;
+ nNumLiterals = 0;
+ }
+
+ if (pCompressor->flags & LZSA_FLAG_RAW_BLOCK) {
+ int nCurSafeDist = (i - nStartOffset) - nOutOffset;
+ if (nCurSafeDist >= 0 && pCompressor->safe_dist < nCurSafeDist)
+ pCompressor->safe_dist = nCurSafeDist;
+ }
+
+ pCompressor->num_commands++;
+ }
+
+ if (pCompressor->flags & LZSA_FLAG_RAW_BLOCK) {
+ /* Emit EOD marker for raw block */
+
+ if (nOutOffset >= nMaxOutDataSize)
+ return -1;
+
+ nOutOffset = lzsa_write_nibble_v2(pOutData, nOutOffset, nMaxOutDataSize, &nCurNibbleOffset, 15); /* Extended match length nibble */
+ if (nOutOffset < 0) return -1;
+
+ if ((nOutOffset + 1) > nMaxOutDataSize)
+ return -1;
+
+ pOutData[nOutOffset++] = 232; /* EOD match length byte */
+ }
+
+ if (nCurNibbleOffset != -1) {
+ nOutOffset = lzsa_write_nibble_v2(pOutData, nOutOffset, nMaxOutDataSize, &nCurNibbleOffset, 0);
+ if (nOutOffset < 0 || nCurNibbleOffset != -1)
+ return -1;
+ }
+
+ return nOutOffset;
+}
+
+/**
+ * Emit raw block of uncompressible data
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param nStartOffset current offset in input window (typically the number of previously compressed bytes)
+ * @param nEndOffset offset to end finding matches at (typically the size of the total input window in bytes
+ * @param pOutData pointer to output buffer
+ * @param nMaxOutDataSize maximum size of output buffer, in bytes
+ *
+ * @return size of compressed data in output buffer, or -1 if the data is uncompressible
+ */
+static int lzsa_write_raw_uncompressed_block_v2(lzsa_compressor *pCompressor, const unsigned char *pInWindow, const int nStartOffset, const int nEndOffset, unsigned char *pOutData, const int nMaxOutDataSize) {
+ int nCurNibbleOffset = -1;
+ int nNumLiterals = nEndOffset - nStartOffset;
+ int nTokenLiteralsLen = (nNumLiterals >= LITERALS_RUN_LEN_V2) ? LITERALS_RUN_LEN_V2 : nNumLiterals;
+ int nOutOffset = 0;
+
+ int nCommandSize = 8 /* token */ + lzsa_get_literals_varlen_size_v2(nNumLiterals) + (nNumLiterals << 3) + 4 + 8;
+ if ((nOutOffset + ((nCommandSize + 7) >> 3)) > nMaxOutDataSize)
+ return -1;
+
+ pCompressor->num_commands = 0;
+ pOutData[nOutOffset++] = (nTokenLiteralsLen << 3) | 0xe7;
+
+ nOutOffset = lzsa_write_literals_varlen_v2(pOutData, nOutOffset, nMaxOutDataSize, &nCurNibbleOffset, nNumLiterals);
+ if (nOutOffset < 0) return -1;
+
+ if (nNumLiterals != 0) {
+ memcpy(pOutData + nOutOffset, pInWindow + nStartOffset, nNumLiterals);
+ nOutOffset += nNumLiterals;
+ nNumLiterals = 0;
+ }
+
+ /* Emit EOD marker for raw block */
+
+ nOutOffset = lzsa_write_nibble_v2(pOutData, nOutOffset, nMaxOutDataSize, &nCurNibbleOffset, 15); /* Extended match length nibble */
+ if (nOutOffset < 0) return -1;
+
+ if ((nOutOffset + 1) > nMaxOutDataSize)
+ return -1;
+
+ pOutData[nOutOffset++] = 232; /* EOD match length byte */
+
+ pCompressor->num_commands++;
+
+ if (nCurNibbleOffset != -1) {
+ nOutOffset = lzsa_write_nibble_v2(pOutData, nOutOffset, nMaxOutDataSize, &nCurNibbleOffset, 0);
+ if (nOutOffset < 0 || nCurNibbleOffset != -1)
+ return -1;
+ }
+
+ return nOutOffset;
+}
+
+/**
+ * Select the most optimal matches, reduce the token count if possible, and then emit a block of compressed LZSA2 data
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param nPreviousBlockSize number of previously compressed bytes (or 0 for none)
+ * @param nInDataSize number of input bytes to compress
+ * @param pOutData pointer to output buffer
+ * @param nMaxOutDataSize maximum size of output buffer, in bytes
+ *
+ * @return size of compressed data in output buffer, or -1 if the data is uncompressible
+ */
+int lzsa_optimize_and_write_block_v2(lzsa_compressor *pCompressor, const unsigned char *pInWindow, const int nPreviousBlockSize, const int nInDataSize, unsigned char *pOutData, const int nMaxOutDataSize) {
+ int nResult, nBaseCompressedSize;
+ int nArrivalsPerPosition = (nInDataSize < 65536) ? NARRIVALS_PER_POSITION_V2_BIG : NARRIVALS_PER_POSITION_V2_SMALL;
+ int *rle_end = (int*)pCompressor->intervals /* reuse */;
+ int i;
+
+ i = 0;
+ while (i < (nPreviousBlockSize + nInDataSize)) {
+ int nRangeStartIdx = i;
+ unsigned char c = pInWindow[nRangeStartIdx];
+ do {
+ i++;
+ } while (i < (nPreviousBlockSize + nInDataSize) && pInWindow[i] == c);
+ while (nRangeStartIdx < i) {
+ rle_end[nRangeStartIdx++] = i;
+ }
+ }
+
+ /* Compress optimally without breaking ties in favor of less tokens */
+
+ memset(pCompressor->best_match, 0, BLOCK_SIZE * sizeof(lzsa_match));
+ lzsa_optimize_forward_v2(pCompressor, pInWindow, pCompressor->best_match - nPreviousBlockSize, nPreviousBlockSize, nPreviousBlockSize + nInDataSize, 0 /* reduce */, (nInDataSize < 65536) ? 1 : 0 /* insert forward reps */, nArrivalsPerPosition);
+
+ int nDidReduce;
+ int nPasses = 0;
+ do {
+ nDidReduce = lzsa_optimize_command_count_v2(pCompressor, pInWindow, pCompressor->best_match - nPreviousBlockSize, nPreviousBlockSize, nPreviousBlockSize + nInDataSize);
+ nPasses++;
+ } while (nDidReduce && nPasses < 20);
+
+ nBaseCompressedSize = lzsa_get_compressed_size_v2(pCompressor, pCompressor->best_match - nPreviousBlockSize, nPreviousBlockSize, nPreviousBlockSize + nInDataSize);
+ lzsa_match *pBestMatch = pCompressor->best_match - nPreviousBlockSize;
+
+ if (nBaseCompressedSize > 0 && nInDataSize < 65536) {
+ int nReducedCompressedSize;
+
+ /* Compress optimally and do break ties in favor of less tokens */
+ memset(pCompressor->improved_match, 0, BLOCK_SIZE * sizeof(lzsa_match));
+ lzsa_optimize_forward_v2(pCompressor, pInWindow, pCompressor->improved_match - nPreviousBlockSize, nPreviousBlockSize, nPreviousBlockSize + nInDataSize, 1 /* reduce */, 0 /* use forward reps */, nArrivalsPerPosition);
+
+ nPasses = 0;
+ do {
+ nDidReduce = lzsa_optimize_command_count_v2(pCompressor, pInWindow, pCompressor->improved_match - nPreviousBlockSize, nPreviousBlockSize, nPreviousBlockSize + nInDataSize);
+ nPasses++;
+ } while (nDidReduce && nPasses < 20);
+
+ nReducedCompressedSize = lzsa_get_compressed_size_v2(pCompressor, pCompressor->improved_match - nPreviousBlockSize, nPreviousBlockSize, nPreviousBlockSize + nInDataSize);
+ if (nReducedCompressedSize > 0 && nReducedCompressedSize <= nBaseCompressedSize) {
+ const int nEndOffset = nPreviousBlockSize + nInDataSize;
+ int nSupplementedCompressedSize;
+
+ /* Pick the parse with the reduced number of tokens as it didn't negatively affect the size */
+ pBestMatch = pCompressor->improved_match - nPreviousBlockSize;
+
+ int* first_offset_for_byte = pCompressor->first_offset_for_byte;
+ int* next_offset_for_pos = pCompressor->next_offset_for_pos;
+ int nPosition;
+
+ /* Supplement small matches */
+
+ memset(first_offset_for_byte, 0xff, sizeof(int) * 65536);
+ memset(next_offset_for_pos, 0xff, sizeof(int) * nInDataSize);
+
+ for (nPosition = nPreviousBlockSize; nPosition < nEndOffset - 1; nPosition++) {
+ next_offset_for_pos[nPosition - nPreviousBlockSize] = first_offset_for_byte[((unsigned int)pInWindow[nPosition]) | (((unsigned int)pInWindow[nPosition + 1]) << 8)];
+ first_offset_for_byte[((unsigned int)pInWindow[nPosition]) | (((unsigned int)pInWindow[nPosition + 1]) << 8)] = nPosition;
+ }
+
+ for (nPosition = nPreviousBlockSize + 1; nPosition < (nEndOffset - 1); nPosition++) {
+ lzsa_match* match = pCompressor->match + ((nPosition - nPreviousBlockSize) << MATCHES_PER_INDEX_SHIFT_V2);
+ int m = 0, nInserted = 0;
+ int nMatchPos;
+
+ while (m < 15 && match[m].length)
+ m++;
+
+ for (nMatchPos = next_offset_for_pos[nPosition - nPreviousBlockSize]; m < 15 && nMatchPos >= 0; nMatchPos = next_offset_for_pos[nMatchPos - nPreviousBlockSize]) {
+ int nMatchOffset = nPosition - nMatchPos;
+ int nExistingMatchIdx;
+ int nAlreadyExists = 0;
+
+ for (nExistingMatchIdx = 0; nExistingMatchIdx < m; nExistingMatchIdx++) {
+ if (match[nExistingMatchIdx].offset == nMatchOffset) {
+ nAlreadyExists = 1;
+ break;
+ }
+ }
+
+ if (!nAlreadyExists) {
+ int nMatchLen = 2;
+ while (nMatchLen < 16 && (nPosition + nMatchLen + 4) < nEndOffset && !memcmp(pInWindow + nMatchPos + nMatchLen, pInWindow + nPosition + nMatchLen, 4))
+ nMatchLen += 4;
+ while (nMatchLen < 16 && (nPosition + nMatchLen) < nEndOffset && pInWindow[nMatchPos + nMatchLen] == pInWindow[nPosition + nMatchLen])
+ nMatchLen++;
+ match[m].length = nMatchLen;
+ match[m].offset = nMatchOffset;
+ m++;
+ nInserted++;
+ if (nInserted >= 15)
+ break;
+ }
+ }
+ }
+
+ /* Compress optimally with the extra matches */
+ memset(pCompressor->best_match, 0, BLOCK_SIZE * sizeof(lzsa_match));
+ lzsa_optimize_forward_v2(pCompressor, pInWindow, pCompressor->best_match - nPreviousBlockSize, nPreviousBlockSize, nPreviousBlockSize + nInDataSize, 1 /* reduce */, 0 /* use forward reps */, nArrivalsPerPosition);
+
+ nPasses = 0;
+ do {
+ nDidReduce = lzsa_optimize_command_count_v2(pCompressor, pInWindow, pCompressor->best_match - nPreviousBlockSize, nPreviousBlockSize, nPreviousBlockSize + nInDataSize);
+ nPasses++;
+ } while (nDidReduce && nPasses < 20);
+
+ nSupplementedCompressedSize = lzsa_get_compressed_size_v2(pCompressor, pCompressor->best_match - nPreviousBlockSize, nPreviousBlockSize, nPreviousBlockSize + nInDataSize);
+ if (nSupplementedCompressedSize > 0 && nSupplementedCompressedSize < nReducedCompressedSize) {
+ /* Pick the parse with the extra matches as it didn't negatively affect the size */
+ pBestMatch = pCompressor->best_match - nPreviousBlockSize;
+ }
+ }
+ }
+
+ nResult = lzsa_write_block_v2(pCompressor, pBestMatch, pInWindow, nPreviousBlockSize, nPreviousBlockSize + nInDataSize, pOutData, nMaxOutDataSize);
+ if (nResult < 0 && pCompressor->flags & LZSA_FLAG_RAW_BLOCK) {
+ nResult = lzsa_write_raw_uncompressed_block_v2(pCompressor, pInWindow, nPreviousBlockSize, nPreviousBlockSize + nInDataSize, pOutData, nMaxOutDataSize);
+ }
+
+ return nResult;
+}
diff --git a/tools/rasm/lzsa-master/src/shrink_block_v2.h b/tools/rasm/lzsa-master/src/shrink_block_v2.h
new file mode 100644
index 0000000..4a83608
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/shrink_block_v2.h
@@ -0,0 +1,53 @@
+/*
+ * shrink_block_v2.h - LZSA2 block compressor definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#ifndef _SHRINK_BLOCK_V2_H
+#define _SHRINK_BLOCK_V2_H
+
+/* Forward declarations */
+typedef struct _lzsa_compressor lzsa_compressor;
+
+/**
+ * Select the most optimal matches, reduce the token count if possible, and then emit a block of compressed LZSA2 data
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param nPreviousBlockSize number of previously compressed bytes (or 0 for none)
+ * @param nInDataSize number of input bytes to compress
+ * @param pOutData pointer to output buffer
+ * @param nMaxOutDataSize maximum size of output buffer, in bytes
+ *
+ * @return size of compressed data in output buffer, or -1 if the data is uncompressible
+ */
+int lzsa_optimize_and_write_block_v2(lzsa_compressor *pCompressor, const unsigned char *pInWindow, const int nPreviousBlockSize, const int nInDataSize, unsigned char *pOutData, const int nMaxOutDataSize);
+
+#endif /* _SHRINK_BLOCK_V2_H */
diff --git a/tools/rasm/lzsa-master/src/shrink_context.c b/tools/rasm/lzsa-master/src/shrink_context.c
new file mode 100644
index 0000000..0bb8a6d
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/shrink_context.c
@@ -0,0 +1,254 @@
+/*
+ * shrink_context.c - compression context implementation
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "shrink_context.h"
+#include "shrink_block_v1.h"
+#include "shrink_block_v2.h"
+#include "format.h"
+#include "matchfinder.h"
+#include "lib.h"
+
+/**
+ * Initialize compression context
+ *
+ * @param pCompressor compression context to initialize
+ * @param nMaxWindowSize maximum size of input data window (previously compressed bytes + bytes to compress)
+ * @param nMinMatchSize minimum match size (cannot be less than MIN_MATCH_SIZE)
+ * @param nFlags compression flags
+ *
+ * @return 0 for success, non-zero for failure
+ */
+int lzsa_compressor_init(lzsa_compressor *pCompressor, const int nMaxWindowSize, const int nMinMatchSize, const int nFormatVersion, const int nFlags) {
+ int nResult;
+ int nMinMatchSizeForFormat = (nFormatVersion == 1) ? MIN_MATCH_SIZE_V1 : MIN_MATCH_SIZE_V2;
+ int nMaxMinMatchForFormat = (nFormatVersion == 1) ? 5 : 3;
+
+ nResult = divsufsort_init(&pCompressor->divsufsort_context);
+ pCompressor->intervals = NULL;
+ pCompressor->pos_data = NULL;
+ pCompressor->open_intervals = NULL;
+ pCompressor->match = NULL;
+ pCompressor->best_match = NULL;
+ pCompressor->improved_match = NULL;
+ pCompressor->arrival = NULL;
+ pCompressor->rep_handled_mask = NULL;
+ pCompressor->first_offset_for_byte = NULL;
+ pCompressor->next_offset_for_pos = NULL;
+ pCompressor->min_match_size = nMinMatchSize;
+ if (pCompressor->min_match_size < nMinMatchSizeForFormat)
+ pCompressor->min_match_size = nMinMatchSizeForFormat;
+ else if (pCompressor->min_match_size > nMaxMinMatchForFormat)
+ pCompressor->min_match_size = nMaxMinMatchForFormat;
+ pCompressor->format_version = nFormatVersion;
+ pCompressor->flags = nFlags;
+ pCompressor->safe_dist = 0;
+ pCompressor->num_commands = 0;
+
+ memset(&pCompressor->stats, 0, sizeof(pCompressor->stats));
+ pCompressor->stats.min_literals = -1;
+ pCompressor->stats.min_match_len = -1;
+ pCompressor->stats.min_offset = -1;
+ pCompressor->stats.min_rle1_len = -1;
+ pCompressor->stats.min_rle2_len = -1;
+
+ if (!nResult) {
+ pCompressor->intervals = (unsigned int *)malloc(nMaxWindowSize * sizeof(unsigned int));
+
+ if (pCompressor->intervals) {
+ pCompressor->pos_data = (unsigned int *)malloc(nMaxWindowSize * sizeof(unsigned int));
+
+ if (pCompressor->pos_data) {
+ pCompressor->open_intervals = (unsigned int *)malloc((LCP_AND_TAG_MAX + 1) * sizeof(unsigned int));
+
+ if (pCompressor->open_intervals) {
+ pCompressor->arrival = (lzsa_arrival *)malloc(((BLOCK_SIZE + 1) << ARRIVALS_PER_POSITION_SHIFT) * sizeof(lzsa_arrival));
+
+ if (pCompressor->arrival) {
+ pCompressor->best_match = (lzsa_match *)malloc(BLOCK_SIZE * sizeof(lzsa_match));
+
+ if (pCompressor->best_match) {
+ pCompressor->improved_match = (lzsa_match *)malloc(BLOCK_SIZE * sizeof(lzsa_match));
+
+ if (pCompressor->improved_match) {
+ if (pCompressor->format_version == 2)
+ pCompressor->match = (lzsa_match *)malloc(BLOCK_SIZE * NMATCHES_PER_INDEX_V2 * sizeof(lzsa_match));
+ else
+ pCompressor->match = (lzsa_match *)malloc(BLOCK_SIZE * NMATCHES_PER_INDEX_V1 * sizeof(lzsa_match));
+ if (pCompressor->match) {
+ if (pCompressor->format_version == 2) {
+ pCompressor->rep_handled_mask = (char*)malloc(NARRIVALS_PER_POSITION_V2_BIG * ((LCP_MAX + 1) / 8) * sizeof(char));
+ if (pCompressor->rep_handled_mask) {
+ pCompressor->first_offset_for_byte = (int*)malloc(65536 * sizeof(int));
+ if (pCompressor->first_offset_for_byte) {
+ pCompressor->next_offset_for_pos = (int*)malloc(BLOCK_SIZE * sizeof(int));
+ if (pCompressor->next_offset_for_pos) {
+ return 0;
+ }
+ }
+ }
+ }
+ else {
+ return 0;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ lzsa_compressor_destroy(pCompressor);
+ return 100;
+}
+
+/**
+ * Clean up compression context and free up any associated resources
+ *
+ * @param pCompressor compression context to clean up
+ */
+void lzsa_compressor_destroy(lzsa_compressor *pCompressor) {
+ divsufsort_destroy(&pCompressor->divsufsort_context);
+
+ if (pCompressor->next_offset_for_pos) {
+ free(pCompressor->next_offset_for_pos);
+ pCompressor->next_offset_for_pos = NULL;
+ }
+
+ if (pCompressor->first_offset_for_byte) {
+ free(pCompressor->first_offset_for_byte);
+ pCompressor->first_offset_for_byte = NULL;
+ }
+
+ if (pCompressor->rep_handled_mask) {
+ free(pCompressor->rep_handled_mask);
+ pCompressor->rep_handled_mask = NULL;
+ }
+
+ if (pCompressor->match) {
+ free(pCompressor->match);
+ pCompressor->match = NULL;
+ }
+
+ if (pCompressor->improved_match) {
+ free(pCompressor->improved_match);
+ pCompressor->improved_match = NULL;
+ }
+
+ if (pCompressor->arrival) {
+ free(pCompressor->arrival);
+ pCompressor->arrival = NULL;
+ }
+
+ if (pCompressor->best_match) {
+ free(pCompressor->best_match);
+ pCompressor->best_match = NULL;
+ }
+
+ if (pCompressor->open_intervals) {
+ free(pCompressor->open_intervals);
+ pCompressor->open_intervals = NULL;
+ }
+
+ if (pCompressor->pos_data) {
+ free(pCompressor->pos_data);
+ pCompressor->pos_data = NULL;
+ }
+
+ if (pCompressor->intervals) {
+ free(pCompressor->intervals);
+ pCompressor->intervals = NULL;
+ }
+}
+
+/**
+ * Compress one block of data
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param nPreviousBlockSize number of previously compressed bytes (or 0 for none)
+ * @param nInDataSize number of input bytes to compress
+ * @param pOutData pointer to output buffer
+ * @param nMaxOutDataSize maximum size of output buffer, in bytes
+ *
+ * @return size of compressed data in output buffer, or -1 if the data is uncompressible
+ */
+int lzsa_compressor_shrink_block(lzsa_compressor *pCompressor, unsigned char *pInWindow, const int nPreviousBlockSize, const int nInDataSize, unsigned char *pOutData, const int nMaxOutDataSize) {
+ int nCompressedSize;
+
+ if (pCompressor->flags & LZSA_FLAG_RAW_BACKWARD) {
+ lzsa_reverse_buffer(pInWindow + nPreviousBlockSize, nInDataSize);
+ }
+
+ if (lzsa_build_suffix_array(pCompressor, pInWindow, nPreviousBlockSize + nInDataSize))
+ nCompressedSize = -1;
+ else {
+ if (nPreviousBlockSize) {
+ lzsa_skip_matches(pCompressor, 0, nPreviousBlockSize);
+ }
+ lzsa_find_all_matches(pCompressor, (pCompressor->format_version == 2) ? NMATCHES_PER_INDEX_V2 : NMATCHES_PER_INDEX_V1, nPreviousBlockSize, nPreviousBlockSize + nInDataSize);
+
+ if (pCompressor->format_version == 1) {
+ nCompressedSize = lzsa_optimize_and_write_block_v1(pCompressor, pInWindow, nPreviousBlockSize, nInDataSize, pOutData, nMaxOutDataSize);
+ if (nCompressedSize != -1 && (pCompressor->flags & LZSA_FLAG_RAW_BACKWARD)) {
+ lzsa_reverse_buffer(pOutData, nCompressedSize);
+ }
+ }
+ else if (pCompressor->format_version == 2) {
+ nCompressedSize = lzsa_optimize_and_write_block_v2(pCompressor, pInWindow, nPreviousBlockSize, nInDataSize, pOutData, nMaxOutDataSize);
+ if (nCompressedSize != -1 && (pCompressor->flags & LZSA_FLAG_RAW_BACKWARD)) {
+ lzsa_reverse_buffer(pOutData, nCompressedSize);
+ }
+ }
+ else {
+ nCompressedSize = -1;
+ }
+ }
+
+ if (pCompressor->flags & LZSA_FLAG_RAW_BACKWARD) {
+ lzsa_reverse_buffer(pInWindow + nPreviousBlockSize, nInDataSize);
+ }
+
+ return nCompressedSize;
+}
+
+/**
+ * Get the number of compression commands issued in compressed data blocks
+ *
+ * @return number of commands
+ */
+int lzsa_compressor_get_command_count(lzsa_compressor *pCompressor) {
+ return pCompressor->num_commands;
+}
diff --git a/tools/rasm/lzsa-master/src/shrink_context.h b/tools/rasm/lzsa-master/src/shrink_context.h
new file mode 100644
index 0000000..54e4671
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/shrink_context.h
@@ -0,0 +1,182 @@
+/*
+ * shrink_context.h - compression context definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#ifndef _SHRINK_CONTEXT_H
+#define _SHRINK_CONTEXT_H
+
+#include "divsufsort.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LCP_BITS 14
+#define TAG_BITS 4
+#define LCP_MAX ((1U<<(LCP_BITS - TAG_BITS)) - 1)
+#define LCP_AND_TAG_MAX (1U<<(LCP_BITS - 1))
+#define LCP_SHIFT (31-LCP_BITS)
+#define LCP_MASK (((1U<<LCP_BITS) - 1) << LCP_SHIFT)
+#define POS_MASK ((1U<<LCP_SHIFT) - 1)
+#define VISITED_FLAG 0x80000000
+#define EXCL_VISITED_MASK 0x7fffffff
+
+#define NARRIVALS_PER_POSITION_V1 8
+#define NARRIVALS_PER_POSITION_V2_SMALL 9
+#define NARRIVALS_PER_POSITION_V2_BIG 32
+#define ARRIVALS_PER_POSITION_SHIFT 5
+
+#define NMATCHES_PER_INDEX_V1 8
+#define MATCHES_PER_INDEX_SHIFT_V1 3
+
+#define NMATCHES_PER_INDEX_V2 64
+#define MATCHES_PER_INDEX_SHIFT_V2 6
+
+#define LEAVE_ALONE_MATCH_SIZE 300
+#define LEAVE_ALONE_MATCH_SIZE_SMALL 1000
+
+#define MODESWITCH_PENALTY 3
+
+/** One match */
+typedef struct _lzsa_match {
+ unsigned short length;
+ unsigned short offset;
+} lzsa_match;
+
+/** Forward arrival slot */
+typedef struct {
+ int cost;
+ unsigned short rep_offset;
+ short from_slot;
+
+ int from_pos;
+ unsigned short rep_len;
+ unsigned short match_len;
+ int rep_pos;
+ int num_literals;
+ int score;
+} lzsa_arrival;
+
+/** Compression statistics */
+typedef struct _lzsa_stats {
+ int min_literals;
+ int max_literals;
+ int total_literals;
+
+ int min_offset;
+ int max_offset;
+ int num_rep_offsets;
+ int total_offsets;
+
+ int min_match_len;
+ int max_match_len;
+ int total_match_lens;
+
+ int min_rle1_len;
+ int max_rle1_len;
+ int total_rle1_lens;
+
+ int min_rle2_len;
+ int max_rle2_len;
+ int total_rle2_lens;
+
+ int literals_divisor;
+ int match_divisor;
+ int rle1_divisor;
+ int rle2_divisor;
+} lzsa_stats;
+
+/** Compression context */
+typedef struct _lzsa_compressor {
+ divsufsort_ctx_t divsufsort_context;
+ unsigned int *intervals;
+ unsigned int *pos_data;
+ unsigned int *open_intervals;
+ lzsa_match *match;
+ lzsa_match *best_match;
+ lzsa_match *improved_match;
+ lzsa_arrival *arrival;
+ char *rep_handled_mask;
+ int *first_offset_for_byte;
+ int *next_offset_for_pos;
+ int min_match_size;
+ int format_version;
+ int flags;
+ int safe_dist;
+ int num_commands;
+ lzsa_stats stats;
+} lzsa_compressor;
+
+/**
+ * Initialize compression context
+ *
+ * @param pCompressor compression context to initialize
+ * @param nMaxWindowSize maximum size of input data window (previously compressed bytes + bytes to compress)
+ * @param nMinMatchSize minimum match size (cannot be less than MIN_MATCH_SIZE)
+ * @param nFlags compression flags
+ *
+ * @return 0 for success, non-zero for failure
+ */
+int lzsa_compressor_init(lzsa_compressor *pCompressor, const int nMaxWindowSize, const int nMinMatchSize, const int nFormatVersion, const int nFlags);
+
+/**
+ * Clean up compression context and free up any associated resources
+ *
+ * @param pCompressor compression context to clean up
+ */
+void lzsa_compressor_destroy(lzsa_compressor *pCompressor);
+
+/**
+ * Compress one block of data
+ *
+ * @param pCompressor compression context
+ * @param pInWindow pointer to input data window (previously compressed bytes + bytes to compress)
+ * @param nPreviousBlockSize number of previously compressed bytes (or 0 for none)
+ * @param nInDataSize number of input bytes to compress
+ * @param pOutData pointer to output buffer
+ * @param nMaxOutDataSize maximum size of output buffer, in bytes
+ *
+ * @return size of compressed data in output buffer, or -1 if the data is uncompressible
+ */
+int lzsa_compressor_shrink_block(lzsa_compressor *pCompressor, unsigned char *pInWindow, const int nPreviousBlockSize, const int nInDataSize, unsigned char *pOutData, const int nMaxOutDataSize);
+
+/**
+ * Get the number of compression commands issued in compressed data blocks
+ *
+ * @return number of commands
+ */
+int lzsa_compressor_get_command_count(lzsa_compressor *pCompressor);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SHRINK_CONTEXT_H */
diff --git a/tools/rasm/lzsa-master/src/shrink_inmem.c b/tools/rasm/lzsa-master/src/shrink_inmem.c
new file mode 100644
index 0000000..9e0a70c
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/shrink_inmem.c
@@ -0,0 +1,185 @@
+/*
+ * shrink_inmem.c - in-memory compression implementation
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "shrink_inmem.h"
+#include "shrink_context.h"
+#include "frame.h"
+#include "format.h"
+#include "lib.h"
+
+/**
+ * Get maximum compressed size of input(source) data
+ *
+ * @param nInputSize input(source) size in bytes
+ *
+ * @return maximum compressed size
+ */
+size_t lzsa_get_max_compressed_size_inmem(size_t nInputSize) {
+ return lzsa_get_header_size() + ((nInputSize + (BLOCK_SIZE - 1)) >> 16) * lzsa_get_frame_size() + nInputSize + lzsa_get_frame_size() /* footer */;
+}
+
+/**
+ * Compress memory
+ *
+ * @param pInputData pointer to input(source) data to compress
+ * @param pOutBuffer buffer for compressed data
+ * @param nInputSize input(source) size in bytes
+ * @param nMaxOutBufferSize maximum capacity of compression buffer
+ * @param nFlags compression flags (LZSA_FLAG_xxx)
+ * @param nMinMatchSize minimum match size
+ * @param nFormatVersion version of format to use (1-2)
+ *
+ * @return actual compressed size, or -1 for error
+ */
+size_t lzsa_compress_inmem(unsigned char *pInputData, unsigned char *pOutBuffer, size_t nInputSize, size_t nMaxOutBufferSize,
+ const unsigned int nFlags, const int nMinMatchSize, const int nFormatVersion) {
+ lzsa_compressor compressor;
+ size_t nOriginalSize = 0;
+ size_t nCompressedSize = 0L;
+ int nResult;
+ int nError = 0;
+
+ nResult = lzsa_compressor_init(&compressor, BLOCK_SIZE * 2, nMinMatchSize, nFormatVersion, nFlags);
+ if (nResult != 0) {
+ return -1;
+ }
+
+ if ((nFlags & LZSA_FLAG_RAW_BLOCK) == 0) {
+ int nHeaderSize = lzsa_encode_header(pOutBuffer, (int)nMaxOutBufferSize, nFormatVersion);
+ if (nHeaderSize < 0)
+ nError = LZSA_ERROR_COMPRESSION;
+ else {
+ nCompressedSize += nHeaderSize;
+ }
+ }
+
+ int nPreviousBlockSize = 0;
+ int nNumBlocks = 0;
+
+ while (nOriginalSize < nInputSize && !nError) {
+ int nInDataSize;
+
+ nInDataSize = (int)(nInputSize - nOriginalSize);
+ if (nInDataSize > BLOCK_SIZE)
+ nInDataSize = BLOCK_SIZE;
+
+ if (nInDataSize > 0) {
+ if ((nFlags & LZSA_FLAG_RAW_BLOCK) != 0 && nNumBlocks) {
+ nError = LZSA_ERROR_RAW_TOOLARGE;
+ break;
+ }
+
+ int nOutDataSize;
+ int nOutDataEnd = (int)(nMaxOutBufferSize - (lzsa_get_frame_size() + nCompressedSize + lzsa_get_frame_size() /* footer */));
+ int nFrameSize = lzsa_get_frame_size();
+
+ if ((nFlags & LZSA_FLAG_RAW_BLOCK) != 0) {
+ nFrameSize = 0;
+ nOutDataEnd = (int)(nMaxOutBufferSize - nCompressedSize);
+ }
+
+ if (nOutDataEnd > BLOCK_SIZE)
+ nOutDataEnd = BLOCK_SIZE;
+
+ nOutDataSize = lzsa_compressor_shrink_block(&compressor, pInputData + nOriginalSize - nPreviousBlockSize, nPreviousBlockSize, nInDataSize, pOutBuffer + nFrameSize + nCompressedSize, nOutDataEnd);
+ if (nOutDataSize >= 0) {
+ /* Write compressed block */
+
+ if ((nFlags & LZSA_FLAG_RAW_BLOCK) == 0) {
+ int nBlockheaderSize = lzsa_encode_compressed_block_frame(pOutBuffer + nCompressedSize, (int)(nMaxOutBufferSize - nCompressedSize), nOutDataSize);
+ if (nBlockheaderSize < 0)
+ nError = LZSA_ERROR_COMPRESSION;
+ else {
+ nCompressedSize += nBlockheaderSize;
+ }
+ }
+
+ if (!nError) {
+ nOriginalSize += nInDataSize;
+ nCompressedSize += nOutDataSize;
+ }
+ }
+ else {
+ /* Write uncompressible, literal block */
+
+ if ((nFlags & LZSA_FLAG_RAW_BLOCK) != 0) {
+ nError = LZSA_ERROR_RAW_UNCOMPRESSED;
+ break;
+ }
+
+ int nBlockheaderSize = lzsa_encode_uncompressed_block_frame(pOutBuffer + nCompressedSize, (int)(nMaxOutBufferSize - nCompressedSize), nInDataSize);
+ if (nBlockheaderSize < 0)
+ nError = LZSA_ERROR_COMPRESSION;
+ else {
+ if ((size_t)nInDataSize > (nMaxOutBufferSize - (nCompressedSize + nBlockheaderSize)))
+ nError = LZSA_ERROR_DST;
+ else {
+ memcpy(pOutBuffer + nBlockheaderSize + nCompressedSize, pInputData + nOriginalSize, nInDataSize);
+
+ nOriginalSize += nInDataSize;
+ nCompressedSize += nBlockheaderSize + nInDataSize;
+ }
+ }
+ }
+
+ nPreviousBlockSize = nInDataSize;
+ nNumBlocks++;
+ }
+ }
+
+ if (!nError) {
+ int nFooterSize;
+
+ if ((nFlags & LZSA_FLAG_RAW_BLOCK) != 0) {
+ nFooterSize = 0;
+ }
+ else {
+ nFooterSize = lzsa_encode_footer_frame(pOutBuffer + nCompressedSize, (int)(nMaxOutBufferSize - nCompressedSize));
+ if (nFooterSize < 0)
+ nError = LZSA_ERROR_COMPRESSION;
+ }
+
+ nCompressedSize += nFooterSize;
+ }
+
+ lzsa_compressor_destroy(&compressor);
+
+ if (nError) {
+ return -1;
+ }
+ else {
+ return nCompressedSize;
+ }
+}
+
diff --git a/tools/rasm/lzsa-master/src/shrink_inmem.h b/tools/rasm/lzsa-master/src/shrink_inmem.h
new file mode 100644
index 0000000..2bd8f27
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/shrink_inmem.h
@@ -0,0 +1,71 @@
+/*
+ * shrink_inmem.h - in-memory compression definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#ifndef _SHRINK_INMEM_H
+#define _SHRINK_INMEM_H
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Get maximum compressed size of input(source) data
+ *
+ * @param nInputSize input(source) size in bytes
+ *
+ * @return maximum compressed size
+ */
+size_t lzsa_get_max_compressed_size_inmem(size_t nInputSize);
+
+/**
+ * Compress memory
+ *
+ * @param pInputData pointer to input(source) data to compress
+ * @param pOutBuffer buffer for compressed data
+ * @param nInputSize input(source) size in bytes
+ * @param nMaxOutBufferSize maximum capacity of compression buffer
+ * @param nFlags compression flags (LZSA_FLAG_xxx)
+ * @param nMinMatchSize minimum match size
+ * @param nFormatVersion version of format to use (1-2)
+ *
+ * @return actual compressed size, or -1 for error
+ */
+size_t lzsa_compress_inmem(unsigned char *pInputData, unsigned char *pOutBuffer, size_t nInputSize, size_t nMaxOutBufferSize,
+ const unsigned int nFlags, const int nMinMatchSize, const int nFormatVersion);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SHRINK_INMEM_H */
diff --git a/tools/rasm/lzsa-master/src/shrink_streaming.c b/tools/rasm/lzsa-master/src/shrink_streaming.c
new file mode 100644
index 0000000..2e1cf12
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/shrink_streaming.c
@@ -0,0 +1,320 @@
+/*
+ * shrink_streaming.c - streaming compression implementation
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "shrink_streaming.h"
+#include "format.h"
+#include "frame.h"
+#include "lib.h"
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <stdio.h>
+#endif
+
+/**
+ * Delete file
+ *
+ * @param pszInFilename name of file to delete
+ */
+static void lzsa_delete_file(const char *pszInFilename) {
+#ifdef _WIN32
+ DeleteFileA(pszInFilename);
+#else
+ remove(pszInFilename);
+#endif
+}
+
+/*-------------- File API -------------- */
+
+/**
+ * Compress file
+ *
+ * @param pszInFilename name of input(source) file to compress
+ * @param pszOutFilename name of output(compressed) file to generate
+ * @param pszDictionaryFilename name of dictionary file, or NULL for none
+ * @param nFlags compression flags (LZSA_FLAG_xxx)
+ * @param nMinMatchSize minimum match size
+ * @param nFormatVersion version of format to use (1-2)
+ * @param progress progress function, called after compressing each block, or NULL for none
+ * @param pOriginalSize pointer to returned input(source) size, updated when this function is successful
+ * @param pCompressedSize pointer to returned output(compressed) size, updated when this function is successful
+ * @param pCommandCount pointer to returned token(compression commands) count, updated when this function is successful
+ * @param pSafeDist pointer to return safe distance for raw blocks, updated when this function is successful
+ * @param pStats pointer to compression stats that are filled if this function is successful, or NULL
+ *
+ * @return LZSA_OK for success, or an error value from lzsa_status_t
+ */
+lzsa_status_t lzsa_compress_file(const char *pszInFilename, const char *pszOutFilename, const char *pszDictionaryFilename, const unsigned int nFlags, const int nMinMatchSize, const int nFormatVersion,
+ void(*progress)(long long nOriginalSize, long long nCompressedSize), long long *pOriginalSize, long long *pCompressedSize, int *pCommandCount, int *pSafeDist, lzsa_stats *pStats) {
+ lzsa_stream_t inStream, outStream;
+ void *pDictionaryData = NULL;
+ int nDictionaryDataSize = 0;
+ lzsa_status_t nStatus;
+
+ if (lzsa_filestream_open(&inStream, pszInFilename, "rb") < 0) {
+ return LZSA_ERROR_SRC;
+ }
+
+ if (lzsa_filestream_open(&outStream, pszOutFilename, "wb") < 0) {
+ inStream.close(&inStream);
+ return LZSA_ERROR_DST;
+ }
+
+ nStatus = lzsa_dictionary_load(pszDictionaryFilename, &pDictionaryData, &nDictionaryDataSize);
+
+ if (nStatus) {
+ outStream.close(&outStream);
+ inStream.close(&inStream);
+ lzsa_delete_file(pszOutFilename);
+ return nStatus;
+ }
+
+ nStatus = lzsa_compress_stream(&inStream, &outStream, pDictionaryData, nDictionaryDataSize, nFlags, nMinMatchSize, nFormatVersion, progress, pOriginalSize, pCompressedSize, pCommandCount, pSafeDist, pStats);
+
+ lzsa_dictionary_free(&pDictionaryData);
+ outStream.close(&outStream);
+ inStream.close(&inStream);
+
+ if (nStatus) {
+ lzsa_delete_file(pszOutFilename);
+ }
+
+ return nStatus;
+}
+
+/*-------------- Streaming API -------------- */
+
+/**
+ * Compress stream
+ *
+ * @param pInStream input(source) stream to compress
+ * @param pOutStream output(compressed) stream to write to
+ * @param pDictionaryData dictionary contents, or NULL for none
+ * @param nDictionaryDataSize size of dictionary contents, or 0
+ * @param nFlags compression flags (LZSA_FLAG_xxx)
+ * @param nMinMatchSize minimum match size
+ * @param nFormatVersion version of format to use (1-2)
+ * @param progress progress function, called after compressing each block, or NULL for none
+ * @param pOriginalSize pointer to returned input(source) size, updated when this function is successful
+ * @param pCompressedSize pointer to returned output(compressed) size, updated when this function is successful
+ * @param pCommandCount pointer to returned token(compression commands) count, updated when this function is successful
+ * @param pSafeDist pointer to return safe distance for raw blocks, updated when this function is successful
+ * @param pStats pointer to compression stats that are filled if this function is successful, or NULL
+ *
+ * @return LZSA_OK for success, or an error value from lzsa_status_t
+ */
+lzsa_status_t lzsa_compress_stream(lzsa_stream_t *pInStream, lzsa_stream_t *pOutStream, const void *pDictionaryData, int nDictionaryDataSize,
+ const unsigned int nFlags, const int nMinMatchSize, const int nFormatVersion,
+ void(*progress)(long long nOriginalSize, long long nCompressedSize), long long *pOriginalSize, long long *pCompressedSize, int *pCommandCount, int *pSafeDist, lzsa_stats *pStats) {
+ unsigned char *pInData, *pOutData;
+ lzsa_compressor compressor;
+ long long nOriginalSize = 0LL, nCompressedSize = 0LL;
+ int nResult;
+ unsigned char cFrameData[16];
+ int nError = 0;
+ int nRawPadding = (nFlags & LZSA_FLAG_RAW_BLOCK) ? 8 : 0;
+
+ pInData = (unsigned char*)malloc(BLOCK_SIZE * 2);
+ if (!pInData) {
+ return LZSA_ERROR_MEMORY;
+ }
+ memset(pInData, 0, BLOCK_SIZE * 2);
+
+ pOutData = (unsigned char*)malloc(BLOCK_SIZE);
+ if (!pOutData) {
+ free(pInData);
+ pInData = NULL;
+
+ return LZSA_ERROR_MEMORY;
+ }
+ memset(pOutData, 0, BLOCK_SIZE);
+
+ nResult = lzsa_compressor_init(&compressor, BLOCK_SIZE * 2, nMinMatchSize, nFormatVersion, nFlags);
+ if (nResult != 0) {
+ free(pOutData);
+ pOutData = NULL;
+
+ free(pInData);
+ pInData = NULL;
+
+ return LZSA_ERROR_MEMORY;
+ }
+
+ if ((nFlags & LZSA_FLAG_RAW_BLOCK) == 0) {
+ int nHeaderSize = lzsa_encode_header(cFrameData, 16, nFormatVersion);
+ if (nHeaderSize < 0)
+ nError = LZSA_ERROR_COMPRESSION;
+ else {
+ if (pOutStream->write(pOutStream, cFrameData, nHeaderSize) != nHeaderSize)
+ nError = LZSA_ERROR_DST;
+ nCompressedSize += (long long)nHeaderSize;
+ }
+ }
+
+ int nPreviousBlockSize = 0;
+ int nNumBlocks = 0;
+
+ while (!pInStream->eof(pInStream) && !nError) {
+ int nInDataSize;
+
+ if (nPreviousBlockSize) {
+ memcpy(pInData + BLOCK_SIZE - nPreviousBlockSize, pInData + BLOCK_SIZE, nPreviousBlockSize);
+ }
+ else if (nDictionaryDataSize && pDictionaryData) {
+ nPreviousBlockSize = nDictionaryDataSize;
+ memcpy(pInData + BLOCK_SIZE - nPreviousBlockSize, pDictionaryData, nPreviousBlockSize);
+ }
+
+ nInDataSize = (int)pInStream->read(pInStream, pInData + BLOCK_SIZE, BLOCK_SIZE);
+ if (nInDataSize > 0) {
+ if ((nFlags & LZSA_FLAG_RAW_BLOCK) != 0 && nNumBlocks) {
+ nError = LZSA_ERROR_RAW_TOOLARGE;
+ break;
+ }
+ nDictionaryDataSize = 0;
+
+ int nOutDataSize;
+
+ nOutDataSize = lzsa_compressor_shrink_block(&compressor, pInData + BLOCK_SIZE - nPreviousBlockSize, nPreviousBlockSize, nInDataSize, pOutData, ((nInDataSize + nRawPadding) >= BLOCK_SIZE) ? BLOCK_SIZE : (nInDataSize + nRawPadding));
+ if (nOutDataSize >= 0) {
+ /* Write compressed block */
+
+ if ((nFlags & LZSA_FLAG_RAW_BLOCK) == 0) {
+ int nBlockheaderSize = lzsa_encode_compressed_block_frame(cFrameData, 16, nOutDataSize);
+ if (nBlockheaderSize < 0)
+ nError = LZSA_ERROR_COMPRESSION;
+ else {
+ nCompressedSize += (long long)nBlockheaderSize;
+ if (pOutStream->write(pOutStream, cFrameData, nBlockheaderSize) != (size_t)nBlockheaderSize) {
+ nError = LZSA_ERROR_DST;
+ }
+ }
+ }
+
+ if (!nError) {
+ if (pOutStream->write(pOutStream, pOutData, (size_t)nOutDataSize) != (size_t)nOutDataSize) {
+ nError = LZSA_ERROR_DST;
+ }
+ else {
+ nOriginalSize += (long long)nInDataSize;
+ nCompressedSize += (long long)nOutDataSize;
+ }
+ }
+ }
+ else {
+ /* Write uncompressible, literal block */
+
+ if ((nFlags & LZSA_FLAG_RAW_BLOCK) != 0) {
+ nError = LZSA_ERROR_RAW_UNCOMPRESSED;
+ break;
+ }
+
+ int nBlockheaderSize = lzsa_encode_uncompressed_block_frame(cFrameData, 16, nInDataSize);
+ if (nBlockheaderSize < 0)
+ nError = LZSA_ERROR_COMPRESSION;
+ else {
+ if (pOutStream->write(pOutStream, cFrameData, nBlockheaderSize) != (size_t)nBlockheaderSize) {
+ nError = LZSA_ERROR_DST;
+ }
+ else {
+ if (pOutStream->write(pOutStream, pInData + BLOCK_SIZE, (size_t)nInDataSize) != (size_t)nInDataSize) {
+ nError = LZSA_ERROR_DST;
+ }
+ else {
+ nOriginalSize += (long long)nInDataSize;
+ nCompressedSize += (long long)nBlockheaderSize + (long long)nInDataSize;
+ }
+ }
+ }
+ }
+
+ nPreviousBlockSize = nInDataSize;
+ nNumBlocks++;
+ }
+
+ if (!nError && !pInStream->eof(pInStream)) {
+ if (progress)
+ progress(nOriginalSize, nCompressedSize);
+ }
+ }
+
+ if (!nError) {
+ int nFooterSize;
+
+ if ((nFlags & LZSA_FLAG_RAW_BLOCK) != 0) {
+ nFooterSize = 0;
+ }
+ else {
+ nFooterSize = lzsa_encode_footer_frame(cFrameData, 16);
+ if (nFooterSize < 0)
+ nError = LZSA_ERROR_COMPRESSION;
+ }
+
+ if (pOutStream->write(pOutStream, cFrameData, nFooterSize) != nFooterSize)
+ nError = LZSA_ERROR_DST;
+ nCompressedSize += (long long)nFooterSize;
+ }
+
+ if (progress)
+ progress(nOriginalSize, nCompressedSize);
+
+ int nCommandCount = lzsa_compressor_get_command_count(&compressor);
+ int nSafeDist = compressor.safe_dist;
+
+ if (pStats)
+ *pStats = compressor.stats;
+
+ lzsa_compressor_destroy(&compressor);
+
+ free(pOutData);
+ pOutData = NULL;
+
+ free(pInData);
+ pInData = NULL;
+
+ if (nError) {
+ return nError;
+ }
+ else {
+ if (pOriginalSize)
+ *pOriginalSize = nOriginalSize;
+ if (pCompressedSize)
+ *pCompressedSize = nCompressedSize;
+ if (pCommandCount)
+ *pCommandCount = nCommandCount;
+ if (pSafeDist)
+ *pSafeDist = nSafeDist;
+ return LZSA_OK;
+ }
+}
diff --git a/tools/rasm/lzsa-master/src/shrink_streaming.h b/tools/rasm/lzsa-master/src/shrink_streaming.h
new file mode 100644
index 0000000..0920edf
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/shrink_streaming.h
@@ -0,0 +1,99 @@
+/*
+ * shrink_streaming.h - streaming compression definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#ifndef _SHRINK_STREAMING_H
+#define _SHRINK_STREAMING_H
+
+#include "stream.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declaration */
+typedef enum _lzsa_status_t lzsa_status_t;
+typedef struct _lzsa_stats lzsa_stats;
+
+/*-------------- File API -------------- */
+
+/**
+ * Compress file
+ *
+ * @param pszInFilename name of input(source) file to compress
+ * @param pszOutFilename name of output(compressed) file to generate
+ * @param pszDictionaryFilename name of dictionary file, or NULL for none
+ * @param nFlags compression flags (LZSA_FLAG_xxx)
+ * @param nMinMatchSize minimum match size
+ * @param nFormatVersion version of format to use (1-2)
+ * @param progress progress function, called after compressing each block, or NULL for none
+ * @param pOriginalSize pointer to returned input(source) size, updated when this function is successful
+ * @param pCompressedSize pointer to returned output(compressed) size, updated when this function is successful
+ * @param pCommandCount pointer to returned token(compression commands) count, updated when this function is successful
+ * @param pSafeDist pointer to return safe distance for raw blocks, updated when this function is successful
+ * @param pStats pointer to compression stats that are filled if this function is successful, or NULL
+ *
+ * @return LZSA_OK for success, or an error value from lzsa_status_t
+ */
+lzsa_status_t lzsa_compress_file(const char *pszInFilename, const char *pszOutFilename, const char *pszDictionaryFilename,
+ const unsigned int nFlags, const int nMinMatchSize, const int nFormatVersion,
+ void(*progress)(long long nOriginalSize, long long nCompressedSize), long long *pOriginalSize, long long *pCompressedSize, int *pCommandCount, int *pSafeDist, lzsa_stats *pStats);
+
+/*-------------- Streaming API -------------- */
+
+/**
+ * Compress stream
+ *
+ * @param pInStream input(source) stream to compress
+ * @param pOutStream output(compressed) stream to write to
+ * @param pDictionaryData dictionary contents, or NULL for none
+ * @param nDictionaryDataSize size of dictionary contents, or 0
+ * @param nFlags compression flags (LZSA_FLAG_xxx)
+ * @param nMinMatchSize minimum match size
+ * @param nFormatVersion version of format to use (1-2)
+ * @param progress progress function, called after compressing each block, or NULL for none
+ * @param pOriginalSize pointer to returned input(source) size, updated when this function is successful
+ * @param pCompressedSize pointer to returned output(compressed) size, updated when this function is successful
+ * @param pCommandCount pointer to returned token(compression commands) count, updated when this function is successful
+ * @param pSafeDist pointer to return safe distance for raw blocks, updated when this function is successful
+ * @param pStats pointer to compression stats that are filled if this function is successful, or NULL
+ *
+ * @return LZSA_OK for success, or an error value from lzsa_status_t
+ */
+lzsa_status_t lzsa_compress_stream(lzsa_stream_t *pInStream, lzsa_stream_t *pOutStream, const void *pDictionaryData, int nDictionaryDataSize,
+ const unsigned int nFlags, const int nMinMatchSize, const int nFormatVersion,
+ void(*progress)(long long nOriginalSize, long long nCompressedSize), long long *pOriginalSize, long long *pCompressedSize, int *pCommandCount, int *pSafeDist, lzsa_stats *pStats);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SHRINK_STREAMING_H */
diff --git a/tools/rasm/lzsa-master/src/stream.c b/tools/rasm/lzsa-master/src/stream.c
new file mode 100644
index 0000000..8937487
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/stream.c
@@ -0,0 +1,111 @@
+/*
+ * stream.c - streaming I/O implementation
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "stream.h"
+
+/**
+ * Close file stream
+ *
+ * @param stream stream
+ */
+static void lzsa_filestream_close(lzsa_stream_t *stream) {
+ if (stream->obj) {
+ fclose((FILE*)stream->obj);
+ stream->obj = NULL;
+ stream->read = NULL;
+ stream->write = NULL;
+ stream->eof = NULL;
+ stream->close = NULL;
+ }
+}
+
+/**
+ * Read from file stream
+ *
+ * @param stream stream
+ * @param ptr buffer to read into
+ * @param size number of bytes to read
+ *
+ * @return number of bytes read
+ */
+static size_t lzsa_filestream_read(lzsa_stream_t *stream, void *ptr, size_t size) {
+ return fread(ptr, 1, size, (FILE*)stream->obj);
+}
+
+/**
+ * Write to file stream
+ *
+ * @param stream stream
+ * @param ptr buffer to write from
+ * @param size number of bytes to write
+ *
+ * @return number of bytes written
+ */
+static size_t lzsa_filestream_write(lzsa_stream_t *stream, void *ptr, size_t size) {
+ return fwrite(ptr, 1, size, (FILE*)stream->obj);
+}
+
+/**
+ * Check if file stream has reached the end of the data
+ *
+ * @param stream stream
+ *
+ * @return nonzero if the end of the data has been reached, 0 if there is more data
+ */
+static int lzsa_filestream_eof(lzsa_stream_t *stream) {
+ return feof((FILE*)stream->obj);
+}
+
+/**
+ * Open file and create an I/O stream from it
+ *
+ * @param stream stream to fill out
+ * @param pszInFilename filename
+ * @param pszMode open mode, as with fopen()
+ *
+ * @return 0 for success, nonzero for failure
+ */
+int lzsa_filestream_open(lzsa_stream_t *stream, const char *pszInFilename, const char *pszMode) {
+ stream->obj = (void*)fopen(pszInFilename, pszMode);
+ if (stream->obj) {
+ stream->read = lzsa_filestream_read;
+ stream->write = lzsa_filestream_write;
+ stream->eof = lzsa_filestream_eof;
+ stream->close = lzsa_filestream_close;
+ return 0;
+ }
+ else
+ return -1;
+}
diff --git a/tools/rasm/lzsa-master/src/stream.h b/tools/rasm/lzsa-master/src/stream.h
new file mode 100644
index 0000000..a8b7922
--- /dev/null
+++ b/tools/rasm/lzsa-master/src/stream.h
@@ -0,0 +1,103 @@
+/*
+ * stream.h - streaming I/O definitions
+ *
+ * Copyright (C) 2019 Emmanuel Marty
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/*
+ * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori
+ *
+ * Inspired by LZ4 by Yann Collet. https://github.com/lz4/lz4
+ * With help, ideas, optimizations and speed measurements by spke <zxintrospec@gmail.com>
+ * With ideas from Lizard by Przemyslaw Skibinski and Yann Collet. https://github.com/inikep/lizard
+ * Also with ideas from smallz4 by Stephan Brumme. https://create.stephan-brumme.com/smallz4/
+ *
+ */
+
+#ifndef _STREAM_H
+#define _STREAM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declaration */
+typedef struct _lzsa_stream_t lzsa_stream_t;
+
+/* I/O stream */
+typedef struct _lzsa_stream_t {
+ /** Opaque stream-specific pointer */
+ void *obj;
+
+ /**
+ * Read from stream
+ *
+ * @param stream stream
+ * @param ptr buffer to read into
+ * @param size number of bytes to read
+ *
+ * @return number of bytes read
+ */
+ size_t(*read)(lzsa_stream_t *stream, void *ptr, size_t size);
+
+ /**
+ * Write to stream
+ *
+ * @param stream stream
+ * @param ptr buffer to write from
+ * @param size number of bytes to write
+ *
+ * @return number of bytes written
+ */
+ size_t(*write)(lzsa_stream_t *stream, void *ptr, size_t size);
+
+
+ /**
+ * Check if stream has reached the end of the data
+ *
+ * @param stream stream
+ *
+ * @return nonzero if the end of the data has been reached, 0 if there is more data
+ */
+ int(*eof)(lzsa_stream_t *stream);
+
+ /**
+ * Close stream
+ *
+ * @param stream stream
+ */
+ void(*close)(lzsa_stream_t *stream);
+} lzsa_stream_t;
+
+/**
+ * Open file and create an I/O stream from it
+ *
+ * @param stream stream to fill out
+ * @param pszInFilename filename
+ * @param pszMode open mode, as with fopen()
+ *
+ * @return 0 for success, nonzero for failure
+ */
+int lzsa_filestream_open(lzsa_stream_t *stream, const char *pszInFilename, const char *pszMode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STREAM_H */
diff --git a/tools/rasm/makefile.MacOS b/tools/rasm/makefile.MacOS
new file mode 100644
index 0000000..cbd5787
--- /dev/null
+++ b/tools/rasm/makefile.MacOS
@@ -0,0 +1,101 @@
+CC=gcc
+EXEC=rasm
+
+CFLAGS=-lm -mcpu=native -o $(EXEC) -w
+CFLAGS_OPT = $(CFLAGS) -O2
+CFLAGS_DBG = $(CFLAGS) -g -pthread -DRDD
+
+SRC_APUDIR=./apultra-master/src
+SRC_LZSADIR=./lzsa-master/src
+SRC_ZX0DIR=./ZX0-main/src
+
+APU_FLAGS=-c -O3 -fomit-frame-pointer -I$(SRC_LZSADIR)/libdivsufsort/include -I$(SRC_APUDIR)
+
+APU_OBJ =$(SRC_APUDIR)/expand.o
+APU_OBJ+=$(SRC_APUDIR)/matchfinder.o
+APU_OBJ+=$(SRC_APUDIR)/shrink.o
+APU_OBJ+=$(SRC_APUDIR)/libdivsufsort/lib/divsufsort.o
+APU_OBJ+=$(SRC_APUDIR)/libdivsufsort/lib/divsufsort_utils.o
+APU_OBJ+=$(SRC_APUDIR)/libdivsufsort/lib/sssort.o
+APU_OBJ+=$(SRC_APUDIR)/libdivsufsort/lib/trsort.o
+
+LZSA_FLAGS=-c -O3 -fomit-frame-pointer -I$(SRC_LZSADIR)/libdivsufsort/include -I$(SRC_LZSADIR)
+
+LZSA_OBJ =$(SRC_LZSADIR)/dictionary.o
+LZSA_OBJ+=$(SRC_LZSADIR)/expand_block_v1.o
+LZSA_OBJ+=$(SRC_LZSADIR)/expand_block_v2.o
+LZSA_OBJ+=$(SRC_LZSADIR)/expand_context.o
+LZSA_OBJ+=$(SRC_LZSADIR)/expand_inmem.o
+LZSA_OBJ+=$(SRC_LZSADIR)/frame.o
+LZSA_OBJ+=$(SRC_LZSADIR)/matchfinder.o
+LZSA_OBJ+=$(SRC_LZSADIR)/shrink_block_v1.o
+LZSA_OBJ+=$(SRC_LZSADIR)/shrink_block_v2.o
+LZSA_OBJ+=$(SRC_LZSADIR)/shrink_context.o
+LZSA_OBJ+=$(SRC_LZSADIR)/shrink_inmem.o
+LZSA_OBJ+=$(SRC_LZSADIR)/stream.o
+
+ZX0_FLAGS=-c -O2 -I$(SRC_ZX0DIR)
+ZX0_OBJ =$(SRC_ZX0DIR)/optimize.o
+ZX0_OBJ+=$(SRC_ZX0DIR)/compress.o
+ZX0_OBJ+=$(SRC_ZX0DIR)/memory.o
+
+.PHONY: prod debug install clean
+
+default: prod
+
+debug:
+ $(CC) $(SRC_ZX0DIR)/optimize.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/optimize.o
+ $(CC) $(SRC_ZX0DIR)/compress.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/compress.o
+ $(CC) $(SRC_ZX0DIR)/memory.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/memory.o
+ $(CC) $(SRC_APUDIR)/expand.c $(APU_FLAGS) -o $(SRC_APUDIR)/expand.o
+ $(CC) $(SRC_APUDIR)/matchfinder.c $(APU_FLAGS) -o $(SRC_APUDIR)/matchfinder.o
+ $(CC) $(SRC_APUDIR)/shrink.c $(APU_FLAGS) -o $(SRC_APUDIR)/shrink.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/divsufsort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/divsufsort.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/divsufsort_utils.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/divsufsort_utils.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/sssort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/sssort.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/trsort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/trsort.o
+ $(CC) $(SRC_LZSADIR)/matchfinder.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/matchfinder.o
+ $(CC) $(SRC_LZSADIR)/dictionary.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/dictionary.o
+ $(CC) $(SRC_LZSADIR)/expand_block_v1.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_block_v1.o
+ $(CC) $(SRC_LZSADIR)/expand_block_v2.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_block_v2.o
+ $(CC) $(SRC_LZSADIR)/expand_context.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_context.o
+ $(CC) $(SRC_LZSADIR)/expand_inmem.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_inmem.o
+ $(CC) $(SRC_LZSADIR)/frame.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/frame.o
+ $(CC) $(SRC_LZSADIR)/shrink_block_v1.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_block_v1.o
+ $(CC) $(SRC_LZSADIR)/shrink_block_v2.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_block_v2.o
+ $(CC) $(SRC_LZSADIR)/shrink_context.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_context.o
+ $(CC) $(SRC_LZSADIR)/shrink_inmem.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_inmem.o
+ $(CC) $(SRC_LZSADIR)/stream.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/stream.o
+ $(CC) rasm.c $(CFLAGS_DBG)
+
+prod:
+ $(CC) $(SRC_ZX0DIR)/optimize.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/optimize.o
+ $(CC) $(SRC_ZX0DIR)/compress.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/compress.o
+ $(CC) $(SRC_ZX0DIR)/memory.c $(ZX0_FLAGS) -o $(SRC_ZX0DIR)/memory.o
+ $(CC) $(SRC_APUDIR)/expand.c $(APU_FLAGS) -o $(SRC_APUDIR)/expand.o
+ $(CC) $(SRC_APUDIR)/matchfinder.c $(APU_FLAGS) -o $(SRC_APUDIR)/matchfinder.o
+ $(CC) $(SRC_APUDIR)/shrink.c $(APU_FLAGS) -o $(SRC_APUDIR)/shrink.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/divsufsort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/divsufsort.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/divsufsort_utils.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/divsufsort_utils.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/sssort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/sssort.o
+ $(CC) $(SRC_LZSADIR)/libdivsufsort/lib/trsort.c $(APU_FLAGS) -o $(SRC_APUDIR)/libdivsufsort/lib/trsort.o
+ $(CC) $(SRC_LZSADIR)/matchfinder.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/matchfinder.o
+ $(CC) $(SRC_LZSADIR)/dictionary.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/dictionary.o
+ $(CC) $(SRC_LZSADIR)/expand_block_v1.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_block_v1.o
+ $(CC) $(SRC_LZSADIR)/expand_block_v2.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_block_v2.o
+ $(CC) $(SRC_LZSADIR)/expand_context.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_context.o
+ $(CC) $(SRC_LZSADIR)/expand_inmem.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/expand_inmem.o
+ $(CC) $(SRC_LZSADIR)/frame.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/frame.o
+ $(CC) $(SRC_LZSADIR)/shrink_block_v1.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_block_v1.o
+ $(CC) $(SRC_LZSADIR)/shrink_block_v2.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_block_v2.o
+ $(CC) $(SRC_LZSADIR)/shrink_context.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_context.o
+ $(CC) $(SRC_LZSADIR)/shrink_inmem.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/shrink_inmem.o
+ $(CC) $(SRC_LZSADIR)/stream.c $(LZSA_FLAGS) -o $(SRC_LZSADIR)/stream.o
+ $(CC) rasm.c $(CFLAGS_OPT) $(APU_OBJ) $(LZSA_OBJ) $(ZX0_OBJ)
+ strip $(EXEC)
+
+install:
+ install rasm /usr/local/bin
+
+clean:
+ rm -f $(APU_OBJ) $(LZSA_OBJ) $(ZX0_OBJ) apultra-master/src/apultra.o lzsa-master/src/shrink_streaming.o lzsa-master/src/expand_streaming.o
diff --git a/tools/rasm/minilib.h b/tools/rasm/minilib.h
index 99d55eb..705b982 100644
--- a/tools/rasm/minilib.h
+++ b/tools/rasm/minilib.h
@@ -1,9 +1,16 @@
-#define __FILENAME__ "minilib.h"
+#define __FILENAME__ "minilib.h"
#include<string.h>
#include<stdlib.h>
#include<stddef.h>
+#ifdef _MSC_VER
+#if _MSC_VER>1500
#include<stdint.h>
+#endif
+#else
+#include<stdint.h>
+#endif
+
#include<stdarg.h>
#include<stdio.h>
#include<errno.h>
@@ -41,12 +48,18 @@
#define MemRealloc realloc
#define MemMalloc malloc
#define MemMove memmove
-#ifdef OS_WIN
+#if defined(__BORLANDC__)
+#define TxtStrDup strdup
+#elif defined(OS_WIN)
#define TxtStrDup _strdup
#else
#define TxtStrDup strdup
#endif
+#ifdef __BORLANDC__
+#define _setmode setmode
+#endif /* __BORLANDC__ */
+
#define loginfo(...); {printf(__VA_ARGS__);printf("\n");}
#define logdebug(...); {printf(__VA_ARGS__);printf("\n");}
#define logwarn(...); {printf(__VA_ARGS__);printf("\n");}
@@ -89,7 +102,7 @@ int MinMaxInt(int zeval, int zemin, int zemax)
}
/* (c) FSF */
-#ifdef __WATCOMC__
+#if defined(__WATCOMC__) || defined(__BORLANDC__)
size_t strnlen (s, maxlen)
register const char *s;
size_t maxlen;
@@ -101,8 +114,63 @@ size_t strnlen (s, maxlen)
;
return n;
}
+#define _strnlen strnlen
#endif
+/*
+** Call syntax: char *stristr(char *String, char *Pattern)
+**
+** Description: This function is an ANSI version of strstr() with
+** case insensitivity.
+** Return item: char *pointer if Pattern is found in String, else
+** pointer to 0
+** Rev History: 07/04/95 Bob Stout ANSI-fy
+** 02/03/94 Fred Cole Original
+** Hereby donated to public domain.
+** Modified for use with libcyrus by Ken Murchison 06/01/00.
+**
+** from Debian package cyrus-imapd
+
+modified for Rasm as pattern is always upper case...
+
+*/
+
+char *_internal_stristr(const char *ZeString, const unsigned int ZeLen, const char *Pattern)
+{
+ char *pptr, *sptr, *start;
+ unsigned int slen,plen;
+
+ start = (char *)ZeString;
+ pptr = (char *)Pattern;
+ plen = strlen(Pattern);
+ slen = ZeLen;
+ for ( /* while string length not shorter than pattern length */;
+ slen >= plen;
+ start++, slen--) {
+ /* find start of pattern in string */
+ while (toupper(*start) != *Pattern) {
+ start++;
+ slen--;
+ /* if pattern longer than string */
+ if (slen < plen)
+ return NULL;
+ }
+
+ // because pattern is always 2 or more...
+ sptr = start+1;
+ pptr = (char *)Pattern+1;
+
+ while (toupper(*sptr) == *pptr) {
+ sptr++;
+ pptr++;
+
+ if ('\0' == *pptr) {
+ return start;
+ }
+ }
+ }
+ return NULL;
+}
char *TxtStrDupLen(char *str, int *len)
{
@@ -665,15 +733,15 @@ char *_internal_fgetsmulti(char *filename, int read_mode)
#define FUNC "_internal_fgetsmulti"
static char buffer[MAX_LINE_BUFFER+1]={0};
FILE *last_id=NULL;
- char * (*_file_get_string)(char *, int, FILE *);
+ char * (*_file_get_string)(char *, int, FILE *)=fgets;
last_id=FileOpen(filename,"r");
switch (read_mode)
{
+ default:logerr("Unknown read mode! (%d)",read_mode);
case RAW_READING:_file_get_string=fgets;break;
case CLOSE_READING:_file_get_string=_internal_fgetsClose;break;
- default:logerr("Unknown read mode! (%d)",read_mode);
}
if (_file_get_string(buffer,MAX_LINE_BUFFER,last_id)!=NULL)
@@ -709,9 +777,9 @@ char **_internal_fgetsmultilines(char *filename, int read_mode)
switch (read_mode)
{
+ default:logerr("Unknown read mode! (%d)",read_mode);
case RAW_READING:_file_get_string=fgets;break;
case CLOSE_READING:_file_get_string=_internal_fgetsClose;break;
- default:logerr("Unknown read mode! (%d)",read_mode);
}
@@ -860,6 +928,31 @@ int FileReadBinary(char *filename,char *data,int n)
}
/***
+ FileTruncate function
+ set file to zero size then leave
+*/
+int FileTruncate(char *filename)
+{
+#undef FUNC
+#define FUNC "FileTruncate"
+FILE *last_id=NULL;
+
+#ifdef OS_WIN
+int sr;
+last_id=FileOpen(filename,"w");
+sr=_setmode(_fileno(last_id), _O_BINARY );
+if (sr==-1) {
+logerr("FATAL: cannot set binary mode for writing");
+exit(ABORT_ERROR);
+}
+#else
+last_id=FileOpen(filename,"a+");
+#endif
+FileClose(last_id);
+return 0;
+}
+
+/***
FileWriteBinary function
write n bytes from buffer to file
@@ -917,6 +1010,7 @@ int FileWriteBinary(char *filename,char *data,int n)
/* NULL buffer sent, this means End of file, we close the handle */
//logdebug("%d byte(s) written to %s",FileGetCPT(last_id),filename);
FileClose(last_id);
+ nn=0;
}
return nn;
}
diff --git a/tools/rasm/msdos.bat b/tools/rasm/msdos.bat
new file mode 100644
index 0000000..0962054
--- /dev/null
+++ b/tools/rasm/msdos.bat
@@ -0,0 +1,4 @@
+wcl386 rasm.c -6r -6s -fp6 -d0 -k4000000 -ox /bt=DOS /l=dos4g -DOS_WIN=1 -DNOAPULTRA=1
+upx.exe --brute rasm.exe
+
+
diff --git a/tools/rasm/rasm_v0120.c b/tools/rasm/rasm.c
index 2c0a96a..88cd59c 100644
--- a/tools/rasm/rasm_v0120.c
+++ b/tools/rasm/rasm.c
@@ -1,6 +1,6 @@
#define PROGRAM_NAME "RASM"
-#define PROGRAM_VERSION "0.120"
-#define PROGRAM_DATE "xx/12/2019"
+#define PROGRAM_VERSION "1.7"
+#define PROGRAM_DATE "xx/11/2021"
#define PROGRAM_COPYRIGHT "© 2017 BERGE Edouard / roudoudou from Resistance"
#define RASM_VERSION PROGRAM_NAME" v"PROGRAM_VERSION" (build "PROGRAM_DATE")"
@@ -9,18 +9,18 @@
#define TRACE_GENERALE 0
#define TRACE_PREPRO 0
#define TRACE_ASSEMBLE 0
+#define TRACE_POPEXPR 0
#define TRACE_COMPUTE_EXPRESSION 0
#define TRACE_HEXBIN 0
#define TRACE_MAKEAMSDOSREAL 0
#define TRACE_STRUCT 0
#define TRACE_EDSK 0
-
-
+#define TRACE_LABEL 0
/***
Rasm (roudoudou assembler) Z80 assembler
-doc & latest official release at: http://www.cpcwiki.eu/forum/programming/rasm-z80-assembler-in-beta/
+doc & latest official release at: https://github.com/EdouardBERGE/rasm
You may send requests/bugs in the same topic
@@ -45,21 +45,21 @@ arising from, out of or in connection with the software or the use or o
Software. »
-----------------------------------------------------------------------------------------------------
Linux compilation with GCC or Clang:
-cc rasm_v0116.c -O2 -lm -lrt -march=native -o rasm
+cc rasm.c -O2 -lm -lrt -march=native -o rasm
strip rasm
Windows compilation with Visual studio:
-cl.exe rasm_v0116.c -O2 -Ob3
+cl.exe rasm.c -O2 -Ob3
-pure MS-DOS 32 bits compilation with Watcom:
-wcl386 rasm_v0116.c -6r -6s -fp6 -d0 -k4000000 -ox /bt=DOS /l=dos4g
+pure MS-DOS 32 bits compilation with Watcom without native support of AP-Ultra:
+wcl386 rasm.c -6r -6s -fp6 -d0 -k4000000 -ox /bt=DOS /l=dos4g -DOS_WIN=1 -DNOAPLIB=1
MorphOS compilation (ixemul):
-ppc-morphos-gcc-5 -O2 -c -o rasm rasm_v0116.c
+gcc -noixemul -O2 -c -o rasm rasm.c
strip rasm
MacOS compilation:
-cc rasm_v0116.c -O2 -lm -march=native -o rasm
+cc rasm.c -O2 -lm -march=native -o rasm
*/
@@ -84,17 +84,49 @@ cc rasm_v0116.c -O2 -lm -march=native -o rasm
#define TxtSplitWithChar _internal_TxtSplitWithChar
#endif
+int MAX_OFFSET_ZX0=32640;
+
#ifndef NO_3RD_PARTIES
#define __FILENAME__ "3rd parties"
/* 3rd parties compression */
#include"zx7.h"
#include"lz4.h"
#include"exomizer.h"
+
+void zx0_reverse(unsigned char *first, unsigned char *last) {
+ unsigned char c;
+
+ while (first < last) {
+ c = *first;
+ *first++ = *last;
+ *last-- = c;
+ }
+}
+
+typedef struct block_t {
+ struct block_t *chain;
+ struct block_t *ghost_chain;
+ int bits;
+ int index;
+ int offset;
+ int references;
+} BLOCK;
+
+BLOCK *allocate(int bits, int index, int offset, BLOCK *chain);
+
+void assign(BLOCK **ptr, BLOCK *chain);
+
+BLOCK *zx0_optimize(unsigned char *input_data, int input_size, int skip, int offset_limit);
+
+unsigned char *zx0_compress(BLOCK *optimal, unsigned char *input_data, int input_size, int skip, int backwards_mode, int invert_mode, int *output_size, int *delta);
+
#endif
#ifdef __MORPHOS__
/* Add standard version string to executable */
const char __attribute__((section(".text"))) ver_version[]={ "\0$VER: "PROGRAM_NAME" "PROGRAM_VERSION" ("PROGRAM_DATE") "PROGRAM_COPYRIGHT"" };
+/* Expand the default stack to match rasm requirements (about 64KiB) */
+unsigned long __stack = 128 * 1024;
#endif
#undef __FILENAME__
@@ -143,26 +175,37 @@ struct s_parameter {
int export_snabrk;
int export_brk;
int nowarning;
+ int erronwarn;
+ int utf8enable;
+ int freequote;
int checkmode;
int dependencies;
int maxerr;
int macrovoid;
int extended_error;
+ int display_stats;
int edskoverwrite;
+ int xpr;
float rough;
- int as80,dams;
+ int as80,dams,pasmo;
int v2;
int warn_unused;
char *symbol_name;
char *binary_name;
char *cartridge_name;
char *snapshot_name;
+ char *rom_name;
char *tape_name;
char *breakpoint_name;
+ char *cprinfo_name;
char **symboldef;
int nsymb,msymb;
char **pathdef;
int npath,mpath;
+ int noampersand;
+ int cprinfo,cprinfoexport;
+ char module_separator;
+ int enforce_symbol_case;
};
@@ -219,13 +262,22 @@ E_COMPUTE_OPERATION_GET_B=42,
E_COMPUTE_OPERATION_SET_R=43,
E_COMPUTE_OPERATION_SET_V=44,
E_COMPUTE_OPERATION_SET_B=45,
-E_COMPUTE_OPERATION_END=46
+E_COMPUTE_OPERATION_SOFT2HARD=46,
+E_COMPUTE_OPERATION_HARD2SOFT=47,
+/* string functions */
+E_COMPUTE_OPERATION_GETNOP=48,
+E_COMPUTE_OPERATION_GETTICK=49,
+E_COMPUTE_OPERATION_DURATION=50,
+E_COMPUTE_OPERATION_FILESIZE=51,
+E_COMPUTE_OPERATION_GETSIZE=52,
+E_COMPUTE_OPERATION_END=53
};
struct s_compute_element {
enum e_compute_operation_type operator;
double value;
int priority;
+char *string;
};
struct s_compute_core_data {
@@ -242,10 +294,10 @@ struct s_compute_core_data {
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];
+char ChunkID[4];
unsigned char ChunkSize[4];
-unsigned char Format[4];
-unsigned char SubChunk1ID[4];
+char Format[4];
+char SubChunk1ID[4];
unsigned char SubChunk1Size[4];
unsigned char AudioFormat[2];
unsigned char NumChannels[2];
@@ -261,7 +313,9 @@ enum e_audio_sample_type {
AUDIOSAMPLE_SMP,
AUDIOSAMPLE_SM2,
AUDIOSAMPLE_SM4,
-AUDIOSAMPLE_DMA,
+AUDIOSAMPLE_DMAA,
+AUDIOSAMPLE_DMAB,
+AUDIOSAMPLE_DMAC,
AUDIOSAMPLE_END
};
@@ -270,17 +324,20 @@ AUDIOSAMPLE_END
***********************************************************************/
enum e_expression {
E_EXPRESSION_J8, /* relative 8bits jump */
- E_EXPRESSION_0V8, /* 8 bits value to current adress */
- E_EXPRESSION_V8, /* 8 bits value to current adress+1 */
- E_EXPRESSION_V16, /* 16 bits value to current adress+1 */
- E_EXPRESSION_V16C, /* 16 bits value to current adress+1 */
- E_EXPRESSION_0V16, /* 16 bits value to current adress */
- E_EXPRESSION_0V32, /* 32 bits value to current adress */
- E_EXPRESSION_0VR, /* AMSDOS real value (5 bytes) to current adress */
- E_EXPRESSION_IV8, /* 8 bits value to current adress+2 */
- E_EXPRESSION_IV81, /* 8 bits value+1 to current adress+2 */
- E_EXPRESSION_3V8, /* 8 bits value to current adress+3 used with LD (IX+n),n */
- E_EXPRESSION_IV16, /* 16 bits value to current adress+2 */
+ E_EXPRESSION_0V8, /* 8 bits value to current address */
+ E_EXPRESSION_V8, /* 8 bits value to current address+1 */
+ E_EXPRESSION_J16, /* 16 bits value to current address+1 */
+ E_EXPRESSION_J16C, /* 16 bits value to current address+1 */
+ E_EXPRESSION_V16, /* 16 bits value to current address+1 */
+ //E_EXPRESSION_V16C, /* 16 bits value to current address+1 */
+ E_EXPRESSION_0V16, /* 16 bits value to current address */
+ E_EXPRESSION_0V32, /* 32 bits value to current address */
+ E_EXPRESSION_0VR, /* AMSDOS real value (5 bytes) to current address */
+ E_EXPRESSION_0VRMike,/* Microsoft IEEE-754 real value (5 bytes) to current address */
+ E_EXPRESSION_IV8, /* 8 bits value to current address+2 */
+ E_EXPRESSION_IV81, /* 8 bits value+1 to current address+2 */
+ E_EXPRESSION_3V8, /* 8 bits value to current address+3 used with LD (IX+n),n */
+ E_EXPRESSION_IV16, /* 16 bits value to current address+2 */
E_EXPRESSION_RST, /* the offset of RST is translated to the opcode */
E_EXPRESSION_IM, /* the interrupt mode is translated to the opcode */
E_EXPRESSION_RUN, /* delayed RUN value */
@@ -299,6 +356,7 @@ struct s_expression {
int lz; /* lz zone */
int ibank; /* ibank of expression */
int iorgzone; /* org of expression */
+ char *module;
};
struct s_expr_dico {
@@ -308,13 +366,29 @@ struct s_expr_dico {
double v;
int used;
int iw;
+ int external;
+};
+
+struct s_external_mapping {
+ int iorgzone;
+ int ptr;
+ int size;
+ int value; // do not relocate outside scope!
+};
+
+struct s_external {
+ char *name;
+ int crc;
+ /* mapping info */
+ struct s_external_mapping *mapping;
+ int nmapping,mmapping;
};
struct s_label {
char *name; /* is alloced for local repeat or struct OR generated global -> in this case iw=-1 */
int iw; /* index of the word of label name */
int crc; /* crc of the label name */
- int ptr; /* "physical" adress */
+ int ptr; /* "physical" address */
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 */
@@ -330,8 +404,11 @@ struct s_alias {
char *alias;
char *translation;
int crc,len,autorise_export;
- int iw;
+ int iw,lz;
int used;
+ /* v1.5 */
+ int ptr;
+ float v;
};
struct s_ticker {
@@ -372,7 +449,8 @@ struct s_crcstring_tree {
struct s_lz_section {
int iw;
int memstart,memend;
- int lzversion; /* 4 -> LZ4 / 7 -> ZX7 / 48 -> LZ48 / 49 -> LZ49 / 8 -> Exomizer */
+ int lzversion; /* 0 -> NO CRUNCH but must be delayed / 4 -> LZ4 / 7 -> ZX7 / 48 -> LZ48 / 49 -> LZ49 / 8 -> Exomizer */
+ int version,minmatch; /* LZSA + ZX0 */
int iorgzone;
int ibank;
/* idx backup */
@@ -385,6 +463,7 @@ struct s_orgzone {
int memstart,memend;
int ifile,iline;
int nocode;
+ int inplace;
};
/**************************************************
@@ -395,6 +474,7 @@ struct s_hexbin {
int datalen,rawlen;
char *filename;
int crunch;
+ int version,minmatch;
};
/**************************************************
@@ -452,6 +532,7 @@ struct s_save {
int ioffset;
int isize;
int iw,irun;
+ char *filename;
int amsdos,hobeta;
int tape,dsk,face,iwdskname;
};
@@ -474,6 +555,7 @@ struct s_repeat {
int maxim;
int repeat_counter;
char *repeatvar;
+ double varincrement;
int repeatcrc;
};
@@ -537,7 +619,9 @@ struct s_macro {
};
struct s_macro_position {
- int start,end,value;
+ int start,end,value,level,pushed;
+ //char *lastlocal;
+ //int lastlocalen,lastlocalalloc;
};
/* preprocessing only */
@@ -597,7 +681,7 @@ struct s_snapshot_symbol {
unsigned char size;
unsigned char name[256];
unsigned char reserved[6];
- unsigned char bigendian_adress[2];
+ unsigned char bigendian_address[2];
};
@@ -748,21 +832,41 @@ struct s_rasmstruct {
/*********************************
D E B U G
*********************************/
-struct s_debug_error {
- char *filename;
- int line;
- char *msg;
- int lenmsg,lenfilename;
+
+#define INSIDE_RASM
+#include "rasm.h"
+
+
+/*******************************************
+ P O K E R
+*******************************************/
+enum e_poker {
+E_POKER_XOR8=0,
+E_POKER_SUM8=1,
+E_POKER_CIPHER001=2,
+E_POKER_CIPHER002=3,
+E_POKER_CIPHER003=4,
+E_POKER_CIPHER004=5,
+E_POKER_END
};
-struct s_debug_symbol {
- char *name;
- int v;
+
+char *strpoker[]={
+ "XORMEM",
+ "SUMMEM",
+ "CIPHER001 running XOR initialised with first value",
+ "CIPHER002 running XOR initialised with memory location",
+ "CIPHER003 XOR with LSB of memory location",
+ "CIPHER004 XOR with key looping",
+ NULL
};
-struct s_rasm_info {
- struct s_debug_error *error;
- int nberror,maxerror;
- struct s_debug_symbol *symbol;
- int nbsymbol,maxsymbol;
+
+struct s_poker {
+ enum e_poker method;
+ int istart,iend;
+ int outputadr;
+ int ibank;
+ int istring;
+ int ipoker;
};
/*******************************************
@@ -775,9 +879,11 @@ struct s_assenv {
unsigned char **mem;
int iwnamebank[BANK_MAX_NUMBER];
int nbbank,maxbank;
- int forcetape,forcezx,forcecpr,forceROM,bankmode,activebank,amsdos,forcesnapshot,packedbank;
+ int forcetape,forcezx,forcecpr,forceROM,forceROMconcat,bankmode,activebank,amsdos,forcesnapshot,packedbank,extendedCPR,xpr,cprinfo,cprinfo_export;
+ char *cprinfo_filename;
struct s_snapshot snapshot;
struct s_zxsnapshot zxsnapshot;
+ int snapRAMsize;
int bankset[BANK_MAX_NUMBER>>2]; /* 64K selected flag */
int bankused[BANK_MAX_NUMBER]; /* 16K selected flag */
int bankgate[BANK_MAX_NUMBER+1];
@@ -791,10 +897,12 @@ struct s_assenv {
int label_line;
char **filename;
int ifile,maxfile;
+ char **rawfile; // case export
+ int *rawlen; // case export
int nberr,flux;
int fastmatch[256];
unsigned char charset[256];
- int maxerr,extended_error,nowarning;
+ int maxerr,extended_error,nowarning,erronwarn,utf8enable,freequote;
/* ORG tracking */
int codeadr,outputadr,nocode;
int codeadrbackup,outputadrbackup;
@@ -813,7 +921,7 @@ struct s_assenv {
/* expressions */
struct s_expression *expression;
int ie,me;
- int maxam,as80,dams;
+ int maxam,as80,dams,pasmo;
float rough;
struct s_compute_core_data *computectx,ctx1,ctx2;
struct s_crcstring_tree stringtree;
@@ -823,14 +931,21 @@ struct s_assenv {
struct s_crclabel_tree labeltree; /* fast label access */
char *module;
int modulen;
+ char module_separator[2];
struct s_breakpoint *breakpoint;
int ibreakpoint,maxbreakpoint;
char *lastgloballabel;
- char *lastsuperglobal;
+ //char *lastsuperglobal;
int lastgloballabellen, lastglobalalloc;
+ char **globalstack; /* retrieve back global from previous scope */
+ int igs,mgs;
+ char *source_bigbuffer;
+ int source_bigbuffer_len;
/* repeat */
struct s_repeat *repeat;
int ir,mr;
+ double repeat_start;
+ double repeat_increment;
/* while/wend */
struct s_whilewend *whilewend;
int iw,mw;
@@ -854,6 +969,9 @@ struct s_assenv {
struct s_lz_section *lzsection;
int ilz,mlz;
int lz,curlz;
+ /* poker */
+ struct s_poker *poker;
+ int nbpoker,maxpoker;
/* macro */
struct s_macro *macro;
int imacro,mmacro;
@@ -884,6 +1002,7 @@ struct s_assenv {
struct s_compute_element AutomateElement[256];
unsigned char psgtab[256];
unsigned char psgfine[256];
+ int noampersand;
/* output */
char *outputfilename;
int export_sym,export_local,export_multisym;
@@ -897,6 +1016,8 @@ struct s_assenv {
char *binary_name;
char *cartridge_name;
char *snapshot_name;
+ char *tape_name;
+ char *rom_name;
struct s_save *save;
int nbsave,maxsave;
int current_run_idx;
@@ -906,10 +1027,24 @@ struct s_assenv {
int checkmode,dependencies;
int stop;
int warn_unused;
+ int display_stats;
+ int enforce_symbol_case;
/* debug */
struct s_rasm_info debug;
struct s_rasm_info **retdebug;
int debug_total_len;
+ /* delayed print */
+ int *dprint_idx;
+ int idprint,mdprint;
+ /* OBJ output */
+ int buildobj;
+ struct s_external *external;
+ int nexternal,mexternal;
+ int external_mapping_size;
+ struct s_external_mapping *relocation;
+ int nrelocation,mrelocation;
+ char **procedurename;
+ int nprocedurename,mprocedurename;
};
/*************************************
@@ -948,6 +1083,15 @@ struct s_math_keyword math_keyword[]={
{"SETV",0,E_COMPUTE_OPERATION_SET_V},
{"SETG",0,E_COMPUTE_OPERATION_SET_V},
{"SETB",0,E_COMPUTE_OPERATION_SET_B},
+{"SOFT2HARD_INK",0,E_COMPUTE_OPERATION_SOFT2HARD},
+{"S2H_INK",0,E_COMPUTE_OPERATION_SOFT2HARD},
+{"HARD2SOFT_INK",0,E_COMPUTE_OPERATION_HARD2SOFT},
+{"H2S_INK",0,E_COMPUTE_OPERATION_HARD2SOFT},
+{"GETNOP",0,E_COMPUTE_OPERATION_GETNOP},
+{"GETTICK",0,E_COMPUTE_OPERATION_GETTICK},
+{"DURATION",0,E_COMPUTE_OPERATION_DURATION},
+{"FILESIZE",0,E_COMPUTE_OPERATION_FILESIZE},
+{"GETSIZE",0,E_COMPUTE_OPERATION_GETSIZE},
{"",0,-1}
};
@@ -989,6 +1133,20 @@ struct s_math_keyword math_keyword[]={
#define CRC_PE 0x4BD5370D
#define CRC_M 0x7A98A6C5
+/* cut registers */
+#define CRC_HL_LOW 0xF9FDE22C
+#define CRC_HL_HIGH 0x2261E25A
+#define CRC_DE_LOW 0x3A3CE221
+#define CRC_DE_HIGH 0x23D0E04F
+#define CRC_BC_LOW 0xFDFF1E1D
+#define CRC_BC_HIGH 0x222BE44B
+#define CRC_IX_LOW 0xB9FD0439
+#define CRC_IX_HIGH 0xA3FD0667
+#define CRC_IY_LOW 0xD9ED6C3A
+#define CRC_IY_HIGH 0x23DD5068
+#define CRC_AF_LOW 0xDDCF141F
+#define CRC_AF_HIGH 0x223FEA4D
+
/* 8 bits registers */
#define CRC_F 0x7A98A6BE
#define CRC_I 0x7A98A6C1
@@ -1040,9 +1198,11 @@ struct s_math_keyword math_keyword[]={
#define CRC_DS 0x4BD5DF0F
#define CRC_DEFR 0x37D15399
#define CRC_DR 0x4BD5DF0E
+#define CRC_DEFF 0x37D1538D
+#define CRC_DF 0x4BD5DF02
/* struct declaration use special instructions for defines */
-int ICRC_DEFB,ICRC_DEFW,ICRC_DEFI,ICRC_DEFR,ICRC_DEFS,ICRC_DB,ICRC_DW,ICRC_DR,ICRC_DS;
+int ICRC_DEFB,ICRC_DEFW,ICRC_DEFI,ICRC_DEFR,ICRC_DEFF,ICRC_DF,ICRC_DEFS,ICRC_DB,ICRC_DW,ICRC_DR,ICRC_DS;
/* need to pre-declare var */
extern struct s_asm_keyword instruction[];
@@ -1054,7 +1214,7 @@ A-Z variable ou fonction (cos, sin, tan, sqr, pow, mod, and, xor, mod, ...)
+*-/&^m| operateur
*/
-#define AutomateExpressionValidCharExtendedDefinition "0123456789.ABCDEFGHIJKLMNOPQRSTUVWXYZ_{}@+-*/~^$#%§<=>|&"
+#define AutomateExpressionValidCharExtendedDefinition "0123456789.ABCDEFGHIJKLMNOPQRSTUVWXYZ_{}@+-*/~^$#%<=>|&" /* § */
#define AutomateExpressionValidCharFirstDefinition "#%0123456789.ABCDEFGHIJKLMNOPQRSTUVWXYZ_@${"
#define AutomateExpressionValidCharDefinition "0123456789.ABCDEFGHIJKLMNOPQRSTUVWXYZ_{}@$"
#define AutomateValidLabelFirstDefinition ".ABCDEFGHIJKLMNOPQRSTUVWXYZ_@"
@@ -1069,7 +1229,83 @@ unsigned char *LZ4_crunch(unsigned char *data, int zelen, int *retlen){
*retlen=LZ4_compress_HC((char*)data,(char*)lzdest,zelen,65536,9);
return lzdest;
}
+#ifndef NOAPULTRA
+size_t apultra_compress(const unsigned char *pInputData, unsigned char *pOutBuffer, size_t nInputSize, size_t nMaxOutBufferSize,
+ const unsigned int nFlags, size_t nMaxWindowSize, size_t nDictionarySize, void(*progress)(long long nOriginalSize, long long nCompressedSize), void *pStats);
+size_t apultra_get_max_compressed_size(size_t nInputSize);
+
+int do_apultra(unsigned char *datain, int lenin, unsigned char **dataout, int *lenout) {
+ size_t nCompressedSize = 0L, nMaxCompressedSize;
+ int nFlags = 0;
+ //apultra_stats stats;
+ unsigned char *pCompressedData;
+
+ /* Allocate max compressed size */
+
+ nMaxCompressedSize = apultra_get_max_compressed_size(lenin);
+ pCompressedData = (unsigned char*)MemMalloc(nMaxCompressedSize);
+ memset(pCompressedData, 0, nMaxCompressedSize);
+
+ nCompressedSize = apultra_compress(datain, pCompressedData, lenin, nMaxCompressedSize, nFlags, 65536, 0 /* dico */, NULL /*compression_progress*/, NULL /*&stats*/);
+
+ if (nCompressedSize == -1) {
+ fprintf(stderr, "APULTRA compression error\n");
+ *lenout=0;
+ *dataout=NULL;
+ return 100;
+ }
+
+ *lenout=nCompressedSize;
+ *dataout=pCompressedData;
+ return 0;
+}
+int APULTRA_crunch(unsigned char *data, int len, unsigned char **dataout, int *lenout) {
+ return do_apultra(data, len, dataout, lenout);
+}
+
+
+size_t lzsa_compress_inmem(unsigned char *pInputData, unsigned char *pOutBuffer, size_t nInputSize, size_t nMaxOutBufferSize,
+ const unsigned int nFlags, const int nMinMatchSize, const int nFormatVersion);
+
+int LZSA_crunch(unsigned char *datain, int lenin, unsigned char **dataout, int *lenout, int version, int matchsize) {
+ size_t nCompressedSize = 0L, nMaxCompressedSize;
+ int nFlags = 0;
+ unsigned char *pCompressedData;
+
+pCompressedData=(unsigned char *)MemMalloc(65536);
+nMaxCompressedSize=65536;
+
+/* RAW */
+nFlags=1<<1; // nFlags=LZSA_FLAG_RAW_BLOCK;
+/* par défaut du LZSA1-Fast */
+if (version<1 || version>2) {
+ version=1;
+}
+if (matchsize<2 || matchsize>5) {
+ switch (version) {
+ case 1:matchsize=5;break;
+ case 2:matchsize=2;break;
+ default:break;
+ }
+}
+
+nCompressedSize=lzsa_compress_inmem(datain, pCompressedData, lenin, nMaxCompressedSize, nFlags, matchsize, version);
+
+ if (nCompressedSize == -1) {
+ fprintf(stderr, "LZSA compression error\n");
+ *lenout=0;
+ *dataout=NULL;
+ return 100;
+ }
+
+ *lenout=nCompressedSize;
+ *dataout=pCompressedData;
+ return 0;
+}
+
+#endif
#endif
+
unsigned char *LZ48_encode_legacy(unsigned char *data, int length, int *retlength);
#define LZ48_crunch LZ48_encode_legacy
unsigned char *LZ49_encode_legacy(unsigned char *data, int length, int *retlength);
@@ -1095,7 +1331,7 @@ unsigned char *_internal_readbinaryfile(char *filename, int *filelength)
}
return binary_data;
}
-char **_internal_readtextfile(char *filename, char replacechar)
+char **_internal_readtextfile(struct s_assenv *ae,char *filename, char replacechar)
{
#undef FUNC
#define FUNC "_internal_readtextfile"
@@ -1138,12 +1374,17 @@ char **_internal_readtextfile(char *filename, char replacechar)
} else {
lines_buffer[nb_lines]=NULL;
}
- MemFree(bigbuffer);
+
+ if (ae->enforce_symbol_case && replacechar==':') {
+ ae->source_bigbuffer=bigbuffer;
+ ae->source_bigbuffer_len=file_size;
+ }
+ //MemFree(bigbuffer);
return lines_buffer;
}
-#define FileReadLines(filename) _internal_readtextfile(filename,':')
-#define FileReadLinesRAW(filename) _internal_readtextfile(filename,0x0D)
+#define FileReadLines(ae,filename) _internal_readtextfile(ae,filename,':')
+#define FileReadLinesRAW(ae,filename) _internal_readtextfile(ae,filename,0x0D)
#define FileReadContent(filename,filesize) _internal_readbinaryfile(filename,filesize)
@@ -1307,6 +1548,16 @@ int _internal_LevenshteinDistance(char *s, char *t)
return r;
}
+unsigned int FastRand()
+{
+ #undef FUNC
+ #define FUNC "FastRand"
+ static unsigned int zeseed=0x12345678;
+ zeseed=214013*zeseed+2531011;
+ return (zeseed>>16)&0x7FFF;
+}
+
+
#ifdef RASM_THREAD
/*
threads used for crunching
@@ -1509,9 +1760,9 @@ printf("filename=[%s]\n",filename);
}
-char *GetPath(char *filename) {
+char *rasm_GetPath(char *filename) {
#undef FUNC
- #define FUNC "GetPath"
+ #define FUNC "rasm_GetPath"
static char curpath[PATH_MAX];
int zelen,idx;
@@ -1557,7 +1808,7 @@ char *MergePath(struct s_assenv *ae,char *dadfilename, char *filename) {
#define FUNC "MergePath"
static char curpath[PATH_MAX];
- int zelen;
+
#ifdef OS_WIN
TxtReplace(filename,"/","\\",1);
@@ -1570,10 +1821,10 @@ char *MergePath(struct s_assenv *ae,char *dadfilename, char *filename) {
exit(-111);
} else {
if (filename[0]=='.' && filename[1]=='\\') {
- strcpy(curpath,GetPath(dadfilename));
+ strcpy(curpath,rasm_GetPath(dadfilename));
strcat(curpath,filename+2);
} else {
- strcpy(curpath,GetPath(dadfilename));
+ strcpy(curpath,rasm_GetPath(dadfilename));
strcat(curpath,filename);
}
}
@@ -1582,10 +1833,10 @@ char *MergePath(struct s_assenv *ae,char *dadfilename, char *filename) {
/* chemin absolu */
strcpy(curpath,filename);
} else if (filename[0]=='.' && filename[1]=='/') {
- strcpy(curpath,GetPath(dadfilename));
+ strcpy(curpath,rasm_GetPath(dadfilename));
strcat(curpath,filename+2);
} else {
- strcpy(curpath,GetPath(dadfilename));
+ strcpy(curpath,rasm_GetPath(dadfilename));
strcat(curpath,filename);
}
#endif
@@ -1603,7 +1854,7 @@ void InitAutomate(char *autotab, const unsigned char *def)
memset(autotab,0,256);
for (i=0;def[i];i++) {
- autotab[(int)def[i]]=1;
+ autotab[(unsigned int)def[i]]=1;
}
}
void StateMachineResizeBuffer(char **ABuf, int idx, int *ASize) {
@@ -1633,6 +1884,8 @@ int GetCRC(char *label)
return crc;
}
+int IsDirective(char *expr);
+
int IsRegister(char *zeexpression)
{
#undef FUNC
@@ -1689,12 +1942,14 @@ int StringIsMem(char *w)
break;
case '(':p++;break;
case ')':p--;
+ /* si on sort de la première parenthèse */
if (!p && w[idx+1]) return 0;
break;
default:break;
}
idx++;
}
+ /* si on ne termine pas par une parenthèse */
if (w[idx-1]!=')') return 0;
} else {
return 0;
@@ -1702,6 +1957,8 @@ int StringIsMem(char *w)
return 1;
}
+
+
int StringIsQuote(char *w)
{
#undef FUNC
@@ -1863,7 +2120,7 @@ void MakeError(struct s_assenv *ae, char *filename, int line, char *format, ...)
}
#endif
if (myalloc<1) {
- /* do not crash */
+ /* does not crash */
return;
}
@@ -1878,126 +2135,245 @@ void MakeError(struct s_assenv *ae, char *filename, int line, char *format, ...)
va_end(argptr);
} else {
fprintf(stdout,KERROR);
- va_start(argptr,format);
if (filename && line) {
printf("[%s:%d] ",filename,line);
} else if (filename) {
printf("[%s] ",filename);
}
+ va_start(argptr,format);
vfprintf(stdout,format,argptr);
va_end(argptr);
fprintf(stdout,KNORMAL);
}
}
-
-/* convert v double value to Amstrad REAL */
-unsigned char *__internal_MakeAmsdosREAL(struct s_assenv *ae, double v, int iexpression)
+/* convert v double value to Microsoft REAL
+ *
+ * https://en.wikipedia.org/wiki/Microsoft_Binary_Format
+ *
+ * exponent:8
+ * sign:1
+ * mantiss:23
+ *
+ * */
+unsigned char *__internal_MakeRosoftREAL(struct s_assenv *ae, double v, int iexpression)
{
#undef FUNC
- #define FUNC "__internal_MakeAmsdosREAL"
+ #define FUNC "__internal_MakeRosoftREAL"
- static unsigned char rc[5];
-
- double tmpval;
- int j,ib,ibb,exp=0;
- unsigned int deci;
+ static unsigned char orc[5]={0};
+ unsigned char rc[5]={0};
+ int j,ib,ibb;
int fracmax=0;
- double frac;
int mesbits[32];
- int ibit=0;
- unsigned int mask;
+ int ibit=0,exp=0;
+ // v2
+ unsigned long mantissa;
+ unsigned long deci;
+ unsigned long mask;
+ int isneg;
- memset(rc,0,sizeof(rc));
+ if (v<0.0) {isneg=1;v=-v;} else isneg=0;
- deci=fabs(floor(v));
- frac=fabs(v)-deci;
+ memset(rc,0,sizeof(rc));
+ // decimal hack
+ deci=v;
+#if TRACE_MAKEAMSDOSREAL
+printf("AmstradREAL decimal part is %s\n",doubletext);
+#endif
+ /*******************************************************************
+ values >= 1.0
+ *******************************************************************/
if (deci) {
mask=0x80000000;
+ // find first significant bit of decimal part in order to get exponent value
while (!(deci & mask)) mask=mask/2;
while (mask) {
- mesbits[ibit]=!!(deci & mask);
+ exp++;
+ mask=mask/2;
+ }
+ mantissa=v*pow(2.0,32-exp)+0.5; // 32 bits unsigned is the maximum value allowed
+ if (mantissa & 0xFF00000000L) mantissa=0xFFFFFFFF;
#if TRACE_MAKEAMSDOSREAL
-printf("%d",mesbits[ibit]);
+printf("decimal part has %d bits\n",exp);
+printf("32 bits mantissa is %lu\n",mantissa);
#endif
+ mask=0x80000000;
+ while (mask) {
+ mesbits[ibit]=!!(mantissa & mask);
ibit++;
mask=mask/2;
}
+ } else {
+ /*******************************************************************
+ negative exponent or zero
+ *******************************************************************/
+ /* handling zero special case */
+ if (v==0.0) {
+ exp=-128;
+ ibit=0;
+ } else {
+ mantissa=(v*4294967296.0+0.5); // as v is ALWAYS <1.0 we never reach the 32 bits maximum
+ if (mantissa & 0xFF00000000L) mantissa=0xFFFFFFFF;
+ mask=0x80000000;
#if TRACE_MAKEAMSDOSREAL
-printf("\nexposant positif: %d\n",ibit);
+printf("32 bits mantissa for fraction is %lu\n",mantissa);
#endif
- exp=ibit;
+ // find first significant bit of fraction part
+ while (!(mantissa & mask)) {
+ mask=mask/2;
+ exp--;
+ }
+
+ mantissa=(v*pow(2.0,32-exp)+0.5); // as v is ALWAYS <1.0 we never reach the 32 bits maximum
+ if (mantissa & 0xFF00000000L) mantissa=0xFFFFFFFF;
+ mask=0x80000000;
+
+ while (mask && ibit<32) {
+ mesbits[ibit]=!!(mantissa & mask);
+ ibit++;
+ mask=mask/2;
+ }
+ }
#if TRACE_MAKEAMSDOSREAL
-printf(".");
+printf("\n%d bits used for mantissa\n",ibit);
#endif
- while (ibit<32 && frac!=0) {
- frac=frac*2;
- if (frac>=1.0) {
- mesbits[ibit++]=1;
+ }
+
+ /* pack bits */
+ ib=3;ibb=0x80;
+ for (j=0;j<ibit;j++) {
+ if (mesbits[j]) rc[ib]|=ibb;
+ ibb>>=1;
+ if (ibb==0) {
+ ibb=0x80;
+ ib--;
+ }
+ }
+ /* exponent */
+ exp+=128;
+ if (exp<0 || exp>255) {
+ if (iexpression) MakeError(ae,GetExpFile(ae,iexpression),ae->wl[ae->expression[iexpression].iw].l,"Exponent overflow\n");
+ else MakeError(ae,GetExpFile(ae,0),ae->wl[ae->idx].l,"Exponent overflow\n");
+ exp=128;
+ }
+ rc[4]=exp;
+
+ /* Microsoft REAL sign */
+ if (!isneg) {
+ rc[3]&=0x7F;
+ } else {
+ rc[3]|=0x80;
+ }
+
+ /* switch byte order */
+ orc[0]=rc[4];
+ orc[1]=rc[3];
+ orc[2]=rc[2];
+ orc[3]=rc[1];
+ orc[4]=rc[0];
+
#if TRACE_MAKEAMSDOSREAL
-printf("1");
+ for (j=0;j<5;j++) printf("%02X ",orc[j]);
+ printf("\n");
#endif
- frac-=1.0;
- } else {
- mesbits[ibit++]=0;
+
+ return orc;
+}
+
+
+/* convert v double value to Amstrad REAL
+ *
+ * http://www.cpcwiki.eu/index.php?title=Technical_information_about_Locomotive_BASIC&mobileaction=toggle_view_desktop#Floating_Point_data_definition
+ *
+ * exponent:8
+ * sign:1
+ * mantiss:23
+ *
+ * */
+unsigned char *__internal_MakeAmsdosREAL(struct s_assenv *ae, double v, int iexpression)
+{
+ #undef FUNC
+ #define FUNC "__internal_MakeAmsdosREAL"
+
+ static unsigned char rc[5];
+ int mesbits[32]={0}; // must be reseted!
+ int j,ib,ibb;
+ int ibit=0,exp=0;
+ // v2
+ unsigned long mantissa;
+ unsigned long deci;
+ unsigned long mask;
+ int isneg;
+
+ memset(rc,0,sizeof(rc));
+
+ if (v<0.0) {isneg=1;v=-v;} else isneg=0;
+
+ // decimal hack
+ deci=v;
#if TRACE_MAKEAMSDOSREAL
-printf("0");
+printf("AmstradREAL decimal part is %s\n",doubletext);
#endif
- }
- fracmax++;
+ /*******************************************************************
+ values >= 1.0
+ *******************************************************************/
+ if (deci) {
+ mask=0x80000000;
+ // find first significant bit of decimal part in order to get exponent value
+ while (!(deci & mask)) mask=mask/2;
+ while (mask) {
+ exp++;
+ mask=mask/2;
}
- } else {
+ mantissa=v*pow(2.0,32-exp)+0.5; // 32 bits unsigned is the maximum value allowed
+ if (mantissa & 0xFF00000000L) mantissa=0xFFFFFFFF;
#if TRACE_MAKEAMSDOSREAL
-printf("\nexposant negatif a definir:\n");
-printf("x.");
+printf("decimal part has %d bits\n",exp);
+printf("32 bits mantissa is %lu\n",mantissa);
#endif
-
- /* handling zero */
- if (frac==0.0) {
- exp=0;
- ibit=0;
+ mask=0x80000000;
+ while (mask) {
+ mesbits[ibit]=!!(mantissa & mask);
+ ibit++;
+ mask=mask/2;
+ }
+ } else {
+ /*******************************************************************
+ negative exponent or zero
+ *******************************************************************/
+ /* handling zero special case */
+ if (v==0.0) {
+ exp=-128;
} else {
- /* looking for first significant bit */
- while (1) {
- frac=frac*2;
- if (frac>=1.0) {
- mesbits[ibit++]=1;
+ mantissa=(v*4294967296.0+0.5); // as v is ALWAYS <1.0 we never reach the 32 bits maximum
+ if (mantissa & 0xFF00000000L) mantissa=0xFFFFFFFF;
+ mask=0x80000000;
#if TRACE_MAKEAMSDOSREAL
-printf("1");
+printf("32 bits mantissa for fraction is %lu\n",mantissa);
#endif
- frac-=1.0;
- break; /* first significant bit found, now looking for limit */
- } else {
-#if TRACE_MAKEAMSDOSREAL
-printf("o");
-#endif
- }
- fracmax++;
+ // find first significant bit of fraction part
+ while (!(mantissa & mask)) {
+ mask=mask/2;
exp--;
}
- while (ibit<32 && frac!=0) {
- frac=frac*2;
- if (frac>=1.0) {
- mesbits[ibit++]=1;
-#if TRACE_MAKEAMSDOSREAL
-printf("1");
-#endif
- frac-=1.0;
- } else {
- mesbits[ibit++]=0;
-#if TRACE_MAKEAMSDOSREAL
-printf("0");
-#endif
- }
- fracmax++;
+
+ mantissa=(v*pow(2.0,32-exp)+0.5); // as v is ALWAYS <1.0 we never reach the 32 bits maximum
+ if (mantissa & 0xFF00000000L) mantissa=0xFFFFFFFF;
+ mask=0x80000000;
+
+ while (mask) {
+ mesbits[ibit]=!!(mantissa & mask);
+ ibit++;
+ mask=mask/2;
}
}
- }
-
#if TRACE_MAKEAMSDOSREAL
-printf("\n%d bits utilises en mantisse\n",ibit);
+printf("\n%d bits used for mantissa\n",ibit);
#endif
+ }
+
/* pack bits */
ib=3;ibb=0x80;
for (j=0;j<ibit;j++) {
@@ -2017,8 +2393,8 @@ printf("\n%d bits utilises en mantisse\n",ibit);
}
rc[4]=exp;
- /* REAL sign */
- if (v>=0) {
+ /* REAL sign replace the most significant implied bit */
+ if (!isneg) {
rc[3]&=0x7F;
} else {
rc[3]|=0x80;
@@ -2026,7 +2402,7 @@ printf("\n%d bits utilises en mantisse\n",ibit);
#if TRACE_MAKEAMSDOSREAL
for (j=0;j<5;j++) printf("%02X ",rc[j]);
- printf("\n");
+ printf("\n------------------\n");
#endif
return rc;
@@ -2121,7 +2497,10 @@ void FreeAssenv(struct s_assenv *ae)
#ifndef RDD
/* let the system free the memory in command line except when debug/dev */
+ #ifndef __MORPHOS__
+ /* MorphOS does not like when memory is not freed before exit */
if (!ae->flux) return;
+ #endif
#endif
/*** debug info ***/
if (!ae->retdebug) {
@@ -2158,6 +2537,12 @@ void FreeAssenv(struct s_assenv *ae)
}
/*** end debug ***/
+ if (ae->enforce_symbol_case) {
+ for (i=0;i<ae->ifile;i++) {
+ if (ae->rawlen[i]) MemFree(ae->rawfile[i]);
+ }
+ }
+
for (i=0;i<ae->nbbank;i++) {
MemFree(ae->mem[i]);
}
@@ -2169,12 +2554,20 @@ void FreeAssenv(struct s_assenv *ae)
/* free labels, expression, orgzone, repeat, ... */
if (ae->mo) MemFree(ae->orgzone);
if (ae->me) {
- for (i=0;i<ae->ie;i++) if (ae->expression[i].reference) MemFree(ae->expression[i].reference);
+ for (i=0;i<ae->ie;i++) {
+ if (ae->expression[i].reference) MemFree(ae->expression[i].reference);
+ if (ae->expression[i].module) MemFree(ae->expression[i].module);
+ }
MemFree(ae->expression);
}
+ if (ae->nbsave) {
+ for (i=0;i<ae->nbsave;i++) {
+ if (ae->save[i].filename) MemFree(ae->save[i].filename);
+ }
+ }
if (ae->mh) {
for (i=0;i<ae->ih;i++) {
- MemFree(ae->hexbin[i].data);
+ //MemFree(ae->hexbin[i].data);
MemFree(ae->hexbin[i].filename);
}
MemFree(ae->hexbin);
@@ -2192,6 +2585,7 @@ void FreeAssenv(struct s_assenv *ae)
for (j=0;j<ae->rasmstruct[i].irasmstructfield;j++) {
MemFree(ae->rasmstruct[i].rasmstructfield[j].fullname);
MemFree(ae->rasmstruct[i].rasmstructfield[j].name);
+ if (ae->rasmstruct[i].rasmstructfield[j].mdata) MemFree(ae->rasmstruct[i].rasmstructfield[j].data);
}
if (ae->rasmstruct[i].mrasmstructfield) MemFree(ae->rasmstruct[i].rasmstructfield);
MemFree(ae->rasmstruct[i].name);
@@ -2230,6 +2624,22 @@ void FreeAssenv(struct s_assenv *ae)
if (ae->mmacro) MemFree(ae->macro);
+ for (i=0;i<ae->igs;i++) {
+ if (ae->globalstack[i]) MemFree(ae->globalstack[i]);
+ }
+ if (ae->mgs) MemFree(ae->globalstack);
+ if (ae->lastglobalalloc) {
+ MemFree(ae->lastgloballabel);
+ ae->lastglobalalloc=0;
+ ae->lastgloballabel=NULL;
+ }
+
+ /* external + mapping */
+ for (i=0;i<ae->nexternal;i++) {
+ if (ae->external[i].mmapping) MemFree(ae->external[i].mapping);
+ }
+ if (ae->mexternal) MemFree(ae->external);
+
for (i=0;i<ae->ialias;i++) {
MemFree(ae->alias[i].alias);
MemFree(ae->alias[i].translation);
@@ -2282,14 +2692,14 @@ void MaxError(struct s_assenv *ae)
#define FUNC "MaxError"
char **source_lines=NULL;
- int idx,crc,zeline;
- char c;
+ int zeline;
+
/* 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));
+ source_lines=FileReadLinesRAW(ae,GetCurrentFile(ae));
zeline=0;
while (zeline<ae->wl[ae->idx].l-1 && source_lines[zeline]) zeline++;
if (zeline==ae->wl[ae->idx].l-1 && source_lines[zeline]) {
@@ -2300,7 +2710,7 @@ void MaxError(struct s_assenv *ae)
FreeArrayDynamicValue(&source_lines);
}
}
-
+
ae->nberr++;
if (ae->nberr==ae->maxerr) {
rasm_printf(ae,KERROR"Too many errors!\n");
@@ -2364,7 +2774,7 @@ void ___output_set_limit(struct s_assenv *ae,int zelimit)
#undef FUNC
#define FUNC "___output_set_limit"
- int limit=65535;
+ int limit=65536;
if (zelimit<=limit) {
/* apply limit */
@@ -2373,7 +2783,7 @@ void ___output_set_limit(struct s_assenv *ae,int zelimit)
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"limit exceed hardware limitation!");
ae->stop=1;
}
- if (ae->outputadr>=0 && ae->outputadr>limit) {
+ if (ae->outputadr>=0 && ae->outputadr>=limit) {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"limit too high for current output!");
ae->stop=1;
}
@@ -2434,7 +2844,7 @@ unsigned char *MakeAMSDOSHeader(int run, int minmem, int maxmem, char *amsdos_na
AmsdosHeader[0x5D]=AmsdosHeader[24];
AmsdosHeader[0x5E]=AmsdosHeader[25];
- sprintf((char *)AmsdosHeader+0x47+17," generated by %s ",RASM_SNAP_VERSION);
+ sprintf((char *)AmsdosHeader+0x47+17," created by %-9.9s ",RASM_SNAP_VERSION);
return AmsdosHeader;
}
@@ -2456,7 +2866,7 @@ unsigned char *MakeHobetaHeader(int minmem, int maxmem, char *trdos_name) {
*/
memset(HobetaHeader,0,sizeof(HobetaHeader));
- strncpy(HobetaHeader,trdos_name,8);
+ strncpy((char*)&HobetaHeader[0],trdos_name,8);
HobetaHeader[8]='C';
HobetaHeader[0x9]=(maxmem-minmem)&0xFF;
HobetaHeader[0xA]=(maxmem-minmem)>>8;
@@ -2516,7 +2926,7 @@ int SearchAlias(struct s_assenv *ae, int crc, char *zemot)
while (ae->alias[dm].crc==crc && strcmp(ae->alias[dm].alias,zemot)) dm++;
if (ae->alias[dm].crc==crc && strcmp(ae->alias[dm].alias,zemot)==0) {
ae->alias[dm].used=1;
-//printf("found\n");
+//printf("[%s] found => [%s]\n",zemot,ae->alias[dm].translation);
return dm;
} else return -1;
} else if (ae->alias[dm].crc>crc) {
@@ -2567,7 +2977,7 @@ void CheckAndSortAliases(struct s_assenv *ae)
#define FUNC "CheckAndSortAliases"
struct s_alias tmpalias;
- int i,dw,dm,du,crc;
+ int i,dw,dm=0,du,crc;
for (i=0;i<ae->ialias-1;i++) {
/* is there previous aliases in the new alias? */
if (strstr(ae->alias[ae->ialias-1].translation,ae->alias[i].alias)) {
@@ -2729,8 +3139,10 @@ void WarnLabelTreeRecurse(struct s_assenv *ae, struct s_crclabel_tree *lt)
if (!lt->label[i].used) {
if (!lt->label[i].name) {
rasm_printf(ae,KWARNING"[%s:%d] Warning: label %s declared but not used\n",ae->filename[lt->label[i].fileidx],lt->label[i].fileline,ae->wl[lt->label[i].iw].w);
+ if (ae->erronwarn) MaxError(ae);
} else {
rasm_printf(ae,KWARNING"[%s:%d] Warning: label %s declared but not used\n",ae->filename[lt->label[i].fileidx],lt->label[i].fileline,lt->label[i].name);
+ if (ae->erronwarn) MaxError(ae);
}
}
}
@@ -2753,9 +3165,9 @@ void WarnDicoTreeRecurse(struct s_assenv *ae, struct s_crcdico_tree *lt)
#undef FUNC
#define FUNC "WarnDicoTreeRecurse"
- char symbol_line[1024];
int i;
+
for (i=0;i<256;i++) {
if (lt->radix[i]) {
WarnDicoTreeRecurse(ae,lt->radix[i]);
@@ -2764,6 +3176,7 @@ void WarnDicoTreeRecurse(struct s_assenv *ae, struct s_crcdico_tree *lt)
for (i=0;i<lt->ndico;i++) {
if (strcmp(lt->dico[i].name,"IX") && strcmp(lt->dico[i].name,"IY") && strcmp(lt->dico[i].name,"PI") && strcmp(lt->dico[i].name,"ASSEMBLER_RASM") && lt->dico[i].autorise_export) {
rasm_printf(ae,KWARNING"[%s:%d] Warning: variable %s declared but not used\n",ae->filename[ae->wl[lt->dico[i].iw].ifile],ae->wl[lt->dico[i].iw].l,lt->dico[i].name);
+ if (ae->erronwarn) MaxError(ae);
}
}
}
@@ -2803,6 +3216,42 @@ void ExportDicoTreeRecurse(struct s_crcdico_tree *lt, char *zefile, char *zeform
}
}
}
+void ExportDicoTreeRecurseCase(struct s_assenv *ae,struct s_crcdico_tree *lt, char *zefile, char *zeformat)
+{
+ #undef FUNC
+ #define FUNC "ExportDicoTreeRecurseCase"
+
+ char symbol_line[512];
+ char symbol_name[512];
+ int i;
+
+ for (i=0;i<256;i++) {
+ if (lt->radix[i]) {
+ ExportDicoTreeRecurseCase(ae,lt->radix[i],zefile,zeformat);
+ }
+ }
+ if (lt->mdico) {
+ for (i=0;i<lt->ndico;i++) {
+ if (strcmp(lt->dico[i].name,"IX") && strcmp(lt->dico[i].name,"IY") && strcmp(lt->dico[i].name,"PI") && strcmp(lt->dico[i].name,"ASSEMBLER_RASM") && lt->dico[i].autorise_export) {
+ // case search
+ char *casefound;
+ int namelen;
+
+ if ((casefound=_internal_stristr(ae->rawfile[ae->wl[lt->dico[i].iw].ifile],ae->rawlen[ae->wl[lt->dico[i].iw].ifile],lt->dico[i].name))!=NULL) {
+ namelen=strlen(lt->dico[i].name);
+ if (namelen>511) namelen=511;
+ memcpy(symbol_name,casefound,namelen);
+ symbol_name[namelen]=0;
+ snprintf(symbol_line,sizeof(symbol_line)-1,zeformat,symbol_name,(int)floor(lt->dico[i].v+0.5));
+ } else {
+ snprintf(symbol_line,sizeof(symbol_line)-1,zeformat,lt->dico[i].name,(int)floor(lt->dico[i].v+0.5));
+ }
+ symbol_line[sizeof(symbol_line)-1]=0xD;
+ FileWriteLine(zefile,symbol_line);
+ }
+ }
+ }
+}
void ExportDicoTree(struct s_assenv *ae, char *zefile, char *zeformat)
{
#undef FUNC
@@ -2810,9 +3259,17 @@ void ExportDicoTree(struct s_assenv *ae, char *zefile, char *zeformat)
int i;
- for (i=0;i<256;i++) {
- if (ae->dicotree.radix[i]) {
- ExportDicoTreeRecurse(ae->dicotree.radix[i],zefile,zeformat);
+ if (!ae->enforce_symbol_case) {
+ for (i=0;i<256;i++) {
+ if (ae->dicotree.radix[i]) {
+ ExportDicoTreeRecurse(ae->dicotree.radix[i],zefile,zeformat);
+ }
+ }
+ } else {
+ for (i=0;i<256;i++) {
+ if (ae->dicotree.radix[i]) {
+ ExportDicoTreeRecurseCase(ae,ae->dicotree.radix[i],zefile,zeformat);
+ }
}
}
}
@@ -2859,7 +3316,6 @@ struct s_expr_dico *SearchDico(struct s_assenv *ae, char *dico, int crc)
#define FUNC "SearchDico"
struct s_crcdico_tree *curdicotree;
- struct s_expr_dico *retdico=NULL;
int i,radix,dek=32;
curdicotree=&ae->dicotree;
@@ -2877,6 +3333,32 @@ struct s_expr_dico *SearchDico(struct s_assenv *ae, char *dico, int crc)
for (i=0;i<curdicotree->ndico;i++) {
if (strcmp(curdicotree->dico[i].name,dico)==0) {
curdicotree->dico[i].used=1;
+
+ if (curdicotree->dico[i].external) {
+ if (ae->external_mapping_size) {
+ /* outside crunched section of in intermediate section */
+ if (ae->lz<1 || ae->lzsection[ae->ilz-1].lzversion==0) {
+ // add mapping
+ struct s_external_mapping mapping;
+ int iex;
+ mapping.iorgzone=ae->io-1;
+ mapping.ptr=ae->outputadr;
+ mapping.size=ae->external_mapping_size;
+ for (iex=0;iex<ae->nexternal;iex++) {
+ if (ae->external[iex].crc==crc && strcmp(ae->external[iex].name,dico)==0) {
+ //printf("add mapping for [%s] ptr=%d size=%d\n",dico,mapping.ptr,mapping.size);
+ ObjectArrayAddDynamicValueConcat((void **)&ae->external[iex].mapping,&ae->external[iex].nmapping,&ae->external[iex].mmapping,&mapping,sizeof(mapping));
+ break;
+ }
+ }
+ } else {
+ MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"cannot use external variable [%s] inside a crunched section!\n",dico);
+ }
+ } else {
+ MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"invalid usage of external variable [%s]\n",dico);
+ }
+ }
+
return &curdicotree->dico[i];
}
}
@@ -2888,7 +3370,6 @@ int DelDico(struct s_assenv *ae, char *dico, int crc)
#define FUNC "DelDico"
struct s_crcdico_tree *curdicotree;
- struct s_expr_dico *retdico=NULL;
int i,radix,dek=32;
curdicotree=&ae->dicotree;
@@ -3106,7 +3587,7 @@ struct s_crclabel_tree {
-/*
+
struct s_crclabel_tree {
struct s_crclabel_tree *radix[256];
struct s_label *label;
@@ -3150,8 +3631,8 @@ struct s_label *SearchLabel(struct s_assenv *ae, char *label, int crc)
#define FUNC "SearchLabel"
struct s_crclabel_tree *curlabeltree;
- struct s_label *retlabel=NULL;
int i,radix,dek=32;
+
//printf("searchLabel [%s]",label);
curlabeltree=&ae->labeltree;
while (dek) {
@@ -3320,7 +3801,7 @@ char *TranslateTag(struct s_assenv *ae, char *varbuffer, int *touched, int enabl
char *starttag,*endtag,*tagcheck,*expr;
int newlen,lenw,taglen,tagidx,tagcount,validx;
char curvalstr[256]={0};
- char *equpos=NULL,*equback;
+
//printf("TranslateTag [%s]\n",varbuffer);
@@ -3388,6 +3869,1424 @@ char *TranslateTag(struct s_assenv *ae, char *varbuffer, int *touched, int enabl
return varbuffer;
}
+#define CRC_HALT 0xD7D1BFA1
+#define CRC_NOP 0xE1830165
+#define CRC_LDI 0xE18B3F51
+#define CRC_LDD 0xE18B3F4C
+#define CRC_DEC 0xE06BDD44
+#define CRC_INC 0xE19F3B52
+#define CRC_CPI 0xE077C754
+#define CRC_CPD 0xE077C74F
+#define CRC_BIT 0xE073D557
+#define CRC_RES 0xE1B32D62
+#define CRC_SET 0xE1B71164
+#define CRC_CCF 0xE0742D44
+#define CRC_IND 0xE19F3B53
+#define CRC_INI 0xE19F3B58
+#define CRC_DAA 0xE068253E
+#define CRC_CPL 0xE077C757
+#define CRC_EI 0x4BD5DD06
+#define CRC_DI 0x4BD5DF05
+#define CRC_IM 0x4BD5250E
+#define CRC_SCF 0xE1B72D54
+#define CRC_NEG 0xE1833D52
+#define CRC_OUTI 0xEFA5F1B9
+#define CRC_OUTD 0xEFA5F1B4
+#define CRC_OUT 0xE1871170
+#define CRC_IN 0x4BD5250F
+
+#define CRC_RLA 0xE1B31F57
+#define CRC_RLCA 0x878DAD9A
+#define CRC_RRCA 0x87A5B5A0
+#define CRC_RRA 0xE1B30B5D
+#define CRC_RLD 0xE1B31F5A
+#define CRC_RRD 0xE1B30B60
+#define CRC_RST 0xE1B30971
+#define CRC_RR 0x4BD5331C
+#define CRC_RL 0x4BD53316
+#define CRC_RRC 0xE1B30B5F
+#define CRC_RLC 0xE1B31F59
+#define CRC_SLA 0xE1B71F58
+#define CRC_SLL 0xE1B71F63
+#define CRC_SRA 0xE1B70B5E
+#define CRC_SRL 0xE1B70B69
+
+#define CRC_ADD 0xE07C2F41
+#define CRC_ADC 0xE07C2F40
+#define CRC_SBC 0xE1B72B50
+#define CRC_SUB 0xE1B77162
+#define CRC_XOR 0xE1DB3971
+#define CRC_AND 0xE07FDB4B
+#define CRC_OR 0x4BD52919
+#define CRC_CP 0x4BD5D10B
+
+#define CRC_PUSH 0x97A1EDB8
+#define CRC_POP 0xE1BB1967
+
+#define CRC_CALL 0x826B994
+#define CRC_JR 0x4BD52314
+#define CRC_JP 0x4BD52312
+#define CRC_DJNZ 0x37CD7BAE
+#define CRC_RET 0xE1B32D63
+#define CRC_RETN 0x87E9EBB1
+#define CRC_RETI 0x87E9EBAC
+
+#define CRC_LD 0x4BD52F08
+
+#define CRC_EX 0x4BD5DD15
+#define CRC_EXX 0xE06FF76D
+#define CRC_LDIR 0xF7F59DA3
+#define CRC_LDDR 0xF7F5A79E
+#define CRC_INIR 0xDFE98BAA
+#define CRC_INDR 0xDFE99DA5
+#define CRC_OTIR 0xEFB9D7B6
+#define CRC_OTDR 0xEFB9A1B1
+#define CRC_CPIR 0xFF96FA6
+#define CRC_CPDR 0xFF959A1
+
+
+
+int __GETNOP(struct s_assenv *ae,char *oplist, int didx)
+{
+ #undef FUNC
+ #define FUNC "__GETNOP"
+
+ int idx=0,crc,tick=0;
+ char **opcode=NULL;
+ char *opref;
+
+ /* upper case */
+ while (oplist[idx]) {
+ oplist[idx]=toupper(oplist[idx]);
+ idx++;
+ }
+ /* duplicata */
+ opref=TxtStrDup(oplist);
+ /* clean-up */
+ TxtReplace(opref,"\t"," ",0);
+ TxtReplace(opref," "," ",1);
+ TxtReplace(opref,": ",":",1);
+ /* simplify extended registers to XL or IX */
+ TxtReplace(opref,"IY","IX",0);
+ TxtReplace(opref,"IXL","XL",0);
+ TxtReplace(opref,"IXH","XL",0);
+ TxtReplace(opref,"LX","XL",0);
+ TxtReplace(opref,"HX","XL",0);
+ TxtReplace(opref,"LY","XL",0);
+ TxtReplace(opref,"HY","XL",0);
+ TxtReplace(opref,"YL","XL",0);
+ TxtReplace(opref,"XH","XL",0);
+ TxtReplace(opref,"YH","XL",0);
+
+ /* count opcodes */
+ opcode=TxtSplitWithChar(opref,':');
+
+ idx=0;
+ while (opcode[idx]) {
+ char *zeopcode,*terminator,*zearg=NULL;
+ char **listarg;
+
+ zeopcode=opcode[idx];
+ /* trim */
+ while (*zeopcode==' ') zeopcode++;
+ terminator=zeopcode;
+ while (*terminator!=0 && *terminator!=' ') terminator++;
+ if (*terminator) {
+ zearg=terminator+1;
+ *terminator=0;
+ /* no space in args */
+ TxtReplace(zearg," ","",1);
+ }
+ if (!zeopcode[0]) {idx++;continue;}
+ crc=GetCRC(zeopcode);
+
+ /*************************************
+ * very simple and simplified parsing *
+ *************************************/
+ switch (crc) {
+ case CRC_RLA:
+ case CRC_RLCA:
+ case CRC_RRCA:
+ case CRC_RRA:
+ case CRC_NOP:
+ case CRC_CCF:
+ case CRC_DAA:
+ case CRC_SCF:
+ case CRC_CPL:
+ case CRC_EXX:
+ case CRC_EI:
+ case CRC_DI:tick+=1;break;
+
+ case CRC_IM:
+ case CRC_NEG:tick+=2;break;
+
+ case CRC_RST:
+ case CRC_RETN:
+ case CRC_RETI:
+ case CRC_CPDR:
+ case CRC_CPIR:
+ case CRC_CPD:
+ case CRC_CPI:tick+=4;break;
+
+ case CRC_RLD:
+ case CRC_RRD:
+ case CRC_LDD:
+ case CRC_LDI:
+ case CRC_OUTI:
+ case CRC_OUTD:
+ case CRC_LDIR:
+ case CRC_LDDR:
+ case CRC_INIR:
+ case CRC_INDR:
+ case CRC_OTIR:
+ case CRC_OTDR:
+ case CRC_IND:
+ case CRC_INI:tick+=5;break;
+
+ case CRC_EX:
+ if (zearg) {
+ if (strstr(zearg,"AF") || strstr(zearg,"DE")) tick+=1; else
+ if (strstr(zearg,"(SP)") && strstr(zearg,"HL")) tick+=6; else
+ if (strstr(zearg,"(SP)") && strstr(zearg,"IX")) tick+=7;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETNOP, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ case CRC_PUSH:
+ if (zearg) {
+ if (strcmp(zearg,"IX")==0) tick+=5; else tick+=4;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETNOP, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ case CRC_POP:
+ if (zearg) {
+ if (strcmp(zearg,"IX")==0) tick+=4; else tick+=3;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETNOP, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ case CRC_SLA:
+ case CRC_SLL:
+ case CRC_SRA:
+ case CRC_SRL:
+ case CRC_RL:
+ case CRC_RLC:
+ case CRC_RR:
+ case CRC_RRC:
+ if (zearg) {
+ if (strstr(zearg,"(HL)")) tick+=4; else
+ if (strstr(zearg,"(IX")) tick+=7; else
+ tick+=2;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETNOP, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ case CRC_OUT:
+ case CRC_IN:
+ if (zearg) {
+ if (strstr(zearg,"(C)")) tick+=4; else tick+=3;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETNOP, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ case CRC_ADD:
+ if (zearg) {
+ /* simplify deprecated notation */
+ TxtReplace(zearg,"A,","",0);
+ if (strcmp(zearg,"IX,BC")==0 || strcmp(zearg,"IX,DE")==0 || strcmp(zearg,"IX,IX")==0 || strcmp(zearg,"IX,SP")==0) tick+=4; else
+ if (strcmp(zearg,"HL,BC")==0 || strcmp(zearg,"HL,DE")==0 || strcmp(zearg,"HL,HL")==0 || strcmp(zearg,"HL,SP")==0) tick+=3; else
+ if (strstr(zearg,"(HL)") || strcmp(zearg,"XL")==0) tick+=2; else
+ if (strstr(zearg,"(IX")) tick+=5; else
+ if ((*zearg>='A' && *zearg<='E') || *zearg=='H' || *zearg=='L') tick+=1; else tick+=2;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETNOP, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ /* ADC/SBC/SUB/XOR/AND/OR */
+ case CRC_ADC:
+ case CRC_SBC:
+ if (zearg) {
+ /* simplify deprecated notation */
+ TxtReplace(zearg,"A,","",0);
+ if (strcmp(zearg,"HL,BC")==0 || strcmp(zearg,"HL,DE")==0 ||strcmp(zearg,"HL,HL")==0 ||strcmp(zearg,"HL,SP")==0) {tick+=4;break;}
+ }
+ case CRC_SUB:
+ /* simplify deprecated notation */
+ TxtReplace(zearg,"A,","",0);
+ case CRC_XOR:
+ case CRC_AND:
+ case CRC_OR:
+ case CRC_CP:
+ if (zearg) {
+ if (strstr(zearg,"(HL)") || strcmp(zearg,"XL")==0) tick+=2; else
+ if (strstr(zearg,"(IX")) tick+=5; else
+ if ((*zearg>='A' && *zearg<='E') || *zearg=='H' || *zearg=='L') tick+=1; else tick+=2;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETNOP, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ /* BIT/RES/SET */
+ case CRC_BIT:
+ if (strstr(zearg,"(HL)")) tick+=3; else
+ if (strstr(zearg,"(IX")) tick+=6; else tick+=2;
+ break;
+ case CRC_RES:
+ case CRC_SET:
+ if (strstr(zearg,"(HL)")) tick+=4; else
+ if (strstr(zearg,"(IX")) tick+=7; else tick+=2;
+ break;
+ case CRC_DEC:
+ case CRC_INC:
+ if (strcmp(zearg,"XL")==0 || strcmp(zearg,"SP")==0 || strcmp(zearg,"BC")==0
+ || strcmp(zearg,"DE")==0 || strcmp(zearg,"HL")==0)
+ tick+=2;
+ else if (strcmp(zearg,"IX")==0 || strcmp(zearg,"(HL)")==0)
+ tick+=3;
+ else if (strncmp(zearg,"(IX",3)==0)
+ tick+=6;
+ else tick++;
+ break;
+ case CRC_JP:
+ // JP is supposed to loop!
+ if (zearg) {
+ if (strstr(zearg,"IX"))
+ tick+=2;
+ else if (strstr(zearg,"HL"))
+ tick+=1;
+ else tick+=3;
+ } else tick+=3;
+ break;
+ case CRC_DJNZ:
+ // DJNZ is supposed to loop!
+ case CRC_CALL:
+ // CALL is supposed to skip!
+ case CRC_JR:
+ // JR is supposed to loop!
+ tick+=3;
+ break;
+ case CRC_RET:
+ // conditionnal RET shorter because it's supposed to be the exit!
+ if (!zearg) tick+=3; else tick+=2;
+ break;
+
+ case CRC_LD:
+ /* big cake! */
+ if (zearg && strchr(zearg,',')) {
+ int crc1,crc2;
+
+ /* split args */
+ listarg=TxtSplitWithChar(zearg,',');
+ crc1=GetCRC(listarg[0]);
+ crc2=GetCRC(listarg[1]);
+
+ switch (crc1) {
+ case CRC_I:
+ case CRC_R:
+ switch (crc2) {
+ case CRC_A:
+ tick+=3;
+ break;
+ default:
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETNOP, see documentation\n",listarg[0],listarg[1]);
+ }
+ break;
+ case CRC_A:
+ case CRC_B:
+ case CRC_C:
+ case CRC_D:
+ case CRC_E:
+ case CRC_H:
+ case CRC_L:
+ switch (crc2) {
+ case CRC_A:
+ case CRC_B:
+ case CRC_C:
+ case CRC_D:
+ case CRC_E:
+ case CRC_H:
+ case CRC_L:
+ tick++;
+ break;
+ case CRC_I:
+ case CRC_R:
+ if (crc1==CRC_A) tick+=3; else
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETNOP, see documentation\n",listarg[0],listarg[1]);
+ break;
+ case CRC_MBC:
+ case CRC_MDE:
+ if (crc1!=CRC_A) {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETNOP, see documentation\n",listarg[0],listarg[1]);
+ break;
+ }
+ case CRC_XL:
+ case CRC_MHL:
+ tick+=2;
+ break;
+ default:
+ /* MIX + memory + value */
+ if (strncmp(listarg[1],"(IX",3)==0) {
+ tick+=5;
+ } else if (listarg[1][0]=='(' && listarg[1][strlen(listarg[1])-1]==')') {
+ /* memory */
+ if (crc1==CRC_A) {
+ tick+=4;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETNOP, see documentation\n",listarg[0],listarg[1]);
+ }
+ } else {
+ /* numeric value as default */
+ tick+=2;
+ }
+ }
+ break;
+
+ case CRC_XL:
+ switch (crc2) {
+ case CRC_A:
+ case CRC_B:
+ case CRC_C:
+ case CRC_D:
+ case CRC_E:
+ case CRC_H:
+ case CRC_L:
+ tick+=2;
+ break;
+ case CRC_XL:
+ tick+=2;
+ break;
+ default:
+ /* value */
+ tick+=3;
+ }
+ break;
+
+ case CRC_BC:
+ case CRC_DE:
+ /* memory / value */
+ if (listarg[1][0]=='(' && listarg[1][strlen(listarg[1])-1]==')') tick+=6; else tick+=3;
+ break;
+ case CRC_HL:
+ /* memory / value */
+ if (listarg[1][0]=='(' && listarg[1][strlen(listarg[1])-1]==')') tick+=5; else tick+=3;
+ break;
+ case CRC_SP:
+ if (crc2==CRC_HL) {
+ tick+=2;
+ } else if (crc2==CRC_IX) {
+ /* IX */
+ tick+=3;
+ } else if (listarg[1][0]=='(' && listarg[1][strlen(listarg[1])-1]==')') {
+ /* memory */
+ tick+=6;
+ } else tick+=3;
+ break;
+ case CRC_IX:
+ /* memory / value */
+ if (listarg[1][0]=='(' && listarg[1][strlen(listarg[1])-1]==')') tick+=6; else tick+=4;
+ break;
+
+ case CRC_MBC:
+ case CRC_MDE:
+ if (crc2==CRC_A) {
+ tick+=2;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETNOP, see documentation\n",listarg[0],listarg[1]);
+ }
+ break;
+ case CRC_MHL:
+ switch (crc2) {
+ case CRC_A:
+ case CRC_B:
+ case CRC_C:
+ case CRC_D:
+ case CRC_E:
+ case CRC_H:
+ case CRC_L:
+ tick+=2;
+ break;
+ default:
+ tick+=3;
+ break;
+ }
+ break;
+ default:
+ if (strncmp(listarg[0],"(IX",3)==0) {
+ /* MIX */
+ switch (crc2) {
+ case CRC_A:
+ case CRC_B:
+ case CRC_C:
+ case CRC_D:
+ case CRC_E:
+ case CRC_H:
+ case CRC_L:tick+=5;break;
+ default:tick+=6;
+ }
+ } else if (listarg[0][0]=='(' && listarg[0][strlen(listarg[0])-1]==')') {
+ /* memory */
+ switch (crc2) {
+ case CRC_A:tick+=4;break;
+ case CRC_HL:tick+=5;break;
+ case CRC_BC:
+ case CRC_DE:
+ case CRC_SP:
+ case CRC_IX:tick+=6;break;
+ default:
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETNOP, see documentation\n",listarg[0],listarg[1]);
+ }
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETNOP, see documentation\n",listarg[0],listarg[1]);
+ }
+ }
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode LD for GETNOP, need 2 arguments [%s]\n",zearg);
+ }
+ break;
+
+ default:
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETNOP, see documentation about this directive\n",opcode[idx]);
+ }
+ idx++;
+ }
+ MemFree(opref);
+ if (opcode) MemFree(opcode);
+ return tick;
+}
+int __GETTICK(struct s_assenv *ae,char *oplist, int didx)
+{
+ #undef FUNC
+ #define FUNC "__GETTICK"
+
+ int idx=0,crc,tick=0;
+ char **opcode=NULL;
+ char *opref;
+
+ /* upper case */
+ while (oplist[idx]) {
+ oplist[idx]=toupper(oplist[idx]);
+ idx++;
+ }
+ /* duplicata */
+ opref=TxtStrDup(oplist);
+ /* clean-up */
+ TxtReplace(opref,"\t"," ",0);
+ TxtReplace(opref," "," ",1);
+ TxtReplace(opref,": ",":",1);
+ /* simplify extended registers to XL or IX */
+ TxtReplace(opref,"IY","IX",0);
+ TxtReplace(opref,"IXL","XL",0);
+ TxtReplace(opref,"IXH","XL",0);
+ TxtReplace(opref,"LX","XL",0);
+ TxtReplace(opref,"HX","XL",0);
+ TxtReplace(opref,"LY","XL",0);
+ TxtReplace(opref,"HY","XL",0);
+ TxtReplace(opref,"YL","XL",0);
+ TxtReplace(opref,"XH","XL",0);
+ TxtReplace(opref,"YH","XL",0);
+
+ /* count opcodes */
+ opcode=TxtSplitWithChar(opref,':');
+
+ idx=0;
+ while (opcode[idx]) {
+ char *zeopcode,*terminator,*zearg=NULL;
+ char **listarg;
+
+ zeopcode=opcode[idx];
+ /* trim */
+ while (*zeopcode==' ') zeopcode++;
+ terminator=zeopcode;
+ while (*terminator!=0 && *terminator!=' ') terminator++;
+ if (*terminator) {
+ zearg=terminator+1;
+ *terminator=0;
+ /* no space in args */
+ TxtReplace(zearg," ","",1);
+ }
+ if (!zeopcode[0]) {idx++;continue;}
+ crc=GetCRC(zeopcode);
+
+ /*************************************
+ * very simple and simplified parsing *
+ *************************************/
+ switch (crc) {
+ case CRC_RLA:
+ case CRC_RLCA:
+ case CRC_RRCA:
+ case CRC_RRA:
+ case CRC_NOP:
+ case CRC_CCF:
+ case CRC_DAA:
+ case CRC_SCF:
+ case CRC_CPL:
+ case CRC_EXX:
+ case CRC_EI:
+ case CRC_DI:tick+=4;break;
+
+ case CRC_IM:
+ case CRC_NEG:tick+=8;break;
+
+ case CRC_RST:tick+=11;break;
+
+ case CRC_RETN:
+ case CRC_RETI:tick+=14;break;
+
+ case CRC_CPIR:
+ case CRC_CPDR:
+ case CRC_CPD:
+ case CRC_CPI:
+ case CRC_OUTI:
+ case CRC_OUTD:
+ case CRC_LDD:
+ case CRC_LDI:
+ case CRC_LDIR:
+ case CRC_LDDR:
+ case CRC_INIR:
+ case CRC_INDR:
+ case CRC_OTIR:
+ case CRC_OTDR:
+ case CRC_IND:
+ case CRC_INI:tick+=16;break;
+
+ case CRC_RLD:
+ case CRC_RRD:tick+=18;break;
+
+ case CRC_EX:
+ if (zearg) {
+ if (strstr(zearg,"AF") || strstr(zearg,"DE")) tick+=4; else
+ if (strstr(zearg,"(SP)") && strstr(zearg,"HL")) tick+=19; else
+ if (strstr(zearg,"(SP)") && strstr(zearg,"IX")) tick+=23;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETTICK, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ case CRC_PUSH:
+ if (zearg) {
+ if (strcmp(zearg,"IX")==0) tick+=15; else tick+=11;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETTICK, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ case CRC_POP:
+ if (zearg) {
+ if (strcmp(zearg,"IX")==0) tick+=14; else tick+=10;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETTICK, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ case CRC_SLA:
+ case CRC_SLL:
+ case CRC_SRA:
+ case CRC_SRL:
+ case CRC_RL:
+ case CRC_RLC:
+ case CRC_RR:
+ case CRC_RRC:
+ if (zearg) {
+ if (strstr(zearg,"(HL)")) tick+=15; else
+ if (strstr(zearg,"(IX")) tick+=23; else
+ tick+=8;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETTICK, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ case CRC_OUT:
+ if (zearg) {
+ if (strstr(zearg,"(C),")) tick+=12; else tick+=11;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETTICK, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+ case CRC_IN:
+ if (zearg) {
+ if (strstr(zearg,"(C)")) tick+=12; else tick+=11;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETTICK, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ case CRC_ADD:
+ if (zearg) {
+ /* simplify deprecated notation */
+ TxtReplace(zearg,"A,","",0);
+ if (strcmp(zearg,"IX,BC")==0 || strcmp(zearg,"IX,DE")==0 || strcmp(zearg,"IX,IX")==0 || strcmp(zearg,"IX,SP")==0) tick+=15; else
+ if (strcmp(zearg,"HL,BC")==0 || strcmp(zearg,"HL,DE")==0 || strcmp(zearg,"HL,HL")==0 || strcmp(zearg,"HL,SP")==0) tick+=11; else
+ if (strstr(zearg,"(HL)")) tick+=7; else
+ if (strstr(zearg,"(IX")) tick+=19; else
+ if (strstr(zearg,"XL")) tick+=8; else
+ if ((*zearg>='A' && *zearg<='E') || *zearg=='H' || *zearg=='L') tick+=4; else tick+=7;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETTICK, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ /* ADC/SBC/SUB/XOR/AND/OR */
+ case CRC_ADC:
+ case CRC_SBC:
+ if (zearg) {
+ /* simplify deprecated notation */
+ TxtReplace(zearg,"A,","",0);
+ if (strcmp(zearg,"HL,BC")==0 || strcmp(zearg,"HL,DE")==0 ||strcmp(zearg,"HL,HL")==0 ||strcmp(zearg,"HL,SP")==0) {tick+=15;break;}
+ }
+ case CRC_SUB:
+ if (zearg) {
+ /* simplify deprecated notation */
+ TxtReplace(zearg,"A,","",0);
+ }
+ case CRC_XOR:
+ case CRC_AND:
+ case CRC_OR:
+ case CRC_CP:
+ if (zearg) {
+ if (strstr(zearg,"(HL)")) tick+=7; else
+ if (strstr(zearg,"(IX")) tick+=19; else
+ if (strstr(zearg,"XL")) tick+=8; else
+ if ((*zearg>='A' && *zearg<='E') || *zearg=='H' || *zearg=='L') tick+=4; else tick+=7;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETTICK, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ /* BIT/RES/SET */
+ case CRC_BIT:
+ if (strstr(zearg,"(HL)")) tick+=12; else
+ if (strstr(zearg,"(IX")) tick+=20; else tick+=8;
+ break;
+ case CRC_RES:
+ case CRC_SET:
+ if (strstr(zearg,"(HL)")) tick+=15; else
+ if (strstr(zearg,"(IX")) tick+=23; else tick+=8;
+ break;
+ case CRC_DEC:
+ case CRC_INC:
+ if (strcmp(zearg,"XL")==0) tick+=8;
+ else if (strcmp(zearg,"SP")==0 || strcmp(zearg,"BC")==0 || strcmp(zearg,"DE")==0 || strcmp(zearg,"HL")==0) tick+=6;
+ else if (strcmp(zearg,"IX")==0) tick+=10;
+ else if (strcmp(zearg,"(HL)")==0) tick+=11;
+ else if (strncmp(zearg,"(IX",3)==0) tick+=23;
+ else tick+=4;
+ break;
+ case CRC_JP:
+ // JP is supposed to loop!
+ if (zearg) {
+ if (strstr(zearg,"IX"))
+ tick+=8;
+ else if (strstr(zearg,"HL"))
+ tick+=4;
+ else tick+=10;
+ } else tick+=10;
+ break;
+ case CRC_DJNZ:
+ // DJNZ is supposed to loop!
+ tick+=13;
+ break;
+ case CRC_CALL:
+ // CALL is supposed to skip!
+ tick+=10;
+ break;
+ case CRC_JR:
+ // JR is supposed to loop!
+ tick+=12;
+ break;
+ case CRC_RET:
+ // conditionnal RET shorter because it's supposed to be the exit!
+ if (!zearg) tick+=10; else tick+=5;
+ break;
+
+ case CRC_LD:
+ /* big cake! */
+ if (zearg && strchr(zearg,',')) {
+ int crc1,crc2;
+
+ /* split args */
+ listarg=TxtSplitWithChar(zearg,',');
+ crc1=GetCRC(listarg[0]);
+ crc2=GetCRC(listarg[1]);
+
+ switch (crc1) {
+ case CRC_I:
+ case CRC_R:
+ switch (crc2) {
+ case CRC_A:
+ tick+=9;
+ break;
+ default:
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETTICK, see documentation\n",listarg[0],listarg[1]);
+ }
+ break;
+ case CRC_A:
+ case CRC_B:
+ case CRC_C:
+ case CRC_D:
+ case CRC_E:
+ case CRC_H:
+ case CRC_L:
+ switch (crc2) {
+ case CRC_A:
+ case CRC_B:
+ case CRC_C:
+ case CRC_D:
+ case CRC_E:
+ case CRC_H:
+ case CRC_L:
+ tick+=4;
+ break;
+ case CRC_I:
+ case CRC_R:
+ if (crc1==CRC_A) tick+=9; else
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETTICK, see documentation\n",listarg[0],listarg[1]);
+ break;
+ case CRC_MBC:
+ case CRC_MDE:
+ if (crc1!=CRC_A) {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETTICK, see documentation\n",listarg[0],listarg[1]);
+ break;
+ }
+ case CRC_MHL:
+ tick+=7;
+ break;
+ case CRC_XL:
+ tick+=8;
+ break;
+ default:
+ /* MIX + memory + value */
+ if (strncmp(listarg[1],"(IX",3)==0) {
+ tick+=19;
+ } else if (listarg[1][0]=='(' && listarg[1][strlen(listarg[1])-1]==')') {
+ /* memory */
+ if (crc1==CRC_A) {
+ tick+=13;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETTICK, see documentation\n",listarg[0],listarg[1]);
+ }
+ } else {
+ /* numeric value as default */
+ tick+=7;
+ }
+ }
+ break;
+
+ case CRC_XL:
+ switch (crc2) {
+ case CRC_A:
+ case CRC_B:
+ case CRC_C:
+ case CRC_D:
+ case CRC_E:
+ case CRC_H:
+ case CRC_L:
+ case CRC_XL:
+ tick+=8;
+ break;
+ default:
+ /* value */
+ tick+=11;
+ }
+ break;
+
+ case CRC_BC:
+ case CRC_DE:
+ /* memory / value */
+ if (listarg[1][0]=='(' && listarg[1][strlen(listarg[1])-1]==')') tick+=20; else tick+=10;
+ break;
+ case CRC_HL:
+ /* memory / value */
+ if (listarg[1][0]=='(' && listarg[1][strlen(listarg[1])-1]==')') tick+=16; else tick+=10;
+ break;
+ case CRC_SP:
+ if (crc2==CRC_HL) {
+ tick+=6;
+ } else if (crc2==CRC_IX) {
+ /* IX */
+ tick+=10;
+ } else if (listarg[1][0]=='(' && listarg[1][strlen(listarg[1])-1]==')') {
+ /* memory */
+ tick+=20;
+ } else tick+=10;
+ break;
+ case CRC_IX:
+ /* memory / value */
+ if (listarg[1][0]=='(' && listarg[1][strlen(listarg[1])-1]==')') tick+=20; else tick+=14;
+ break;
+
+ case CRC_MBC:
+ case CRC_MDE:
+ if (crc2==CRC_A) {
+ tick+=7;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETTICK, see documentation\n",listarg[0],listarg[1]);
+ }
+ break;
+ case CRC_MHL:
+ switch (crc2) {
+ case CRC_A:
+ case CRC_B:
+ case CRC_C:
+ case CRC_D:
+ case CRC_E:
+ case CRC_H:
+ case CRC_L:
+ tick+=7;
+ break;
+ default:
+ tick+=10;
+ break;
+ }
+ break;
+ default:
+ if (strncmp(listarg[0],"(IX",3)==0) {
+ /* MIX */
+ switch (crc2) {
+ case CRC_A:
+ case CRC_B:
+ case CRC_C:
+ case CRC_D:
+ case CRC_E:
+ case CRC_H:
+ case CRC_L:tick+=19;break;
+ default:tick+=23;
+ }
+ } else if (listarg[0][0]=='(' && listarg[0][strlen(listarg[0])-1]==')') {
+ /* memory */
+ switch (crc2) {
+ case CRC_A:tick+=13;break;
+ case CRC_HL:tick+=16;break;
+ case CRC_BC:
+ case CRC_DE:
+ case CRC_SP:
+ case CRC_IX:tick+=20;break;
+ default:
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETTICK, see documentation\n",listarg[0],listarg[1]);
+ }
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETTICK, see documentation\n",listarg[0],listarg[1]);
+ }
+ }
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode LD for GETTICK, need 2 arguments [%s]\n",zearg);
+ }
+ break;
+
+ default:
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETTICK, see documentation about this directive\n",opcode[idx]);
+ }
+ idx++;
+ }
+ MemFree(opref);
+ if (opcode) MemFree(opcode);
+ return tick;
+}
+int __GETSIZE(struct s_assenv *ae,char *oplist, int didx)
+{
+ #undef FUNC
+ #define FUNC "__GETSIZE"
+
+ int idx=0,crc,osize=0;
+ char **opcode=NULL;
+ char *opref;
+
+ /* upper case */
+ while (oplist[idx]) {
+ oplist[idx]=toupper(oplist[idx]);
+ idx++;
+ }
+ /* duplicata */
+ opref=TxtStrDup(oplist);
+ /* clean-up */
+ TxtReplace(opref,"\t"," ",0);
+ TxtReplace(opref," "," ",1);
+ TxtReplace(opref,": ",":",1);
+ /* simplify extended registers to XL or IX */
+ TxtReplace(opref,"IY","IX",0);
+ TxtReplace(opref,"IXL","XL",0);
+ TxtReplace(opref,"IXH","XL",0);
+ TxtReplace(opref,"LX","XL",0);
+ TxtReplace(opref,"HX","XL",0);
+ TxtReplace(opref,"LY","XL",0);
+ TxtReplace(opref,"HY","XL",0);
+ TxtReplace(opref,"YL","XL",0);
+ TxtReplace(opref,"XH","XL",0);
+ TxtReplace(opref,"YH","XL",0);
+
+ /* count opcodes */
+ opcode=TxtSplitWithChar(opref,':');
+
+ idx=0;
+ while (opcode[idx]) {
+ char *zeopcode,*terminator,*zearg=NULL;
+ char **listarg;
+
+ zeopcode=opcode[idx];
+ /* trim */
+ while (*zeopcode==' ') zeopcode++;
+ terminator=zeopcode;
+ while (*terminator!=0 && *terminator!=' ') terminator++;
+ if (*terminator) {
+ zearg=terminator+1;
+ *terminator=0;
+ /* no space in args */
+ TxtReplace(zearg," ","",1);
+ }
+ if (!zeopcode[0]) {idx++;continue;}
+ crc=GetCRC(zeopcode);
+
+ /*************************************
+ * very simple and simplified parsing *
+ *************************************/
+ switch (crc) {
+ case CRC_HALT:
+ case CRC_RLA:
+ case CRC_RLCA:
+ case CRC_RRCA:
+ case CRC_RRA:
+ case CRC_NOP:
+ case CRC_CCF:
+ case CRC_DAA:
+ case CRC_SCF:
+ case CRC_CPL:
+ case CRC_EXX:
+ case CRC_EI:
+ case CRC_RST:
+ case CRC_RET:
+ case CRC_DI:osize+=1;break;
+
+ case CRC_OUT:
+ case CRC_IN:
+ case CRC_LDD:
+ case CRC_LDI:
+ case CRC_LDIR:
+ case CRC_LDDR:
+ case CRC_CPDR:
+ case CRC_CPIR:
+ case CRC_CPD:
+ case CRC_CPI:
+ case CRC_RETN:
+ case CRC_RETI:
+ case CRC_OUTI:
+ case CRC_OUTD:
+ case CRC_INIR:
+ case CRC_INDR:
+ case CRC_OTIR:
+ case CRC_OTDR:
+ case CRC_IND:
+ case CRC_INI:
+ case CRC_RLD:
+ case CRC_RRD:
+ case CRC_IM:
+ case CRC_DJNZ:
+ case CRC_JR:
+ case CRC_NEG:osize+=2;break;
+
+ case CRC_CALL:osize+=3;break;
+
+ case CRC_EX:
+ if (zearg) {
+ if (strstr(zearg,"AF") || strstr(zearg,"DE")) osize+=1; else
+ if (strstr(zearg,"(SP)") && strstr(zearg,"HL")) osize+=1; else
+ if (strstr(zearg,"(SP)") && strstr(zearg,"IX")) osize+=2;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETSIZE, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ case CRC_PUSH:
+ if (zearg) {
+ if (strcmp(zearg,"IX")==0) osize+=2; else osize+=1;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETSIZE, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ case CRC_POP:
+ if (zearg) {
+ if (strcmp(zearg,"IX")==0) osize+=2; else osize+=1;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETSIZE, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ case CRC_SLA:
+ case CRC_SLL:
+ case CRC_SRA:
+ case CRC_SRL:
+ case CRC_RL:
+ case CRC_RLC:
+ case CRC_RR:
+ case CRC_RRC:
+ if (zearg) {
+ if (strstr(zearg,"(HL)")) osize+=2; else
+ if (strstr(zearg,"(IX")) osize+=4; else
+ osize+=2;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETSIZE, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+
+ case CRC_ADD:
+ if (zearg) {
+ /* simplify deprecated notation */
+ TxtReplace(zearg,"A,","",0);
+ if (strcmp(zearg,"IX,")==0 || strcmp(zearg,"XL")==0) osize+=2; else
+ if (strstr(zearg,"(IX")) osize+=3; else
+ if (strstr(zearg,"HL") || (*zearg>='A' && *zearg<='E') || *zearg=='H' || *zearg=='L') osize+=1; else osize+=2;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETSIZE, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ /* ADC/SBC/SUB/XOR/AND/OR */
+ case CRC_ADC:
+ case CRC_SBC:
+ if (zearg) {
+ /* simplify deprecated notation */
+ TxtReplace(zearg,"A,","",0);
+ if (strcmp(zearg,"HL,BC")==0 || strcmp(zearg,"HL,DE")==0 || strcmp(zearg,"HL,HL")==0 || strcmp(zearg,"HL,SP")==0) {osize+=2;break;}
+ }
+ case CRC_SUB:
+ /* simplify deprecated notation */
+ TxtReplace(zearg,"A,","",0);
+ case CRC_XOR:
+ case CRC_AND:
+ case CRC_OR:
+ case CRC_CP:
+ if (zearg) {
+ if (strstr(zearg,"(IX")) osize+=3; else
+ if (strcmp(zearg,"XL")==0) osize+=2; else
+ if (strcmp(zearg,"(HL)")==0 || (*zearg>='A' && *zearg<='E') || *zearg=='H' || *zearg=='L') osize+=1; else osize+=2;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETSIZE, see documentation about this directive\n",opcode[idx]);
+ }
+ break;
+
+ /* BIT/RES/SET */
+ case CRC_BIT:
+ case CRC_RES:
+ case CRC_SET:
+ if (strstr(zearg,"(IX")) osize+=4; else osize+=2;
+ break;
+ case CRC_DEC:
+ case CRC_INC:
+ if (strcmp(zearg,"(HL)")==0 || strcmp(zearg,"SP")==0 || strcmp(zearg,"BC")==0
+ || strcmp(zearg,"DE")==0 || strcmp(zearg,"HL")==0)
+ osize+=1;
+ else if (strcmp(zearg,"IX")==0 || strcmp(zearg,"XL")==0)
+ osize+=2;
+ else if (strncmp(zearg,"(IX",3)==0)
+ osize+=3;
+ else osize++;
+ break;
+ case CRC_JP:
+ // JP is supposed to loop!
+ if (zearg) {
+ if (strstr(zearg,"IX"))
+ osize+=2;
+ else if (strstr(zearg,"HL"))
+ osize+=1;
+ else osize+=3;
+ } else osize+=3;
+ break;
+
+ case CRC_LD:
+ /* big cake! */
+ if (zearg && strchr(zearg,',')) {
+ int crc1,crc2;
+
+ /* split args */
+ listarg=TxtSplitWithChar(zearg,',');
+ crc1=GetCRC(listarg[0]);
+ crc2=GetCRC(listarg[1]);
+
+ switch (crc1) {
+ case CRC_I:
+ case CRC_R:
+ switch (crc2) {
+ case CRC_A:
+ osize+=2;
+ break;
+ default:
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETSIZE, see documentation\n",listarg[0],listarg[1]);
+ }
+ break;
+ case CRC_A:
+ case CRC_B:
+ case CRC_C:
+ case CRC_D:
+ case CRC_E:
+ case CRC_H:
+ case CRC_L:
+ switch (crc2) {
+ // heading +1
+ case CRC_MBC:
+ case CRC_MDE:
+ if (crc1!=CRC_A) {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETSIZE, see documentation\n",listarg[0],listarg[1]);
+ break;
+ }
+ case CRC_A:
+ case CRC_B:
+ case CRC_C:
+ case CRC_D:
+ case CRC_E:
+ case CRC_H:
+ case CRC_L:
+ case CRC_MHL:
+ osize++;
+ break;
+ case CRC_I:
+ case CRC_R:
+ if (crc1==CRC_A) osize+=2; else
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETSIZE, see documentation\n",listarg[0],listarg[1]);
+ break;
+ case CRC_XL:
+ osize+=2;
+ break;
+ default:
+ /* MIX + memory + value */
+ if (strncmp(listarg[1],"(IX",3)==0) {
+ osize+=3;
+ } else if (listarg[1][0]=='(' && listarg[1][strlen(listarg[1])-1]==')') {
+ /* absolute memory address */
+ if (crc1==CRC_A) {
+ osize+=3;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETSIZE, see documentation\n",listarg[0],listarg[1]);
+ }
+ } else {
+ /* numeric value as default */
+ osize+=2;
+ }
+ }
+ break;
+
+ case CRC_XL:
+ switch (crc2) {
+ case CRC_A:
+ case CRC_B:
+ case CRC_C:
+ case CRC_D:
+ case CRC_E:
+ case CRC_H:
+ case CRC_L://legal???
+ case CRC_XL:
+ osize+=2;
+ break;
+ default:
+ /* value */
+ osize+=3;
+ }
+ break;
+
+ case CRC_BC:
+ case CRC_DE:
+ /* memory / value */
+ if (listarg[1][0]=='(' && listarg[1][strlen(listarg[1])-1]==')') osize+=4; else osize+=3;
+ break;
+ case CRC_HL:
+ /* memory / value */
+ osize+=3;
+ break;
+ case CRC_SP:
+ if (crc2==CRC_HL) {
+ osize+=1;
+ } else if (crc2==CRC_IX) {
+ /* IX */
+ osize+=2;
+ } else if (listarg[1][0]=='(' && listarg[1][strlen(listarg[1])-1]==')') {
+ /* memory */
+ osize+=4;
+ } else osize+=3; /* value */
+ break;
+ case CRC_IX:
+ /* memory / value */
+ osize+=4;
+ break;
+
+ case CRC_MBC:
+ case CRC_MDE:
+ if (crc2==CRC_A) {
+ osize+=1;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETSIZE, see documentation\n",listarg[0],listarg[1]);
+ }
+ break;
+ case CRC_MHL:
+ switch (crc2) {
+ case CRC_A:
+ case CRC_B:
+ case CRC_C:
+ case CRC_D:
+ case CRC_E:
+ case CRC_H:
+ case CRC_L:
+ osize+=1;
+ break;
+ default:
+ osize+=2; /* value */
+ break;
+ }
+ break;
+ default:
+ if (strncmp(listarg[0],"(IX",3)==0) {
+ /* MIX */
+ switch (crc2) {
+ case CRC_A:
+ case CRC_B:
+ case CRC_C:
+ case CRC_D:
+ case CRC_E:
+ case CRC_H:
+ case CRC_L:osize+=3;break;
+ default:osize+=4; /* value */
+ }
+ } else if (listarg[0][0]=='(' && listarg[0][strlen(listarg[0])-1]==')') {
+ /* memory */
+ switch (crc2) {
+ case CRC_A:
+ case CRC_HL:osize+=3;break;
+ case CRC_BC:
+ case CRC_DE:
+ case CRC_SP:
+ case CRC_IX:osize+=4;break;
+ default:
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETSIZE, see documentation\n",listarg[0],listarg[1]);
+ }
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported LD %s,%s for GETSIZE, see documentation\n",listarg[0],listarg[1]);
+ }
+ }
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode LD for GETSIZE, need 2 arguments [%s]\n",zearg);
+ }
+ break;
+
+ default:
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"unsupported opcode [%s] for GETSIZE, see documentation about this directive\n",opcode[idx]);
+ }
+ idx++;
+ }
+ MemFree(opref);
+ if (opcode) MemFree(opcode);
+ return osize;
+}
+/*
+ default returned value of Duration is NOP
+ but BUILDZX usage change this to ticks!
+*/
+int __DURATION(struct s_assenv *ae,char *opcode, int didx)
+{
+ #undef FUNC
+ #define FUNC "__DURATION"
+
+ if (!ae->forcezx) return __GETNOP(ae,opcode,didx);
+ return __GETTICK(ae,opcode,didx);
+}
+int __FILESIZE(struct s_assenv *ae,char *zefile, int didx)
+{
+ #undef FUNC
+ #define FUNC "__DURATION"
+
+ FILE *f;
+ int zesize;
+
+ f=fopen(zefile,"rb");
+ if (!f) {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"cannot retrieve filesize of [%s] file\n",zefile);
+ return 0;
+ }
+ fseek(f,0,SEEK_END);
+ zesize=ftell(f);
+ fclose(f);
+ return zesize;
+}
+
+int __Soft2HardInk(struct s_assenv *ae,int soft, int didx) {
+ switch (soft) {
+ case 0:return 64+20;break;
+ case 1:return 64+4 ;break;
+ case 2:return 64+21 ;break;
+ case 3:return 64+28 ;break;
+ case 4:return 64+24 ;break;
+ case 5:return 64+29 ;break;
+ case 6:return 64+12 ;break;
+ case 7:return 64+5 ;break;
+ case 8:return 64+13 ;break;
+ case 9:return 64+22 ;break;
+ case 10:return 64+6 ;break;
+ case 11:return 64+23 ;break;
+ case 12:return 64+30 ;break;
+ case 13:return 64+0 ;break;
+ case 14:return 64+31 ;break;
+ case 15:return 64+14 ;break;
+ case 16:return 64+7 ;break;
+ case 17:return 64+15 ;break;
+ case 18:return 64+18 ;break;
+ case 19:return 64+2 ;break;
+ case 20:return 64+19 ;break;
+ case 21:return 64+26 ;break;
+ case 22:return 64+25 ;break;
+ case 23:return 64+27 ;break;
+ case 24:return 64+10 ;break;
+ case 25:return 64+3 ;break;
+ case 26:return 64+11 ;break;
+ default:
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"SOFT2HARD_INK needs 0-26 color index");
+ }
+ return 0;
+}
+int __Hard2SoftInk(struct s_assenv *ae,int hard, int didx) {
+ hard&=31;
+ switch (hard) {
+ case 0:return 13;break;
+ case 1:return 13;break;
+ case 2:return 19;break;
+ case 3:return 25;break;
+ case 4:return 1;break;
+ case 5:return 7;break;
+ case 6:return 10;break;
+ case 7:return 16;break;
+ case 8:return 7;break;
+ case 9:return 25;break;
+ case 10:return 24;break;
+ case 11:return 26;break;
+ case 12:return 6;break;
+ case 13:return 8;break;
+ case 14:return 15;break;
+ case 15:return 17;break;
+ case 16:return 1;break;
+ case 17:return 19;break;
+ case 18:return 18;break;
+ case 19:return 20;break;
+ case 20:return 0;break;
+ case 21:return 2;break;
+ case 22:return 9;break;
+ case 23:return 11;break;
+ case 24:return 4;break;
+ case 25:return 22;break;
+ case 26:return 21;break;
+ case 27:return 23;break;
+ case 28:return 3;break;
+ case 29:return 5;break;
+ case 30:return 12;break;
+ case 31:return 14;break;
+ default:/*warning remover*/
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"SOFT2HARD_INK warning remover");
+ }
+ return 0;
+}
+
double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int ptr, int didx)
{
#undef FUNC
@@ -3413,14 +5312,14 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int
/* backup alias replace */
char *zeexpression,*expr;
int original=1;
- int ialias,startvar;
+ int ialias,startvar=0;
int newlen,lenw;
/* dictionnary */
struct s_expr_dico *curdic;
struct s_label *curlabel;
- char *localname;
- int minusptr,imkey,bank,page,idxmacro;
+ int minusptr,imkey,bank,page;
double curval;
+ int is_string=0;
/* negative value */
int allow_minus_as_sign=0;
/* extended replace in labels */
@@ -3434,16 +5333,6 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int
accu=NULL;maccu=0;
if (maxcomputestack) MemFree(computestack);
computestack=NULL;maxcomputestack=0;
-#if 0
- if (maxivar) MemFree(varbuffer);
- if (maxtokenstack) MemFree(tokenstack);
- if (maxoperatorstack) MemFree(operatorstack);
- maxtokenstack=maxoperatorstack=0;
- maxivar=1;
- varbuffer=NULL;
- tokenstack=NULL;
- operatorstack=NULL;
-#endif
return 0.0;
}
@@ -3452,7 +5341,7 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int
#if TRACE_COMPUTE_EXPRESSION
- printf("expression=[%s]\n",zeexpression);
+ printf("expression=[%s]\n",original_zeexpression);
#endif
zeexpression=original_zeexpression;
if (!zeexpression[0]) {
@@ -3487,9 +5376,13 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int
memcpy(zeexpression+idx,asciivalue,3);
idx+=2;
} else {
- MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"Only single char may be quoted [%s]\n",TradExpression(zeexpression));
- zeexpression[0]=0;
- return 0;
+ //printf("Expression with => moar than one char in quotes\n");
+ //MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"Only single char may be quoted [%s]\n",TradExpression(zeexpression));
+ //zeexpression[0]=0;
+ //return 0;
+ idx++;
+ while (zeexpression[idx] && zeexpression[idx]!=c) idx++; // no escape code management
+
}
}
@@ -3507,6 +5400,21 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int
***********************************************************/
while ((c=zeexpression[idx])!=0) {
switch (c) {
+ case '"':
+ case '\'':
+ //printf("COMPUTE => string detected!\n");
+ ivar=0;
+ idx++;
+ while (zeexpression[idx] && zeexpression[idx]!=c) {
+ ae->computectx->varbuffer[ivar++]=zeexpression[idx];
+ StateMachineResizeBuffer(&ae->computectx->varbuffer,ivar,&ae->computectx->maxivar);
+ idx++;
+ }
+ if (zeexpression[idx]) idx++; else MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"ComputeExpression [%s] quote bug!\n",TradExpression(zeexpression));
+ ae->computectx->varbuffer[ivar]=0;
+ is_string=1; // donc on ira jamais utiliser startvar derriere
+ break;
+
/* parenthesis */
case ')':
/* next to a closing parenthesis, a minus is an operator */
@@ -3693,13 +5601,13 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int
}
ae->computectx->varbuffer[ivar]=0;
if (!ivar) {
- MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"invalid char (%d=%c) expression [%s]\n",c,c>31?c:' ',TradExpression(zeexpression));
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"ComputeExpression invalid char (%d=%c) expression [%s]\n",c,c>31?c:' ',TradExpression(zeexpression));
if (!original) {
MemFree(zeexpression);
}
return 0;
} else if (curly) {
- MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"wrong curly brackets in expression [%s]\n",TradExpression(zeexpression));
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"ComputeExpression wrong curly brackets in expression [%s]\n",TradExpression(zeexpression));
if (!original) {
MemFree(zeexpression);
}
@@ -3713,6 +5621,9 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int
************************************/
/* push operator or stack value */
if (!ivar) {
+#if TRACE_COMPUTE_EXPRESSION
+ printf("pushoperator [%c]\n",c);
+#endif
/************************************
O P E R A T O R
************************************/
@@ -3721,6 +5632,16 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int
MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] has unknown operator %c (%d)\n",TradExpression(zeexpression),c>31?c:'.',c);
}
/* stackelement.value isn't used */
+ stackelement.string=NULL;
+ } else if (is_string) {
+#if TRACE_COMPUTE_EXPRESSION
+ printf("pushstring [%s]\n",ae->computectx->varbuffer);
+#endif
+ stackelement.operator=E_COMPUTE_OPERATION_PUSH_DATASTC;
+ /* priority & value isn't used */
+ stackelement.string=TxtStrDup(ae->computectx->varbuffer);
+ allow_minus_as_sign=0;
+ ivar=is_string=0;
} else {
/************************************
V A L U E
@@ -3733,9 +5654,9 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int
switch (ae->computectx->varbuffer[minusptr]) {
case '0':
/* 0x hexa value hack */
- if (ae->computectx->varbuffer[minusptr+1]=='X' && ae->AutomateHexa[ae->computectx->varbuffer[minusptr+2]]) {
+ if (ae->computectx->varbuffer[minusptr+1]=='X' && ae->AutomateHexa[(int)ae->computectx->varbuffer[minusptr+2]&0xFF]) {
for (icheck=minusptr+3;ae->computectx->varbuffer[icheck];icheck++) {
- if (ae->AutomateHexa[ae->computectx->varbuffer[icheck]]) continue;
+ if (ae->AutomateHexa[(int)ae->computectx->varbuffer[icheck]&0xFF]) continue;
MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is not a valid hex number\n",TradExpression(zeexpression),ae->computectx->varbuffer);
break;
}
@@ -3773,12 +5694,12 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int
case '9':
/* check number */
for (icheck=minusptr;ae->computectx->varbuffer[icheck];icheck++) {
- if (ae->AutomateDigit[ae->computectx->varbuffer[icheck]]) continue;
+ if (ae->AutomateDigit[(int)ae->computectx->varbuffer[icheck]&0xFF]) continue;
/* Intel hexa & binary style */
switch (ae->computectx->varbuffer[strlen(ae->computectx->varbuffer)-1]) {
case 'H':
for (icheck=minusptr;ae->computectx->varbuffer[icheck+1];icheck++) {
- if (ae->AutomateHexa[ae->computectx->varbuffer[icheck]]) continue;
+ if (ae->AutomateHexa[(int)ae->computectx->varbuffer[icheck]&0xFF]) continue;
MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is not a valid hex number\n",TradExpression(zeexpression),ae->computectx->varbuffer);
}
curval=strtol(ae->computectx->varbuffer+minusptr,NULL,16);
@@ -3816,7 +5737,7 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int
MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is an empty hex number\n",TradExpression(zeexpression),ae->computectx->varbuffer);
}
for (icheck=minusptr+1;ae->computectx->varbuffer[icheck];icheck++) {
- if (ae->AutomateHexa[ae->computectx->varbuffer[icheck]]) continue;
+ if (ae->AutomateHexa[(int)ae->computectx->varbuffer[icheck]&0xFF]) continue;
MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is not a valid hex number\n",TradExpression(zeexpression),ae->computectx->varbuffer);
break;
}
@@ -3825,9 +5746,9 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int
default:
if (1 || !curlyflag) {
/* $ hex value hack */
- if (ae->computectx->varbuffer[minusptr+0]=='$' && ae->AutomateHexa[ae->computectx->varbuffer[minusptr+1]]) {
+ if (ae->computectx->varbuffer[minusptr+0]=='$' && ae->AutomateHexa[(int)ae->computectx->varbuffer[minusptr+1]&0xFF]) {
for (icheck=minusptr+2;ae->computectx->varbuffer[icheck];icheck++) {
- if (ae->AutomateHexa[ae->computectx->varbuffer[icheck]]) continue;
+ if (ae->AutomateHexa[(int)ae->computectx->varbuffer[icheck]&0xFF]) continue;
MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is not a valid hex number\n",TradExpression(zeexpression),ae->computectx->varbuffer);
break;
}
@@ -3845,10 +5766,10 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int
break;
}
/* Intel hexa value hack */
- if (ae->AutomateHexa[ae->computectx->varbuffer[minusptr+0]]) {
+ if (ae->AutomateHexa[(int)ae->computectx->varbuffer[minusptr+0]&0xFF]) {
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->AutomateHexa[(int)ae->computectx->varbuffer[icheck]&0xFF]) break;
}
if (!ae->computectx->varbuffer[icheck+1]) {
curval=strtol(ae->computectx->varbuffer+minusptr,NULL,16);
@@ -3893,7 +5814,7 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int
if (c=='(') {
/* push function as operator! */
stackelement.operator=math_keyword[imkey].operation;
- //stackelement.priority=0;
+ stackelement.string=NULL;
/************************************************
C R E A T E E X T R A T O K E N
************************************************/
@@ -3982,6 +5903,8 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int
}
} else {
MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] - %s is an unknown prefix!\n",TradExpression(zeexpression),ae->computectx->varbuffer);
+ bank=0; // on pourrait sauter le tag pour eviter la merde a suivre
+ page=0;
}
/* limited label translation while processing crunched blocks
ae->curlz == current crunched block processed
@@ -3991,10 +5914,68 @@ double ComputeExpressionCore(struct s_assenv *ae,char *original_zeexpression,int
*/
if (page!=3) {
-#if TRACE_COMPUTE_EXPRESSION
-printf("search label [%s]\n",ae->computectx->varbuffer+minusptr+bank);
+
+
+if (didx>0 && didx<ae->ie) {
+ if (ae->expression[didx].module) {
+ char *dblvarbuffer;
+#if TRACE_LABEL || TRACE_COMPUTE_EXPRESSION
+ printf("search label [%s] in an expression / module=[%s]\n",ae->computectx->varbuffer+minusptr+bank,ae->expression[didx].module);
#endif
- curlabel=SearchLabel(ae,ae->computectx->varbuffer+minusptr+bank,crc);
+ dblvarbuffer=MemMalloc(strlen(ae->computectx->varbuffer)+strlen(ae->expression[didx].module)+2);
+
+ strcpy(dblvarbuffer,ae->expression[didx].module);
+ strcat(dblvarbuffer,ae->module_separator);
+ strcat(dblvarbuffer,ae->computectx->varbuffer+minusptr+bank);
+
+ /* always try to find label from current module */
+ curlabel=SearchLabel(ae,dblvarbuffer,GetCRC(dblvarbuffer));
+ MemFree(dblvarbuffer);
+ } else {
+#if TRACE_LABEL || TRACE_COMPUTE_EXPRESSION
+ printf("search label [%s] in an expression without module\n",ae->computectx->varbuffer+minusptr+bank);
+#endif
+ curlabel=NULL;
+ }
+
+ /* pas trouvé on cherche LEGACY */
+ if (!curlabel) {
+ curlabel=SearchLabel(ae,ae->computectx->varbuffer+minusptr+bank,crc);
+#if TRACE_LABEL || TRACE_COMPUTE_EXPRESSION
+ if (curlabel) printf("label LEGACY trouve! ptr=%d\n",curlabel->ptr); else printf("label non trouve!\n");
+#endif
+ }
+#if TRACE_LABEL || TRACE_COMPUTE_EXPRESSION
+ else printf("label trouve via ajout du MODULE\n");
+#endif
+
+} else {
+#if TRACE_LABEL || TRACE_COMPUTE_EXPRESSION
+ printf("search label [%s] outside an expression taking current module!\n",ae->computectx->varbuffer+minusptr+bank);
+#endif
+ if (ae->module) {
+ char *dblvarbuffer;
+ dblvarbuffer=MemMalloc(strlen(ae->computectx->varbuffer)+strlen(ae->module)+2);
+ strcpy(dblvarbuffer,ae->module);
+ strcat(dblvarbuffer,ae->module_separator);
+ strcat(dblvarbuffer,ae->computectx->varbuffer+minusptr+bank);
+
+ /* on essaie toujours de trouver le label du module courant */
+ curlabel=SearchLabel(ae,dblvarbuffer,GetCRC(dblvarbuffer));
+ /* pas trouvé on cherche LEGACY */
+ if (!curlabel) curlabel=SearchLabel(ae,ae->computectx->varbuffer+minusptr+bank,crc);
+#if TRACE_LABEL || TRACE_COMPUTE_EXPRESSION
+ else printf("label trouve via ajout du MODULE\n");
+#endif
+
+ MemFree(dblvarbuffer);
+ } else {
+ curlabel=SearchLabel(ae,ae->computectx->varbuffer+minusptr+bank,crc);
+ }
+}
+
+
+
if (curlabel) {
if (ae->stage<2) {
if (curlabel->lz==-1) {
@@ -4033,8 +6014,8 @@ printf("page=%d | ptr=%X ibank=%d\n",page,curlabel->ptr,curlabel->ibank);
}
}
} else {
- /* label MUST be in the crunched block */
- if (curlabel->iorgzone==ae->expression[didx].iorgzone && curlabel->ibank==ae->expression[didx].ibank && curlabel->lz<=ae->expression[didx].lz) {
+ /* label MUST be intermediate OR in the crunched block */
+ if (ae->lzsection[curlabel->lz].lzversion==0 || (curlabel->iorgzone==ae->expression[didx].iorgzone && curlabel->ibank==ae->expression[didx].ibank && curlabel->lz<=ae->expression[didx].lz)) {
if (!bank) {
curval=curlabel->ptr;
} else {
@@ -4063,7 +6044,7 @@ printf("page=%d | ptr=%X ibank=%d\n",page,curlabel->ptr,curlabel->ibank);
}
break;
case 0:curval=curlabel->ibank;break;
- default:MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INTERNAL ERROR (unknown paging)\n",GetExpFile(ae,didx),GetExpLine(ae,didx));FreeAssenv(ae);exit(-664);
+ default:MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INTERNAL ERROR (unknown paging)\n");FreeAssenv(ae);exit(-664);
}
}
}
@@ -4151,19 +6132,22 @@ printf("stage 2 | page=%d | ptr=%X ibank=%d\n",page,curlabel->ptr,curlabel->iban
validx=atoi(ae->computectx->varbuffer+reverse_idx);
structlabel=TxtStrDup(ae->computectx->varbuffer+minusptr);
structlabel[reverse_idx-minusptr]=0;
-#ifdef TRACE_STRUCT
+#if TRACE_STRUCT
printf("EVOL 119 -> looking for struct %s IDX=%d\n",structlabel,validx);
#endif
/* unoptimized search in structures aliases */
crc=GetCRC(structlabel);
for (i=0;i<ae->irasmstructalias;i++) {
if (ae->rasmstructalias[i].crc==crc && strcmp(ae->rasmstructalias[i].name,structlabel)==0) {
-#ifdef TRACE_STRUCT
+#if TRACE_STRUCT
printf("EVOL 119 -> found! ptr=%d size=%d\n",ae->rasmstructalias[i].ptr,ae->rasmstructalias[i].size);
#endif
curval=ae->rasmstructalias[i].size*validx+ae->rasmstructalias[i].ptr;
if (validx>=ae->rasmstructalias[i].nbelem) {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: index out of array size!\n",GetExpFile(ae,didx),GetExpLine(ae,didx));
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: index out of array size!\n",GetExpFile(ae,didx),GetExpLine(ae,didx));
+ if (ae->erronwarn) MaxError(ae);
+ }
}
break;
}
@@ -4195,12 +6179,17 @@ printf("stage 2 | page=%d | ptr=%X ibank=%d\n",page,curlabel->ptr,curlabel->iban
if (IsRegister(ae->computectx->varbuffer+minusptr)) {
MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"cannot use register %s in this context\n",TradExpression(zeexpression));
} else {
- MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] keyword [%s] not found in variables, labels or aliases\n",TradExpression(zeexpression),ae->computectx->varbuffer+minusptr);
- if (ae->extended_error) {
- char *lookstr;
- lookstr=StringLooksLike(ae,ae->computectx->varbuffer+minusptr);
- if (lookstr) {
- rasm_printf(ae,KERROR" did you mean [%s] ?\n",lookstr);
+ if (IsDirective(ae->computectx->varbuffer+minusptr)) {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"cannot use directive %s in this context\n",TradExpression(zeexpression));
+ } else {
+
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"expression [%s] keyword [%s] not found in variables, labels or aliases\n",TradExpression(zeexpression),ae->computectx->varbuffer+minusptr);
+ if (ae->extended_error) {
+ char *lookstr;
+ lookstr=StringLooksLike(ae,ae->computectx->varbuffer+minusptr);
+ if (lookstr) {
+ rasm_printf(ae,KERROR" did you mean [%s] ?\n",lookstr);
+ }
}
}
}
@@ -4218,6 +6207,7 @@ printf("stage 2 | page=%d | ptr=%X ibank=%d\n",page,curlabel->ptr,curlabel->iban
stackelement.operator=E_COMPUTE_OPERATION_PUSH_DATASTC;
stackelement.value=curval;
/* priority isn't used */
+ stackelement.string=NULL;
allow_minus_as_sign=0;
ivar=0;
@@ -4234,7 +6224,7 @@ printf("stage 2 | page=%d | ptr=%X ibank=%d\n",page,curlabel->ptr,curlabel->iban
#if DEBUG_STACK
for (itoken=0;itoken<nbtokenstack;itoken++) {
switch (ae->computectx->tokenstack[itoken].operator) {
- case E_COMPUTE_OPERATION_PUSH_DATASTC:printf("%lf ",ae->computectx->tokenstack[itoken].value);break;
+ case E_COMPUTE_OPERATION_PUSH_DATASTC:printf("%lf %s",ae->computectx->tokenstack[itoken].value,ae->computectx->tokenstack[itoken].string?ae->computectx->tokenstack[itoken].string:"(null)");break;
case E_COMPUTE_OPERATION_OPEN:printf("(");break;
case E_COMPUTE_OPERATION_CLOSE:printf(")");break;
case E_COMPUTE_OPERATION_ADD:printf("+ ");break;
@@ -4280,6 +6270,13 @@ printf("stage 2 | page=%d | ptr=%X ibank=%d\n",page,curlabel->ptr,curlabel->iban
case E_COMPUTE_OPERATION_SET_R:printf("set_r ");break;
case E_COMPUTE_OPERATION_SET_V:printf("set_v ");break;
case E_COMPUTE_OPERATION_SET_B:printf("set_b ");break;
+ case E_COMPUTE_OPERATION_SOFT2HARD:printf("soft2hard ");break;
+ case E_COMPUTE_OPERATION_HARD2SOFT:printf("hard2soft ");break;
+ case E_COMPUTE_OPERATION_GETNOP:printf("getnop ");break;
+ case E_COMPUTE_OPERATION_GETTICK:printf("gettick ");break;
+ case E_COMPUTE_OPERATION_DURATION:printf("duration ");break;
+ case E_COMPUTE_OPERATION_FILESIZE:printf("filesize ");break;
+ case E_COMPUTE_OPERATION_GETSIZE:printf("getsize ");break;
default:printf("bug\n");break;
}
@@ -4291,14 +6288,14 @@ printf("stage 2 | page=%d | ptr=%X ibank=%d\n",page,curlabel->ptr,curlabel->iban
switch (ae->computectx->tokenstack[itoken].operator) {
case E_COMPUTE_OPERATION_PUSH_DATASTC:
#if DEBUG_STACK
-printf("data\n");
+printf("data string=%X\n",ae->computectx->tokenstack[itoken].string);
#endif
ObjectArrayAddDynamicValueConcat((void **)&computestack,&nbcomputestack,&maxcomputestack,&ae->computectx->tokenstack[itoken],sizeof(stackelement));
break;
case E_COMPUTE_OPERATION_OPEN:
ObjectArrayAddDynamicValueConcat((void **)&ae->computectx->operatorstack,&nboperatorstack,&ae->computectx->maxoperatorstack,&ae->computectx->tokenstack[itoken],sizeof(stackelement));
#if DEBUG_STACK
-printf("ajout (\n");
+printf("ajout ( string=%X\n",ae->computectx->tokenstack[itoken].string);
#endif
break;
case E_COMPUTE_OPERATION_CLOSE:
@@ -4313,7 +6310,7 @@ printf("close\n");
ObjectArrayAddDynamicValueConcat((void **)&computestack,&nbcomputestack,&maxcomputestack,&ae->computectx->operatorstack[o2],sizeof(stackelement));
nboperatorstack--;
#if DEBUG_STACK
-printf("op--\n");
+printf("op-- string=%X\n",ae->computectx->operatorstack[o2].string);
#endif
o2--;
} else {
@@ -4339,7 +6336,7 @@ printf("discard )\n");
ObjectArrayAddDynamicValueConcat((void **)&computestack,&nbcomputestack,&maxcomputestack,&ae->computectx->operatorstack[o2],sizeof(stackelement));
nboperatorstack--;
#if DEBUG_STACK
-printf("pop function\n");
+printf("pop function string=%X\n",ae->computectx->operatorstack[o2].string);
#endif
}
break;
@@ -4362,13 +6359,13 @@ printf("pop function\n");
case E_COMPUTE_OPERATION_NOTEQUAL:
case E_COMPUTE_OPERATION_LOWEREQ:
case E_COMPUTE_OPERATION_GREATEREQ:
-#if DEBUG_STACK
-printf("operator\n");
-#endif
o2=nboperatorstack-1;
while (o2>=0 && ae->computectx->operatorstack[o2].operator!=E_COMPUTE_OPERATION_OPEN) {
if (ae->computectx->tokenstack[itoken].priority>=ae->computectx->operatorstack[o2].priority || ae->computectx->operatorstack[o2].operator>=E_COMPUTE_OPERATION_SIN) {
ObjectArrayAddDynamicValueConcat((void **)&computestack,&nbcomputestack,&maxcomputestack,&ae->computectx->operatorstack[o2],sizeof(stackelement));
+#if DEBUG_STACK
+printf("operator string=%X\n",ae->computectx->operatorstack[o2].string);
+#endif
nboperatorstack--;
o2--;
} else {
@@ -4401,6 +6398,13 @@ printf("operator\n");
case E_COMPUTE_OPERATION_SET_R:
case E_COMPUTE_OPERATION_SET_V:
case E_COMPUTE_OPERATION_SET_B:
+ case E_COMPUTE_OPERATION_SOFT2HARD:
+ case E_COMPUTE_OPERATION_HARD2SOFT:
+ case E_COMPUTE_OPERATION_GETNOP:
+ case E_COMPUTE_OPERATION_GETTICK:
+ case E_COMPUTE_OPERATION_DURATION:
+ case E_COMPUTE_OPERATION_FILESIZE:
+ case E_COMPUTE_OPERATION_GETSIZE:
#if DEBUG_STACK
printf("ajout de la fonction\n");
#endif
@@ -4412,6 +6416,9 @@ printf("ajout de la fonction\n");
/* pop remaining operators */
while (nboperatorstack>0) {
ObjectArrayAddDynamicValueConcat((void **)&computestack,&nbcomputestack,&maxcomputestack,&ae->computectx->operatorstack[--nboperatorstack],sizeof(stackelement));
+#if DEBUG_STACK
+printf("final POP string=%X\n",ae->computectx->operatorstack[nboperatorstack+1].string);
+#endif
}
/********************************************
@@ -4430,7 +6437,13 @@ printf("ajout de la fonction\n");
maccu=16+paccu;
accu=MemRealloc(accu,sizeof(double)*maccu);
}
- accu[paccu]=computestack[i].value;paccu++;
+ if (computestack[i].string) {
+ /* string hack */
+ accu[paccu]=i+0.1;
+ } else {
+ accu[paccu]=computestack[i].value;
+ }
+ paccu++;
break;
case E_COMPUTE_OPERATION_OPEN:
case E_COMPUTE_OPERATION_CLOSE:/* cannot happend */ break;
@@ -4445,7 +6458,8 @@ printf("ajout de la fonction\n");
case E_COMPUTE_OPERATION_SHL:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2])<<((int)accu[paccu-1]);
if (((int)accu[paccu-1])>31 || ((int)accu[paccu-1])<-31) {
if (!ae->nowarning) {
- rasm_printf(ae,KWARNING"Warning - shifting %d is architecture dependant, result forced to ZERO\n",(int)accu[paccu-1]);
+ rasm_printf(ae,KWARNING"[%s:%d] Warning - shifting %d is architecture dependant, result forced to ZERO\n",GetExpFile(ae,didx),GetExpLine(ae,didx),(int)accu[paccu-1]);
+ if (ae->erronwarn) MaxError(ae);
}
accu[paccu-2]=0;
}
@@ -4453,7 +6467,8 @@ printf("ajout de la fonction\n");
case E_COMPUTE_OPERATION_SHR:if (paccu>1) accu[paccu-2]=((int)accu[paccu-2])>>((int)accu[paccu-1]);
if (((int)accu[paccu-1])>31 || ((int)accu[paccu-1])<-31) {
if (!ae->nowarning) {
- rasm_printf(ae,KWARNING"Warning - shifting %d is architecture dependant, result forced to ZERO\n",(int)accu[paccu-1]);
+ rasm_printf(ae,KWARNING"[%s:%d] Warning - shifting %d is architecture dependant, result forced to ZERO\n",GetExpFile(ae,didx),GetExpLine(ae,didx),(int)accu[paccu-1]);
+ if (ae->erronwarn) MaxError(ae);
}
accu[paccu-2]=0;
}
@@ -4483,7 +6498,17 @@ printf("ajout de la fonction\n");
case E_COMPUTE_OPERATION_LOW:if (paccu>0) accu[paccu-1]=((int)accu[paccu-1])&0xFF;break;
case E_COMPUTE_OPERATION_HIGH:if (paccu>0) accu[paccu-1]=(((int)accu[paccu-1])&0xFF00)>>8;break;
case E_COMPUTE_OPERATION_PSG:if (paccu>0) accu[paccu-1]=ae->psgfine[((int)accu[paccu-1])&0xFF];break;
- case E_COMPUTE_OPERATION_RND:if (paccu>0) accu[paccu-1]=rand()%((int)accu[paccu-1]);break;
+ case E_COMPUTE_OPERATION_RND:if (paccu>0) {
+ int zemod;
+ zemod=(int)floor(accu[paccu-1]+0.5);
+ if (zemod>0) {
+ accu[paccu-1]=FastRand()%zemod;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"RND function needs a value greater than zero to perform a random value\n");
+ accu[paccu-1]=0;
+ }
+ }
+ break;
case E_COMPUTE_OPERATION_FRAC:if (paccu>0) accu[paccu-1]=((int)(accu[paccu-1]-(int)accu[paccu-1]));break;
case E_COMPUTE_OPERATION_CEIL:if (paccu>0) accu[paccu-1]=(int)ceil(accu[paccu-1])&workinterval;break;
case E_COMPUTE_OPERATION_GET_R:if (paccu>0) accu[paccu-1]=((((int)accu[paccu-1])&0xF0)>>4);break;
@@ -4492,7 +6517,109 @@ printf("ajout de la fonction\n");
case E_COMPUTE_OPERATION_SET_R:if (paccu>0) accu[paccu-1]=MinMaxInt(accu[paccu-1],0,15)<<4;break;
case E_COMPUTE_OPERATION_SET_V:if (paccu>0) accu[paccu-1]=MinMaxInt(accu[paccu-1],0,15)<<8;break;
case E_COMPUTE_OPERATION_SET_B:if (paccu>0) accu[paccu-1]=MinMaxInt(accu[paccu-1],0,15);break;
- default:MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"invalid computing state! (%d)\n",GetExpFile(ae,didx),GetExpLine(ae,didx),computestack[i].operator);paccu=0;
+ case E_COMPUTE_OPERATION_SOFT2HARD:if (paccu>0) accu[paccu-1]=__Soft2HardInk(ae,accu[paccu-1],didx);break;
+ case E_COMPUTE_OPERATION_HARD2SOFT:if (paccu>0) accu[paccu-1]=__Hard2SoftInk(ae,accu[paccu-1],didx);break;
+ /* functions with strings */
+ case E_COMPUTE_OPERATION_GETNOP:if (paccu>0) {
+ int integeridx;
+ integeridx=floor(accu[paccu-1]);
+
+ if (integeridx>=0 && integeridx<nbcomputestack && computestack[integeridx].string) {
+ accu[paccu-1]=__GETNOP(ae,computestack[integeridx].string,didx);
+ MemFree(computestack[integeridx].string);
+ computestack[integeridx].string=NULL;
+ } else {
+ if (integeridx>=0 && integeridx<nbcomputestack) {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"GETNOP function needs a proper string\n");
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"GETNOP internal error (wrong string index)\n");
+ }
+ }
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"GETNOP is empty\n");
+ }
+ break;
+ /* CC GETNOP */
+ case E_COMPUTE_OPERATION_GETTICK:if (paccu>0) {
+ int integeridx;
+ integeridx=floor(accu[paccu-1]);
+
+ if (integeridx>=0 && integeridx<nbcomputestack && computestack[integeridx].string) {
+ accu[paccu-1]=__GETTICK(ae,computestack[integeridx].string,didx);
+ MemFree(computestack[integeridx].string);
+ computestack[integeridx].string=NULL;
+ } else {
+ if (integeridx>=0 && integeridx<nbcomputestack) {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"GETTICK function needs a proper string\n");
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"GETTICK internal error (wrong string index)\n");
+ }
+ }
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"GETTICK is empty\n");
+ }
+ break;
+ /* CC GETNOP */
+ case E_COMPUTE_OPERATION_DURATION:if (paccu>0) {
+ int integeridx;
+ integeridx=floor(accu[paccu-1]);
+
+ if (integeridx>=0 && integeridx<nbcomputestack && computestack[integeridx].string) {
+ accu[paccu-1]=__DURATION(ae,computestack[integeridx].string,didx);
+ MemFree(computestack[integeridx].string);
+ computestack[integeridx].string=NULL;
+ } else {
+ if (integeridx>=0 && integeridx<nbcomputestack) {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"DURATION function needs a proper string\n");
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"DURATION internal error (wrong string index)\n");
+ }
+ }
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"DURATION is empty\n");
+ }
+ break;
+ case E_COMPUTE_OPERATION_FILESIZE:if (paccu>0) {
+ int integeridx;
+ integeridx=floor(accu[paccu-1]);
+
+ if (integeridx>=0 && integeridx<nbcomputestack && computestack[integeridx].string) {
+ accu[paccu-1]=__FILESIZE(ae,computestack[integeridx].string,didx);
+ MemFree(computestack[integeridx].string);
+ computestack[integeridx].string=NULL;
+ } else {
+ if (integeridx>=0 && integeridx<nbcomputestack) {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"FILESIZE function needs a proper string\n");
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"FILESIZE internal error (wrong string index)\n");
+ }
+ }
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"DURATION is empty\n");
+ }
+ break;
+ /* CC GETNOP */
+ case E_COMPUTE_OPERATION_GETSIZE:if (paccu>0) {
+ int integeridx;
+ integeridx=floor(accu[paccu-1]);
+
+ if (integeridx>=0 && integeridx<nbcomputestack && computestack[integeridx].string) {
+ accu[paccu-1]=__GETSIZE(ae,computestack[integeridx].string,didx);
+ MemFree(computestack[integeridx].string);
+ computestack[integeridx].string=NULL;
+ } else {
+ if (integeridx>=0 && integeridx<nbcomputestack) {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"GETSIZE function needs a proper string\n");
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"GETSIZE internal error (wrong string index)\n");
+ }
+ }
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"GETTICK is empty\n");
+ }
+ break;
+ /* CC GETNOP */
+ default:MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"invalid computing state! (%d)\n",computestack[i].operator);paccu=0;
}
if (!paccu) {
if (zeexpression[0]=='&') {
@@ -4510,7 +6637,7 @@ printf("ajout de la fonction\n");
int kk;
for (kk=0;kk<paccu;kk++) printf("stack[%d]=%lf\n",kk,accu[kk]);
if (computestack[i].operator==E_COMPUTE_OPERATION_PUSH_DATASTC) {
- printf("pacc=%d push %.1lf\n",paccu,computestack[i].value);
+ printf("pacc=%d push %.1lf or %s\n",paccu,computestack[i].value,computestack[i].string?computestack[i].string:"null");
} else {
printf("pacc=%d operation %s p=%d\n",paccu,computestack[i].operator==E_COMPUTE_OPERATION_MUL?"*":
computestack[i].operator==E_COMPUTE_OPERATION_ADD?"+":
@@ -4528,6 +6655,7 @@ printf("ajout de la fonction\n");
computestack[i].operator==E_COMPUTE_OPERATION_GREATEREQ?">=":
computestack[i].operator==E_COMPUTE_OPERATION_OPEN?"(":
computestack[i].operator==E_COMPUTE_OPERATION_CLOSE?")":
+ computestack[i].operator==E_COMPUTE_OPERATION_GETNOP?"getnpo":
"<autre>",computestack[i].priority);
}
#endif
@@ -4537,7 +6665,13 @@ printf("ajout de la fonction\n");
maccu=16+paccu;
accu=MemRealloc(accu,sizeof(double)*maccu);
}
- accu[paccu]=computestack[i].value;paccu++;
+ if (computestack[i].string) {
+ /* string hack */
+ accu[paccu]=i+0.1;
+ } else {
+ accu[paccu]=computestack[i].value;
+ }
+ paccu++;
break;
case E_COMPUTE_OPERATION_OPEN:
case E_COMPUTE_OPERATION_CLOSE: /* cannot happend */ break;
@@ -4553,7 +6687,8 @@ printf("ajout de la fonction\n");
case E_COMPUTE_OPERATION_SHL:if (paccu>1) accu[paccu-2]=((int)floor(accu[paccu-2]+0.5))<<((int)floor(accu[paccu-1]+0.5));
if (((int)accu[paccu-1])>31 || ((int)accu[paccu-1])<-31) {
if (!ae->nowarning) {
- rasm_printf(ae,KWARNING"Warning - shifting %d is architecture dependant, result forced to ZERO\n",(int)accu[paccu-1]);
+ rasm_printf(ae,KWARNING"[%s:%d] Warning - shifting %d is architecture dependant, result forced to ZERO\n",GetExpFile(ae,didx),GetExpLine(ae,didx),(int)accu[paccu-1]);
+ if (ae->erronwarn) MaxError(ae);
}
accu[paccu-2]=0;
}
@@ -4561,7 +6696,8 @@ printf("ajout de la fonction\n");
case E_COMPUTE_OPERATION_SHR:if (paccu>1) accu[paccu-2]=((int)floor(accu[paccu-2]+0.5))>>((int)floor(accu[paccu-1]+0.5));
if (((int)accu[paccu-1])>31 || ((int)accu[paccu-1])<-31) {
if (!ae->nowarning) {
- rasm_printf(ae,KWARNING"Warning - shifting %d is architecture dependant, result forced to ZERO\n",(int)accu[paccu-1]);
+ rasm_printf(ae,KWARNING"[%s:%d] Warning - shifting %d is architecture dependant, result forced to ZERO\n",GetExpFile(ae,didx),GetExpLine(ae,didx),(int)accu[paccu-1]);
+ if (ae->erronwarn) MaxError(ae);
}
accu[paccu-2]=0;
}
@@ -4591,7 +6727,17 @@ printf("ajout de la fonction\n");
case E_COMPUTE_OPERATION_LOW:if (paccu>0) accu[paccu-1]=((int)floor(accu[paccu-1]+0.5))&0xFF;break;
case E_COMPUTE_OPERATION_HIGH:if (paccu>0) accu[paccu-1]=(((int)floor(accu[paccu-1]+0.5))&0xFF00)>>8;break;
case E_COMPUTE_OPERATION_PSG:if (paccu>0) accu[paccu-1]=ae->psgfine[((int)floor(accu[paccu-1]+0.5))&0xFF];break;
- case E_COMPUTE_OPERATION_RND:if (paccu>0) accu[paccu-1]=rand()%((int)accu[paccu-1]);break;
+ case E_COMPUTE_OPERATION_RND:if (paccu>0) {
+ int zemod;
+ zemod=(int)floor(accu[paccu-1]+0.5);
+ if (zemod>0) {
+ accu[paccu-1]=FastRand()%zemod;
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"RND function needs a value greater than zero to perform a random value\n");
+ accu[paccu-1]=0;
+ }
+ }
+ break;
case E_COMPUTE_OPERATION_FRAC:if (paccu>0) accu[paccu-1]=modf(accu[paccu-1],&dummint);break;
case E_COMPUTE_OPERATION_CEIL:if (paccu>0) accu[paccu-1]=ceil(accu[paccu-1]);break;
case E_COMPUTE_OPERATION_GET_R:if (paccu>0) accu[paccu-1]=((((int)accu[paccu-1])&0xF0)>>4);break;
@@ -4600,7 +6746,109 @@ printf("ajout de la fonction\n");
case E_COMPUTE_OPERATION_SET_R:if (paccu>0) accu[paccu-1]=MinMaxInt(accu[paccu-1],0,15)<<4;break;
case E_COMPUTE_OPERATION_SET_V:if (paccu>0) accu[paccu-1]=MinMaxInt(accu[paccu-1],0,15)<<8;break;
case E_COMPUTE_OPERATION_SET_B:if (paccu>0) accu[paccu-1]=MinMaxInt(accu[paccu-1],0,15);break;
- default:MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"invalid computing state! (%d)\n",GetExpFile(ae,didx),GetExpLine(ae,didx),computestack[i].operator);paccu=0;
+ case E_COMPUTE_OPERATION_SOFT2HARD:if (paccu>0) accu[paccu-1]=__Soft2HardInk(ae,accu[paccu-1],didx);break;
+ case E_COMPUTE_OPERATION_HARD2SOFT:if (paccu>0) accu[paccu-1]=__Hard2SoftInk(ae,accu[paccu-1],didx);break;
+ /* functions with strings */
+ case E_COMPUTE_OPERATION_GETNOP:if (paccu>0) {
+ int integeridx;
+ integeridx=floor(accu[paccu-1]);
+
+ if (integeridx>=0 && integeridx<nbcomputestack && computestack[integeridx].string) {
+ accu[paccu-1]=__GETNOP(ae,computestack[integeridx].string,didx);
+ MemFree(computestack[integeridx].string);
+ computestack[integeridx].string=NULL;
+ } else {
+ if (integeridx>=0 && integeridx<nbcomputestack) {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"GETNOP function needs a proper string\n");
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"GETNOP internal error (wrong string index)\n");
+ }
+ }
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"GETNOP is empty\n");
+ }
+ break;
+ /* CC GETNOP */
+ case E_COMPUTE_OPERATION_GETTICK:if (paccu>0) {
+ int integeridx;
+ integeridx=floor(accu[paccu-1]);
+
+ if (integeridx>=0 && integeridx<nbcomputestack && computestack[integeridx].string) {
+ accu[paccu-1]=__GETTICK(ae,computestack[integeridx].string,didx);
+ MemFree(computestack[integeridx].string);
+ computestack[integeridx].string=NULL;
+ } else {
+ if (integeridx>=0 && integeridx<nbcomputestack) {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"GETTICK function needs a proper string\n");
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"GETTICK internal error (wrong string index)\n");
+ }
+ }
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"GETTICK is empty\n");
+ }
+ break;
+ /* CC GETNOP */
+ case E_COMPUTE_OPERATION_DURATION:if (paccu>0) {
+ int integeridx;
+ integeridx=floor(accu[paccu-1]);
+
+ if (integeridx>=0 && integeridx<nbcomputestack && computestack[integeridx].string) {
+ accu[paccu-1]=__DURATION(ae,computestack[integeridx].string,didx);
+ MemFree(computestack[integeridx].string);
+ computestack[integeridx].string=NULL;
+ } else {
+ if (integeridx>=0 && integeridx<nbcomputestack) {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"DURATION function needs a proper string\n");
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"DURATION internal error (wrong string index)\n");
+ }
+ }
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"DURATION is empty\n");
+ }
+ break;
+ case E_COMPUTE_OPERATION_FILESIZE:if (paccu>0) {
+ int integeridx;
+ integeridx=floor(accu[paccu-1]);
+
+ if (integeridx>=0 && integeridx<nbcomputestack && computestack[integeridx].string) {
+ accu[paccu-1]=__FILESIZE(ae,computestack[integeridx].string,didx);
+ MemFree(computestack[integeridx].string);
+ computestack[integeridx].string=NULL;
+ } else {
+ if (integeridx>=0 && integeridx<nbcomputestack) {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"FILESIZE function needs a proper string\n");
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"FILESIZE internal error (wrong string index)\n");
+ }
+ }
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"DURATION is empty\n");
+ }
+ break;
+ /* CC GETNOP */
+ case E_COMPUTE_OPERATION_GETSIZE:if (paccu>0) {
+ int integeridx;
+ integeridx=floor(accu[paccu-1]);
+
+ if (integeridx>=0 && integeridx<nbcomputestack && computestack[integeridx].string) {
+ accu[paccu-1]=__GETSIZE(ae,computestack[integeridx].string,didx);
+ MemFree(computestack[integeridx].string);
+ computestack[integeridx].string=NULL;
+ } else {
+ if (integeridx>=0 && integeridx<nbcomputestack) {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"GETSIZE function needs a proper string\n");
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"GETSIZE internal error (wrong string index)\n");
+ }
+ }
+ } else {
+ MakeError(ae,GetExpFile(ae,didx),GetExpLine(ae,didx),"GETTICK is empty\n");
+ }
+ break;
+ /* CC GETNOP */
+ default:MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"invalid computing state! (%d)\n",computestack[i].operator);paccu=0;
}
if (!paccu) {
if (zeexpression[0]=='&') {
@@ -4633,7 +6881,7 @@ int RoundComputeExpressionCore(struct s_assenv *ae,char *zeexpression,int ptr,in
return floor(ComputeExpressionCore(ae,zeexpression,ptr,didx)+ae->rough);
}
-void ExpressionSetDicoVar(struct s_assenv *ae,char *name, double v)
+void ExpressionSetDicoVar(struct s_assenv *ae,char *name, double v, int var_external)
{
#undef FUNC
#define FUNC "ExpressionSetDicoVar"
@@ -4644,6 +6892,7 @@ void ExpressionSetDicoVar(struct s_assenv *ae,char *name, double v)
curdic.v=v;
curdic.iw=ae->idx;
curdic.autorise_export=ae->autorise_export;
+ curdic.external=var_external;
//ObjectArrayAddDynamicValueConcat((void**)&ae->dico,&ae->idic,&ae->mdic,&curdic,sizeof(curdic));
if (SearchLabel(ae,curdic.name,curdic.crc)) {
MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"cannot create variable [%s] as there is already a label with the same name\n",name);
@@ -4658,12 +6907,12 @@ double ComputeExpression(struct s_assenv *ae,char *expr, int ptr, int didx, int
#undef FUNC
#define FUNC "ComputeExpression"
- char *ptr_exp,*ptr_exp2,backupeval;
- int crc,idic,idx=0,ialias,touched,hasformula=0;
- double v,vl;
+ char *ptr_exp,*ptr_exp2;
+ int crc,idx=0,ialias,touched;
+ double v;
struct s_alias curalias;
struct s_expr_dico *curdic;
- char *minibuffer;
+
while (!ae->AutomateExpressionDecision[((int)expr[idx])&0xFF]) idx++;
@@ -4688,7 +6937,6 @@ printf("WARNING! alias is local! [%s]\n",expr);
/* local label creation does not handle formula in tags */
curalias.alias=TranslateTag(ae,TxtStrDup(expr),&touched,0,E_TAGOPTION_NONE);
curalias.alias=MakeLocalLabel(ae,curalias.alias,NULL);
- hasformula=1;
} else if (strchr(expr,'{')) {
#if TRACE_COMPUTE_EXPRESSION
printf("WARNING! alias has tag! [%s]\n",expr);
@@ -4698,11 +6946,13 @@ printf("WARNING! alias has tag! [%s]\n",expr);
#if TRACE_COMPUTE_EXPRESSION
printf("MakeAlias (2) EXPR=[%s EQU %s]\n",expr,ptr_exp2);
#endif
- hasformula=1;
} else {
curalias.alias=TxtStrDup(expr);
}
curalias.crc=GetCRC(curalias.alias);
+ curalias.ptr=ae->codeadr;
+ curalias.lz=ae->ilz;
+
if ((ialias=SearchAlias(ae,curalias.crc,curalias.alias))>=0) {
MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"Duplicate alias [%s]\n",expr);
MemFree(curalias.alias);
@@ -4716,7 +6966,7 @@ printf("MakeAlias (2) EXPR=[%s EQU %s]\n",expr,ptr_exp2);
printf("MakeAlias (3) EXPR=[%s EQU %s]\n",expr,ptr_exp2);
printf("alias translation [%s] -> ",curalias.translation);fflush(stdout);
#endif
- ExpressionFastTranslate(ae,&curalias.translation,2); // FAST type 2
+ ExpressionFastTranslate(ae,&curalias.translation,2); // FAST type 2 replace at least $ value
#if TRACE_COMPUTE_EXPRESSION
printf("%s\n",curalias.translation);
#endif
@@ -4787,7 +7037,7 @@ printf("***********\n");
curdic=SearchDico(ae,expr,crc);
if (curdic) {
switch (operatorassignment) {
- default:printf("warning remover\n");
+ default:printf("warning remover\n");break;
case 0:curdic->v=v;break;
case '+':curdic->v+=v;ptr_exp[-1]='+';break;
case '-':curdic->v-=v;ptr_exp[-1]='-';break;
@@ -4802,6 +7052,7 @@ printf("***********\n");
if (v>31 || v<-31) {
if (!ae->nowarning) {
rasm_printf(ae,KWARNING"Warning - shifting %d is architecture dependant, result forced to ZERO\n",(int)v);
+ if (ae->erronwarn) MaxError(ae);
}
curdic->v=0;
}
@@ -4810,6 +7061,7 @@ printf("***********\n");
if (v>31 || v<-31) {
if (!ae->nowarning) {
rasm_printf(ae,KWARNING"Warning - shifting %d is architecture dependant, result forced to ZERO\n",(int)v);
+ if (ae->erronwarn) MaxError(ae);
}
curdic->v=0;
}
@@ -4821,7 +7073,7 @@ printf("***********\n");
MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"Cannot do an operator assignment on non existing variable [%s]\n",expr);
return 0;
case 0: /* assign a new variable */
- ExpressionSetDicoVar(ae,expr,v);
+ ExpressionSetDicoVar(ae,expr,v,0);
break;
}
}
@@ -4849,6 +7101,10 @@ int RoundComputeExpression(struct s_assenv *ae,char *expr, int ptr, int didx, in
ExpressionFastTranslate
purpose: translate all known symbols in an expression (especially variables acting like counters)
+
+0:
+1:
+2: (equ declaration)
*/
void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullreplace)
{
@@ -4858,9 +7114,9 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla
struct s_label *curlabel;
struct s_expr_dico *curdic;
static char *varbuffer=NULL;
- static int ivar=0,maxivar=1;
+ static int ivar,maxivar=1;
char curval[256]={0};
- int c,lenw=0,idx=0,crc,startvar,newlen,ialias,found_replace,yves,dek,reidx,lenbuf,rlen,tagoffset;
+ int c,lenw=0,idx=0,crc,startvar=0,newlen,ialias,found_replace,yves,dek,reidx,lenbuf,rlen,tagoffset;
double v;
char tmpuchar[16];
char *expr,*locallabel;
@@ -4879,6 +7135,8 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla
StateMachineResizeBuffer(&varbuffer,128,&maxivar);
expr=*ptr_expr;
+ ivar=0;
+
//printf("fast [%s]\n",expr);
while (!ae->AutomateExpressionDecision[((int)expr[idx])&0xFF]) idx++;
@@ -4899,7 +7157,7 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla
/* is there ascii char? */
while ((c=expr[idx])!=0) {
if (c=='\'' || c=='"') {
- /* echappement */
+ /* one char escape code */
if (expr[idx+1]=='\\') {
if (expr[idx+2] && expr[idx+3]==c) {
/* no charset conversion for escaped chars */
@@ -4923,13 +7181,16 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla
return;
}
} else if (expr[idx+1] && expr[idx+2]==c) {
- sprintf(tmpuchar,"#%02X",ae->charset[(int)expr[idx+1]]);
+ sprintf(tmpuchar,"#%02X",ae->charset[((unsigned int)expr[idx+1])&0xFF]);
memcpy(expr+idx,tmpuchar,3);
idx+=2;
} else {
- MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"expression [%s] - Only single char may be quoted\n",expr);
- expr[0]=0;
- return;
+ //printf("FAST => moar than one quoted char\n");
+ //MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"expression [%s] - Only single char may be quoted\n",expr);
+ //expr[0]=0;
+ //return;
+ idx++;
+ while (expr[idx] && expr[idx]!=c) idx++;
}
}
idx++;
@@ -4938,6 +7199,15 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla
idx=reidx;
while ((c=expr[idx])!=0) {
switch (c) {
+ /* string in expression */
+ case '"':
+ case '\'':
+ //printf("FAST => skip string [%s]\n",expr);
+ idx++;
+ while (expr[idx] && expr[idx]!=c) idx++;
+ if (expr[idx]) idx++;
+ ivar=0;
+ break;
/* operator / parenthesis */
case '!':
case '=':
@@ -5002,7 +7272,6 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla
if (curlyflag) {
char *minivarbuffer;
int touched;
-//printf("ExpressionFastTranslate curly\n");
minivarbuffer=TranslateTag(ae,TxtStrDup(varbuffer), &touched,0,E_TAGOPTION_NONE|(fullreplace?0:E_TAGOPTION_PRESERVE));
StateMachineResizeBuffer(&varbuffer,strlen(minivarbuffer)+1,&maxivar);
strcpy(varbuffer,minivarbuffer);
@@ -5025,31 +7294,35 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla
/******* ivar must be updated in case of label or alias following ***********/
ivar=newlen;
}
-
+
/* recherche dans dictionnaire et remplacement */
crc=GetCRC(varbuffer);
found_replace=0;
/* pour les affectations ou les tests conditionnels on ne remplace pas le dico (pour le Push oui par contre!) */
if (fullreplace) {
+//printf("ExpressionFastTranslate (full) => varbuffer=[%s] lz=%d\n",varbuffer,ae->lz);
if (varbuffer[0]=='$' && !varbuffer[1]) {
- #ifdef OS_WIN
- snprintf(curval,sizeof(curval)-1,"%d",ae->codeadr);
- newlen=strlen(curval);
- #else
- newlen=snprintf(curval,sizeof(curval)-1,"%d",ae->codeadr);
- #endif
- lenw=strlen(expr);
- if (newlen>ivar) {
- /* realloc bigger */
- expr=*ptr_expr=MemRealloc(expr,lenw+newlen-ivar+1);
- }
- if (newlen!=ivar ) {
- MemMove(expr+startvar+newlen,expr+startvar+ivar,lenw-startvar-ivar+1);
- found_replace=1;
+ if (ae->lz==-1) {
+ #ifdef OS_WIN
+ snprintf(curval,sizeof(curval)-1,"%d",ae->codeadr);
+ newlen=strlen(curval);
+ #else
+ newlen=snprintf(curval,sizeof(curval)-1,"%d",ae->codeadr);
+ #endif
+ lenw=strlen(expr);
+ if (newlen>ivar) {
+ /* realloc bigger */
+ expr=*ptr_expr=MemRealloc(expr,lenw+newlen-ivar+1);
+ }
+ if (newlen!=ivar ) {
+ MemMove(expr+startvar+newlen,expr+startvar+ivar,lenw-startvar-ivar+1);
+ found_replace=1;
+ }
+ strncpy(expr+startvar,curval,newlen); /* copy without zero terminator */
+ idx=startvar+newlen;
+ ivar=0;
}
- strncpy(expr+startvar,curval,newlen); /* copy without zero terminator */
- idx=startvar+newlen;
- ivar=0;
+ /* qu'on le remplace ou pas on passe a la suite */
found_replace=1;
} else {
curdic=SearchDico(ae,varbuffer,crc);
@@ -5079,7 +7352,7 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla
}
}
}
- /* on cherche aussi dans les labels existants */
+ /* on cherche aussi dans les labels existants => priorité aux modules!!! */ // modulmodif => pas utile?
if (!found_replace) {
curlabel=SearchLabel(ae,varbuffer,crc);
if (curlabel) {
@@ -5141,7 +7414,7 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla
}
}
if (!found_replace) {
- //printf("fasttranslate test local label\n");
+ //printf("fasttranslate test local label\n");
/* non trouve c'est peut-etre un label local - mais pas de l'octal */
if (varbuffer[0]=='@' && (varbuffer[1]<'0' || varbuffer[1]>'9')) {
char *zepoint;
@@ -5198,36 +7471,59 @@ void ExpressionFastTranslate(struct s_assenv *ae, char **ptr_expr, int fullrepla
tagoffset=0;
MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"Unknown prefix tag\n");
}
-
- if (varbuffer[tagoffset]=='@') {
+
+ if (varbuffer[tagoffset]=='.') {
+ int lenadd;
+ startvar+=tagoffset;
+ lenbuf=strlen(varbuffer+tagoffset);
+ locallabel=MakeLocalLabel(ae,varbuffer+tagoffset,NULL);
+ /*** le grand remplacement meriterait une modif pour DEK dans MakeLocalLabel ***/
+ rlen=strlen(expr+startvar+lenbuf)+1;
+ lenadd=strlen(locallabel)-strlen(varbuffer+tagoffset);
+ expr=*ptr_expr=MemRealloc(expr,strlen(expr)+lenadd+1);
+
+//printf("expr[%s] move to %d from %d len=%d\n",expr,startvar+lenadd,startvar,rlen+lenbuf);
+ MemMove(expr+startvar+lenadd,expr+startvar,rlen+lenbuf);
+ strncpy(expr+startvar,locallabel,lenadd);
+
+ MemFree(locallabel);
+ found_replace=1;
+ idx+=lenadd;
+ } else if (varbuffer[tagoffset]=='@') {
char *zepoint;
startvar+=tagoffset;
lenbuf=strlen(varbuffer+tagoffset);
//printf("MakeLocalLabel(ae,varbuffer,&dek); (3)\n");
locallabel=MakeLocalLabel(ae,varbuffer+tagoffset,&dek);
+//printf("local [%s] =>",locallabel);
/*** le grand remplacement ***/
rlen=strlen(expr+startvar+lenbuf)+1;
expr=*ptr_expr=MemRealloc(expr,strlen(expr)+dek+1);
/* move end of expression in order to insert local ID */
- zepoint=strchr(varbuffer,'.');
+ zepoint=strchr(varbuffer+tagoffset,'.'); // +tagoffset
if (zepoint) {
/* far proximity access */
int suffixlen,dotpos;
dotpos=(zepoint-varbuffer);
suffixlen=lenbuf-dotpos;
-
+ //printf("prox [%s] => ",expr);
MemMove(expr+startvar+dotpos+dek,expr+startvar+dotpos,rlen+suffixlen);
strncpy(expr+startvar+dotpos,locallabel,dek);
} else {
/* legacy */
+ //printf("legacy [%s] => ",expr);
MemMove(expr+startvar+lenbuf+dek,expr+startvar+lenbuf,rlen);
strncpy(expr+startvar+lenbuf,locallabel,dek);
}
idx+=dek;
MemFree(locallabel);
found_replace=1;
+ //printf("exprout=[%s]\n",expr);
} else if (varbuffer[tagoffset]=='$') {
int tagvalue=-1;
+ /*
+ * There is no {SLOT}$ support...
+ */
if (strcmp(varbuffer,"{BANK}$")==0) {
if (ae->forcecpr) {
if (ae->activebank<32) {
@@ -5375,11 +7671,14 @@ void PushExpression(struct s_assenv *ae,int iw,enum e_expression zetype)
curexp.ibank=ae->activebank;
curexp.iorgzone=ae->io-1;
curexp.lz=ae->lz;
+ /* need the module to know where we are */
+ if (ae->module) curexp.module=TxtStrDup(ae->module); else curexp.module=NULL;
/* on traduit de suite les variables du dictionnaire pour les boucles et increments
- SAUF si c'est une affectation */
+ SAUF si c'est une affectation
+ */
if (!ae->wl[iw].e) {
switch (zetype) {
- case E_EXPRESSION_V16C:
+ case E_EXPRESSION_J16C:
/* check non register usage */
switch (GetCRC(ae->wl[iw].w)) {
case CRC_IX:
@@ -5391,6 +7690,7 @@ void PushExpression(struct s_assenv *ae,int iw,enum e_expression zetype)
}
case E_EXPRESSION_J8:
case E_EXPRESSION_V8:
+ case E_EXPRESSION_J16:
case E_EXPRESSION_V16:
case E_EXPRESSION_IM:startptr=-1;
break;
@@ -5409,6 +7709,36 @@ void PushExpression(struct s_assenv *ae,int iw,enum e_expression zetype)
/* hack pourri pour gérer le $ */
ae->codeadr+=startptr;
/* ok mais les labels locaux des macros? */
+
+ /* if external declared then fill some informations */
+ if (ae->nexternal) {
+ switch (zetype) {
+ case E_EXPRESSION_0V8:
+ case E_EXPRESSION_V8:
+ case E_EXPRESSION_IV81:
+ case E_EXPRESSION_IV8:
+ case E_EXPRESSION_3V8:
+ ae->external_mapping_size=1;
+ break;
+ case E_EXPRESSION_J16C:
+ case E_EXPRESSION_J16:
+ case E_EXPRESSION_V16:
+ case E_EXPRESSION_0V16:
+ case E_EXPRESSION_IV16:
+ ae->external_mapping_size=2;
+ break;
+ case E_EXPRESSION_0V32:
+ ae->external_mapping_size=4;
+ break;
+ case E_EXPRESSION_0VR:
+ case E_EXPRESSION_0VRMike:
+ ae->external_mapping_size=5;
+ break;
+ default:
+ ae->external_mapping_size=0;
+ break;
+ }
+ }
if (ae->ir || ae->iw || ae->imacro) {
curexp.reference=TxtStrDup(ae->wl[iw].w);
ExpressionFastTranslate(ae,&curexp.reference,1);
@@ -5425,7 +7755,9 @@ void PushExpression(struct s_assenv *ae,int iw,enum e_expression zetype)
case E_EXPRESSION_0V16:curexp.ptr=ae->codeadr;ae->outputadr+=2;ae->codeadr+=2;break;
case E_EXPRESSION_0V32:curexp.ptr=ae->codeadr;ae->outputadr+=4;ae->codeadr+=4;break;
case E_EXPRESSION_0VR:curexp.ptr=ae->codeadr;ae->outputadr+=5;ae->codeadr+=5;break;
- case E_EXPRESSION_V16C:
+ case E_EXPRESSION_0VRMike:curexp.ptr=ae->codeadr;ae->outputadr+=5;ae->codeadr+=5;break;
+ case E_EXPRESSION_J16C:
+ case E_EXPRESSION_J16:
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;
@@ -5456,7 +7788,9 @@ void PushExpression(struct s_assenv *ae,int iw,enum e_expression zetype)
case E_EXPRESSION_0V16:ae->outputadr+=2;ae->codeadr+=2;break;
case E_EXPRESSION_0V32:ae->outputadr+=4;ae->codeadr+=4;break;
case E_EXPRESSION_0VR:ae->outputadr+=5;ae->codeadr+=5;break;
- case E_EXPRESSION_V16C:
+ case E_EXPRESSION_0VRMike:ae->outputadr+=5;ae->codeadr+=5;break;
+ case E_EXPRESSION_J16C:
+ case E_EXPRESSION_J16:
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;
@@ -5471,7 +7805,7 @@ void PushExpression(struct s_assenv *ae,int iw,enum e_expression zetype)
}
if (ae->outputadr<=ae->maxptr) {
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"NOCODE output exceed limit %d\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->maxptr);
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"NOCODE output exceed limit %d\n",ae->maxptr);
FreeAssenv(ae);exit(3);
}
}
@@ -5545,20 +7879,33 @@ int EDSK_getdirid(struct s_edsk_wrapper *curwrap) {
}
return -1;
}
-char *MakeAMSDOS_name(struct s_assenv *ae, char *filename)
+char *MakeAMSDOS_name(struct s_assenv *ae, char *reference_filename)
{
#undef FUNC
#define FUNC "MakeAMSDOS_name"
static char amsdos_name[12];
+ char *filename,*jo;
int i,ia;
char *pp;
+
+ /* remove path */
+ filename=reference_filename;
+ while ((jo=strchr(filename,'/'))!=NULL) filename=jo+1;
+ while ((jo=strchr(filename,'\\'))!=NULL) filename=jo+1;
+
/* warning */
if (strlen(filename)>12) {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"Warning - filename [%s] too long for AMSDOS, will be truncated\n",filename);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"Warning - filename [%s] too long for AMSDOS, will be truncated\n",filename);
+ if (ae->erronwarn) MaxError(ae);
+ }
} else if ((pp=strchr(filename,'.'))!=NULL) {
if (pp-filename>8) {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"Warning - filename [%s] too long for AMSDOS, will be truncated\n",filename);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"Warning - filename [%s] too long for AMSDOS, will be truncated\n",filename);
+ if (ae->erronwarn) MaxError(ae);
+ }
}
}
/* copy filename */
@@ -5618,6 +7965,7 @@ void EDSK_load(struct s_assenv *ae,struct s_edsk_wrapper *curwrap, char *edskfil
}
if (face>=sidenumber) {
rasm_printf(ae,KWARNING"[%s] Warning - DSK has no face %d - DSK updated\n",edskfilename,face);
+ if (ae->erronwarn) MaxError(ae);
return;
}
@@ -5699,6 +8047,7 @@ void EDSK_load(struct s_assenv *ae,struct s_edsk_wrapper *curwrap, char *edskfil
}
if (face>=sidenumber) {
rasm_printf(ae,KWARNING"[%s] EDSK has no face %d - DSK updated\n",edskfilename,face);
+ if (ae->erronwarn) MaxError(ae);
return;
}
@@ -5761,6 +8110,7 @@ void EDSK_load(struct s_assenv *ae,struct s_edsk_wrapper *curwrap, char *edskfil
}
if (track_sectorsize!=2) {
rasm_printf(ae,KWARNING"track %02d has invalid sector size but sectors are OK\n",t);
+ if (ae->erronwarn) MaxError(ae);
}
#if TRACE_EDSK
printf("\n");
@@ -6073,6 +8423,7 @@ void EDSK_write_file(struct s_assenv *ae,struct s_edsk_wrapper *faceA,struct s_e
struct s_edsk_wrapper emptyface={0};
unsigned char header[256]={0};
unsigned char trackblock[256]={0};
+ unsigned char headertag[25];
int idblock,blockoffset;
int i,t;
@@ -6083,7 +8434,8 @@ void EDSK_write_file(struct s_assenv *ae,struct s_edsk_wrapper *faceA,struct s_e
EDSK_build_amsdos_directory(faceB);
/* écriture header */
strcpy((char *)header,"EXTENDED CPC DSK File\r\nDisk-Info\r\n");
- strcpy((char *)header+0x22,RASM_SNAP_VERSION);
+ sprintf(headertag,"%-9.9s",RASM_SNAP_VERSION);
+ strcpy((char *)header+0x22,headertag);
header[0x30]=40;
if (!faceA) {
faceA=&emptyface;
@@ -6218,8 +8570,8 @@ void EDSK_write(struct s_assenv *ae)
#define FUNC "EDSK_write"
struct s_edsk_wrapper *faceA,*faceB;
- char *edskfilename;
int i,j;
+
/* on passe en revue toutes les structs */
for (i=0;i<ae->nbedskwrapper;i++) {
@@ -6245,6 +8597,134 @@ void EDSK_write(struct s_assenv *ae)
EDSK_write_file(ae,faceA,faceB);
}
}
+
+/* CDT output code / courtesy of CNG */
+void update11(unsigned char *head,int n,int is1st,int islast,int l, int fileload)
+{
+ head[0x10]=n;
+ head[0x11]=islast?-1:0;
+ head[0x13]=l;
+ head[0x14]=l>>8;
+ head[0x15]=fileload;
+ head[0x16]=fileload>>8;
+ head[0x17]=is1st?-1:0;
+}
+#define fputcc(x,y) { fputc((x),y); fputc((x)>>8,y); }
+#define fputccc(x,y) { fputc((x),y); fputc((x)>>8,y); fputc((x)>>16,y); }
+void record11(char *filename,unsigned char *t,int first,int l,int p, int flag_bb, int flag_b)
+{
+ FILE *fo;
+ #ifdef OS_WIN
+ fo=FileOpen(filename,"w");
+ #else
+ fo=FileOpen(filename,"a+");
+ #endif
+
+ /* almost legacy */
+ fputc(0x11,fo);
+ fputcc(flag_bb,fo);
+ fputcc(flag_b,fo);
+ fputcc(flag_b,fo);
+ fputcc(flag_b,fo);
+ fputcc(flag_bb,fo);
+ //fputcc(flag_o,fo);
+ fputcc(4096,fo); // 4K block
+ fputc(8,fo);
+ fputcc(p,fo);
+ p=1+(((l+255)/256)*258)+4; //flag_z;
+ fputccc(p,fo);
+ fputc(first,fo);
+ p=0;
+ while (l>0)
+ {
+ int crc16=0xFFFF;
+ fwrite(t+p,1,256,fo);
+ first=256;
+ while (first--) {
+ // early CRC-16-CCITT as used by Amstrad
+ int xor8=(t[p++]<<8)+1;
+ while (xor8&0xFF)
+ {
+ if ((xor8^crc16)&0x8000)
+ crc16=((crc16^0x0810)<<1)+1;
+ else
+ crc16<<=1;
+ xor8<<=1;
+ }
+ }
+ crc16=~crc16;
+ fputc(crc16>>8,fo); // HI FIRST,
+ fputc(crc16,fo); // AND LO NEXT!
+ l-=256;
+ }
+ l=4; //flag_z;
+ while (l--)
+ fputc(255,fo);
+}
+
+void __output_CDT(struct s_assenv *ae, char *tapefilename,char *filename,char *mydata,int size, int offset, int run)
+{
+ unsigned char *AmsdosHeader;
+ unsigned char head[256];
+ char TZX_header[14];
+ int wrksize,fileload,nbblock=0;
+ unsigned char body[65536+128];
+ int flag_h=2560, flag_p=10240, flag_bb, flag_b=1000,i,j,k;
+
+ FileRemoveIfExists(tapefilename); // pas de append pour le moment
+
+ memcpy(TZX_header,"ZXTape!\032\001\000\040\000\012",13);
+ FileWriteBinary(tapefilename,(char *)TZX_header,13);
+
+ AmsdosHeader=MakeAMSDOSHeader(run,offset,offset+size,MakeAMSDOS_name(ae,filename));
+ memcpy(body,AmsdosHeader,128);
+ wrksize=size;
+
+ memset(head,0,16);
+ strcpy(head,MakeAMSDOS_name(ae,filename));
+ head[0x12]=body[0x12];
+ head[0x18]=body[0x40];
+ head[0x19]=body[0x41];
+ head[0x1A]=body[0x1A];
+ head[0x1B]=body[0x1B];
+ fileload=body[0x15]+body[0x16]*256;
+ flag_b=(3500000/3+flag_b/2)/flag_b;
+ flag_bb=flag_b*2;
+ memcpy(body,mydata,size);
+
+ if (wrksize>0x800) {
+ update11(head,j=1,1,0,0x800,fileload); // FIRST BLOCK
+ record11(tapefilename,head,44,28,16,flag_bb,flag_b);
+ record11(tapefilename,body,22,0x800,flag_h,flag_bb,flag_b);
+ k=wrksize-0x800;
+ i=0x800;
+ nbblock=1;
+ while (k>0x800) {
+ fileload+=0x800;
+ update11(head,++j,0,0,0x800,fileload); // MID BLOCK
+ record11(tapefilename,head,44,28,16,flag_bb,flag_b);
+ record11(tapefilename,body+i,22,0x800,flag_h,flag_bb,flag_b);
+ k-=0x800;
+ i+=0x800;
+ nbblock++;
+ }
+ nbblock++;
+ fileload+=0x800;
+ update11(head,++j,0,1,k,fileload); // LAST BLOCK
+ record11(tapefilename,head,44,28,16,flag_bb,flag_b);
+ record11(tapefilename,body+i,22,k,flag_p,flag_bb,flag_b);
+ } else {
+ update11(head,1,1,1,wrksize,fileload); // SINGLE BLOCK
+ record11(tapefilename,head,44,28,16,flag_bb,flag_b);
+ record11(tapefilename,body,22,wrksize,flag_p,flag_bb,flag_b);
+ nbblock=1;
+ }
+ FileWriteBinaryClose(tapefilename);
+ rasm_printf(ae,KIO"Write tape file %s (%d block%s) run=#%04X\n",tapefilename,nbblock,nbblock>1?"s":"",run);
+}
+
+
+
void PopAllSave(struct s_assenv *ae)
{
#undef FUNC
@@ -6258,11 +8738,13 @@ void PopAllSave(struct s_assenv *ae)
for (is=0;is<ae->nbsave;is++) {
/* avoid quotes */
- filename=ae->wl[ae->save[is].iw].w;
- filename[strlen(filename)-1]=0;
- filename=TxtStrDup(filename+1);
- /* translate tags! */
- filename=TranslateTag(ae,filename,&touched,1,E_TAGOPTION_REMOVESPACE);
+ if (!ae->save[is].iw) filename=ae->save[is].filename; else {
+ filename=ae->wl[ae->save[is].iw].w;
+ filename[strlen(filename)-1]=0;
+ filename=TxtStrDup(filename+1);
+ /* crappy POST translate tags! => deprecated!
+ filename=TranslateTag(ae,filename,&touched,1,E_TAGOPTION_REMOVESPACE); */
+ }
#if TRACE_EDSK
printf("woff=[%s](%d) wsize=[%s](%d)\n",ae->wl[ae->save[is].ioffset].w,ae->save[is].ioffset,ae->wl[ae->save[is].isize].w,ae->save[is].isize);
@@ -6286,14 +8768,17 @@ void PopAllSave(struct s_assenv *ae)
if (size<1 || size>65536) {
MakeError(ae,NULL,0,"cannot save [%s] as the size is invalid!\n",filename);
+ MemFree(filename);
continue;
}
if (offset<0 || offset>65535) {
MakeError(ae,NULL,0,"cannot save [%s] as the offset is invalid!\n",filename);
+ MemFree(filename);
continue;
}
if (offset+size>65536) {
MakeError(ae,NULL,0,"cannot save [%s] as the offset+size will be out of bounds!\n",filename);
+ MemFree(filename);
continue;
}
/* DSK management */
@@ -6304,66 +8789,22 @@ void PopAllSave(struct s_assenv *ae)
dskfilename[strlen(dskfilename)-1]=0;
if (!EDSK_addfile(ae,dskfilename+1,ae->save[is].face,filename,ae->mem[ae->save[is].ibank]+offset,size,offset,run)) {
erreur++;
- break;
+ //break;
}
MemFree(dskfilename);
}
} else if (ae->save[is].tape) {
- char TZX_header[10];
- unsigned char IDval[2];
- int wrksize,nbblock;
+ char *tapefilename;
- /* output file on filesystem */
- FileRemoveIfExists(filename);
-
- strcpy(TZX_header,"ZXTape!");
- TZX_header[7]=0x1A;
- TZX_header[8]=1;
- TZX_header[9]=20;
- FileWriteBinary(filename,(char *)TZX_header,10);
-
- IDval[0]=0x20;
- FileWriteBinary(filename,(char *)IDval,1);
- IDval[0]=0x03;
- IDval[1]=0x03;
- FileWriteBinary(filename,(char *)IDval,2); // first silence
-
- IDval[0]=0x10;
- FileWriteBinary(filename,(char *)IDval,1);
- IDval[0]=0x03;
- IDval[1]=0x03;
- FileWriteBinary(filename,(char *)IDval,2); // little silence
- if (size+128<=2048) wrksize=size+128; else wrksize=2048;
- IDval[0]=(wrksize+128) & 0xFF;
- IDval[1]=((wrksize+128)>>8) & 0xFF;
- FileWriteBinary(filename,(char *)IDval,2); // block len
- nbblock=1;
- AmsdosHeader=MakeAMSDOSHeader(run,offset,offset+size,MakeAMSDOS_name(ae,filename));
- FileWriteBinary(filename,(char *)AmsdosHeader,128);
- if (size<=2048-128) {
- FileWriteBinary(filename,(char*)ae->mem[ae->save[is].ibank]+offset,size);
+ if (ae->save[is].iwdskname>0) {
+ tapefilename=ae->wl[ae->save[is].iwdskname].w;
+ tapefilename[strlen(tapefilename)-1]=0;
+ tapefilename=TxtStrDup(tapefilename+1);
} else {
- FileWriteBinary(filename,(char*)ae->mem[ae->save[is].ibank]+offset,2048-128);
- size=size-2048+128;
- while (size>0) {
- nbblock++;
- /* additionnal block */
- IDval[0]=0x10;
- FileWriteBinary(filename,(char *)IDval,1);
- IDval[0]=0x04;
- IDval[1]=0x04;
- FileWriteBinary(filename,(char *)IDval,2); // silence 1s delay
- if (size<=2048) wrksize=size; else wrksize=2048;
- IDval[0]=(wrksize+128) & 0xFF;
- IDval[1]=((wrksize+128)>>8) & 0xFF;
- FileWriteBinary(filename,(char *)IDval,2); // block len
- FileWriteBinary(filename,(char*)ae->mem[ae->save[is].ibank]+offset,wrksize);
- /* adjust */
- size=size-2048;
- }
+ tapefilename=TxtStrDup("rasmoutput.cdt");
}
- FileWriteBinaryClose(filename);
- rasm_printf(ae,KIO"Write tape file %s (%d block%s)\n",filename,nbblock,nbblock>1?"s":"");
+
+ __output_CDT(ae,tapefilename,filename,(char*)ae->mem[ae->save[is].ibank]+offset,size,offset,run);
} else {
/* output file on filesystem */
rasm_printf(ae,KIO"Write binary file %s (%d byte%s)\n",filename,size,size>1?"s":"");
@@ -6371,6 +8812,10 @@ void PopAllSave(struct s_assenv *ae)
if (ae->save[is].amsdos) {
AmsdosHeader=MakeAMSDOSHeader(run,offset,offset+size,MakeAMSDOS_name(ae,filename));
FileWriteBinary(filename,(char *)AmsdosHeader,128);
+ } else if (ae->save[is].hobeta) {
+ // HOBETA header is 17 bytes long so i reuse Amsdos buffer and name cleaning
+ AmsdosHeader=MakeHobetaHeader(offset,offset+size,MakeAMSDOS_name(ae,filename));
+ FileWriteBinary(filename,(char *)AmsdosHeader,17);
}
FileWriteBinary(filename,(char*)ae->mem[ae->save[is].ibank]+offset,size);
FileWriteBinaryClose(filename);
@@ -6397,7 +8842,7 @@ void PopAllExpression(struct s_assenv *ae, int crunched_zone)
static int first=1;
double v;
long r;
- int i;
+ int i,mapflag=0;
unsigned char *mem;
char *expr;
@@ -6422,10 +8867,11 @@ void PopAllExpression(struct s_assenv *ae, int crunched_zone)
}
for (i=first;i<ae->ie;i++) {
- /* first compute only crunched expression (0,1,2,3,...) then (-1) at the end */
+ /* first compute only crunched expression (0,1,2,3,...) then intermediates and (-1) at the end */
if (crunched_zone>=0) {
- /* calcul des expressions en zone crunch */
+ /* jump over previous crunched or non-crunched zones */
if (ae->expression[i].lz<crunched_zone) continue;
+ /* OPTIM: keep index and stop when we are after the current crunched zone */
if (ae->expression[i].lz>crunched_zone) {
first=i;
break;
@@ -6441,8 +8887,31 @@ void PopAllExpression(struct s_assenv *ae, int crunched_zone)
} else {
expr=ae->wl[ae->expression[i].iw].w;
}
+
+#if TRACE_POPEXPR
+ printf("PopAll (%d) expr=[%s] ptr=%X outputadr=%X\n",crunched_zone,expr,ae->expression[i].ptr,ae->expression[i].wptr);
+#endif
+ if (ae->nexternal) {
+ int iex,jex;
+ mapflag=0;
+ for (iex=0;iex<ae->nexternal;iex++) {
+ for (jex=0;jex<ae->external[iex].nmapping;jex++) {
+ if (ae->expression[i].wptr==ae->external[iex].mapping[jex].ptr) {
+#if TRACE_POPEXPR
+ printf("MAPPING [%s] adr=%d size=%d\n",ae->external[iex].name,ae->expression[i].wptr,ae->external[iex].mapping[jex].size);
+#endif
+ mapflag=1;
+ break;
+ }
+ }
+ }
+ }
v=ComputeExpressionCore(ae,expr,ae->expression[i].ptr,i);
r=(long)floor(v+ae->rough);
+#if TRACE_POPEXPR
+ printf("resultat du compute=>%ld (%lf + rough=%lf)\n",r,v,ae->rough);
+#endif
+
switch (ae->expression[i].zetype) {
case E_EXPRESSION_J8:
r=r-ae->expression[i].ptr-2;
@@ -6459,16 +8928,33 @@ void PopAllExpression(struct s_assenv *ae, int crunched_zone)
case E_EXPRESSION_3V8:
case E_EXPRESSION_V8:
if (r>255 || r<-128) {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: truncating value #%X to #%X\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,r&0xFF);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: truncating value #%X to #%X\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,r&0xFF);
+ if (ae->erronwarn) MaxError(ae);
+ }
}
mem[ae->expression[i].wptr]=(unsigned char)r;
break;
+ case E_EXPRESSION_J16:
+ case E_EXPRESSION_J16C:
+ /* buildobj */
+ if (ae->buildobj && !mapflag) {
+ struct s_external_mapping relocation;
+ //printf("RELOCATION %04X\n",ae->expression[i].wptr);
+ relocation.iorgzone=ae->expression[i].ibank; // bank hack
+ relocation.ptr=ae->expression[i].wptr;
+ relocation.size=2;
+ relocation.value=r&0xFFFF;
+ ObjectArrayAddDynamicValueConcat((void**)&ae->relocation,&ae->nrelocation,&ae->mrelocation,&relocation,sizeof(relocation));
+ }
case E_EXPRESSION_IV16:
case E_EXPRESSION_V16:
- case E_EXPRESSION_V16C:
case E_EXPRESSION_0V16:
if (r>65535 || r<-32768) {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: truncating value #%X to #%X\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,r&0xFFFF);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: truncating value #%X to #%X\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,r&0xFFFF);
+ if (ae->erronwarn) MaxError(ae);
+ }
}
mem[ae->expression[i].wptr]=(unsigned char)r&0xFF;
mem[ae->expression[i].wptr+1]=(unsigned char)((r&0xFF00)>>8);
@@ -6476,7 +8962,10 @@ void PopAllExpression(struct s_assenv *ae, int crunched_zone)
case E_EXPRESSION_0V32:
/* meaningless in 32 bits architecture... */
if (v>4294967295 || v<-2147483648) {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: truncating value\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: truncating value\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l);
+ if (ae->erronwarn) MaxError(ae);
+ }
}
mem[ae->expression[i].wptr]=(unsigned char)r&0xFF;
mem[ae->expression[i].wptr+1]=(unsigned char)((r>>8)&0xFF);
@@ -6487,6 +8976,10 @@ void PopAllExpression(struct s_assenv *ae, int crunched_zone)
/* convert v double value to Amstrad REAL */
memcpy(&mem[ae->expression[i].wptr],__internal_MakeAmsdosREAL(ae,v,i),5);
break;
+ case E_EXPRESSION_0VRMike:
+ /* convert v double value to Microsoft 40bits REAL */
+ memcpy(&mem[ae->expression[i].wptr],__internal_MakeRosoftREAL(ae,v,i),5);
+ break;
case E_EXPRESSION_IM:
switch (r) {
case 0x00:mem[ae->expression[i].wptr]=0x46;break;
@@ -6514,20 +9007,29 @@ void PopAllExpression(struct s_assenv *ae, int crunched_zone)
break;
case E_EXPRESSION_RUN:
if (r<0 || r>65535) {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: run adress truncated from %X to %X\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,r&0xFFFF);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: run address truncated from %X to %X\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,r&0xFFFF);
+ if (ae->erronwarn) MaxError(ae);
+ }
}
ae->snapshot.registers.LPC=r&0xFF;
ae->snapshot.registers.HPC=(r>>8)&0xFF;
break;
case E_EXPRESSION_ZXRUN:
if (r<0 || r>65535) {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: run adress truncated from %X to %X\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,r&0xFFFF);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: run address truncated from %X to %X\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,r&0xFFFF);
+ if (ae->erronwarn) MaxError(ae);
+ }
}
ae->zxsnapshot.run=r&0xFFFF;
break;
case E_EXPRESSION_ZXSTACK:
if (r<0 || r>65535) {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: stack adress truncated from %X to %X\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,r&0xFFFF);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: stack address truncated from %X to %X\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l,r,r&0xFFFF);
+ if (ae->erronwarn) MaxError(ae);
+ }
}
ae->zxsnapshot.stack=r&0xFFFF;
break;
@@ -6539,7 +9041,7 @@ void PopAllExpression(struct s_assenv *ae, int crunched_zone)
}
break;
default:
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - unknown expression type\n",GetExpFile(ae,i),ae->wl[ae->expression[i].iw].l);
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - unknown expression type\n");
FreeAssenv(ae);exit(-8);
}
}
@@ -6581,6 +9083,7 @@ void PushLabelLight(struct s_assenv *ae, struct s_label *curlabel) {
MemFree(curlabel->name);
} else {
curlabel->backidx=ae->il;
+ curlabel->autorise_export=ae->autorise_export&(!ae->getstruct);
ObjectArrayAddDynamicValueConcat((void **)&ae->label,&ae->il,&ae->ml,curlabel,sizeof(struct s_label));
InsertLabelToTree(ae,curlabel);
}
@@ -6591,21 +9094,20 @@ void PushLabel(struct s_assenv *ae)
#define FUNC "PushLabel"
struct s_label curlabel={0},*searched_label;
- char *curlabelname;
int i;
/* label with counters */
- struct s_expr_dico *curdic;
- char curval[32];
- char *varbuffer,*expr;
- char *starttag,*endtag,*tagcheck;
- int taglen,tagidx,lenw,tagcount=0;
- int crc,newlen,touched;
+ char *varbuffer;
+ int tagcount=0;
+ int touched;
- if (ae->AutomateValidLabelFirst[ae->wl[ae->idx].w[0]]) {
+#if TRACE_LABEL
+ printf("check label [%s]\n",ae->wl[ae->idx].w);
+#endif
+ if (ae->AutomateValidLabelFirst[(int)ae->wl[ae->idx].w[0]&0xFF]) {
for (i=1;ae->wl[ae->idx].w[i];i++) {
if (ae->wl[ae->idx].w[i]=='{') tagcount++; else if (ae->wl[ae->idx].w[i]=='}') tagcount--;
if (!tagcount) {
- if (!ae->AutomateValidLabel[ae->wl[ae->idx].w[i]]) {
+ if (!ae->AutomateValidLabel[(int)ae->wl[ae->idx].w[i]&0xFF]) {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Invalid char in label declaration (%c)\n",ae->wl[ae->idx].w[i]);
return;
}
@@ -6659,26 +9161,34 @@ void PushLabel(struct s_assenv *ae)
/*******************************************************
v a r i a b l e s i n l a b e l n a m e
+
+ -- varbuffer is always allocated --
*******************************************************/
- varbuffer=TranslateTag(ae,TxtStrDup(ae->wl[ae->idx].w),&touched,1,E_TAGOPTION_NONE);
-
+ varbuffer=TranslateTag(ae,TxtStrDup(ae->wl[ae->idx].w),&touched,1,E_TAGOPTION_NONE); // on se moque du touched ici => varbuffer toujours "new"
+#if TRACE_LABEL
+ printf("label after translation [%s]\n",varbuffer);
+#endif
/**************************************************
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 TRACE_LABEL
+ printf("label used for structs! [%s]\n",varbuffer);
+#endif
if (varbuffer[0]=='@') {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Please no local label in a struct [%s]\n",ae->wl[ae->idx].w);
+ MemFree(varbuffer);
return;
}
/* copy label+offset in the structure */
- rasmstructfield.name=TxtStrDup(varbuffer);
+ rasmstructfield.name=varbuffer;
rasmstructfield.offset=ae->codeadr;
ObjectArrayAddDynamicValueConcat((void **)&ae->rasmstruct[ae->irasmstruct-1].rasmstructfield,
&ae->rasmstruct[ae->irasmstruct-1].irasmstructfield,&ae->rasmstruct[ae->irasmstruct-1].mrasmstructfield,
&rasmstructfield,sizeof(rasmstructfield));
/* label is structname+field */
- curlabelname=curlabel.name=MemMalloc(strlen(ae->rasmstruct[ae->irasmstruct-1].name)+strlen(varbuffer)+2);
+ 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 */
@@ -6693,9 +9203,12 @@ void PushLabel(struct s_assenv *ae)
**************************************************/
/* labels locaux */
if (varbuffer[0]=='@' && (ae->ir || ae->iw || ae->imacro)) {
+#if TRACE_LABEL
+ printf("PUSH LOCAL\n");
+#endif
curlabel.iw=-1;
curlabel.local=1;
- curlabelname=curlabel.name=MakeLocalLabel(ae,varbuffer,NULL);
+ curlabel.name=MakeLocalLabel(ae,varbuffer,NULL); MemFree(varbuffer);
curlabel.crc=GetCRC(curlabel.name);
/* local labels ALSO set new reference */
@@ -6703,11 +9216,15 @@ void PushLabel(struct s_assenv *ae)
//printf("push LOCAL is freeing lastgloballabel\n");
MemFree(ae->lastgloballabel);
}
- ae->lastgloballabel=TxtStrDup(curlabelname);
-//printf("push LOCAL as reference for proximity label -> [%s]\n",ae->lastgloballabel);
+ ae->lastgloballabel=TxtStrDup(curlabel.name);
ae->lastgloballabellen=strlen(ae->lastgloballabel);
ae->lastglobalalloc=1;
+//printf("push LOCAL as reference [%d] for proximity label -> [%s]\n",im, ae->lastgloballabel);
+
} else {
+#if TRACE_LABEL
+ printf("PUSH GLOBAL or PROXIMITY\n");
+#endif
switch (varbuffer[0]) {
case '.':
if (ae->dams) {
@@ -6715,68 +9232,76 @@ void PushLabel(struct s_assenv *ae)
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;
+
+ curlabel.iw=-1;
+ curlabel.name=varbuffer;
+ curlabel.crc=GetCRC(curlabel.name);
} else {
/* proximity labels */
if (ae->lastgloballabel) {
- curlabelname=MemMalloc(strlen(varbuffer)+1+ae->lastgloballabellen);
- sprintf(curlabelname,"%s%s",ae->lastgloballabel,varbuffer);
+ curlabel.name=MemMalloc(strlen(varbuffer)+1+ae->lastgloballabellen);
+ sprintf(curlabel.name,"%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);
+ curlabel.crc=GetCRC(curlabel.name);
+#if TRACE_LABEL
+printf("PUSH PROXIMITY label that may be exported [%s]->[%s]\n",ae->wl[ae->idx].w,curlabel.name);
+#endif
} else {
- /* MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"cannot create proximity label [%s] as there is no previous global label\n",varbuffer);
- return; */
+#if TRACE_LABEL
+printf("PUSH Orphan PROXIMITY label that cannot be exported [%s]->[%s]\n",ae->wl[ae->idx].w,curlabel.name);
+#endif
- // not optimal but!
- curlabelname=TxtStrDup(varbuffer);
- MemFree(varbuffer);
- touched=1; // cause realloc!
curlabel.iw=-1;
- curlabel.name=varbuffer=curlabelname;
+ curlabel.name=varbuffer;
curlabel.crc=GetCRC(varbuffer);
}
}
break;
default:
- if (!touched) {
- curlabel.iw=ae->idx;
- } else {
- curlabel.iw=-1;
- curlabel.name=varbuffer;
- }
+#if TRACE_LABEL
+ printf("PUSH => GLOBAL [%s]\n",varbuffer);
+#endif
+ curlabel.iw=-1;
+ curlabel.name=varbuffer;
curlabel.crc=GetCRC(varbuffer);
- curlabelname=varbuffer;
+
/* global labels set new reference */
if (ae->lastglobalalloc) MemFree(ae->lastgloballabel);
- ae->lastgloballabel=ae->wl[ae->idx].w;
- ae->lastsuperglobal=ae->wl[ae->idx].w;
- ae->lastgloballabellen=strlen(ae->wl[ae->idx].w);
- ae->lastglobalalloc=0;
-//printf("SET global label [%s] l=%d\n",ae->lastgloballabel,ae->lastgloballabellen);
+ ae->lastgloballabel=TxtStrDup(curlabel.name);
+ ae->lastgloballabellen=strlen(curlabel.name);
+ ae->lastglobalalloc=1;
break;
}
+
+ /* this stage varbuffer maybe already freed or used */
+ if (curlabel.name[0]!='@' && ae->module && ae->modulen) {
+ char *newlabelname;
+
+ newlabelname=MemMalloc(strlen(curlabel.name)+ae->modulen+2);
+ strcpy(newlabelname,ae->module);
+ strcat(newlabelname,ae->module_separator);
+ strcat(newlabelname,curlabel.name);
+ MemFree(curlabel.name);
+ curlabel.name=newlabelname;
+ curlabel.crc=GetCRC(curlabel.name);
+ //curlabel.iw=-1; => deja mis depuis longtemps
+ }
+#if TRACE_LABEL
+ if (curlabel.name[0]!='@') printf("PUSH => ADD MODULE [%s] => [%s]\n",ae->module?ae->module:"(null)",curlabel.name);
+ else printf("PUSH => NO MODULE for local label\n");
+#endif
+
/* contrôle dico uniquement avec des labels non locaux */
- if (SearchDico(ae,curlabelname,curlabel.crc)) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"cannot create label [%s] as there is already a variable with the same name\n",curlabelname);
+ if (SearchDico(ae,curlabel.name,curlabel.crc)) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"cannot create label [%s] as there is already a variable with the same name\n",curlabel.name);
return;
}
- if(SearchAlias(ae,curlabel.crc,curlabelname)!=-1) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"cannot create label [%s] as there is already an alias with the same name\n",curlabelname);
+ if(SearchAlias(ae,curlabel.crc,curlabel.name)!=-1) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"cannot create label [%s] as there is already an alias with the same name\n",curlabel.name);
return;
}
}
@@ -6786,20 +9311,19 @@ void PushLabel(struct s_assenv *ae)
curlabel.lz=ae->lz;
}
- if ((searched_label=SearchLabel(ae,curlabelname,curlabel.crc))!=NULL) {
- MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"Duplicate label [%s] - previously defined in [%s:%d]\n",curlabelname,ae->filename[searched_label->fileidx],searched_label->fileline);
- if (curlabel.iw==-1) MemFree(curlabelname);
+ if ((searched_label=SearchLabel(ae,curlabel.name,curlabel.crc))!=NULL) {
+ MakeError(ae,GetCurrentFile(ae),GetExpLine(ae,0),"Duplicate label [%s] - previously defined in [%s:%d]\n",curlabel.name,ae->filename[searched_label->fileidx],searched_label->fileline);
+ MemFree(curlabel.name);
} else {
-//printf("PushLabel(%s) name=%s crc=%X\n",curlabelname,curlabel.name?curlabel.name:"null",curlabel.crc);
+//printf("PushLabel(%s) name=%s crc=%X lz=%d\n",curlabel.name,curlabel.name?curlabel.name:"null",curlabel.crc,curlabel.lz);
curlabel.fileidx=ae->wl[ae->idx].ifile;
curlabel.fileline=ae->wl[ae->idx].l;
- curlabel.autorise_export=ae->autorise_export;
+ curlabel.autorise_export=ae->autorise_export&(!ae->getstruct);
curlabel.backidx=ae->il;
ObjectArrayAddDynamicValueConcat((void **)&ae->label,&ae->il,&ae->ml,&curlabel,sizeof(curlabel));
InsertLabelToTree(ae,&curlabel);
}
- if (!touched) MemFree(varbuffer);
}
@@ -6808,12 +9332,14 @@ unsigned char *EncodeSnapshotRLE(unsigned char *memin, int *lenout) {
#define FUNC "EncodeSnapshotRLE"
int i,cpt,idx=0;
- unsigned char *memout=NULL;
+ unsigned char *memout;
- memout=MemMalloc(65540);
+ memout=MemMalloc(65536*2);
for (i=0;i<65536;) {
- for (cpt=1;cpt<255;cpt++) if (memin[i]!=memin[i+cpt]) break;
+
+ for (cpt=1;cpt<255 && i+cpt<65536;cpt++) if (memin[i]!=memin[i+cpt]) break;
+
if (cpt>=3 || memin[i]==0xE5) {
memout[idx++]=0xE5;
memout[idx++]=cpt;
@@ -6824,10 +9350,12 @@ unsigned char *EncodeSnapshotRLE(unsigned char *memin, int *lenout) {
}
}
if (lenout) *lenout=idx;
- if (idx<65536) return memout;
-
- MemFree(memout);
- return NULL;
+ if (idx<65536) return memout;
+
+ MemFree(memout);
+ *lenout=65536; // means cannot pack
+ return NULL;
+
}
@@ -6840,14 +9368,14 @@ void _IN(struct s_assenv *ae) {
if (strcmp(ae->wl[ae->idx+2].w,"(C)")==0) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
case CRC_0:
- case CRC_F:___output(ae,0xED);___output(ae,0x70);ae->nop+=4;break;
- case CRC_A:___output(ae,0xED);___output(ae,0x78);ae->nop+=3;break;
- case CRC_B:___output(ae,0xED);___output(ae,0x40);ae->nop+=4;break;
- case CRC_C:___output(ae,0xED);___output(ae,0x48);ae->nop+=4;break;
- case CRC_D:___output(ae,0xED);___output(ae,0x50);ae->nop+=4;break;
- case CRC_E:___output(ae,0xED);___output(ae,0x58);ae->nop+=4;break;
- case CRC_H:___output(ae,0xED);___output(ae,0x60);ae->nop+=4;break;
- case CRC_L:___output(ae,0xED);___output(ae,0x68);ae->nop+=4;break;
+ case CRC_F:___output(ae,0xED);___output(ae,0x70);ae->nop+=4;ae->tick+=12;break;
+ case CRC_A:___output(ae,0xED);___output(ae,0x78);ae->nop+=4;ae->tick+=12;break;
+ case CRC_B:___output(ae,0xED);___output(ae,0x40);ae->nop+=4;ae->tick+=12;break;
+ case CRC_C:___output(ae,0xED);___output(ae,0x48);ae->nop+=4;ae->tick+=12;break;
+ case CRC_D:___output(ae,0xED);___output(ae,0x50);ae->nop+=4;ae->tick+=12;break;
+ case CRC_E:___output(ae,0xED);___output(ae,0x58);ae->nop+=4;ae->tick+=12;break;
+ case CRC_H:___output(ae,0xED);___output(ae,0x60);ae->nop+=4;ae->tick+=12;break;
+ case CRC_L:___output(ae,0xED);___output(ae,0x68);ae->nop+=4;ae->tick+=12;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is IN [0,F,A,B,C,D,E,H,L],(C)\n");
}
@@ -6855,6 +9383,7 @@ void _IN(struct s_assenv *ae) {
___output(ae,0xDB);
PushExpression(ae,ae->idx+2,E_EXPRESSION_V8);
ae->nop+=3;
+ ae->tick+=11;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IN [0,F,A,B,C,D,E,H,L],(C) or IN A,(n) only\n");
}
@@ -6868,14 +9397,14 @@ void _OUT(struct s_assenv *ae) {
if (!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) {
if (strcmp(ae->wl[ae->idx+1].w,"(C)")==0) {
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_0:___output(ae,0xED);___output(ae,0x71);ae->nop+=4;break;
- case CRC_A:___output(ae,0xED);___output(ae,0x79);ae->nop+=4;break;
- case CRC_B:___output(ae,0xED);___output(ae,0x41);ae->nop+=4;break;
- case CRC_C:___output(ae,0xED);___output(ae,0x49);ae->nop+=4;break;
- case CRC_D:___output(ae,0xED);___output(ae,0x51);ae->nop+=4;break;
- case CRC_E:___output(ae,0xED);___output(ae,0x59);ae->nop+=4;break;
- case CRC_H:___output(ae,0xED);___output(ae,0x61);ae->nop+=4;break;
- case CRC_L:___output(ae,0xED);___output(ae,0x69);ae->nop+=4;break;
+ case CRC_0:___output(ae,0xED);___output(ae,0x71);ae->nop+=4;ae->tick+=12;break;
+ case CRC_A:___output(ae,0xED);___output(ae,0x79);ae->nop+=4;ae->tick+=12;break;
+ case CRC_B:___output(ae,0xED);___output(ae,0x41);ae->nop+=4;ae->tick+=12;break;
+ case CRC_C:___output(ae,0xED);___output(ae,0x49);ae->nop+=4;ae->tick+=12;break;
+ case CRC_D:___output(ae,0xED);___output(ae,0x51);ae->nop+=4;ae->tick+=12;break;
+ case CRC_E:___output(ae,0xED);___output(ae,0x59);ae->nop+=4;ae->tick+=12;break;
+ case CRC_H:___output(ae,0xED);___output(ae,0x61);ae->nop+=4;ae->tick+=12;break;
+ case CRC_L:___output(ae,0xED);___output(ae,0x69);ae->nop+=4;ae->tick+=12;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is OUT (C),[0,A,B,C,D,E,H,L]\n");
}
@@ -6883,6 +9412,7 @@ void _OUT(struct s_assenv *ae) {
___output(ae,0xD3);
PushExpression(ae,ae->idx+1,E_EXPRESSION_V8);
ae->nop+=3;
+ ae->tick+=11;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"OUT (C),[0,A,B,C,D,E,H,L] or OUT (n),A only\n");
}
@@ -6897,45 +9427,45 @@ void _EX(struct s_assenv *ae) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
case CRC_HL:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_DE:___output(ae,0xEB);ae->nop+=1;break;
- case CRC_MSP:___output(ae,0xE3);ae->nop+=6;break;
+ case CRC_DE:___output(ae,0xEB);ae->nop+=1;ae->tick+=4;break;
+ case CRC_MSP:___output(ae,0xE3);ae->nop+=6;ae->tick+=19;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is EX HL,[(SP),DE]\n");
}
break;
case CRC_AF:
if (strcmp(ae->wl[ae->idx+2].w,"AF'")==0) {
- ___output(ae,0x08);ae->nop+=1;
+ ___output(ae,0x08);ae->nop+=1;ae->tick+=4;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is EX AF,AF'\n");
}
break;
case CRC_MSP:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_HL:___output(ae,0xE3);ae->nop+=6;break;
- case CRC_IX:___output(ae,0xDD);___output(ae,0xE3);ae->nop+=7;break;
- case CRC_IY:___output(ae,0xFD);___output(ae,0xE3);ae->nop+=7;break;
+ case CRC_HL:___output(ae,0xE3);ae->nop+=6;ae->tick+=19;break;
+ case CRC_IX:___output(ae,0xDD);___output(ae,0xE3);ae->nop+=7;ae->tick+=23;break;
+ case CRC_IY:___output(ae,0xFD);___output(ae,0xE3);ae->nop+=7;ae->tick+=23;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is EX (SP),[HL,IX,IY]\n");
}
break;
case CRC_DE:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_HL:___output(ae,0xEB);ae->nop+=1;break;
+ case CRC_HL:___output(ae,0xEB);ae->nop+=1;ae->tick+=4;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is EX DE,HL\n");
}
break;
case CRC_IX:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_MSP:___output(ae,0xDD);___output(ae,0xE3);ae->nop+=7;break;
+ case CRC_MSP:___output(ae,0xDD);___output(ae,0xE3);ae->nop+=7;ae->tick+=23;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is EX IX,(SP)\n");
}
break;
case CRC_IY:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_MSP:___output(ae,0xFD);___output(ae,0xE3);ae->nop+=7;break;
+ case CRC_MSP:___output(ae,0xFD);___output(ae,0xE3);ae->nop+=7;ae->tick+=23;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is EX IY,(SP)\n");
}
@@ -6945,7 +9475,7 @@ void _EX(struct s_assenv *ae) {
}
ae->idx+=2;
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use EX reg16,reg16\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use EX reg16,[DE|(SP)]\n");
}
}
@@ -6954,18 +9484,18 @@ void _SBC(struct s_assenv *ae) {
if (!ae->wl[ae->idx+1].t) ae->idx++;
/* do implicit A */
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_A:___output(ae,0x9F);ae->nop+=1;break;
- case CRC_MHL:___output(ae,0x9E);ae->nop+=2;break;
- case CRC_B:___output(ae,0x98);ae->nop+=1;break;
- case CRC_C:___output(ae,0x99);ae->nop+=1;break;
- case CRC_D:___output(ae,0x9A);ae->nop+=1;break;
- case CRC_E:___output(ae,0x9B);ae->nop+=1;break;
- case CRC_H:___output(ae,0x9C);ae->nop+=1;break;
- case CRC_L:___output(ae,0x9D);ae->nop+=1;break;
- case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x9C);ae->nop+=2;break;
- case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x9D);ae->nop+=2;break;
- case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x9C);ae->nop+=2;break;
- case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x9D);ae->nop+=2;break;
+ case CRC_A:___output(ae,0x9F);ae->nop+=1;ae->tick+=4;break;
+ case CRC_MHL:___output(ae,0x9E);ae->nop+=2;ae->tick+=7;break;
+ case CRC_B:___output(ae,0x98);ae->nop+=1;ae->tick+=4;break;
+ case CRC_C:___output(ae,0x99);ae->nop+=1;ae->tick+=4;break;
+ case CRC_D:___output(ae,0x9A);ae->nop+=1;ae->tick+=4;break;
+ case CRC_E:___output(ae,0x9B);ae->nop+=1;ae->tick+=4;break;
+ case CRC_H:___output(ae,0x9C);ae->nop+=1;ae->tick+=4;break;
+ case CRC_L:___output(ae,0x9D);ae->nop+=1;ae->tick+=4;break;
+ case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x9C);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x9D);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x9C);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x9D);ae->nop+=2;ae->tick+=8;break;
case CRC_IX:case CRC_IY:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use SBC with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n");
ae->idx++;
@@ -6974,15 +9504,15 @@ void _SBC(struct s_assenv *ae) {
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0x9E);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=3;
+ ae->nop+=5;ae->tick+=19;
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0x9E);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=3;
+ ae->nop+=5;ae->tick+=19;
} else {
___output(ae,0xDE);
PushExpression(ae,ae->idx+1,E_EXPRESSION_V8);
- ae->nop+=2;
+ ae->nop+=2;ae->tick+=7;
}
}
ae->idx++;
@@ -6990,10 +9520,10 @@ void _SBC(struct s_assenv *ae) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
case CRC_HL:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_BC:___output(ae,0xED);___output(ae,0x42);ae->nop+=4;break;
- case CRC_DE:___output(ae,0xED);___output(ae,0x52);ae->nop+=4;break;
- case CRC_HL:___output(ae,0xED);___output(ae,0x62);ae->nop+=4;break;
- case CRC_SP:___output(ae,0xED);___output(ae,0x72);ae->nop+=4;break;
+ case CRC_BC:___output(ae,0xED);___output(ae,0x42);ae->nop+=4;ae->tick+=15;break;
+ case CRC_DE:___output(ae,0xED);___output(ae,0x52);ae->nop+=4;ae->tick+=15;break;
+ case CRC_HL:___output(ae,0xED);___output(ae,0x62);ae->nop+=4;ae->tick+=15;break;
+ case CRC_SP:___output(ae,0xED);___output(ae,0x72);ae->nop+=4;ae->tick+=15;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SBC HL,[BC,DE,HL,SP]\n");
}
@@ -7012,18 +9542,18 @@ void _ADC(struct s_assenv *ae) {
if (!ae->wl[ae->idx+1].t) ae->idx++;
/* also implicit A */
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_A:___output(ae,0x8F);ae->nop+=1;break;
- case CRC_MHL:___output(ae,0x8E);ae->nop+=2;break;
- case CRC_B:___output(ae,0x88);ae->nop+=1;break;
- case CRC_C:___output(ae,0x89);ae->nop+=1;break;
- case CRC_D:___output(ae,0x8A);ae->nop+=1;break;
- case CRC_E:___output(ae,0x8B);ae->nop+=1;break;
- case CRC_H:___output(ae,0x8C);ae->nop+=1;break;
- case CRC_L:___output(ae,0x8D);ae->nop+=1;break;
- case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x8C);ae->nop+=2;break;
- case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x8D);ae->nop+=2;break;
- case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x8C);ae->nop+=2;break;
- case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x8D);ae->nop+=2;break;
+ case CRC_A:___output(ae,0x8F);ae->nop+=1;ae->tick+=4;break;
+ case CRC_MHL:___output(ae,0x8E);ae->nop+=2;ae->tick+=7;break;
+ case CRC_B:___output(ae,0x88);ae->nop+=1;ae->tick+=4;break;
+ case CRC_C:___output(ae,0x89);ae->nop+=1;ae->tick+=4;break;
+ case CRC_D:___output(ae,0x8A);ae->nop+=1;ae->tick+=4;break;
+ case CRC_E:___output(ae,0x8B);ae->nop+=1;ae->tick+=4;break;
+ case CRC_H:___output(ae,0x8C);ae->nop+=1;ae->tick+=4;break;
+ case CRC_L:___output(ae,0x8D);ae->nop+=1;ae->tick+=4;break;
+ case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x8C);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x8D);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x8C);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x8D);ae->nop+=2;ae->tick+=8;break;
case CRC_IX:case CRC_IY:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use ADC with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n");
ae->idx++;
@@ -7032,15 +9562,15 @@ void _ADC(struct s_assenv *ae) {
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0x8E);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=3;
+ ae->nop+=5;ae->tick+=19;
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0x8E);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=3;
+ ae->nop+=5;ae->tick+=19;
} else {
___output(ae,0xCE);
PushExpression(ae,ae->idx+1,E_EXPRESSION_V8);
- ae->nop+=2;
+ ae->nop+=2;ae->tick+=7;
}
}
ae->idx++;
@@ -7048,10 +9578,10 @@ void _ADC(struct s_assenv *ae) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
case CRC_HL:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_BC:___output(ae,0xED);___output(ae,0x4A);ae->nop+=4;break;
- case CRC_DE:___output(ae,0xED);___output(ae,0x5A);ae->nop+=4;break;
- case CRC_HL:___output(ae,0xED);___output(ae,0x6A);ae->nop+=4;break;
- case CRC_SP:___output(ae,0xED);___output(ae,0x7A);ae->nop+=4;break;
+ case CRC_BC:___output(ae,0xED);___output(ae,0x4A);ae->nop+=4;ae->tick+=15;break;
+ case CRC_DE:___output(ae,0xED);___output(ae,0x5A);ae->nop+=4;ae->tick+=15;break;
+ case CRC_HL:___output(ae,0xED);___output(ae,0x6A);ae->nop+=4;ae->tick+=15;break;
+ case CRC_SP:___output(ae,0xED);___output(ae,0x7A);ae->nop+=4;ae->tick+=15;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is ADC HL,[BC,DE,HL,SP]\n");
}
@@ -7070,18 +9600,18 @@ void _ADD(struct s_assenv *ae) {
if (!ae->wl[ae->idx+1].t) ae->idx++;
/* also implicit A */
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_A:___output(ae,0x87);ae->nop+=1;break;
- case CRC_MHL:___output(ae,0x86);ae->nop+=2;break;
- case CRC_B:___output(ae,0x80);ae->nop+=1;break;
- case CRC_C:___output(ae,0x81);ae->nop+=1;break;
- case CRC_D:___output(ae,0x82);ae->nop+=1;break;
- case CRC_E:___output(ae,0x83);ae->nop+=1;break;
- case CRC_H:___output(ae,0x84);ae->nop+=1;break;
- case CRC_L:___output(ae,0x85);ae->nop+=1;break;
- case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x84);ae->nop+=2;break;
- case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x85);ae->nop+=2;break;
- case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x84);ae->nop+=2;break;
- case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x85);ae->nop+=2;break;
+ case CRC_A:___output(ae,0x87);ae->nop+=1;ae->tick+=4;break;
+ case CRC_MHL:___output(ae,0x86);ae->nop+=2;ae->tick+=7;break;
+ case CRC_B:___output(ae,0x80);ae->nop+=1;ae->tick+=4;break;
+ case CRC_C:___output(ae,0x81);ae->nop+=1;ae->tick+=4;break;
+ case CRC_D:___output(ae,0x82);ae->nop+=1;ae->tick+=4;break;
+ case CRC_E:___output(ae,0x83);ae->nop+=1;ae->tick+=4;break;
+ case CRC_H:___output(ae,0x84);ae->nop+=1;ae->tick+=4;break;
+ case CRC_L:___output(ae,0x85);ae->nop+=1;ae->tick+=4;break;
+ case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x84);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x85);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x84);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x85);ae->nop+=2;ae->tick+=8;break;
case CRC_IX:case CRC_IY:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use ADD with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n");
ae->idx++;
@@ -7090,15 +9620,15 @@ void _ADD(struct s_assenv *ae) {
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0x86);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0x86);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else {
___output(ae,0xC6);
PushExpression(ae,ae->idx+1,E_EXPRESSION_V8);
- ae->nop+=2;
+ ae->nop+=2;ae->tick+=7;
}
}
ae->idx++;
@@ -7106,30 +9636,30 @@ void _ADD(struct s_assenv *ae) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
case CRC_HL:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_BC:___output(ae,0x09);ae->nop+=3;break;
- case CRC_DE:___output(ae,0x19);ae->nop+=3;break;
- case CRC_HL:___output(ae,0x29);ae->nop+=3;break;
- case CRC_SP:___output(ae,0x39);ae->nop+=3;break;
+ case CRC_BC:___output(ae,0x09);ae->nop+=3;ae->tick+=11;break;
+ case CRC_DE:___output(ae,0x19);ae->nop+=3;ae->tick+=11;break;
+ case CRC_HL:___output(ae,0x29);ae->nop+=3;ae->tick+=11;break;
+ case CRC_SP:___output(ae,0x39);ae->nop+=3;ae->tick+=11;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is ADD HL,[BC,DE,HL,SP]\n");
}
break;
case CRC_IX:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_BC:___output(ae,0xDD);___output(ae,0x09);ae->nop+=4;break;
- case CRC_DE:___output(ae,0xDD);___output(ae,0x19);ae->nop+=4;break;
- case CRC_IX:___output(ae,0xDD);___output(ae,0x29);ae->nop+=4;break;
- case CRC_SP:___output(ae,0xDD);___output(ae,0x39);ae->nop+=4;break;
+ case CRC_BC:___output(ae,0xDD);___output(ae,0x09);ae->nop+=4;ae->tick+=15;break;
+ case CRC_DE:___output(ae,0xDD);___output(ae,0x19);ae->nop+=4;ae->tick+=15;break;
+ case CRC_IX:___output(ae,0xDD);___output(ae,0x29);ae->nop+=4;ae->tick+=15;break;
+ case CRC_SP:___output(ae,0xDD);___output(ae,0x39);ae->nop+=4;ae->tick+=15;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is ADD IX,[BC,DE,IX,SP]\n");
}
break;
case CRC_IY:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_BC:___output(ae,0xFD);___output(ae,0x09);ae->nop+=4;break;
- case CRC_DE:___output(ae,0xFD);___output(ae,0x19);ae->nop+=4;break;
- case CRC_IY:___output(ae,0xFD);___output(ae,0x29);ae->nop+=4;break;
- case CRC_SP:___output(ae,0xFD);___output(ae,0x39);ae->nop+=4;break;
+ case CRC_BC:___output(ae,0xFD);___output(ae,0x09);ae->nop+=4;ae->tick+=15;break;
+ case CRC_DE:___output(ae,0xFD);___output(ae,0x19);ae->nop+=4;ae->tick+=15;break;
+ case CRC_IY:___output(ae,0xFD);___output(ae,0x29);ae->nop+=4;ae->tick+=15;break;
+ case CRC_SP:___output(ae,0xFD);___output(ae,0x39);ae->nop+=4;ae->tick+=15;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is ADD IY,[BC,DE,IY,SP]\n");
}
@@ -7148,31 +9678,31 @@ void _CP(struct s_assenv *ae) {
if (!ae->wl[ae->idx+1].t) ae->idx++;
/* also implicit A */
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_A:___output(ae,0xBF);ae->nop+=1;break;
- case CRC_MHL:___output(ae,0xBE);ae->nop+=2;break;
- case CRC_B:___output(ae,0xB8);ae->nop+=1;break;
- case CRC_C:___output(ae,0xB9);ae->nop+=1;break;
- case CRC_D:___output(ae,0xBA);ae->nop+=1;break;
- case CRC_E:___output(ae,0xBB);ae->nop+=1;break;
- case CRC_H:___output(ae,0xBC);ae->nop+=1;break;
- case CRC_L:___output(ae,0xBD);ae->nop+=1;break;
- case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0xBC);ae->nop+=2;break;
- case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0xBD);ae->nop+=2;break;
- case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0xBC);ae->nop+=2;break;
- case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0xBD);ae->nop+=2;break;
+ case CRC_A:___output(ae,0xBF);ae->nop+=1;ae->tick+=4;break;
+ case CRC_MHL:___output(ae,0xBE);ae->nop+=2;ae->tick+=7;break;
+ case CRC_B:___output(ae,0xB8);ae->nop+=1;ae->tick+=4;break;
+ case CRC_C:___output(ae,0xB9);ae->nop+=1;ae->tick+=4;break;
+ case CRC_D:___output(ae,0xBA);ae->nop+=1;ae->tick+=4;break;
+ case CRC_E:___output(ae,0xBB);ae->nop+=1;ae->tick+=4;break;
+ case CRC_H:___output(ae,0xBC);ae->nop+=1;ae->tick+=4;break;
+ case CRC_L:___output(ae,0xBD);ae->nop+=1;ae->tick+=4;break;
+ case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0xBC);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0xBD);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0xBC);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0xBD);ae->nop+=2;ae->tick+=8;break;
default:
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0xBE);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0xBE);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else {
___output(ae,0xFE);
PushExpression(ae,ae->idx+1,E_EXPRESSION_V8);
- ae->nop+=2;
+ ae->nop+=2;ae->tick+=7;
}
}
ae->idx++;
@@ -7184,21 +9714,21 @@ void _CP(struct s_assenv *ae) {
void _RET(struct s_assenv *ae) {
if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_NZ:___output(ae,0xC0);ae->nop+=2;break;
- case CRC_Z:___output(ae,0xC8);ae->nop+=2;break;
- case CRC_C:___output(ae,0xD8);ae->nop+=2;break;
- case CRC_NC:___output(ae,0xD0);ae->nop+=2;break;
- case CRC_PE:___output(ae,0xE8);ae->nop+=2;break;
- case CRC_PO:___output(ae,0xE0);ae->nop+=2;break;
- case CRC_P:___output(ae,0xF0);ae->nop+=2;break;
- case CRC_M:___output(ae,0xF8);ae->nop+=2;break;
+ case CRC_NZ:___output(ae,0xC0);ae->nop+=2;ae->tick+=5;break;
+ case CRC_Z:___output(ae,0xC8);ae->nop+=2;ae->tick+=5;break;
+ case CRC_C:___output(ae,0xD8);ae->nop+=2;ae->tick+=5;break;
+ case CRC_NC:___output(ae,0xD0);ae->nop+=2;ae->tick+=5;break;
+ case CRC_PE:___output(ae,0xE8);ae->nop+=2;ae->tick+=5;break;
+ case CRC_PO:___output(ae,0xE0);ae->nop+=2;ae->tick+=5;break;
+ case CRC_P:___output(ae,0xF0);ae->nop+=2;ae->tick+=5;break;
+ case CRC_M:___output(ae,0xF8);ae->nop+=2;ae->tick+=5;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Available flags for RET are C,NC,Z,NZ,PE,PO,P,M\n");
}
ae->idx++;
} else if (ae->wl[ae->idx].t==1) {
___output(ae,0xC9);
- ae->nop+=3;
+ ae->nop+=3;ae->tick+=10;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Invalid RET syntax\n");
}
@@ -7207,24 +9737,24 @@ void _RET(struct s_assenv *ae) {
void _CALL(struct s_assenv *ae) {
if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==0 && ae->wl[ae->idx+2].t==1) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_C:___output(ae,0xDC);ae->nop+=3;break;
- case CRC_Z:___output(ae,0xCC);ae->nop+=3;break;
- case CRC_NZ:___output(ae,0xC4);ae->nop+=3;break;
- case CRC_NC:___output(ae,0xD4);ae->nop+=3;break;
- case CRC_PE:___output(ae,0xEC);ae->nop+=3;break;
- case CRC_PO:___output(ae,0xE4);ae->nop+=3;break;
- case CRC_P:___output(ae,0xF4);ae->nop+=3;break;
- case CRC_M:___output(ae,0xFC);ae->nop+=3;break;
+ case CRC_C:___output(ae,0xDC);ae->nop+=3;ae->tick+=10;break;
+ case CRC_Z:___output(ae,0xCC);ae->nop+=3;ae->tick+=10;break;
+ case CRC_NZ:___output(ae,0xC4);ae->nop+=3;ae->tick+=10;break;
+ case CRC_NC:___output(ae,0xD4);ae->nop+=3;ae->tick+=10;break;
+ case CRC_PE:___output(ae,0xEC);ae->nop+=3;ae->tick+=10;break;
+ case CRC_PO:___output(ae,0xE4);ae->nop+=3;ae->tick+=10;break;
+ case CRC_P:___output(ae,0xF4);ae->nop+=3;ae->tick+=10;break;
+ case CRC_M:___output(ae,0xFC);ae->nop+=3;ae->tick+=10;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Available flags for CALL are C,NC,Z,NZ,PE,PO,P,M\n");
}
- PushExpression(ae,ae->idx+2,E_EXPRESSION_V16C);
+ PushExpression(ae,ae->idx+2,E_EXPRESSION_J16C);
ae->idx+=2;
} else if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) {
___output(ae,0xCD);
- PushExpression(ae,ae->idx+1,E_EXPRESSION_V16C);
+ PushExpression(ae,ae->idx+1,E_EXPRESSION_J16C);
ae->idx++;
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=17;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Invalid CALL syntax\n");
}
@@ -7233,10 +9763,10 @@ void _CALL(struct s_assenv *ae) {
void _JR(struct s_assenv *ae) {
if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==0 && ae->wl[ae->idx+2].t==1) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_NZ:___output(ae,0x20);ae->nop+=2;break;
- case CRC_C:___output(ae,0x38);ae->nop+=2;break;
- case CRC_Z:___output(ae,0x28);ae->nop+=2;break;
- case CRC_NC:___output(ae,0x30);ae->nop+=2;break;
+ case CRC_NZ:___output(ae,0x20);ae->nop+=2;ae->tick+=7;break;
+ case CRC_C:___output(ae,0x38);ae->nop+=2;ae->tick+=7;break;
+ case CRC_Z:___output(ae,0x28);ae->nop+=2;ae->tick+=7;break;
+ case CRC_NC:___output(ae,0x30);ae->nop+=2;ae->tick+=7;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Available flags for JR are C,NC,Z,NZ\n");
}
@@ -7246,7 +9776,7 @@ void _JR(struct s_assenv *ae) {
___output(ae,0x18);
PushExpression(ae,ae->idx+1,E_EXPRESSION_J8);
ae->idx++;
- ae->nop+=3;
+ ae->nop+=3;ae->tick+=12;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Invalid JR syntax\n");
}
@@ -7255,31 +9785,37 @@ void _JR(struct s_assenv *ae) {
void _JP(struct s_assenv *ae) {
if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==0 && ae->wl[ae->idx+2].t==1) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_C:___output(ae,0xDA);ae->nop+=3;break;
- case CRC_Z:___output(ae,0xCA);ae->nop+=3;break;
- case CRC_NZ:___output(ae,0xC2);ae->nop+=3;break;
- case CRC_NC:___output(ae,0xD2);ae->nop+=3;break;
- case CRC_PE:___output(ae,0xEA);ae->nop+=3;break;
- case CRC_PO:___output(ae,0xE2);ae->nop+=3;break;
- case CRC_P:___output(ae,0xF2);ae->nop+=3;break;
- case CRC_M:___output(ae,0xFA);ae->nop+=3;break;
+ case CRC_C:___output(ae,0xDA);ae->nop+=3;ae->tick+=10;break;
+ case CRC_Z:___output(ae,0xCA);ae->nop+=3;ae->tick+=10;break;
+ case CRC_NZ:___output(ae,0xC2);ae->nop+=3;ae->tick+=10;break;
+ case CRC_NC:___output(ae,0xD2);ae->nop+=3;ae->tick+=10;break;
+ case CRC_PE:___output(ae,0xEA);ae->nop+=3;ae->tick+=10;break;
+ case CRC_PO:___output(ae,0xE2);ae->nop+=3;ae->tick+=10;break;
+ case CRC_P:___output(ae,0xF2);ae->nop+=3;ae->tick+=10;break;
+ case CRC_M:___output(ae,0xFA);ae->nop+=3;ae->tick+=10;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Available flags for JP are C,NC,Z,NZ,PE,PO,P,M\n");
}
if (!strcmp(ae->wl[ae->idx+2].w,"(IX)") || !strcmp(ae->wl[ae->idx+2].w,"(IY)")) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"conditionnal JP cannot use register adressing\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"conditionnal JP cannot use register addressing\n");
} else {
- PushExpression(ae,ae->idx+2,E_EXPRESSION_V16);
+ PushExpression(ae,ae->idx+2,E_EXPRESSION_J16);
}
ae->idx+=2;
} else if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_HL:case CRC_MHL:___output(ae,0xE9);ae->nop+=1;break;
- case CRC_IX:case CRC_MIX:___output(ae,0xDD);___output(ae,0xE9);ae->nop+=2;break;
- case CRC_IY:case CRC_MIY:___output(ae,0xFD);___output(ae,0xE9);ae->nop+=2;break;
+ case CRC_HL:case CRC_MHL:___output(ae,0xE9);ae->nop+=1;ae->tick+=4;break;
+ case CRC_IX:case CRC_MIX:___output(ae,0xDD);___output(ae,0xE9);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IY:case CRC_MIY:___output(ae,0xFD);___output(ae,0xE9);ae->nop+=2;ae->tick+=8;break;
default:
- ___output(ae,0xC3);
- PushExpression(ae,ae->idx+1,E_EXPRESSION_V16);
+ if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0 || strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"JP (IX) or JP (IY) only\n");
+ } else {
+ ___output(ae,0xC3);
+ PushExpression(ae,ae->idx+1,E_EXPRESSION_J16);
+ ae->tick+=10;
+ ae->nop+=3;
+ }
}
ae->idx++;
} else {
@@ -7292,33 +9828,33 @@ void _DEC(struct s_assenv *ae) {
if (!ae->wl[ae->idx].t) {
do {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_A:___output(ae,0x3D);ae->nop+=1;break;
- case CRC_B:___output(ae,0x05);ae->nop+=1;break;
- case CRC_C:___output(ae,0x0D);ae->nop+=1;break;
- case CRC_D:___output(ae,0x15);ae->nop+=1;break;
- case CRC_E:___output(ae,0x1D);ae->nop+=1;break;
- case CRC_H:___output(ae,0x25);ae->nop+=1;break;
- case CRC_L:___output(ae,0x2D);ae->nop+=1;break;
- case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x25);ae->nop+=2;break;
- case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x2D);ae->nop+=2;break;
- case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x25);ae->nop+=2;break;
- case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x2D);ae->nop+=2;break;
- case CRC_BC:___output(ae,0x0B);ae->nop+=2;break;
- case CRC_DE:___output(ae,0x1B);ae->nop+=2;break;
- case CRC_HL:___output(ae,0x2B);ae->nop+=2;break;
- case CRC_IX:___output(ae,0xDD);___output(ae,0x2B);ae->nop+=3;break;
- case CRC_IY:___output(ae,0xFD);___output(ae,0x2B);ae->nop+=3;break;
- case CRC_SP:___output(ae,0x3B);ae->nop+=2;break;
- case CRC_MHL:___output(ae,0x35);ae->nop+=3;break;
+ case CRC_A:___output(ae,0x3D);ae->nop+=1;ae->tick+=4;break;
+ case CRC_B:___output(ae,0x05);ae->nop+=1;ae->tick+=4;break;
+ case CRC_C:___output(ae,0x0D);ae->nop+=1;ae->tick+=4;break;
+ case CRC_D:___output(ae,0x15);ae->nop+=1;ae->tick+=4;break;
+ case CRC_E:___output(ae,0x1D);ae->nop+=1;ae->tick+=4;break;
+ case CRC_H:___output(ae,0x25);ae->nop+=1;ae->tick+=4;break;
+ case CRC_L:___output(ae,0x2D);ae->nop+=1;ae->tick+=4;break;
+ case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x25);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x2D);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x25);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x2D);ae->nop+=2;ae->tick+=8;break;
+ case CRC_BC:___output(ae,0x0B);ae->nop+=2;ae->tick+=6;break;
+ case CRC_DE:___output(ae,0x1B);ae->nop+=2;ae->tick+=6;break;
+ case CRC_HL:___output(ae,0x2B);ae->nop+=2;ae->tick+=6;break;
+ case CRC_IX:___output(ae,0xDD);___output(ae,0x2B);ae->nop+=3;ae->tick+=10;break;
+ case CRC_IY:___output(ae,0xFD);___output(ae,0x2B);ae->nop+=3;ae->tick+=10;break;
+ case CRC_SP:___output(ae,0x3B);ae->nop+=2;ae->tick+=6;break;
+ case CRC_MHL:___output(ae,0x35);ae->nop+=3;ae->tick+=11;break;
default:
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0x35);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=6;
+ ae->nop+=6;ae->tick+=23;
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0x35);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=6;
+ ae->nop+=6;ae->tick+=23;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use DEC with A,B,C,D,E,H,L,XH,XL,YH,YL,BC,DE,HL,SP,(HL),(IX),(IY)\n");
}
@@ -7333,33 +9869,33 @@ void _INC(struct s_assenv *ae) {
if (!ae->wl[ae->idx].t) {
do {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_A:___output(ae,0x3C);ae->nop+=1;break;
- case CRC_B:___output(ae,0x04);ae->nop+=1;break;
- case CRC_C:___output(ae,0x0C);ae->nop+=1;break;
- case CRC_D:___output(ae,0x14);ae->nop+=1;break;
- case CRC_E:___output(ae,0x1C);ae->nop+=1;break;
- case CRC_H:___output(ae,0x24);ae->nop+=1;break;
- case CRC_L:___output(ae,0x2C);ae->nop+=1;break;
- case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x24);ae->nop+=2;break;
- case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x2C);ae->nop+=2;break;
- case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x24);ae->nop+=2;break;
- case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x2C);ae->nop+=2;break;
- case CRC_BC:___output(ae,0x03);ae->nop+=2;break;
- case CRC_DE:___output(ae,0x13);ae->nop+=2;break;
- case CRC_HL:___output(ae,0x23);ae->nop+=2;break;
- case CRC_IX:___output(ae,0xDD);___output(ae,0x23);ae->nop+=3;break;
- case CRC_IY:___output(ae,0xFD);___output(ae,0x23);ae->nop+=3;break;
- case CRC_SP:___output(ae,0x33);ae->nop+=2;break;
- case CRC_MHL:___output(ae,0x34);ae->nop+=3;break;
+ case CRC_A:___output(ae,0x3C);ae->nop+=1;ae->tick+=4;break;
+ case CRC_B:___output(ae,0x04);ae->nop+=1;ae->tick+=4;break;
+ case CRC_C:___output(ae,0x0C);ae->nop+=1;ae->tick+=4;break;
+ case CRC_D:___output(ae,0x14);ae->nop+=1;ae->tick+=4;break;
+ case CRC_E:___output(ae,0x1C);ae->nop+=1;ae->tick+=4;break;
+ case CRC_H:___output(ae,0x24);ae->nop+=1;ae->tick+=4;break;
+ case CRC_L:___output(ae,0x2C);ae->nop+=1;ae->tick+=4;break;
+ case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x24);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x2C);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x24);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x2C);ae->nop+=2;ae->tick+=8;break;
+ case CRC_BC:___output(ae,0x03);ae->nop+=2;ae->tick+=6;break;
+ case CRC_DE:___output(ae,0x13);ae->nop+=2;ae->tick+=6;break;
+ case CRC_HL:___output(ae,0x23);ae->nop+=2;ae->tick+=6;break;
+ case CRC_IX:___output(ae,0xDD);___output(ae,0x23);ae->nop+=3;ae->tick+=10;break;
+ case CRC_IY:___output(ae,0xFD);___output(ae,0x23);ae->nop+=3;ae->tick+=10;break;
+ case CRC_SP:___output(ae,0x33);ae->nop+=2;ae->tick+=6;break;
+ case CRC_MHL:___output(ae,0x34);ae->nop+=3;ae->tick+=11;break;
default:
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0x34);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=6;
+ ae->nop+=6;ae->tick+=23;
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0x34);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=6;
+ ae->nop+=6;ae->tick+=23;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use INC with A,B,C,D,E,H,L,XH,XL,YH,YL,BC,DE,HL,SP,(HL),(IX),(IY)\n");
}
@@ -7380,18 +9916,18 @@ void _SUB(struct s_assenv *ae) {
if ((!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) || ((!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) && strcmp(ae->wl[ae->idx+1].w,"A")==0)) {
if (!ae->wl[ae->idx+1].t) ae->idx++;
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_A:___output(ae,OPCODE+7);ae->nop+=1;break;
- case CRC_MHL:___output(ae,OPCODE+6);ae->nop+=2;break;
- case CRC_B:___output(ae,OPCODE);ae->nop+=1;break;
- case CRC_C:___output(ae,OPCODE+1);ae->nop+=1;break;
- case CRC_D:___output(ae,OPCODE+2);ae->nop+=1;break;
- case CRC_E:___output(ae,OPCODE+3);ae->nop+=1;break;
- case CRC_H:___output(ae,OPCODE+4);ae->nop+=1;break;
- case CRC_L:___output(ae,OPCODE+5);ae->nop+=1;break;
- case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,OPCODE+4);ae->nop+=2;break;
- case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,OPCODE+5);ae->nop+=2;break;
- case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,OPCODE+4);ae->nop+=2;break;
- case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,OPCODE+5);ae->nop+=2;break;
+ case CRC_A:___output(ae,OPCODE+7);ae->nop+=1;ae->tick+=4;break;
+ case CRC_MHL:___output(ae,OPCODE+6);ae->nop+=2;ae->tick+=7;break;
+ case CRC_B:___output(ae,OPCODE);ae->nop+=1;ae->tick+=4;break;
+ case CRC_C:___output(ae,OPCODE+1);ae->nop+=1;ae->tick+=4;break;
+ case CRC_D:___output(ae,OPCODE+2);ae->nop+=1;ae->tick+=4;break;
+ case CRC_E:___output(ae,OPCODE+3);ae->nop+=1;ae->tick+=4;break;
+ case CRC_H:___output(ae,OPCODE+4);ae->nop+=1;ae->tick+=4;break;
+ case CRC_L:___output(ae,OPCODE+5);ae->nop+=1;ae->tick+=4;break;
+ case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,OPCODE+4);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,OPCODE+5);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,OPCODE+4);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,OPCODE+5);ae->nop+=2;ae->tick+=8;break;
case CRC_IX:case CRC_IY:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use SUB with A,B,C,D,E,H,L,XH,XL,YH,YL,(HL),(IX),(IY)\n");
ae->idx++;
@@ -7400,15 +9936,15 @@ void _SUB(struct s_assenv *ae) {
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,OPCODE+6);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,OPCODE+6);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else {
___output(ae,0xD6);
PushExpression(ae,ae->idx+1,E_EXPRESSION_V8);
- ae->nop+=2;
+ ae->nop+=2;ae->tick+=7;
}
}
ae->idx++;
@@ -7424,31 +9960,31 @@ void _AND(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,OPCODE+7);ae->nop+=1;break;
- case CRC_MHL:___output(ae,OPCODE+6);ae->nop+=2;break;
- case CRC_B:___output(ae,OPCODE);ae->nop+=1;break;
- case CRC_C:___output(ae,OPCODE+1);ae->nop+=1;break;
- case CRC_D:___output(ae,OPCODE+2);ae->nop+=1;break;
- case CRC_E:___output(ae,OPCODE+3);ae->nop+=1;break;
- case CRC_H:___output(ae,OPCODE+4);ae->nop+=1;break;
- case CRC_L:___output(ae,OPCODE+5);ae->nop+=1;break;
- case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,OPCODE+4);ae->nop+=2;break;
- case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,OPCODE+5);ae->nop+=2;break;
- case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,OPCODE+4);ae->nop+=2;break;
- case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,OPCODE+5);ae->nop+=2;break;
+ case CRC_A:___output(ae,OPCODE+7);ae->nop+=1;ae->tick+=4;break;
+ case CRC_MHL:___output(ae,OPCODE+6);ae->nop+=2;ae->tick+=7;break;
+ case CRC_B:___output(ae,OPCODE);ae->nop+=1;ae->tick+=4;break;
+ case CRC_C:___output(ae,OPCODE+1);ae->nop+=1;ae->tick+=4;break;
+ case CRC_D:___output(ae,OPCODE+2);ae->nop+=1;ae->tick+=4;break;
+ case CRC_E:___output(ae,OPCODE+3);ae->nop+=1;ae->tick+=4;break;
+ case CRC_H:___output(ae,OPCODE+4);ae->nop+=1;ae->tick+=4;break;
+ case CRC_L:___output(ae,OPCODE+5);ae->nop+=1;ae->tick+=4;break;
+ case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,OPCODE+4);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,OPCODE+5);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,OPCODE+4);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,OPCODE+5);ae->nop+=2;ae->tick+=8;break;
default:
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,OPCODE+6);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,OPCODE+6);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else {
___output(ae,0xE6);
PushExpression(ae,ae->idx+1,E_EXPRESSION_V8);
- ae->nop+=2;
+ ae->nop+=2;ae->tick+=7;
}
}
ae->idx++;
@@ -7464,31 +10000,31 @@ void _OR(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,OPCODE+7);ae->nop+=1;break;
- case CRC_MHL:___output(ae,OPCODE+6);ae->nop+=2;break;
- case CRC_B:___output(ae,OPCODE);ae->nop+=1;break;
- case CRC_C:___output(ae,OPCODE+1);ae->nop+=1;break;
- case CRC_D:___output(ae,OPCODE+2);ae->nop+=1;break;
- case CRC_E:___output(ae,OPCODE+3);ae->nop+=1;break;
- case CRC_H:___output(ae,OPCODE+4);ae->nop+=1;break;
- case CRC_L:___output(ae,OPCODE+5);ae->nop+=1;break;
- case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,OPCODE+4);ae->nop+=2;break;
- case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,OPCODE+5);ae->nop+=2;break;
- case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,OPCODE+4);ae->nop+=2;break;
- case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,OPCODE+5);ae->nop+=2;break;
+ case CRC_A:___output(ae,OPCODE+7);ae->nop+=1;ae->tick+=4;break;
+ case CRC_MHL:___output(ae,OPCODE+6);ae->nop+=2;ae->tick+=7;break;
+ case CRC_B:___output(ae,OPCODE);ae->nop+=1;ae->tick+=4;break;
+ case CRC_C:___output(ae,OPCODE+1);ae->nop+=1;ae->tick+=4;break;
+ case CRC_D:___output(ae,OPCODE+2);ae->nop+=1;ae->tick+=4;break;
+ case CRC_E:___output(ae,OPCODE+3);ae->nop+=1;ae->tick+=4;break;
+ case CRC_H:___output(ae,OPCODE+4);ae->nop+=1;ae->tick+=4;break;
+ case CRC_L:___output(ae,OPCODE+5);ae->nop+=1;ae->tick+=4;break;
+ case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,OPCODE+4);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,OPCODE+5);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,OPCODE+4);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,OPCODE+5);ae->nop+=2;ae->tick+=8;break;
default:
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,OPCODE+6);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,OPCODE+6);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else {
___output(ae,0xF6);
PushExpression(ae,ae->idx+1,E_EXPRESSION_V8);
- ae->nop+=2;
+ ae->nop+=2;ae->tick+=7;
}
}
ae->idx++;
@@ -7504,31 +10040,31 @@ void _XOR(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,OPCODE+7);ae->nop+=1;break;
- case CRC_MHL:___output(ae,OPCODE+6);ae->nop+=2;break;
- case CRC_B:___output(ae,OPCODE);ae->nop+=1;break;
- case CRC_C:___output(ae,OPCODE+1);ae->nop+=1;break;
- case CRC_D:___output(ae,OPCODE+2);ae->nop+=1;break;
- case CRC_E:___output(ae,OPCODE+3);ae->nop+=1;break;
- case CRC_H:___output(ae,OPCODE+4);ae->nop+=1;break;
- case CRC_L:___output(ae,OPCODE+5);ae->nop+=1;break;
- case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,OPCODE+4);ae->nop+=2;break;
- case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,OPCODE+5);ae->nop+=2;break;
- case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,OPCODE+4);ae->nop+=2;break;
- case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,OPCODE+5);ae->nop+=2;break;
+ case CRC_A:___output(ae,OPCODE+7);ae->nop+=1;ae->tick+=4;break;
+ case CRC_MHL:___output(ae,OPCODE+6);ae->nop+=2;ae->tick+=7;break;
+ case CRC_B:___output(ae,OPCODE);ae->nop+=1;ae->tick+=4;break;
+ case CRC_C:___output(ae,OPCODE+1);ae->nop+=1;ae->tick+=4;break;
+ case CRC_D:___output(ae,OPCODE+2);ae->nop+=1;ae->tick+=4;break;
+ case CRC_E:___output(ae,OPCODE+3);ae->nop+=1;ae->tick+=4;break;
+ case CRC_H:___output(ae,OPCODE+4);ae->nop+=1;ae->tick+=4;break;
+ case CRC_L:___output(ae,OPCODE+5);ae->nop+=1;ae->tick+=4;break;
+ case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,OPCODE+4);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,OPCODE+5);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,OPCODE+4);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,OPCODE+5);ae->nop+=2;ae->tick+=8;break;
default:
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,OPCODE+6);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,OPCODE+6);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else {
___output(ae,0xEE);
PushExpression(ae,ae->idx+1,E_EXPRESSION_V8);
- ae->nop+=2;
+ ae->nop+=2;ae->tick+=7;
}
}
ae->idx++;
@@ -7543,12 +10079,12 @@ void _POP(struct s_assenv *ae) {
do {
ae->idx++;
switch (GetCRC(ae->wl[ae->idx].w)) {
- case CRC_AF:___output(ae,0xF1);ae->nop+=3;break;
- case CRC_BC:___output(ae,0xC1);ae->nop+=3;break;
- case CRC_DE:___output(ae,0xD1);ae->nop+=3;break;
- case CRC_HL:___output(ae,0xE1);ae->nop+=3;break;
- case CRC_IX:___output(ae,0xDD);___output(ae,0xE1);ae->nop+=4;break;
- case CRC_IY:___output(ae,0xFD);___output(ae,0xE1);ae->nop+=4;break;
+ case CRC_AF:___output(ae,0xF1);ae->nop+=3;ae->tick+=10;break;
+ case CRC_BC:___output(ae,0xC1);ae->nop+=3;ae->tick+=10;break;
+ case CRC_DE:___output(ae,0xD1);ae->nop+=3;ae->tick+=10;break;
+ case CRC_HL:___output(ae,0xE1);ae->nop+=3;ae->tick+=10;break;
+ case CRC_IX:___output(ae,0xDD);___output(ae,0xE1);ae->nop+=4;ae->tick+=14;break;
+ case CRC_IY:___output(ae,0xFD);___output(ae,0xE1);ae->nop+=4;ae->tick+=14;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use POP with AF,BC,DE,HL,IX,IY\n");
}
@@ -7562,12 +10098,12 @@ void _PUSH(struct s_assenv *ae) {
do {
ae->idx++;
switch (GetCRC(ae->wl[ae->idx].w)) {
- case CRC_AF:___output(ae,0xF5);ae->nop+=4;break;
- case CRC_BC:___output(ae,0xC5);ae->nop+=4;break;
- case CRC_DE:___output(ae,0xD5);ae->nop+=4;break;
- case CRC_HL:___output(ae,0xE5);ae->nop+=4;break;
- case CRC_IX:___output(ae,0xDD);___output(ae,0xE5);ae->nop+=5;break;
- case CRC_IY:___output(ae,0xFD);___output(ae,0xE5);ae->nop+=5;break;
+ case CRC_AF:___output(ae,0xF5);ae->nop+=4;ae->tick+=11;break;
+ case CRC_BC:___output(ae,0xC5);ae->nop+=4;ae->tick+=11;break;
+ case CRC_DE:___output(ae,0xD5);ae->nop+=4;ae->tick+=11;break;
+ case CRC_HL:___output(ae,0xE5);ae->nop+=4;ae->tick+=11;break;
+ case CRC_IX:___output(ae,0xDD);___output(ae,0xE5);ae->nop+=5;ae->tick+=15;break;
+ case CRC_IY:___output(ae,0xFD);___output(ae,0xE5);ae->nop+=5;ae->tick+=15;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Use PUSH with AF,BC,DE,HL,IX,IY\n");
}
@@ -7584,6 +10120,7 @@ void _IM(struct s_assenv *ae) {
PushExpression(ae,ae->idx+1,E_EXPRESSION_IM);
ae->idx++;
ae->nop+=2;
+ ae->tick+=8;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IM need one parameter\n");
}
@@ -7593,6 +10130,7 @@ void _RLCA(struct s_assenv *ae) {
if (ae->wl[ae->idx].t) {
___output(ae,0x7);
ae->nop+=1;
+ ae->tick+=4;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RLCA does not need parameter\n");
}
@@ -7601,6 +10139,7 @@ void _RRCA(struct s_assenv *ae) {
if (ae->wl[ae->idx].t) {
___output(ae,0xF);
ae->nop+=1;
+ ae->tick+=4;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RRCA does not need parameter\n");
}
@@ -7610,6 +10149,7 @@ void _NEG(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0x44);
ae->nop+=2;
+ ae->tick+=8;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"NEG does not need parameter\n");
}
@@ -7618,6 +10158,7 @@ void _DAA(struct s_assenv *ae) {
if (ae->wl[ae->idx].t) {
___output(ae,0x27);
ae->nop+=1;
+ ae->tick+=4;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DAA does not need parameter\n");
}
@@ -7626,6 +10167,7 @@ void _CPL(struct s_assenv *ae) {
if (ae->wl[ae->idx].t) {
___output(ae,0x2F);
ae->nop+=1;
+ ae->tick+=4;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CPL does not need parameter\n");
}
@@ -7635,6 +10177,7 @@ void _RETI(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0x4D);
ae->nop+=4;
+ ae->tick+=14;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RETI does not need parameter\n");
}
@@ -7643,6 +10186,7 @@ void _SCF(struct s_assenv *ae) {
if (ae->wl[ae->idx].t) {
___output(ae,0x37);
ae->nop+=1;
+ ae->tick+=4;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SCF does not need parameter\n");
}
@@ -7652,6 +10196,7 @@ void _LDD(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0xA8);
ae->nop+=5;
+ ae->tick+=16;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LDD does not need parameter\n");
}
@@ -7661,6 +10206,7 @@ void _LDDR(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0xB8);
ae->nop+=5;
+ ae->tick+=16;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LDDR does not need parameter\n");
}
@@ -7670,6 +10216,7 @@ void _LDI(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0xA0);
ae->nop+=5;
+ ae->tick+=16;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LDI does not need parameter\n");
}
@@ -7679,6 +10226,7 @@ void _LDIR(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0xB0);
ae->nop+=5;
+ ae->tick+=16;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LDIR does not need parameter\n");
}
@@ -7686,7 +10234,8 @@ void _LDIR(struct s_assenv *ae) {
void _CCF(struct s_assenv *ae) {
if (ae->wl[ae->idx].t) {
___output(ae,0x3F);
- ae->nop+=5;
+ ae->nop+=1;
+ ae->tick+=4;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CCF does not need parameter\n");
}
@@ -7696,6 +10245,7 @@ void _CPD(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0xA9);
ae->nop+=4;
+ ae->tick+=16;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CPD does not need parameter\n");
}
@@ -7705,6 +10255,7 @@ void _CPDR(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0xB9);
ae->nop+=4;
+ ae->tick+=16;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CPDR does not need parameter\n");
}
@@ -7714,6 +10265,7 @@ void _CPI(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0xA1);
ae->nop+=4;
+ ae->tick+=16;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CPI does not need parameter\n");
}
@@ -7723,6 +10275,7 @@ void _CPIR(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0xB1);
ae->nop+=4;
+ ae->tick+=16;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CPIR does not need parameter\n");
}
@@ -7732,6 +10285,7 @@ void _OUTD(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0xAB);
ae->nop+=5;
+ ae->tick+=16;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"OUTD does not need parameter\n");
}
@@ -7741,6 +10295,7 @@ void _OTDR(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0xBB);
ae->nop+=5;
+ ae->tick+=16;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"OTDR does not need parameter\n");
}
@@ -7750,6 +10305,7 @@ void _OUTI(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0xA3);
ae->nop+=5;
+ ae->tick+=16;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"OUTI does not need parameter\n");
}
@@ -7759,6 +10315,7 @@ void _OTIR(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0xB3);
ae->nop+=5;
+ ae->tick+=16;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"OTIR does not need parameter\n");
}
@@ -7768,6 +10325,7 @@ void _RETN(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0x45);
ae->nop+=4;
+ ae->tick+=14;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RETN does not need parameter\n");
}
@@ -7777,6 +10335,7 @@ void _IND(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0xAA);
ae->nop+=5;
+ ae->tick+=16;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IND does not need parameter\n");
}
@@ -7786,6 +10345,7 @@ void _INDR(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0xBA);
ae->nop+=5;
+ ae->tick+=16;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INDR does not need parameter\n");
}
@@ -7795,6 +10355,7 @@ void _INI(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0xA2);
ae->nop+=5;
+ ae->tick+=16;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INI does not need parameter\n");
}
@@ -7804,6 +10365,7 @@ void _INIR(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0xB2);
ae->nop+=5;
+ ae->tick+=16;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INIR does not need parameter\n");
}
@@ -7812,6 +10374,7 @@ void _EXX(struct s_assenv *ae) {
if (ae->wl[ae->idx].t==1) {
___output(ae,0xD9);
ae->nop+=1;
+ ae->tick+=4;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"EXX does not need parameter\n");
}
@@ -7820,6 +10383,7 @@ void _HALT(struct s_assenv *ae) {
if (ae->wl[ae->idx].t==1) {
___output(ae,0x76);
ae->nop+=1;
+ ae->tick+=4;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"HALT does not need parameter\n");
}
@@ -7829,6 +10393,7 @@ void _RLA(struct s_assenv *ae) {
if (ae->wl[ae->idx].t==1) {
___output(ae,0x17);
ae->nop+=1;
+ ae->tick+=4;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RLA does not need parameter\n");
}
@@ -7837,6 +10402,7 @@ void _RRA(struct s_assenv *ae) {
if (ae->wl[ae->idx].t==1) {
___output(ae,0x1F);
ae->nop+=1;
+ ae->tick+=4;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RRA does not need parameter\n");
}
@@ -7846,6 +10412,7 @@ void _RLD(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0x6F);
ae->nop+=5;
+ ae->tick+=18;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RLD does not need parameter\n");
}
@@ -7855,6 +10422,7 @@ void _RRD(struct s_assenv *ae) {
___output(ae,0xED);
___output(ae,0x67);
ae->nop+=5;
+ ae->tick+=18;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RRD does not need parameter\n");
}
@@ -7864,6 +10432,7 @@ void _RRD(struct s_assenv *ae) {
void _EXA(struct s_assenv *ae) {
if (ae->wl[ae->idx].t==1) {
___output(ae,0x08);ae->nop+=1;
+ ae->tick+=4;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"EXA alias does not need parameter\n");
}
@@ -7875,6 +10444,7 @@ void _NOP(struct s_assenv *ae) {
if (ae->wl[ae->idx].t) {
___output(ae,0x00);
ae->nop+=1;
+ ae->tick+=4;
} else if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) {
ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0);
o=RoundComputeExpressionCore(ae,ae->wl[ae->idx+1].w,ae->codeadr,0);
@@ -7882,6 +10452,7 @@ void _NOP(struct s_assenv *ae) {
while (o>0) {
___output(ae,0x00);
ae->nop+=1;
+ ae->tick+=4;
o--;
}
}
@@ -7893,6 +10464,7 @@ void _DI(struct s_assenv *ae) {
if (ae->wl[ae->idx].t) {
___output(ae,0xF3);
ae->nop+=1;
+ ae->tick+=4;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DI does not need parameter\n");
}
@@ -7901,6 +10473,7 @@ void _EI(struct s_assenv *ae) {
if (ae->wl[ae->idx].t) {
___output(ae,0xFB);
ae->nop+=1;
+ ae->tick+=4;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"EI does not need parameter\n");
}
@@ -7916,6 +10489,7 @@ void _RST(struct s_assenv *ae) {
}
ae->idx++;
ae->nop+=4;
+ ae->tick+=11;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"RST need one parameter\n");
}
@@ -7931,6 +10505,7 @@ void _DJNZ(struct s_assenv *ae) {
___output(ae,0x10);
PushExpression(ae,ae->idx+1,E_EXPRESSION_J8);
ae->nop+=3;
+ ae->tick+=13;
}
ae->idx++;
} else {
@@ -7944,47 +10519,47 @@ void _LD(struct s_assenv *ae) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
case CRC_A:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_I:___output(ae,0xED);___output(ae,0x57);ae->nop+=3;break;
- case CRC_R:___output(ae,0xED);___output(ae,0x5F);ae->nop+=3;break;
- case CRC_B:___output(ae,0x78);ae->nop+=1;break;
- case CRC_C:___output(ae,0x79);ae->nop+=1;break;
- case CRC_D:___output(ae,0x7A);ae->nop+=1;break;
- case CRC_E:___output(ae,0x7B);ae->nop+=1;break;
- case CRC_H:___output(ae,0x7C);ae->nop+=1;break;
- case CRC_L:___output(ae,0x7D);ae->nop+=1;break;
- case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x7C);ae->nop+=2;break;
- case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x7D);ae->nop+=2;break;
- case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x7C);ae->nop+=2;break;
- case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x7D);ae->nop+=2;break;
- case CRC_MHL:___output(ae,0x7E);ae->nop+=2;break;
- case CRC_A:___output(ae,0x7F);ae->nop+=1;break;
- case CRC_MBC:___output(ae,0x0A);ae->nop+=2;break;
- case CRC_MDE:___output(ae,0x1A);ae->nop+=2;break;
+ case CRC_I:___output(ae,0xED);___output(ae,0x57);ae->nop+=3;ae->tick+=9;break;
+ case CRC_R:___output(ae,0xED);___output(ae,0x5F);ae->nop+=3;ae->tick+=9;break;
+ case CRC_B:___output(ae,0x78);ae->nop+=1;ae->tick+=4;break;
+ case CRC_C:___output(ae,0x79);ae->nop+=1;ae->tick+=4;break;
+ case CRC_D:___output(ae,0x7A);ae->nop+=1;ae->tick+=4;break;
+ case CRC_E:___output(ae,0x7B);ae->nop+=1;ae->tick+=4;break;
+ case CRC_H:___output(ae,0x7C);ae->nop+=1;ae->tick+=4;break;
+ case CRC_L:___output(ae,0x7D);ae->nop+=1;ae->tick+=4;break;
+ case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x7C);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x7D);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x7C);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x7D);ae->nop+=2;ae->tick+=8;break;
+ case CRC_MHL:___output(ae,0x7E);ae->nop+=2;ae->tick+=7;break;
+ case CRC_A:___output(ae,0x7F);ae->nop+=1;ae->tick+=4;break;
+ case CRC_MBC:___output(ae,0x0A);ae->nop+=2;ae->tick+=7;break;
+ case CRC_MDE:___output(ae,0x1A);ae->nop+=2;ae->tick+=7;break;
default:
/* (ix+expression) (iy+expression) (expression) expression */
if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0x7E);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0x7E);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else if (StringIsMem(ae->wl[ae->idx+2].w)) {
___output(ae,0x3A);
PushExpression(ae,ae->idx+2,E_EXPRESSION_V16);
- ae->nop+=4;
+ ae->nop+=4;ae->tick+=13;
} else {
___output(ae,0x3E);
PushExpression(ae,ae->idx+2,E_EXPRESSION_V8);
- ae->nop+=2;
+ ae->nop+=2;ae->tick+=7;
}
}
break;
case CRC_I:
if (GetCRC(ae->wl[ae->idx+2].w)==CRC_A) {
___output(ae,0xED);___output(ae,0x47);
- ae->nop+=3;
+ ae->nop+=3;ae->tick+=9;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD I,A only\n");
}
@@ -7992,269 +10567,289 @@ void _LD(struct s_assenv *ae) {
case CRC_R:
if (GetCRC(ae->wl[ae->idx+2].w)==CRC_A) {
___output(ae,0xED);___output(ae,0x4F);
- ae->nop+=3;
+ ae->nop+=3;ae->tick+=9;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD R,A only\n");
}
break;
case CRC_B:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:___output(ae,0x40);ae->nop+=1;break;
- case CRC_C:___output(ae,0x41);ae->nop+=1;break;
- case CRC_D:___output(ae,0x42);ae->nop+=1;break;
- case CRC_E:___output(ae,0x43);ae->nop+=1;break;
- case CRC_H:___output(ae,0x44);ae->nop+=1;break;
- case CRC_L:___output(ae,0x45);ae->nop+=1;break;
- case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x44);ae->nop+=2;break;
- case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x45);ae->nop+=2;break;
- case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x44);ae->nop+=2;break;
- case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x45);ae->nop+=2;break;
- case CRC_MHL:___output(ae,0x46);ae->nop+=2;break;
- case CRC_A:___output(ae,0x47);ae->nop+=1;break;
+ case CRC_B:___output(ae,0x40);ae->nop+=1;ae->tick+=4;break;
+ case CRC_C:___output(ae,0x41);ae->nop+=1;ae->tick+=4;break;
+ case CRC_D:___output(ae,0x42);ae->nop+=1;ae->tick+=4;break;
+ case CRC_E:___output(ae,0x43);ae->nop+=1;ae->tick+=4;break;
+ case CRC_H:___output(ae,0x44);ae->nop+=1;ae->tick+=4;break;
+ case CRC_L:___output(ae,0x45);ae->nop+=1;ae->tick+=4;break;
+ case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x44);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x45);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x44);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x45);ae->nop+=2;ae->tick+=8;break;
+ case CRC_MHL:___output(ae,0x46);ae->nop+=2;ae->tick+=7;break;
+ case CRC_A:___output(ae,0x47);ae->nop+=1;ae->tick+=4;break;
default:
/* (ix+expression) (iy+expression) expression */
if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0x46);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0x46);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else {
___output(ae,0x06);
PushExpression(ae,ae->idx+2,E_EXPRESSION_V8);
- ae->nop+=2;
+ ae->nop+=2;ae->tick+=7;
}
}
break;
case CRC_C:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:___output(ae,0x48);ae->nop+=1;break;
- case CRC_C:___output(ae,0x49);ae->nop+=1;break;
- case CRC_D:___output(ae,0x4A);ae->nop+=1;break;
- case CRC_E:___output(ae,0x4B);ae->nop+=1;break;
- case CRC_H:___output(ae,0x4C);ae->nop+=1;break;
- case CRC_L:___output(ae,0x4D);ae->nop+=1;break;
- case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x4C);ae->nop+=2;break;
- case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x4D);ae->nop+=2;break;
- case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x4C);ae->nop+=2;break;
- case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x4D);ae->nop+=2;break;
- case CRC_MHL:___output(ae,0x4E);ae->nop+=2;break;
- case CRC_A:___output(ae,0x4F);ae->nop+=1;break;
+ case CRC_B:___output(ae,0x48);ae->nop+=1;ae->tick+=4;break;
+ case CRC_C:___output(ae,0x49);ae->nop+=1;ae->tick+=4;break;
+ case CRC_D:___output(ae,0x4A);ae->nop+=1;ae->tick+=4;break;
+ case CRC_E:___output(ae,0x4B);ae->nop+=1;ae->tick+=4;break;
+ case CRC_H:___output(ae,0x4C);ae->nop+=1;ae->tick+=4;break;
+ case CRC_L:___output(ae,0x4D);ae->nop+=1;ae->tick+=4;break;
+ case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x4C);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x4D);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x4C);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x4D);ae->nop+=2;ae->tick+=8;break;
+ case CRC_MHL:___output(ae,0x4E);ae->nop+=2;ae->tick+=7;break;
+ case CRC_A:___output(ae,0x4F);ae->nop+=1;ae->tick+=4;break;
default:
/* (ix+expression) (iy+expression) expression */
if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0x4E);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0x4E);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else {
___output(ae,0x0E);
PushExpression(ae,ae->idx+2,E_EXPRESSION_V8);
- ae->nop+=2;
+ ae->nop+=2;ae->tick+=7;
}
}
break;
case CRC_D:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:___output(ae,0x50);ae->nop+=1;break;
- case CRC_C:___output(ae,0x51);ae->nop+=1;break;
- case CRC_D:___output(ae,0x52);ae->nop+=1;break;
- case CRC_E:___output(ae,0x53);ae->nop+=1;break;
- case CRC_H:___output(ae,0x54);ae->nop+=1;break;
- case CRC_L:___output(ae,0x55);ae->nop+=1;break;
- case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x54);ae->nop+=2;break;
- case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x55);ae->nop+=2;break;
- case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x54);ae->nop+=2;break;
- case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x55);ae->nop+=2;break;
- case CRC_MHL:___output(ae,0x56);ae->nop+=2;break;
- case CRC_A:___output(ae,0x57);ae->nop+=1;break;
+ case CRC_B:___output(ae,0x50);ae->nop+=1;ae->tick+=4;break;
+ case CRC_C:___output(ae,0x51);ae->nop+=1;ae->tick+=4;break;
+ case CRC_D:___output(ae,0x52);ae->nop+=1;ae->tick+=4;break;
+ case CRC_E:___output(ae,0x53);ae->nop+=1;ae->tick+=4;break;
+ case CRC_H:___output(ae,0x54);ae->nop+=1;ae->tick+=4;break;
+ case CRC_L:___output(ae,0x55);ae->nop+=1;ae->tick+=4;break;
+ case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x54);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x55);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x54);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x55);ae->nop+=2;ae->tick+=8;break;
+ case CRC_MHL:___output(ae,0x56);ae->nop+=2;ae->tick+=7;break;
+ case CRC_A:___output(ae,0x57);ae->nop+=1;ae->tick+=4;break;
default:
/* (ix+expression) (iy+expression) expression */
if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0x56);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0x56);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else {
___output(ae,0x16);
PushExpression(ae,ae->idx+2,E_EXPRESSION_V8);
- ae->nop+=2;
+ ae->nop+=2;ae->tick+=7;
}
}
break;
case CRC_E:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:___output(ae,0x58);ae->nop+=1;break;
- case CRC_C:___output(ae,0x59);ae->nop+=1;break;
- case CRC_D:___output(ae,0x5A);ae->nop+=1;break;
- case CRC_E:___output(ae,0x5B);ae->nop+=1;break;
- case CRC_H:___output(ae,0x5C);ae->nop+=1;break;
- case CRC_L:___output(ae,0x5D);ae->nop+=1;break;
- case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x5C);ae->nop+=2;break;
- case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x5D);ae->nop+=2;break;
- case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x5C);ae->nop+=2;break;
- case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x5D);ae->nop+=2;break;
- case CRC_MHL:___output(ae,0x5E);ae->nop+=2;break;
- case CRC_A:___output(ae,0x5F);ae->nop+=1;break;
+ case CRC_B:___output(ae,0x58);ae->nop+=1;ae->tick+=4;break;
+ case CRC_C:___output(ae,0x59);ae->nop+=1;ae->tick+=4;break;
+ case CRC_D:___output(ae,0x5A);ae->nop+=1;ae->tick+=4;break;
+ case CRC_E:___output(ae,0x5B);ae->nop+=1;ae->tick+=4;break;
+ case CRC_H:___output(ae,0x5C);ae->nop+=1;ae->tick+=4;break;
+ case CRC_L:___output(ae,0x5D);ae->nop+=1;ae->tick+=4;break;
+ case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x5C);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x5D);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x5C);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x5D);ae->nop+=2;ae->tick+=8;break;
+ case CRC_MHL:___output(ae,0x5E);ae->nop+=2;ae->tick+=7;break;
+ case CRC_A:___output(ae,0x5F);ae->nop+=1;ae->tick+=4;break;
default:
/* (ix+expression) (iy+expression) expression */
if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0x5E);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0x5E);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else {
___output(ae,0x1E);
PushExpression(ae,ae->idx+2,E_EXPRESSION_V8);
- ae->nop+=2;
+ ae->nop+=2;ae->tick+=7;
}
}
break;
case CRC_IYH:case CRC_HY:case CRC_YH:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:___output(ae,0xFD);___output(ae,0x60);ae->nop+=2;break;
- case CRC_C:___output(ae,0xFD);___output(ae,0x61);ae->nop+=2;break;
- case CRC_D:___output(ae,0xFD);___output(ae,0x62);ae->nop+=2;break;
- case CRC_E:___output(ae,0xFD);___output(ae,0x63);ae->nop+=2;break;
- case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x64);ae->nop+=2;break;
- case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x65);ae->nop+=2;break;
- case CRC_A:___output(ae,0xFD);___output(ae,0x67);ae->nop+=2;break;
+ case CRC_B:___output(ae,0xFD);___output(ae,0x60);ae->nop+=2;ae->tick+=8;break;
+ case CRC_C:___output(ae,0xFD);___output(ae,0x61);ae->nop+=2;ae->tick+=8;break;
+ case CRC_D:___output(ae,0xFD);___output(ae,0x62);ae->nop+=2;ae->tick+=8;break;
+ case CRC_E:___output(ae,0xFD);___output(ae,0x63);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x64);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x65);ae->nop+=2;ae->tick+=8;break;
+ case CRC_A:___output(ae,0xFD);___output(ae,0x67);ae->nop+=2;ae->tick+=8;break;
default:
- ___output(ae,0xFD);___output(ae,0x26);
- PushExpression(ae,ae->idx+2,E_EXPRESSION_V8);
- ae->nop+=3;
+ if (strncmp(ae->wl[ae->idx+2].w,"(IX",3) && strncmp(ae->wl[ae->idx+2].w,"(IY",3)) {
+ ___output(ae,0xFD);___output(ae,0x26);
+ PushExpression(ae,ae->idx+2,E_EXPRESSION_V8);
+ ae->nop+=3;ae->tick+=11;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD iyh,n/r only\n");
+ }
}
break;
case CRC_IYL:case CRC_LY:case CRC_YL:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:___output(ae,0xFD);___output(ae,0x68);ae->nop+=2;break;
- case CRC_C:___output(ae,0xFD);___output(ae,0x69);ae->nop+=2;break;
- case CRC_D:___output(ae,0xFD);___output(ae,0x6A);ae->nop+=2;break;
- case CRC_E:___output(ae,0xFD);___output(ae,0x6B);ae->nop+=2;break;
- case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x6C);ae->nop+=2;break;
- case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x6D);ae->nop+=2;break;
- case CRC_A:___output(ae,0xFD);___output(ae,0x6F);ae->nop+=2;break;
+ case CRC_B:___output(ae,0xFD);___output(ae,0x68);ae->nop+=2;ae->tick+=8;break;
+ case CRC_C:___output(ae,0xFD);___output(ae,0x69);ae->nop+=2;ae->tick+=8;break;
+ case CRC_D:___output(ae,0xFD);___output(ae,0x6A);ae->nop+=2;ae->tick+=8;break;
+ case CRC_E:___output(ae,0xFD);___output(ae,0x6B);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYH:case CRC_HY:case CRC_YH:___output(ae,0xFD);___output(ae,0x6C);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IYL:case CRC_LY:case CRC_YL:___output(ae,0xFD);___output(ae,0x6D);ae->nop+=2;ae->tick+=8;break;
+ case CRC_A:___output(ae,0xFD);___output(ae,0x6F);ae->nop+=2;ae->tick+=8;break;
default:
- ___output(ae,0xFD);___output(ae,0x2E);
- PushExpression(ae,ae->idx+2,E_EXPRESSION_V8);
- ae->nop+=3;
+ if (strncmp(ae->wl[ae->idx+2].w,"(IX",3) && strncmp(ae->wl[ae->idx+2].w,"(IY",3)) {
+ ___output(ae,0xFD);___output(ae,0x2E);
+ PushExpression(ae,ae->idx+2,E_EXPRESSION_V8);
+ ae->nop+=3;ae->tick+=11;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD iyl,n/r only\n");
+ }
}
break;
case CRC_IXH:case CRC_HX:case CRC_XH:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:___output(ae,0xDD);___output(ae,0x60);ae->nop+=2;break;
- case CRC_C:___output(ae,0xDD);___output(ae,0x61);ae->nop+=2;break;
- case CRC_D:___output(ae,0xDD);___output(ae,0x62);ae->nop+=2;break;
- case CRC_E:___output(ae,0xDD);___output(ae,0x63);ae->nop+=2;break;
- case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x64);ae->nop+=2;break;
- case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x65);ae->nop+=2;break;
- case CRC_A:___output(ae,0xDD);___output(ae,0x67);ae->nop+=2;break;
+ case CRC_B:___output(ae,0xDD);___output(ae,0x60);ae->nop+=2;ae->tick+=8;break;
+ case CRC_C:___output(ae,0xDD);___output(ae,0x61);ae->nop+=2;ae->tick+=8;break;
+ case CRC_D:___output(ae,0xDD);___output(ae,0x62);ae->nop+=2;ae->tick+=8;break;
+ case CRC_E:___output(ae,0xDD);___output(ae,0x63);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x64);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x65);ae->nop+=2;ae->tick+=8;break;
+ case CRC_A:___output(ae,0xDD);___output(ae,0x67);ae->nop+=2;ae->tick+=8;break;
default:
- ___output(ae,0xDD);___output(ae,0x26);
- PushExpression(ae,ae->idx+2,E_EXPRESSION_V8);
- ae->nop+=3;
+ if (strncmp(ae->wl[ae->idx+2].w,"(IX",3) && strncmp(ae->wl[ae->idx+2].w,"(IY",3)) {
+ ___output(ae,0xDD);___output(ae,0x26);
+ PushExpression(ae,ae->idx+2,E_EXPRESSION_V8);
+ ae->nop+=3;ae->tick+=11;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD ixh,n/r only\n");
+ }
}
break;
case CRC_IXL:case CRC_LX:case CRC_XL:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:___output(ae,0xDD);___output(ae,0x68);ae->nop+=2;break;
- case CRC_C:___output(ae,0xDD);___output(ae,0x69);ae->nop+=2;break;
- case CRC_D:___output(ae,0xDD);___output(ae,0x6A);ae->nop+=2;break;
- case CRC_E:___output(ae,0xDD);___output(ae,0x6B);ae->nop+=2;break;
- case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x6C);ae->nop+=2;break;
- case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x6D);ae->nop+=2;break;
- case CRC_A:___output(ae,0xDD);___output(ae,0x6F);ae->nop+=2;break;
+ case CRC_B:___output(ae,0xDD);___output(ae,0x68);ae->nop+=2;ae->tick+=8;break;
+ case CRC_C:___output(ae,0xDD);___output(ae,0x69);ae->nop+=2;ae->tick+=8;break;
+ case CRC_D:___output(ae,0xDD);___output(ae,0x6A);ae->nop+=2;ae->tick+=8;break;
+ case CRC_E:___output(ae,0xDD);___output(ae,0x6B);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXH:case CRC_HX:case CRC_XH:___output(ae,0xDD);___output(ae,0x6C);ae->nop+=2;ae->tick+=8;break;
+ case CRC_IXL:case CRC_LX:case CRC_XL:___output(ae,0xDD);___output(ae,0x6D);ae->nop+=2;ae->tick+=8;break;
+ case CRC_A:___output(ae,0xDD);___output(ae,0x6F);ae->nop+=2;ae->tick+=8;break;
default:
- ___output(ae,0xDD);___output(ae,0x2E);
- PushExpression(ae,ae->idx+2,E_EXPRESSION_V8);
- ae->nop+=3;
+ if (strncmp(ae->wl[ae->idx+2].w,"(IX",3) && strncmp(ae->wl[ae->idx+2].w,"(IY",3)) {
+ ___output(ae,0xDD);___output(ae,0x2E);
+ PushExpression(ae,ae->idx+2,E_EXPRESSION_V8);
+ ae->nop+=3;ae->tick+=11;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD ixl,n/r only\n");
+ }
}
break;
case CRC_H:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:___output(ae,0x60);ae->nop+=1;break;
- case CRC_C:___output(ae,0x61);ae->nop+=1;break;
- case CRC_D:___output(ae,0x62);ae->nop+=1;break;
- case CRC_E:___output(ae,0x63);ae->nop+=1;break;
- case CRC_H:___output(ae,0x64);ae->nop+=1;break;
- case CRC_L:___output(ae,0x65);ae->nop+=1;break;
- case CRC_MHL:___output(ae,0x66);ae->nop+=2;break;
- case CRC_A:___output(ae,0x67);ae->nop+=1;break;
+ case CRC_B:___output(ae,0x60);ae->nop+=1;ae->tick+=4;break;
+ case CRC_C:___output(ae,0x61);ae->nop+=1;ae->tick+=4;break;
+ case CRC_D:___output(ae,0x62);ae->nop+=1;ae->tick+=4;break;
+ case CRC_E:___output(ae,0x63);ae->nop+=1;ae->tick+=4;break;
+ case CRC_H:___output(ae,0x64);ae->nop+=1;ae->tick+=4;break;
+ case CRC_L:___output(ae,0x65);ae->nop+=1;ae->tick+=4;break;
+ case CRC_MHL:___output(ae,0x66);ae->nop+=2;ae->tick+=7;break;
+ case CRC_A:___output(ae,0x67);ae->nop+=1;ae->tick+=4;break;
default:
/* (ix+expression) (iy+expression) expression */
if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0x66);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0x66);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else {
___output(ae,0x26);
PushExpression(ae,ae->idx+2,E_EXPRESSION_V8);
- ae->nop+=2;
+ ae->nop+=2;ae->tick+=7;
}
}
break;
case CRC_L:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:___output(ae,0x68);ae->nop+=1;break;
- case CRC_C:___output(ae,0x69);ae->nop+=1;break;
- case CRC_D:___output(ae,0x6A);ae->nop+=1;break;
- case CRC_E:___output(ae,0x6B);ae->nop+=1;break;
- case CRC_H:___output(ae,0x6C);ae->nop+=1;break;
- case CRC_L:___output(ae,0x6D);ae->nop+=1;break;
- case CRC_MHL:___output(ae,0x6E);ae->nop+=2;break;
- case CRC_A:___output(ae,0x6F);ae->nop+=1;break;
+ case CRC_B:___output(ae,0x68);ae->nop+=1;ae->tick+=4;break;
+ case CRC_C:___output(ae,0x69);ae->nop+=1;ae->tick+=4;break;
+ case CRC_D:___output(ae,0x6A);ae->nop+=1;ae->tick+=4;break;
+ case CRC_E:___output(ae,0x6B);ae->nop+=1;ae->tick+=4;break;
+ case CRC_H:___output(ae,0x6C);ae->nop+=1;ae->tick+=4;break;
+ case CRC_L:___output(ae,0x6D);ae->nop+=1;ae->tick+=4;break;
+ case CRC_MHL:___output(ae,0x6E);ae->nop+=2;ae->tick+=7;break;
+ case CRC_A:___output(ae,0x6F);ae->nop+=1;ae->tick+=4;break;
default:
/* (ix+expression) (iy+expression) expression */
if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0x6E);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0x6E);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=19;
} else {
___output(ae,0x2E);
PushExpression(ae,ae->idx+2,E_EXPRESSION_V8);
- ae->nop+=2;
+ ae->nop+=2;ae->tick+=7;
}
}
break;
case CRC_MHL:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:___output(ae,0x70);ae->nop+=2;break;
- case CRC_C:___output(ae,0x71);ae->nop+=2;break;
- case CRC_D:___output(ae,0x72);ae->nop+=2;break;
- case CRC_E:___output(ae,0x73);ae->nop+=2;break;
- case CRC_H:___output(ae,0x74);ae->nop+=2;break;
- case CRC_L:___output(ae,0x75);ae->nop+=2;break;
- case CRC_A:___output(ae,0x77);ae->nop+=2;break;
+ case CRC_B:___output(ae,0x70);ae->nop+=2;ae->tick+=7;break;
+ case CRC_C:___output(ae,0x71);ae->nop+=2;ae->tick+=7;break;
+ case CRC_D:___output(ae,0x72);ae->nop+=2;ae->tick+=7;break;
+ case CRC_E:___output(ae,0x73);ae->nop+=2;ae->tick+=7;break;
+ case CRC_H:___output(ae,0x74);ae->nop+=2;ae->tick+=7;break;
+ case CRC_L:___output(ae,0x75);ae->nop+=2;ae->tick+=7;break;
+ case CRC_A:___output(ae,0x77);ae->nop+=2;ae->tick+=7;break;
default:
/* expression */
- ___output(ae,0x36);
- PushExpression(ae,ae->idx+2,E_EXPRESSION_V8);
- ae->nop+=3;
+ if (!StringIsMem(ae->wl[ae->idx+2].w)) {
+ ___output(ae,0x36);
+ PushExpression(ae,ae->idx+2,E_EXPRESSION_V8);
+ ae->nop+=3;ae->tick+=10;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD (HL),n/r only\n");
+ }
}
break;
case CRC_MBC:
if (GetCRC(ae->wl[ae->idx+2].w)==CRC_A) {
___output(ae,0x02);
- ae->nop+=2;
+ ae->nop+=2;ae->tick+=7;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD (BC),A only\n");
}
@@ -8262,140 +10857,178 @@ void _LD(struct s_assenv *ae) {
case CRC_MDE:
if (GetCRC(ae->wl[ae->idx+2].w)==CRC_A) {
___output(ae,0x12);
- ae->nop+=2;
+ ae->nop+=2;ae->tick+=7;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD (DE),A only\n");
}
break;
case CRC_HL:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_BC:___output(ae,0x60);___output(ae,0x69);ae->nop+=2;break;
- case CRC_DE:___output(ae,0x62);___output(ae,0x6B);ae->nop+=2;break;
- case CRC_HL:___output(ae,0x64);___output(ae,0x6D);ae->nop+=2;break;
+ case CRC_BC:___output(ae,0x60);___output(ae,0x69);ae->nop+=2;ae->tick+=8;break;
+ case CRC_DE:___output(ae,0x62);___output(ae,0x6B);ae->nop+=2;ae->tick+=8;break;
+ case CRC_HL:___output(ae,0x64);___output(ae,0x6D);ae->nop+=2;ae->tick+=8;break;
default:
- if (strncmp(ae->wl[ae->idx+2].w,"(IX+",4)==0) {
+ if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0 && (ae->wl[ae->idx+2].w[3]=='+' || ae->wl[ae->idx+2].w[3]=='-')) {
/* enhanced LD HL,(IX+nn) */
___output(ae,0xDD);___output(ae,0x66);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV81);
___output(ae,0xDD);___output(ae,0x6E);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=10;
- } else if (strncmp(ae->wl[ae->idx+2].w,"(IY+",4)==0) {
+ ae->nop+=10;ae->tick+=19;ae->tick+=19;
+ } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0 && (ae->wl[ae->idx+2].w[3]=='+' || ae->wl[ae->idx+2].w[3]=='-')) {
/* enhanced LD HL,(IY+nn) */
___output(ae,0xFD);___output(ae,0x66);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV81);
___output(ae,0xFD);___output(ae,0x6E);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=10;
+ ae->nop+=10;ae->tick+=19;ae->tick+=19;
} else if (StringIsMem(ae->wl[ae->idx+2].w)) {
___output(ae,0x2A);
PushExpression(ae,ae->idx+2,E_EXPRESSION_V16);
- ae->nop+=5;
+ ae->nop+=5;ae->tick+=16;
} else {
___output(ae,0x21);
PushExpression(ae,ae->idx+2,E_EXPRESSION_V16);
- ae->nop+=3;
+ ae->nop+=3;ae->tick+=10;
}
}
break;
case CRC_BC:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_BC:___output(ae,0x40);___output(ae,0x49);ae->nop+=2;break;
- case CRC_DE:___output(ae,0x42);___output(ae,0x4B);ae->nop+=2;break;
- case CRC_HL:___output(ae,0x44);___output(ae,0x4D);ae->nop+=2;break;
+ case CRC_BC:___output(ae,0x40);___output(ae,0x49);ae->nop+=2;ae->tick+=8;break;
+ case CRC_DE:___output(ae,0x42);___output(ae,0x4B);ae->nop+=2;ae->tick+=8;break;
+ case CRC_HL:___output(ae,0x44);___output(ae,0x4D);ae->nop+=2;ae->tick+=8;break;
+ /* enhanced LD BC,IX / LD BC,IY */
+ case CRC_IX:___output(ae,0xDD);___output(ae,0x44);ae->nop+=4;
+ ___output(ae,0xDD);___output(ae,0x4D);ae->tick+=16;break;
+ case CRC_IY:___output(ae,0xFD);___output(ae,0x44);ae->nop+=4;
+ ___output(ae,0xFD);___output(ae,0x4D);ae->tick+=16;break;
default:
- if (strncmp(ae->wl[ae->idx+2].w,"(IX+",4)==0) {
+ if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0 && (ae->wl[ae->idx+2].w[3]=='+' || ae->wl[ae->idx+2].w[3]=='-')) {
/* enhanced LD BC,(IX+nn) */
___output(ae,0xDD);___output(ae,0x46);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV81);
___output(ae,0xDD);___output(ae,0x4E);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=10;
- } else if (strncmp(ae->wl[ae->idx+2].w,"(IY+",4)==0) {
+ ae->nop+=10;ae->tick+=19;ae->tick+=19;
+ } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0 && (ae->wl[ae->idx+2].w[3]=='+' || ae->wl[ae->idx+2].w[3]=='-')) {
/* enhanced LD BC,(IY+nn) */
___output(ae,0xFD);___output(ae,0x46);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV81);
___output(ae,0xFD);___output(ae,0x4E);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=10;
+ ae->nop+=10;ae->tick+=19;ae->tick+=19;
} else if (StringIsMem(ae->wl[ae->idx+2].w)) {
___output(ae,0xED);___output(ae,0x4B);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16);
- ae->nop+=6;
+ ae->nop+=6;ae->tick+=20;
} else {
___output(ae,0x01);
PushExpression(ae,ae->idx+2,E_EXPRESSION_V16);
- ae->nop+=3;
+ ae->nop+=3;ae->tick+=10;
}
}
break;
case CRC_DE:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_BC:___output(ae,0x50);___output(ae,0x59);ae->nop+=2;break;
- case CRC_DE:___output(ae,0x52);___output(ae,0x5B);ae->nop+=2;break;
- case CRC_HL:___output(ae,0x54);___output(ae,0x5D);ae->nop+=2;break;
+ case CRC_BC:___output(ae,0x50);___output(ae,0x59);ae->nop+=2;ae->tick+=8;break;
+ case CRC_DE:___output(ae,0x52);___output(ae,0x5B);ae->nop+=2;ae->tick+=8;break;
+ case CRC_HL:___output(ae,0x54);___output(ae,0x5D);ae->nop+=2;ae->tick+=8;break;
+ /* enhanced LD DE,IX / LD DE,IY */
+ case CRC_IX:___output(ae,0xDD);___output(ae,0x54);ae->nop+=4;
+ ___output(ae,0xDD);___output(ae,0x5D);ae->tick+=16;break;
+ case CRC_IY:___output(ae,0xFD);___output(ae,0x54);ae->nop+=4;
+ ___output(ae,0xFD);___output(ae,0x5D);ae->tick+=16;break;
default:
- if (strncmp(ae->wl[ae->idx+2].w,"(IX+",4)==0) {
+ if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0 && (ae->wl[ae->idx+2].w[3]=='+' || ae->wl[ae->idx+2].w[3]=='-')) {
/* enhanced LD DE,(IX+nn) */
___output(ae,0xDD);___output(ae,0x56);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV81);
___output(ae,0xDD);___output(ae,0x5E);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=10;
- } else if (strncmp(ae->wl[ae->idx+2].w,"(IY+",4)==0) {
+ ae->nop+=10;ae->tick+=19;ae->tick+=19;
+ } else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0 && (ae->wl[ae->idx+2].w[3]=='+' || ae->wl[ae->idx+2].w[3]=='-')) {
/* enhanced LD DE,(IY+nn) */
___output(ae,0xFD);___output(ae,0x56);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV81);
___output(ae,0xFD);___output(ae,0x5E);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
- ae->nop+=10;
+ ae->nop+=10;ae->tick+=19;ae->tick+=19;
} else if (StringIsMem(ae->wl[ae->idx+2].w)) {
___output(ae,0xED);___output(ae,0x5B);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16);
- ae->nop+=6;
+ ae->nop+=6;ae->tick+=20;
} else {
___output(ae,0x11);
PushExpression(ae,ae->idx+2,E_EXPRESSION_V16);
- ae->nop+=3;
+ ae->nop+=3;ae->tick+=10;
}
}
break;
case CRC_IX:
- if (StringIsMem(ae->wl[ae->idx+2].w)) {
- ___output(ae,0xDD);___output(ae,0x2A);
- PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16);
- ae->nop+=6;
- } else {
- ___output(ae,0xDD);___output(ae,0x21);
- PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16);
- ae->nop+=4;
+ switch (GetCRC(ae->wl[ae->idx+2].w)) {
+ /* enhanced LD IX,BC / LD IX,DE */
+ case CRC_BC:___output(ae,0xDD);___output(ae,0x60);
+ ___output(ae,0xDD);___output(ae,0x69);ae->nop+=4;ae->tick+=16;break;
+ case CRC_DE:___output(ae,0xDD);___output(ae,0x62);
+ ___output(ae,0xDD);___output(ae,0x6B);ae->nop+=4;ae->tick+=16;break;
+ default:
+ if (strncmp(ae->wl[ae->idx+2].w,"(IX",3) && strncmp(ae->wl[ae->idx+2].w,"(IY",3)) {
+ if (StringIsMem(ae->wl[ae->idx+2].w)) {
+ ___output(ae,0xDD);___output(ae,0x2A);
+ PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16);
+ ae->nop+=6;ae->tick+=20;
+ } else {
+ ___output(ae,0xDD);___output(ae,0x21);
+ PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16);
+ ae->nop+=4;ae->tick+=14;
+ }
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD IX,(nn)/BC/DE/nn only\n");
+ }
}
break;
case CRC_IY:
- if (StringIsMem(ae->wl[ae->idx+2].w)) {
- ___output(ae,0xFD);___output(ae,0x2A);
- PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16);
- ae->nop+=6;
- } else {
- ___output(ae,0xFD);___output(ae,0x21);
- PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16);
- ae->nop+=4;
+ switch (GetCRC(ae->wl[ae->idx+2].w)) {
+ /* enhanced LD IY,BC / LD IY,DE */
+ case CRC_BC:___output(ae,0xFD);___output(ae,0x60);
+ ___output(ae,0xFD);___output(ae,0x69);ae->nop+=4;ae->tick+=16;break;
+ case CRC_DE:___output(ae,0xFD);___output(ae,0x62);
+ ___output(ae,0xFD);___output(ae,0x6B);ae->nop+=4;ae->tick+=16;break;
+ default:
+ if (strncmp(ae->wl[ae->idx+2].w,"(IX",3) && strncmp(ae->wl[ae->idx+2].w,"(IY",3)) {
+ if (StringIsMem(ae->wl[ae->idx+2].w)) {
+ ___output(ae,0xFD);___output(ae,0x2A);
+ PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16);
+ ae->nop+=6;ae->tick+=20;
+ } else {
+ ___output(ae,0xFD);___output(ae,0x21);
+ PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16);
+ ae->nop+=4;ae->tick+=14;
+ }
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD IY,(nn)/BC/DE/nn only\n");
+ }
}
break;
case CRC_SP:
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_HL:___output(ae,0xF9);ae->nop+=2;break;
- case CRC_IX:___output(ae,0xDD);___output(ae,0xF9);ae->nop+=3;break;
- case CRC_IY:___output(ae,0xFD);___output(ae,0xF9);ae->nop+=3;break;
+ case CRC_HL:___output(ae,0xF9);ae->nop+=2;ae->tick+=6;break;
+ case CRC_IX:___output(ae,0xDD);___output(ae,0xF9);ae->nop+=3;ae->tick+=10;break;
+ case CRC_IY:___output(ae,0xFD);___output(ae,0xF9);ae->nop+=3;ae->tick+=10;break;
default:
- if (StringIsMem(ae->wl[ae->idx+2].w)) {
- ___output(ae,0xED);___output(ae,0x7B);
- PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16);
- ae->nop+=6;
+ if (strncmp(ae->wl[ae->idx+2].w,"(IX",3) && strncmp(ae->wl[ae->idx+2].w,"(IY",3)) {
+ if (StringIsMem(ae->wl[ae->idx+2].w)) {
+ ___output(ae,0xED);___output(ae,0x7B);
+ PushExpression(ae,ae->idx+2,E_EXPRESSION_IV16);
+ ae->nop+=6;ae->tick+=20;
+ } else {
+ ___output(ae,0x31);
+ PushExpression(ae,ae->idx+2,E_EXPRESSION_V16);
+ ae->nop+=3;ae->tick+=10;
+ }
} else {
- ___output(ae,0x31);
- PushExpression(ae,ae->idx+2,E_EXPRESSION_V16);
- ae->nop+=3;
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD SP,(nn)/HL/IX/IY only\n");
}
}
break;
@@ -8403,47 +11036,57 @@ void _LD(struct s_assenv *ae) {
/* (ix+expression) (iy+expression) (expression) expression */
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:___output(ae,0xDD);___output(ae,0x70);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break;
- case CRC_C:___output(ae,0xDD);___output(ae,0x71);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break;
- case CRC_D:___output(ae,0xDD);___output(ae,0x72);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break;
- case CRC_E:___output(ae,0xDD);___output(ae,0x73);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break;
- case CRC_H:___output(ae,0xDD);___output(ae,0x74);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break;
- case CRC_L:___output(ae,0xDD);___output(ae,0x75);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break;
- case CRC_A:___output(ae,0xDD);___output(ae,0x77);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break;
- case CRC_HL:___output(ae,0xDD);___output(ae,0x74);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV81);___output(ae,0xDD);___output(ae,0x75);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=10;break;
- case CRC_DE:___output(ae,0xDD);___output(ae,0x72);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV81);___output(ae,0xDD);___output(ae,0x73);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=10;break;
- case CRC_BC:___output(ae,0xDD);___output(ae,0x70);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV81);___output(ae,0xDD);___output(ae,0x71);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=10;break;
- default:___output(ae,0xDD);___output(ae,0x36);
- PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- PushExpression(ae,ae->idx+2,E_EXPRESSION_3V8);
- ae->nop+=6;
+ case CRC_B:___output(ae,0xDD);___output(ae,0x70);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;ae->tick+=19;break;
+ case CRC_C:___output(ae,0xDD);___output(ae,0x71);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;ae->tick+=19;break;
+ case CRC_D:___output(ae,0xDD);___output(ae,0x72);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;ae->tick+=19;break;
+ case CRC_E:___output(ae,0xDD);___output(ae,0x73);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;ae->tick+=19;break;
+ case CRC_H:___output(ae,0xDD);___output(ae,0x74);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;ae->tick+=19;break;
+ case CRC_L:___output(ae,0xDD);___output(ae,0x75);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;ae->tick+=19;break;
+ case CRC_A:___output(ae,0xDD);___output(ae,0x77);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;ae->tick+=19;break;
+ case CRC_HL:___output(ae,0xDD);___output(ae,0x74);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV81);___output(ae,0xDD);___output(ae,0x75);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=10;ae->tick+=38;break;
+ case CRC_DE:___output(ae,0xDD);___output(ae,0x72);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV81);___output(ae,0xDD);___output(ae,0x73);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=10;ae->tick+=38;break;
+ case CRC_BC:___output(ae,0xDD);___output(ae,0x70);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV81);___output(ae,0xDD);___output(ae,0x71);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=10;ae->tick+=38;break;
+ default:
+ if (!StringIsMem(ae->wl[ae->idx+2].w)) {
+ ___output(ae,0xDD);___output(ae,0x36);
+ PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
+ PushExpression(ae,ae->idx+2,E_EXPRESSION_3V8);
+ ae->nop+=6;ae->tick+=23;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD (IX+n),n/r only\n");
+ }
}
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:___output(ae,0xFD);___output(ae,0x70);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break;
- case CRC_C:___output(ae,0xFD);___output(ae,0x71);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break;
- case CRC_D:___output(ae,0xFD);___output(ae,0x72);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break;
- case CRC_E:___output(ae,0xFD);___output(ae,0x73);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break;
- case CRC_H:___output(ae,0xFD);___output(ae,0x74);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break;
- case CRC_L:___output(ae,0xFD);___output(ae,0x75);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break;
- case CRC_A:___output(ae,0xFD);___output(ae,0x77);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;break;
- case CRC_HL:___output(ae,0xFD);___output(ae,0x74);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV81);___output(ae,0xFD);___output(ae,0x75);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=10;break;
- case CRC_DE:___output(ae,0xFD);___output(ae,0x72);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV81);___output(ae,0xFD);___output(ae,0x73);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=10;break;
- case CRC_BC:___output(ae,0xFD);___output(ae,0x70);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV81);___output(ae,0xFD);___output(ae,0x71);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=10;break;
- default:___output(ae,0xFD);___output(ae,0x36);
- PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- PushExpression(ae,ae->idx+2,E_EXPRESSION_3V8);
- ae->nop+=6;
+ case CRC_B:___output(ae,0xFD);___output(ae,0x70);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;ae->tick+=19;break;
+ case CRC_C:___output(ae,0xFD);___output(ae,0x71);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;ae->tick+=19;break;
+ case CRC_D:___output(ae,0xFD);___output(ae,0x72);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;ae->tick+=19;break;
+ case CRC_E:___output(ae,0xFD);___output(ae,0x73);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;ae->tick+=19;break;
+ case CRC_H:___output(ae,0xFD);___output(ae,0x74);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;ae->tick+=19;break;
+ case CRC_L:___output(ae,0xFD);___output(ae,0x75);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;ae->tick+=19;break;
+ case CRC_A:___output(ae,0xFD);___output(ae,0x77);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=5;ae->tick+=19;break;
+ case CRC_HL:___output(ae,0xFD);___output(ae,0x74);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV81);___output(ae,0xFD);___output(ae,0x75);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=10;ae->tick+=38;break;
+ case CRC_DE:___output(ae,0xFD);___output(ae,0x72);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV81);___output(ae,0xFD);___output(ae,0x73);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=10;ae->tick+=38;break;
+ case CRC_BC:___output(ae,0xFD);___output(ae,0x70);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV81);___output(ae,0xFD);___output(ae,0x71);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);ae->nop+=10;ae->tick+=38;break;
+ default:
+ if (!StringIsMem(ae->wl[ae->idx+2].w)) {
+ ___output(ae,0xFD);___output(ae,0x36);
+ PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
+ PushExpression(ae,ae->idx+2,E_EXPRESSION_3V8);
+ ae->nop+=6;ae->tick+=23;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD (IX+n),n/r only\n");
+ }
}
} else if (StringIsMem(ae->wl[ae->idx+1].w)) {
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_A:___output(ae,0x32);PushExpression(ae,ae->idx+1,E_EXPRESSION_V16);ae->nop+=4;break;
- case CRC_BC:___output(ae,0xED);___output(ae,0x43);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV16);ae->nop+=6;break;
- case CRC_DE:___output(ae,0xED);___output(ae,0x53);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV16);ae->nop+=6;break;
- case CRC_HL:___output(ae,0x22);PushExpression(ae,ae->idx+1,E_EXPRESSION_V16);ae->nop+=5;break;
- case CRC_IX:___output(ae,0xDD);___output(ae,0x22);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV16);ae->nop+=6;break;
- case CRC_IY:___output(ae,0xFD);___output(ae,0x22);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV16);ae->nop+=6;break;
- case CRC_SP:___output(ae,0xED);___output(ae,0x73);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV16);ae->nop+=6;break;
+ case CRC_A:___output(ae,0x32);PushExpression(ae,ae->idx+1,E_EXPRESSION_V16);ae->nop+=4;ae->tick+=13;break;
+ case CRC_BC:___output(ae,0xED);___output(ae,0x43);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV16);ae->nop+=6;ae->tick+=20;break;
+ case CRC_DE:___output(ae,0xED);___output(ae,0x53);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV16);ae->nop+=6;ae->tick+=20;break;
+ case CRC_HL:___output(ae,0x22);PushExpression(ae,ae->idx+1,E_EXPRESSION_V16);ae->nop+=5;ae->tick+=16;break;
+ case CRC_IX:___output(ae,0xDD);___output(ae,0x22);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV16);ae->nop+=6;ae->tick+=20;break;
+ case CRC_IY:___output(ae,0xFD);___output(ae,0x22);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV16);ae->nop+=6;ae->tick+=20;break;
+ case CRC_SP:___output(ae,0xED);___output(ae,0x73);PushExpression(ae,ae->idx+1,E_EXPRESSION_IV16);ae->nop+=6;ae->tick+=20;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LD (#nnnn),[A,BC,DE,HL,SP,IX,IY] only\n");
}
@@ -8463,25 +11106,25 @@ void _RLC(struct s_assenv *ae) {
/* on check qu'il y a un ou deux parametres */
if (ae->wl[ae->idx+1].t==1) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_B:___output(ae,0xCB);___output(ae,0x0);ae->nop+=2;break;
- case CRC_C:___output(ae,0xCB);___output(ae,0x1);ae->nop+=2;break;
- case CRC_D:___output(ae,0xCB);___output(ae,0x2);ae->nop+=2;break;
- case CRC_E:___output(ae,0xCB);___output(ae,0x3);ae->nop+=2;break;
- case CRC_H:___output(ae,0xCB);___output(ae,0x4);ae->nop+=2;break;
- case CRC_L:___output(ae,0xCB);___output(ae,0x5);ae->nop+=2;break;
- case CRC_MHL:___output(ae,0xCB);___output(ae,0x6);ae->nop+=4;break;
- case CRC_A:___output(ae,0xCB);___output(ae,0x7);ae->nop+=2;break;
+ case CRC_B:___output(ae,0xCB);___output(ae,0x0);ae->nop+=2;ae->tick+=8;break;
+ case CRC_C:___output(ae,0xCB);___output(ae,0x1);ae->nop+=2;ae->tick+=8;break;
+ case CRC_D:___output(ae,0xCB);___output(ae,0x2);ae->nop+=2;ae->tick+=8;break;
+ case CRC_E:___output(ae,0xCB);___output(ae,0x3);ae->nop+=2;ae->tick+=8;break;
+ case CRC_H:___output(ae,0xCB);___output(ae,0x4);ae->nop+=2;ae->tick+=8;break;
+ case CRC_L:___output(ae,0xCB);___output(ae,0x5);ae->nop+=2;ae->tick+=8;break;
+ case CRC_MHL:___output(ae,0xCB);___output(ae,0x6);ae->nop+=4;ae->tick+=15;break;
+ case CRC_A:___output(ae,0xCB);___output(ae,0x7);ae->nop+=2;ae->tick+=8;break;
default:
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0xCB);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
___output(ae,0x6);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0xCB);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
___output(ae,0x6);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RLC reg8/(HL)/(IX+n)/(IY+n)\n");
}
@@ -8497,13 +11140,13 @@ void _RLC(struct s_assenv *ae) {
}
___output(ae,0xCB);
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x0);ae->nop+=7;break;
- case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1);ae->nop+=7;break;
- case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2);ae->nop+=7;break;
- case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3);ae->nop+=7;break;
- case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x4);ae->nop+=7;break;
- case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x5);ae->nop+=7;break;
- case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x7);ae->nop+=7;break;
+ case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x0);ae->nop+=7;ae->tick+=23;break;
+ case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1);ae->nop+=7;ae->tick+=23;break;
+ case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2);ae->nop+=7;ae->tick+=23;break;
+ case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3);ae->nop+=7;ae->tick+=23;break;
+ case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x4);ae->nop+=7;ae->tick+=23;break;
+ case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x5);ae->nop+=7;ae->tick+=23;break;
+ case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x7);ae->nop+=7;ae->tick+=23;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RLC (IX+n),reg8\n");
}
@@ -8516,24 +11159,24 @@ void _RRC(struct s_assenv *ae) {
/* on check qu'il y a un ou deux parametres */
if (ae->wl[ae->idx+1].t==1) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_B:___output(ae,0xCB);___output(ae,0x8);ae->nop+=2;break;
- case CRC_C:___output(ae,0xCB);___output(ae,0x9);ae->nop+=2;break;
- case CRC_D:___output(ae,0xCB);___output(ae,0xA);ae->nop+=2;break;
- case CRC_E:___output(ae,0xCB);___output(ae,0xB);ae->nop+=2;break;
- case CRC_H:___output(ae,0xCB);___output(ae,0xC);ae->nop+=2;break;
- case CRC_L:___output(ae,0xCB);___output(ae,0xD);ae->nop+=2;break;
- case CRC_MHL:___output(ae,0xCB);___output(ae,0xE);ae->nop+=4;break;
- case CRC_A:___output(ae,0xCB);___output(ae,0xF);ae->nop+=2;break;
+ case CRC_B:___output(ae,0xCB);___output(ae,0x8);ae->nop+=2;ae->tick+=8;break;
+ case CRC_C:___output(ae,0xCB);___output(ae,0x9);ae->nop+=2;ae->tick+=8;break;
+ case CRC_D:___output(ae,0xCB);___output(ae,0xA);ae->nop+=2;ae->tick+=8;break;
+ case CRC_E:___output(ae,0xCB);___output(ae,0xB);ae->nop+=2;ae->tick+=8;break;
+ case CRC_H:___output(ae,0xCB);___output(ae,0xC);ae->nop+=2;ae->tick+=8;break;
+ case CRC_L:___output(ae,0xCB);___output(ae,0xD);ae->nop+=2;ae->tick+=8;break;
+ case CRC_MHL:___output(ae,0xCB);___output(ae,0xE);ae->nop+=4;ae->tick+=15;break;
+ case CRC_A:___output(ae,0xCB);___output(ae,0xF);ae->nop+=2;ae->tick+=8;break;
default:
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0xCB);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
___output(ae,0xE);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0xCB);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
- ___output(ae,0xE);
+ ___output(ae,0xE);ae->tick+=23;
ae->nop+=7;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RRC reg8/(HL)/(IX+n)/(IY+n)\n");
@@ -8550,13 +11193,13 @@ void _RRC(struct s_assenv *ae) {
}
___output(ae,0xCB);
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x8);ae->nop+=7;break;
- case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x9);ae->nop+=7;break;
- case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0xA);ae->nop+=7;break;
- case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0xB);ae->nop+=7;break;
- case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0xC);ae->nop+=7;break;
- case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0xD);ae->nop+=7;break;
- case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0xF);ae->nop+=7;break;
+ case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x8);ae->nop+=7;ae->tick+=23;break;
+ case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x9);ae->nop+=7;ae->tick+=23;break;
+ case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0xA);ae->nop+=7;ae->tick+=23;break;
+ case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0xB);ae->nop+=7;ae->tick+=23;break;
+ case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0xC);ae->nop+=7;ae->tick+=23;break;
+ case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0xD);ae->nop+=7;ae->tick+=23;break;
+ case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0xF);ae->nop+=7;ae->tick+=23;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RRC (IX+n),reg8\n");
}
@@ -8570,28 +11213,28 @@ void _RL(struct s_assenv *ae) {
/* on check qu'il y a un ou deux parametres */
if (ae->wl[ae->idx+1].t==1) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_BC:___output(ae,0xCB);___output(ae,0x10);___output(ae,0xCB);___output(ae,0x11);ae->nop+=4;break;
- case CRC_B:___output(ae,0xCB);___output(ae,0x10);ae->nop+=2;break;
- case CRC_C:___output(ae,0xCB);___output(ae,0x11);ae->nop+=2;break;
- case CRC_DE:___output(ae,0xCB);___output(ae,0x12);___output(ae,0xCB);___output(ae,0x13);ae->nop+=4;break;
- case CRC_D:___output(ae,0xCB);___output(ae,0x12);ae->nop+=2;break;
- case CRC_E:___output(ae,0xCB);___output(ae,0x13);ae->nop+=2;break;
- case CRC_HL:___output(ae,0xCB);___output(ae,0x14);___output(ae,0xCB);___output(ae,0x15);ae->nop+=4;break;
- case CRC_H:___output(ae,0xCB);___output(ae,0x14);ae->nop+=2;break;
- case CRC_L:___output(ae,0xCB);___output(ae,0x15);ae->nop+=2;break;
- case CRC_MHL:___output(ae,0xCB);___output(ae,0x16);ae->nop+=4;break;
- case CRC_A:___output(ae,0xCB);___output(ae,0x17);ae->nop+=2;break;
+ case CRC_BC:___output(ae,0xCB);___output(ae,0x10);___output(ae,0xCB);___output(ae,0x11);ae->nop+=4;ae->tick+=16;break;
+ case CRC_B:___output(ae,0xCB);___output(ae,0x10);ae->nop+=2;ae->tick+=8;break;
+ case CRC_C:___output(ae,0xCB);___output(ae,0x11);ae->nop+=2;ae->tick+=8;break;
+ case CRC_DE:___output(ae,0xCB);___output(ae,0x12);___output(ae,0xCB);___output(ae,0x13);ae->nop+=4;ae->tick+=16;break;
+ case CRC_D:___output(ae,0xCB);___output(ae,0x12);ae->nop+=2;ae->tick+=8;break;
+ case CRC_E:___output(ae,0xCB);___output(ae,0x13);ae->nop+=2;ae->tick+=8;break;
+ case CRC_HL:___output(ae,0xCB);___output(ae,0x14);___output(ae,0xCB);___output(ae,0x15);ae->nop+=4;ae->tick+=16;break;
+ case CRC_H:___output(ae,0xCB);___output(ae,0x14);ae->nop+=2;ae->tick+=8;break;
+ case CRC_L:___output(ae,0xCB);___output(ae,0x15);ae->nop+=2;ae->tick+=8;break;
+ case CRC_MHL:___output(ae,0xCB);___output(ae,0x16);ae->nop+=4;ae->tick+=15;break;
+ case CRC_A:___output(ae,0xCB);___output(ae,0x17);ae->nop+=2;ae->tick+=8;break;
default:
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0xCB);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
___output(ae,0x16);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0xCB);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
___output(ae,0x16);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RL reg8/(HL)/(IX+n)/(IY+n)\n");
}
@@ -8607,13 +11250,13 @@ void _RL(struct s_assenv *ae) {
}
___output(ae,0xCB);
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x10);ae->nop+=7;break;
- case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x11);ae->nop+=7;break;
- case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x12);ae->nop+=7;break;
- case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x13);ae->nop+=7;break;
- case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x14);ae->nop+=7;break;
- case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x15);ae->nop+=7;break;
- case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x17);ae->nop+=7;break;
+ case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x10);ae->nop+=7;ae->tick+=23;break;
+ case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x11);ae->nop+=7;ae->tick+=23;break;
+ case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x12);ae->nop+=7;ae->tick+=23;break;
+ case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x13);ae->nop+=7;ae->tick+=23;break;
+ case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x14);ae->nop+=7;ae->tick+=23;break;
+ case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x15);ae->nop+=7;ae->tick+=23;break;
+ case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x17);ae->nop+=7;ae->tick+=23;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RL (IX+n),reg8\n");
}
@@ -8628,28 +11271,28 @@ void _RR(struct s_assenv *ae) {
/* on check qu'il y a un ou deux parametres */
if (ae->wl[ae->idx+1].t==1) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_BC:___output(ae,0xCB);___output(ae,0x18);___output(ae,0xCB);___output(ae,0x19);ae->nop+=4;break;
- case CRC_B:___output(ae,0xCB);___output(ae,0x18);ae->nop+=2;break;
- case CRC_C:___output(ae,0xCB);___output(ae,0x19);ae->nop+=2;break;
- case CRC_DE:___output(ae,0xCB);___output(ae,0x1A);___output(ae,0xCB);___output(ae,0x1B);ae->nop+=4;break;
- case CRC_D:___output(ae,0xCB);___output(ae,0x1A);ae->nop+=2;break;
- case CRC_E:___output(ae,0xCB);___output(ae,0x1B);ae->nop+=2;break;
- case CRC_HL:___output(ae,0xCB);___output(ae,0x1C);___output(ae,0xCB);___output(ae,0x1D);ae->nop+=4;break;
- case CRC_H:___output(ae,0xCB);___output(ae,0x1C);ae->nop+=2;break;
- case CRC_L:___output(ae,0xCB);___output(ae,0x1D);ae->nop+=2;break;
- case CRC_MHL:___output(ae,0xCB);___output(ae,0x1E);ae->nop+=4;break;
- case CRC_A:___output(ae,0xCB);___output(ae,0x1F);ae->nop+=2;break;
+ case CRC_BC:___output(ae,0xCB);___output(ae,0x18);___output(ae,0xCB);___output(ae,0x19);ae->nop+=4;ae->tick+=16;break;
+ case CRC_B:___output(ae,0xCB);___output(ae,0x18);ae->nop+=2;ae->tick+=8;break;
+ case CRC_C:___output(ae,0xCB);___output(ae,0x19);ae->nop+=2;ae->tick+=8;break;
+ case CRC_DE:___output(ae,0xCB);___output(ae,0x1A);___output(ae,0xCB);___output(ae,0x1B);ae->nop+=4;ae->tick+=16;break;
+ case CRC_D:___output(ae,0xCB);___output(ae,0x1A);ae->nop+=2;ae->tick+=8;break;
+ case CRC_E:___output(ae,0xCB);___output(ae,0x1B);ae->nop+=2;ae->tick+=8;break;
+ case CRC_HL:___output(ae,0xCB);___output(ae,0x1C);___output(ae,0xCB);___output(ae,0x1D);ae->nop+=4;ae->tick+=16;break;
+ case CRC_H:___output(ae,0xCB);___output(ae,0x1C);ae->nop+=2;ae->tick+=8;break;
+ case CRC_L:___output(ae,0xCB);___output(ae,0x1D);ae->nop+=2;ae->tick+=8;break;
+ case CRC_MHL:___output(ae,0xCB);___output(ae,0x1E);ae->nop+=4;ae->tick+=15;break;
+ case CRC_A:___output(ae,0xCB);___output(ae,0x1F);ae->nop+=2;ae->tick+=8;break;
default:
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0xCB);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
___output(ae,0x1E);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0xCB);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
___output(ae,0x1E);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RR reg8/(HL)/(IX+n)/(IY+n)\n");
}
@@ -8665,13 +11308,13 @@ void _RR(struct s_assenv *ae) {
}
___output(ae,0xCB);
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x18);ae->nop+=7;break;
- case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x19);ae->nop+=7;break;
- case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1A);ae->nop+=7;break;
- case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1B);ae->nop+=7;break;
- case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1C);ae->nop+=7;break;
- case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1D);ae->nop+=7;break;
- case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1F);ae->nop+=7;break;
+ case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x18);ae->nop+=7;ae->tick+=23;break;
+ case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x19);ae->nop+=7;ae->tick+=23;break;
+ case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1A);ae->nop+=7;ae->tick+=23;break;
+ case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1B);ae->nop+=7;ae->tick+=23;break;
+ case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1C);ae->nop+=7;ae->tick+=23;break;
+ case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1D);ae->nop+=7;ae->tick+=23;break;
+ case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x1F);ae->nop+=7;ae->tick+=23;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RR (IX+n),reg8\n");
}
@@ -8682,36 +11325,32 @@ void _RR(struct s_assenv *ae) {
}
}
-
-
-
-
void _SLA(struct s_assenv *ae) {
/* on check qu'il y a un ou deux parametres */
if (ae->wl[ae->idx+1].t==1) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_BC:___output(ae,0xCB);___output(ae,0x21);___output(ae,0xCB);___output(ae,0x10);ae->nop+=4;break; /* SLA C : RL B */
- case CRC_B:___output(ae,0xCB);___output(ae,0x20);ae->nop+=2;break;
- case CRC_C:___output(ae,0xCB);___output(ae,0x21);ae->nop+=2;break;
- case CRC_DE:___output(ae,0xCB);___output(ae,0x23);___output(ae,0xCB);___output(ae,0x12);ae->nop+=4;break; /* SLA E : RL D */
- case CRC_D:___output(ae,0xCB);___output(ae,0x22);ae->nop+=2;break;
- case CRC_E:___output(ae,0xCB);___output(ae,0x23);ae->nop+=2;break;
- case CRC_HL:___output(ae,0xCB);___output(ae,0x25);___output(ae,0xCB);___output(ae,0x14);ae->nop+=4;break; /* SLA L : RL H */
- case CRC_H:___output(ae,0xCB);___output(ae,0x24);ae->nop+=2;break;
- case CRC_L:___output(ae,0xCB);___output(ae,0x25);ae->nop+=2;break;
- case CRC_MHL:___output(ae,0xCB);___output(ae,0x26);ae->nop+=4;break;
- case CRC_A:___output(ae,0xCB);___output(ae,0x27);ae->nop+=2;break;
+ case CRC_BC:___output(ae,0xCB);___output(ae,0x21);___output(ae,0xCB);___output(ae,0x10);ae->nop+=4;ae->tick+=16;break; /* SLA C : RL B */
+ case CRC_B:___output(ae,0xCB);___output(ae,0x20);ae->nop+=2;ae->tick+=8;break;
+ case CRC_C:___output(ae,0xCB);___output(ae,0x21);ae->nop+=2;ae->tick+=8;break;
+ case CRC_DE:___output(ae,0xCB);___output(ae,0x23);___output(ae,0xCB);___output(ae,0x12);ae->nop+=4;ae->tick+=16;break; /* SLA E : RL D */
+ case CRC_D:___output(ae,0xCB);___output(ae,0x22);ae->nop+=2;ae->tick+=8;break;
+ case CRC_E:___output(ae,0xCB);___output(ae,0x23);ae->nop+=2;ae->tick+=8;break;
+ case CRC_HL:___output(ae,0xCB);___output(ae,0x25);___output(ae,0xCB);___output(ae,0x14);ae->nop+=4;ae->tick+=16;break; /* SLA L : RL H */
+ case CRC_H:___output(ae,0xCB);___output(ae,0x24);ae->nop+=2;ae->tick+=8;break;
+ case CRC_L:___output(ae,0xCB);___output(ae,0x25);ae->nop+=2;ae->tick+=8;break;
+ case CRC_MHL:___output(ae,0xCB);___output(ae,0x26);ae->nop+=4;ae->tick+=15;break;
+ case CRC_A:___output(ae,0xCB);___output(ae,0x27);ae->nop+=2;ae->tick+=8;break;
default:
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0xCB);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
___output(ae,0x26);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0xCB);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
___output(ae,0x26);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SLA reg8/(HL)/(IX+n)/(IY+n)\n");
}
@@ -8723,17 +11362,17 @@ void _SLA(struct s_assenv *ae) {
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SLL (IX+n),reg8\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SLA (IX+n),reg8\n");
}
___output(ae,0xCB);
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x20);ae->nop+=7;break;
- case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x21);ae->nop+=7;break;
- case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x22);ae->nop+=7;break;
- case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x23);ae->nop+=7;break;
- case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x24);ae->nop+=7;break;
- case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x25);ae->nop+=7;break;
- case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x27);ae->nop+=7;break;
+ case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x20);ae->nop+=7;ae->tick+=23;break;
+ case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x21);ae->nop+=7;ae->tick+=23;break;
+ case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x22);ae->nop+=7;ae->tick+=23;break;
+ case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x23);ae->nop+=7;ae->tick+=23;break;
+ case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x24);ae->nop+=7;ae->tick+=23;break;
+ case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x25);ae->nop+=7;ae->tick+=23;break;
+ case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x27);ae->nop+=7;ae->tick+=23;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SLA (IX+n),reg8\n");
}
@@ -8748,28 +11387,28 @@ void _SRA(struct s_assenv *ae) {
/* on check qu'il y a un ou deux parametres */
if (ae->wl[ae->idx+1].t==1) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_BC:___output(ae,0xCB);___output(ae,0x28);___output(ae,0xCB);___output(ae,0x19);ae->nop+=4;break; /* SRA B : RR C */
- case CRC_B:___output(ae,0xCB);___output(ae,0x28);ae->nop+=2;break;
- case CRC_C:___output(ae,0xCB);___output(ae,0x29);ae->nop+=2;break;
- case CRC_DE:___output(ae,0xCB);___output(ae,0x2A);___output(ae,0xCB);___output(ae,0x1B);ae->nop+=4;break; /* SRA D : RR E */
- case CRC_D:___output(ae,0xCB);___output(ae,0x2A);ae->nop+=2;break;
- case CRC_E:___output(ae,0xCB);___output(ae,0x2B);ae->nop+=2;break;
- case CRC_HL:___output(ae,0xCB);___output(ae,0x2C);___output(ae,0xCB);___output(ae,0x1D);ae->nop+=4;break; /* SRA H : RR L */
- case CRC_H:___output(ae,0xCB);___output(ae,0x2C);ae->nop+=2;break;
- case CRC_L:___output(ae,0xCB);___output(ae,0x2D);ae->nop+=2;break;
- case CRC_MHL:___output(ae,0xCB);___output(ae,0x2E);ae->nop+=4;break;
- case CRC_A:___output(ae,0xCB);___output(ae,0x2F);ae->nop+=2;break;
+ case CRC_BC:___output(ae,0xCB);___output(ae,0x28);___output(ae,0xCB);___output(ae,0x19);ae->nop+=4;ae->tick+=16;break; /* SRA B : RR C */
+ case CRC_B:___output(ae,0xCB);___output(ae,0x28);ae->nop+=2;ae->tick+=8;break;
+ case CRC_C:___output(ae,0xCB);___output(ae,0x29);ae->nop+=2;ae->tick+=8;break;
+ case CRC_DE:___output(ae,0xCB);___output(ae,0x2A);___output(ae,0xCB);___output(ae,0x1B);ae->nop+=4;ae->tick+=16;break; /* SRA D : RR E */
+ case CRC_D:___output(ae,0xCB);___output(ae,0x2A);ae->nop+=2;ae->tick+=8;break;
+ case CRC_E:___output(ae,0xCB);___output(ae,0x2B);ae->nop+=2;ae->tick+=8;break;
+ case CRC_HL:___output(ae,0xCB);___output(ae,0x2C);___output(ae,0xCB);___output(ae,0x1D);ae->nop+=4;ae->tick+=16;break; /* SRA H : RR L */
+ case CRC_H:___output(ae,0xCB);___output(ae,0x2C);ae->nop+=2;ae->tick+=8;break;
+ case CRC_L:___output(ae,0xCB);___output(ae,0x2D);ae->nop+=2;ae->tick+=8;break;
+ case CRC_MHL:___output(ae,0xCB);___output(ae,0x2E);ae->nop+=4;ae->tick+=15;break;
+ case CRC_A:___output(ae,0xCB);___output(ae,0x2F);ae->nop+=2;ae->tick+=8;break;
default:
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0xCB);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
___output(ae,0x2E);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0xCB);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
___output(ae,0x2E);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SRA reg8/(HL)/(IX+n)/(IY+n)\n");
}
@@ -8785,13 +11424,13 @@ void _SRA(struct s_assenv *ae) {
}
___output(ae,0xCB);
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x28);ae->nop+=7;break;
- case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x29);ae->nop+=7;break;
- case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2A);ae->nop+=7;break;
- case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2B);ae->nop+=7;break;
- case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2C);ae->nop+=7;break;
- case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2D);ae->nop+=7;break;
- case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2F);ae->nop+=7;break;
+ case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x28);ae->nop+=7;ae->tick+=23;break;
+ case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x29);ae->nop+=7;ae->tick+=23;break;
+ case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2A);ae->nop+=7;ae->tick+=23;break;
+ case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2B);ae->nop+=7;ae->tick+=23;break;
+ case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2C);ae->nop+=7;ae->tick+=23;break;
+ case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2D);ae->nop+=7;ae->tick+=23;break;
+ case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x2F);ae->nop+=7;ae->tick+=23;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SRA (IX+n),reg8\n");
}
@@ -8807,28 +11446,28 @@ void _SLL(struct s_assenv *ae) {
/* on check qu'il y a un ou deux parametres */
if (ae->wl[ae->idx+1].t==1) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_BC:___output(ae,0xCB);___output(ae,0x31);___output(ae,0xCB);___output(ae,0x10);ae->nop+=4;break; /* SLL C : RL B */
- case CRC_B:___output(ae,0xCB);___output(ae,0x30);ae->nop+=2;break;
- case CRC_C:___output(ae,0xCB);___output(ae,0x31);ae->nop+=2;break;
- case CRC_DE:___output(ae,0xCB);___output(ae,0x33);___output(ae,0xCB);___output(ae,0x12);ae->nop+=4;break; /* SLL E : RL D */
- case CRC_D:___output(ae,0xCB);___output(ae,0x32);ae->nop+=2;break;
- case CRC_E:___output(ae,0xCB);___output(ae,0x33);ae->nop+=2;break;
- case CRC_HL:___output(ae,0xCB);___output(ae,0x35);___output(ae,0xCB);___output(ae,0x14);ae->nop+=4;break; /* SLL L : RL H */
- case CRC_H:___output(ae,0xCB);___output(ae,0x34);ae->nop+=2;break;
- case CRC_L:___output(ae,0xCB);___output(ae,0x35);ae->nop+=2;break;
- case CRC_MHL:___output(ae,0xCB);___output(ae,0x36);ae->nop+=4;break;
- case CRC_A:___output(ae,0xCB);___output(ae,0x37);ae->nop+=2;break;
+ case CRC_BC:___output(ae,0xCB);___output(ae,0x31);___output(ae,0xCB);___output(ae,0x10);ae->nop+=4;ae->tick+=16;break; /* SLL C : RL B */
+ case CRC_B:___output(ae,0xCB);___output(ae,0x30);ae->nop+=2;ae->tick+=8;break;
+ case CRC_C:___output(ae,0xCB);___output(ae,0x31);ae->nop+=2;ae->tick+=8;break;
+ case CRC_DE:___output(ae,0xCB);___output(ae,0x33);___output(ae,0xCB);___output(ae,0x12);ae->nop+=4;ae->tick+=16;break; /* SLL E : RL D */
+ case CRC_D:___output(ae,0xCB);___output(ae,0x32);ae->nop+=2;ae->tick+=8;break;
+ case CRC_E:___output(ae,0xCB);___output(ae,0x33);ae->nop+=2;ae->tick+=8;break;
+ case CRC_HL:___output(ae,0xCB);___output(ae,0x35);___output(ae,0xCB);___output(ae,0x14);ae->nop+=4;ae->tick+=16;break; /* SLL L : RL H */
+ case CRC_H:___output(ae,0xCB);___output(ae,0x34);ae->nop+=2;ae->tick+=8;break;
+ case CRC_L:___output(ae,0xCB);___output(ae,0x35);ae->nop+=2;ae->tick+=8;break;
+ case CRC_MHL:___output(ae,0xCB);___output(ae,0x36);ae->nop+=4;ae->tick+=15;break;
+ case CRC_A:___output(ae,0xCB);___output(ae,0x37);ae->nop+=2;ae->tick+=8;break;
default:
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0xCB);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
___output(ae,0x36);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0xCB);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
___output(ae,0x36);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SLL reg8/(HL)/(IX+n)/(IY+n)\n");
}
@@ -8844,13 +11483,13 @@ void _SLL(struct s_assenv *ae) {
}
___output(ae,0xCB);
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x30);ae->nop+=7;break;
- case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x31);ae->nop+=7;break;
- case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x32);ae->nop+=7;break;
- case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x33);ae->nop+=7;break;
- case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x34);ae->nop+=7;break;
- case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x35);ae->nop+=7;break;
- case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x37);ae->nop+=7;break;
+ case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x30);ae->nop+=7;ae->tick+=23;break;
+ case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x31);ae->nop+=7;ae->tick+=23;break;
+ case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x32);ae->nop+=7;ae->tick+=23;break;
+ case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x33);ae->nop+=7;ae->tick+=23;break;
+ case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x34);ae->nop+=7;ae->tick+=23;break;
+ case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x35);ae->nop+=7;ae->tick+=23;break;
+ case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x37);ae->nop+=7;ae->tick+=23;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SLL (IX+n),reg8\n");
}
@@ -8865,28 +11504,28 @@ void _SRL(struct s_assenv *ae) {
/* on check qu'il y a un ou deux parametres */
if (ae->wl[ae->idx+1].t==1) {
switch (GetCRC(ae->wl[ae->idx+1].w)) {
- case CRC_BC:___output(ae,0xCB);___output(ae,0x38);___output(ae,0xCB);___output(ae,0x11);ae->nop+=4;break; /* SRL B : RL C */
- case CRC_B:___output(ae,0xCB);___output(ae,0x38);ae->nop+=2;break;
- case CRC_C:___output(ae,0xCB);___output(ae,0x39);ae->nop+=2;break;
- case CRC_DE:___output(ae,0xCB);___output(ae,0x3A);___output(ae,0xCB);___output(ae,0x13);ae->nop+=4;break; /* SRL D : RL E */
- case CRC_D:___output(ae,0xCB);___output(ae,0x3A);ae->nop+=2;break;
- case CRC_E:___output(ae,0xCB);___output(ae,0x3B);ae->nop+=2;break;
- case CRC_HL:___output(ae,0xCB);___output(ae,0x3C);___output(ae,0xCB);___output(ae,0x15);ae->nop+=4;break; /* SRL H : RL L */
- case CRC_H:___output(ae,0xCB);___output(ae,0x3C);ae->nop+=2;break;
- case CRC_L:___output(ae,0xCB);___output(ae,0x3D);ae->nop+=2;break;
- case CRC_MHL:___output(ae,0xCB);___output(ae,0x3E);ae->nop+=4;break;
- case CRC_A:___output(ae,0xCB);___output(ae,0x3F);ae->nop+=2;break;
+ case CRC_BC:___output(ae,0xCB);___output(ae,0x38);___output(ae,0xCB);___output(ae,0x19);ae->nop+=4;ae->tick+=16;break; /* SRL B : RR C */
+ case CRC_B:___output(ae,0xCB);___output(ae,0x38);ae->nop+=2;ae->tick+=8;break;
+ case CRC_C:___output(ae,0xCB);___output(ae,0x39);ae->nop+=2;ae->tick+=8;break;
+ case CRC_DE:___output(ae,0xCB);___output(ae,0x3A);___output(ae,0xCB);___output(ae,0x1B);ae->nop+=4;ae->tick+=16;break; /* SRL D : RR E */
+ case CRC_D:___output(ae,0xCB);___output(ae,0x3A);ae->nop+=2;ae->tick+=8;break;
+ case CRC_E:___output(ae,0xCB);___output(ae,0x3B);ae->nop+=2;ae->tick+=8;break;
+ case CRC_HL:___output(ae,0xCB);___output(ae,0x3C);___output(ae,0xCB);___output(ae,0x1D);ae->nop+=4;ae->tick+=16;break; /* SRL H : RR L */
+ case CRC_H:___output(ae,0xCB);___output(ae,0x3C);ae->nop+=2;ae->tick+=8;break;
+ case CRC_L:___output(ae,0xCB);___output(ae,0x3D);ae->nop+=2;ae->tick+=8;break;
+ case CRC_MHL:___output(ae,0xCB);___output(ae,0x3E);ae->nop+=4;ae->tick+=15;break;
+ case CRC_A:___output(ae,0xCB);___output(ae,0x3F);ae->nop+=2;ae->tick+=8;break;
default:
if (strncmp(ae->wl[ae->idx+1].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0xCB);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
___output(ae,0x3E);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else if (strncmp(ae->wl[ae->idx+1].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0xCB);
PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);
___output(ae,0x3E);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SRL reg8/(HL)/(IX+n)/(IY+n)\n");
}
@@ -8902,13 +11541,13 @@ void _SRL(struct s_assenv *ae) {
}
___output(ae,0xCB);
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x38);ae->nop+=7;break;
- case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x39);ae->nop+=7;break;
- case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3A);ae->nop+=7;break;
- case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3B);ae->nop+=7;break;
- case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3C);ae->nop+=7;break;
- case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3D);ae->nop+=7;break;
- case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3F);ae->nop+=7;break;
+ case CRC_B:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x38);ae->nop+=7;ae->tick+=23;break;
+ case CRC_C:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x39);ae->nop+=7;ae->tick+=23;break;
+ case CRC_D:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3A);ae->nop+=7;ae->tick+=23;break;
+ case CRC_E:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3B);ae->nop+=7;ae->tick+=23;break;
+ case CRC_H:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3C);ae->nop+=7;ae->tick+=23;break;
+ case CRC_L:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3D);ae->nop+=7;ae->tick+=23;break;
+ case CRC_A:PushExpression(ae,ae->idx+1,E_EXPRESSION_IV8);___output(ae,0x3F);ae->nop+=7;ae->tick+=23;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SRL (IX+n),reg8\n");
}
@@ -8933,25 +11572,25 @@ void _BIT(struct s_assenv *ae) {
o=0x40+o*8;
if (ae->wl[ae->idx+1].t==0 && ae->wl[ae->idx+2].t==1) {
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x0+o);ae->nop+=2;break;
- case CRC_C:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x1+o);ae->nop+=2;break;
- case CRC_D:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x2+o);ae->nop+=2;break;
- case CRC_E:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x3+o);ae->nop+=2;break;
- case CRC_H:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x4+o);ae->nop+=2;break;
- case CRC_L:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x5+o);ae->nop+=2;break;
- case CRC_MHL:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o);ae->nop+=3;break;
- case CRC_A:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x7+o);ae->nop+=2;break;
+ case CRC_B:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x0+o);ae->nop+=2;ae->tick+=8;break;
+ case CRC_C:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x1+o);ae->nop+=2;ae->tick+=8;break;
+ case CRC_D:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x2+o);ae->nop+=2;ae->tick+=8;break;
+ case CRC_E:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x3+o);ae->nop+=2;ae->tick+=8;break;
+ case CRC_H:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x4+o);ae->nop+=2;ae->tick+=8;break;
+ case CRC_L:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x5+o);ae->nop+=2;ae->tick+=8;break;
+ case CRC_MHL:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o);ae->nop+=3;ae->tick+=12;break;
+ case CRC_A:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x7+o);ae->nop+=2;ae->tick+=8;break;
default:
if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0xCB);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o);
- ae->nop+=6;
+ ae->nop+=6;ae->tick+=20;
} else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0xCB);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o);
- ae->nop+=6;
+ ae->nop+=6;ae->tick+=20;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is BIT n,reg8/(HL)/(IX+n)/(IY+n)\n");
}
@@ -8967,13 +11606,13 @@ void _BIT(struct s_assenv *ae) {
}
___output(ae,0xCB);
switch (GetCRC(ae->wl[ae->idx+3].w)) {
- case CRC_B:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x0+o);ae->nop+=6;break;
- case CRC_C:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x1+o);ae->nop+=6;break;
- case CRC_D:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x2+o);ae->nop+=6;break;
- case CRC_E:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x3+o);ae->nop+=6;break;
- case CRC_H:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x4+o);ae->nop+=6;break;
- case CRC_L:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x5+o);ae->nop+=6;break;
- case CRC_A:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x7+o);ae->nop+=6;break;
+ case CRC_B:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x0+o);ae->nop+=6;ae->tick+=20;break;
+ case CRC_C:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x1+o);ae->nop+=6;ae->tick+=20;break;
+ case CRC_D:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x2+o);ae->nop+=6;ae->tick+=20;break;
+ case CRC_E:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x3+o);ae->nop+=6;ae->tick+=20;break;
+ case CRC_H:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x4+o);ae->nop+=6;ae->tick+=20;break;
+ case CRC_L:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x5+o);ae->nop+=6;ae->tick+=20;break;
+ case CRC_A:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x7+o);ae->nop+=6;ae->tick+=20;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is BIT n,(IX+n),reg8\n");
}
@@ -8996,25 +11635,25 @@ void _RES(struct s_assenv *ae) {
o=0x80+o*8;
if (ae->wl[ae->idx+1].t==0 && ae->wl[ae->idx+2].t==1) {
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x0+o);ae->nop+=2;break;
- case CRC_C:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x1+o);ae->nop+=2;break;
- case CRC_D:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x2+o);ae->nop+=2;break;
- case CRC_E:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x3+o);ae->nop+=2;break;
- case CRC_H:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x4+o);ae->nop+=2;break;
- case CRC_L:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x5+o);ae->nop+=2;break;
- case CRC_MHL:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o);ae->nop+=4;break;
- case CRC_A:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x7+o);ae->nop+=2;break;
+ case CRC_B:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x0+o);ae->nop+=2;ae->tick+=8;break;
+ case CRC_C:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x1+o);ae->nop+=2;ae->tick+=8;break;
+ case CRC_D:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x2+o);ae->nop+=2;ae->tick+=8;break;
+ case CRC_E:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x3+o);ae->nop+=2;ae->tick+=8;break;
+ case CRC_H:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x4+o);ae->nop+=2;ae->tick+=8;break;
+ case CRC_L:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x5+o);ae->nop+=2;ae->tick+=8;break;
+ case CRC_MHL:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o);ae->nop+=4;ae->tick+=15;break;
+ case CRC_A:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x7+o);ae->nop+=2;ae->tick+=8;break;
default:
if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0xCB);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0xCB);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RES n,reg8/(HL)/(IX+n)/(IY+n)\n");
}
@@ -9030,13 +11669,13 @@ void _RES(struct s_assenv *ae) {
}
___output(ae,0xCB);
switch (GetCRC(ae->wl[ae->idx+3].w)) {
- case CRC_B:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x0+o);ae->nop+=7;break;
- case CRC_C:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x1+o);ae->nop+=7;break;
- case CRC_D:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x2+o);ae->nop+=7;break;
- case CRC_E:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x3+o);ae->nop+=7;break;
- case CRC_H:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x4+o);ae->nop+=7;break;
- case CRC_L:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x5+o);ae->nop+=7;break;
- case CRC_A:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x7+o);ae->nop+=7;break;
+ case CRC_B:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x0+o);ae->nop+=7;ae->tick+=23;break;
+ case CRC_C:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x1+o);ae->nop+=7;ae->tick+=23;break;
+ case CRC_D:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x2+o);ae->nop+=7;ae->tick+=23;break;
+ case CRC_E:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x3+o);ae->nop+=7;ae->tick+=23;break;
+ case CRC_H:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x4+o);ae->nop+=7;ae->tick+=23;break;
+ case CRC_L:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x5+o);ae->nop+=7;ae->tick+=23;break;
+ case CRC_A:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x7+o);ae->nop+=7;ae->tick+=23;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is RES n,(IX+n),reg8\n");
}
@@ -9059,25 +11698,25 @@ void _SET(struct s_assenv *ae) {
o=0xC0+o*8;
if (ae->wl[ae->idx+1].t==0 && ae->wl[ae->idx+2].t==1) {
switch (GetCRC(ae->wl[ae->idx+2].w)) {
- case CRC_B:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x0+o);ae->nop+=2;break;
- case CRC_C:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x1+o);ae->nop+=2;break;
- case CRC_D:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x2+o);ae->nop+=2;break;
- case CRC_E:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x3+o);ae->nop+=2;break;
- case CRC_H:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x4+o);ae->nop+=2;break;
- case CRC_L:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x5+o);ae->nop+=2;break;
- case CRC_MHL:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o);ae->nop+=4;break;
- case CRC_A:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x7+o);ae->nop+=2;break;
+ case CRC_B:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x0+o);ae->nop+=2;ae->tick+=8;break;
+ case CRC_C:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x1+o);ae->nop+=2;ae->tick+=8;break;
+ case CRC_D:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x2+o);ae->nop+=2;ae->tick+=8;break;
+ case CRC_E:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x3+o);ae->nop+=2;ae->tick+=8;break;
+ case CRC_H:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x4+o);ae->nop+=2;ae->tick+=8;break;
+ case CRC_L:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x5+o);ae->nop+=2;ae->tick+=8;break;
+ case CRC_MHL:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o);ae->nop+=4;ae->tick+=15;break;
+ case CRC_A:___output(ae,0xCB);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x7+o);ae->nop+=2;ae->tick+=8;break;
default:
if (strncmp(ae->wl[ae->idx+2].w,"(IX",3)==0) {
___output(ae,0xDD);___output(ae,0xCB);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else if (strncmp(ae->wl[ae->idx+2].w,"(IY",3)==0) {
___output(ae,0xFD);___output(ae,0xCB);
PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);
PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x6+o);
- ae->nop+=7;
+ ae->nop+=7;ae->tick+=23;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SET n,reg8/(HL)/(IX+n)/(IY+n)\n");
}
@@ -9093,13 +11732,13 @@ void _SET(struct s_assenv *ae) {
}
___output(ae,0xCB);
switch (GetCRC(ae->wl[ae->idx+3].w)) {
- case CRC_B:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x0+o);ae->nop+=7;break;
- case CRC_C:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x1+o);ae->nop+=7;break;
- case CRC_D:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x2+o);ae->nop+=7;break;
- case CRC_E:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x3+o);ae->nop+=7;break;
- case CRC_H:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x4+o);ae->nop+=7;break;
- case CRC_L:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x5+o);ae->nop+=7;break;
- case CRC_A:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x7+o);ae->nop+=7;break;
+ case CRC_B:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x0+o);ae->nop+=7;ae->tick+=23;break;
+ case CRC_C:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x1+o);ae->nop+=7;ae->tick+=23;break;
+ case CRC_D:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x2+o);ae->nop+=7;ae->tick+=23;break;
+ case CRC_E:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x3+o);ae->nop+=7;ae->tick+=23;break;
+ case CRC_H:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x4+o);ae->nop+=7;ae->tick+=23;break;
+ case CRC_L:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x5+o);ae->nop+=7;ae->tick+=23;break;
+ case CRC_A:PushExpression(ae,ae->idx+2,E_EXPRESSION_IV8);PushExpression(ae,ae->idx+1,E_EXPRESSION_BRS);___output(ae,0x7+o);ae->nop+=7;ae->tick+=23;break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is SET n,(IX+n),reg8\n");
}
@@ -9210,9 +11849,9 @@ void _STR(struct s_assenv *ae) {
} else {
/* charset conversion on the fly */
if (ae->wl[ae->idx].w[i+1]!=tquote) {
- ___output(ae,ae->charset[(int)ae->wl[ae->idx].w[i]]);
+ ___output(ae,ae->charset[((unsigned int)ae->wl[ae->idx].w[i])&0xFF]);
} else {
- ___output(ae,ae->charset[(int)ae->wl[ae->idx].w[i]]|0x80);
+ ___output(ae,ae->charset[((unsigned int)ae->wl[ae->idx].w[i]|0x80)&0xFF]);
}
}
@@ -9227,6 +11866,45 @@ void _STR(struct s_assenv *ae) {
}
}
+/* Microsoft IEEE-754 40bits float value */
+void _DEFF(struct s_assenv *ae) {
+ if (!ae->wl[ae->idx].t) {
+ do {
+ ae->idx++;
+ PushExpression(ae,ae->idx,E_EXPRESSION_0VRMike);
+ } while (ae->wl[ae->idx].t==0);
+ } else {
+ if (ae->getstruct) {
+ ___output(ae,0);___output(ae,0);___output(ae,0);___output(ae,0);___output(ae,0);
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFF needs one or more parameters\n");
+ }
+ }
+}
+void _DEFF_struct(struct s_assenv *ae) {
+ unsigned char *rc;
+ double v;
+ if (!ae->wl[ae->idx].t) {
+ do {
+ ae->idx++;
+ /* conversion des symboles connus */
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx].w,0);
+ /* calcul de la valeur définitive de l'expression */
+ v=ComputeExpressionCore(ae,ae->wl[ae->idx].w,ae->outputadr,0);
+ /* conversion en réel Amsdos */
+ rc=__internal_MakeRosoftREAL(ae,v,0);
+ ___output(ae,rc[0]);___output(ae,rc[1]);___output(ae,rc[2]);___output(ae,rc[3]);___output(ae,rc[4]);
+ } while (ae->wl[ae->idx].t==0);
+ } else {
+ if (ae->getstruct) {
+ ___output(ae,0);___output(ae,0);___output(ae,0);___output(ae,0);___output(ae,0);
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFF needs one or more parameters\n");
+ }
+ }
+}
+
+
void _DEFR(struct s_assenv *ae) {
if (!ae->wl[ae->idx].t) {
do {
@@ -9278,20 +11956,22 @@ void _DEFB(struct s_assenv *ae) {
/* no conversion on escaped chars */
c=ae->wl[ae->idx].w[i];
switch (c) {
+ case 'e':___output(ae,0x1B);break;
+ case 'a':___output(ae,0x07);break; // alarm
case 'b':___output(ae,'\b');break;
- case 'v':___output(ae,'\v');break;
- case 'f':___output(ae,'\f');break;
+ case 'v':___output(ae,'\v');break; // v-tab
+ case 'f':___output(ae,'\f');break; // feed
case '0':___output(ae,'\0');break;
- case 'r':___output(ae,'\r');break;
- case 'n':___output(ae,'\n');break;
- case 't':___output(ae,'\t');break;
+ case 'r':___output(ae,'\r');break; // return
+ case 'n':___output(ae,'\n');break; // carriage-return
+ case 't':___output(ae,'\t');break; // tab
default:
___output(ae,c);
- ae->nop+=1;
}
+ ae->nop+=1;
} else {
/* charset conversion on the fly */
- ___output(ae,ae->charset[(int)ae->wl[ae->idx].w[i]]);
+ ___output(ae,ae->charset[(unsigned int)(ae->wl[ae->idx].w[i]&0xFF)]);
ae->nop+=1;
}
i++;
@@ -9336,7 +12016,7 @@ void _DEFB_struct(struct s_assenv *ae) {
}
} else {
/* charset conversion on the fly */
- ___output(ae,ae->charset[(int)ae->wl[ae->idx].w[i]]);
+ ___output(ae,ae->charset[(unsigned int)ae->wl[ae->idx].w[i]&0xFF]);
ae->nop+=1;
}
i++;
@@ -9436,7 +12116,7 @@ void _DEFB_as80(struct s_assenv *ae) {
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]]);
+ ___output(ae,ae->charset[(unsigned int)ae->wl[ae->idx].w[i]&0xFF]);
ae->nop+=1;
ae->codeadr--;modadr++;
i++;
@@ -9530,14 +12210,57 @@ void _DEFSTR(struct s_assenv *ae) {
#endif
#undef FUNC
+#define FUNC "Import/Export CORE"
+
+// symbol export
+void __SYMBOL(struct s_assenv *ae) {
+}
+
+// external symbol import => declare one or more new external variables
+void __EXTERNAL(struct s_assenv *ae) {
+ struct s_external zexternal={0};
+
+ while (!ae->wl[ae->idx].t) {
+ ExpressionSetDicoVar(ae,ae->wl[ae->idx+1].w,0.0,1);
+ zexternal.name=TxtStrDup(ae->wl[ae->idx+1].w);
+ zexternal.crc=GetCRC(zexternal.name);
+ ObjectArrayAddDynamicValueConcat((void**)&ae->external,&ae->nexternal,&ae->mexternal,&zexternal,sizeof(struct s_external));
+ ae->idx++;
+ }
+}
+
+// procedure export => tag and declare a label for export
+void __PROCEDURE(struct s_assenv *ae) {
+ char *dupname;
+ int cpt=1;
+ while (!ae->wl[ae->idx].t) {
+ ae->idx++;
+ /* store procedure label */
+ dupname=TxtStrDup(ae->wl[ae->idx].w);
+ ObjectArrayAddDynamicValueConcat((void**)&ae->procedurename,&ae->nprocedurename,&ae->mprocedurename,&dupname,sizeof(char *));
+ /* push label as usual */
+ PushLabel(ae);
+ if (cpt>1) {
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: PROCEDURE directive is not supposed to declare more than one label\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (ae->erronwarn) MaxError(ae);
+ }
+ }
+ cpt++;
+ }
+}
+
+void __ENDPROC(struct s_assenv *ae) {
+}
+
+
+
+
+#undef FUNC
#define FUNC "Directive CORE"
void __internal_UpdateLZBlockIfAny(struct s_assenv *ae) {
- /* there was a crunched block opened in the previous bank */
- if (ae->lz>=0) {
- //ae->lzsection[ae->ilz-1].iorgzone=ae->io-1;
- //ae->lzsection[ae->ilz-1].ibank=ae->activebank;
- }
+ /* if there was a crunched block opened in the previous bank */
ae->lz=-1;
}
@@ -9593,62 +12316,326 @@ void __ENOEXPORT(struct s_assenv *ae) {
__internal_EXPORT(ae,1);
}
+void __BUILDOBJ(struct s_assenv *ae) {
+ if (!ae->wl[ae->idx].t) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BUILDOBJ does not need a parameter\n");
+ }
+ ae->buildobj=1;
+}
void __BUILDZX(struct s_assenv *ae) {
if (!ae->wl[ae->idx].t) {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BUILDZX does not need a parameter\n");
}
- if (!ae->forcesnapshot && !ae->forcetape && !ae->forcecpr) {
+ if (!ae->forcesnapshot && !ae->forcetape && !ae->forcecpr && !ae->forceROM) {
+ ae->forcesnapshot=1;
ae->forcezx=1;
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot select ZX output when already in Amstrad cartridge/snapshot/tape output\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot select ZX output when already in Amstrad ROM/cartridge/snapshot/tape output\n");
}
}
void __BUILDCPR(struct s_assenv *ae) {
- if (!ae->wl[ae->idx].t) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BUILDCPR does not need a parameter\n");
+ if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1 && strcmp(ae->wl[ae->idx+1].w,"EXTENDED")==0) {
+ ae->extendedCPR=1;
+ } else if (!ae->wl[ae->idx].t) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BUILDCPR unknown parameter\n");
}
- if (!ae->forcesnapshot && !ae->forcetape && !ae->forcezx) {
+ if (!ae->forcesnapshot && !ae->forcetape && !ae->forcezx && !ae->forceROM) {
ae->forcecpr=1;
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot select Amstrad cartridge output when already in snapshot/tape output\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot select Amstrad cartridge output when already in ZX/ROM/snapshot/tape output\n");
}
}
-void __BUILDSNA(struct s_assenv *ae) {
+void __BUILDROM(struct s_assenv *ae) {
+ if (!ae->forcesnapshot && !ae->forcetape && !ae->forcezx && !ae->forcecpr) {
+ if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t) {
+ if (strcmp(ae->wl[ae->idx+1].w,"CONCAT")==0) {
+ ae->forceROMconcat=1;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is BUILDROM [CONCAT]\n");
+ }
+ }
+ ae->forceROM=1;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot select ROM output when already in ZX/cartridge/snapshot/tape output\n");
+ }
+}
+
+
+void __SNAPINIT(struct s_assenv *ae) {
+ unsigned char *dataout;
+ unsigned char *snapdata;
+ int src,idx,rep,i,srcmax;
+ int chunksize;
+ int version,size;
+ int snapsize;
+ int slot;
+ // integration
+ char *newfilename=NULL;
+ int fileok=0;
+
+ if (!ae->forcecpr && !ae->forcetape && !ae->forcezx && !ae->forceROM) {
+ // automatic BUILDSNA
+ ae->forcesnapshot=1;
+ }
+
if (!ae->wl[ae->idx].t) {
- if (strcmp(ae->wl[ae->idx+1].w,"V2")==0) {
- ae->snapshot.version=2;
+ if (!StringIsQuote(ae->wl[ae->idx+1].w)) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SNAPINIT needs a snapshot filename to proceed\n");
+ return;
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BUILDSNA unrecognized option\n");
+ newfilename=TxtStrDup(ae->wl[ae->idx+1].w+1); // skip first quote
+ newfilename[strlen(newfilename)-1]=0; // remove last quote
}
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SNAPINIT needs a snapshot filename to proceed\n");
+ return;
}
- if (!ae->forcecpr && !ae->forcetape && !ae->forcezx) {
- ae->forcesnapshot=1;
+
+ /* Where is the file to load? */
+ if (!FileExists(newfilename)) {
+ int ilookfile;
+ char *filename_toread;
+
+ /* on cherche dans les include */
+ for (ilookfile=0;ilookfile<ae->ipath && !fileok;ilookfile++) {
+ filename_toread=MergePath(ae,ae->includepath[ilookfile],newfilename);
+ if (FileExists(filename_toread)) {
+ fileok=1;
+ MemFree(newfilename);
+ newfilename=TxtStrDup(filename_toread); // Merge renvoie un static
+ }
+ }
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot select snapshot output when already in cartridge/tape output\n");
+ fileok=1;
}
+
+ if (fileok) {
+ snapsize=FileGetSize(newfilename);
+ snapdata=MemMalloc(snapsize);
+ if (FileReadBinary(newfilename,(char*)snapdata,snapsize)!=snapsize) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"read error on file [%s]\n",newfilename);
+ MemFree(newfilename);
+ MemFree(snapdata);
+ return;
+ }
+ FileReadBinaryClose(newfilename);
+
+ if (snapsize<0x100) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"file [%s] seems too small to be a snapshot\n",newfilename);
+ } else if (snapdata[0]!='M' || snapdata[1]!='V' || snapdata[2]!=' ' || snapdata[3]!='-' || snapdata[4]!=' ' || snapdata[5]!='S' || snapdata[6]!='N' || snapdata[7]!='A') {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"file [%s] invalid snapshot header\n",newfilename);
+ } else {
+ }
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"file [%s] not found!\n",newfilename);
+ return;
+ }
+
+ // data extraction
+ size=snapdata[0x6B]*1024;
+ src=0x100;
+ switch (snapdata[0x6B]) {
+ default:
+ case 0:
+ if (snapdata[16]<3) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"file [%s] empty snapshot v2\n",newfilename);
+ snapsize=0;
+ }
+ break;
+ case 64:
+ if (snapsize>=size+0x100) {
+ memcpy(ae->mem[0],snapdata+0x100,65536);
+ src+=65536;
+ ae->snapRAMsize=4;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"file [%s] snapshot v2 inconsistency (supposed to be 64k)\n",newfilename);
+ snapsize=0;
+ }
+ break;
+ case 128:
+ if (snapsize>=size+0x100) {
+ memcpy(ae->mem[0],snapdata+0x100,65536);
+ memcpy(ae->mem[4],snapdata+0x100+65536,65536);
+ src+=65536*2;
+ ae->snapRAMsize=8;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"file [%s] snapshot v2 inconsistency (supposed to be 128k)\n",newfilename);
+ snapsize=0;
+ }
+ break;
+ }
+
+ // raw copy of header for output (check for v2 or v3 ?)
+ memcpy(&ae->snapshot,snapdata,0x100);
+ if (ae->snapshot.version<2) {
+ rasm_printf(ae,KWARNING"[%s:%d] early version of snapshot, upgrading to V2, you may need to use SNASET to get a proper snapshot\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ ae->snapshot.version=2;
+ }
+
+ while (src+8<snapsize) {
+ chunksize=snapdata[src+4]+snapdata[src+5]*256+snapdata[src+6]*65536+snapdata[src+7]*65536*256;
+ if (snapdata[src+0]=='M' && snapdata[src+1]=='E' && snapdata[src+2]=='M') {
+ // v3 snapshot has chunk MEM%d ou MX%02X en RLE + chunksize + data
+ slot=snapdata[src+3]-'0';
+ idx=0;
+ src+=8;
+ srcmax=src+chunksize;
+ if (srcmax>snapsize) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"file [%s] invalid chunk in snapshot (overrun) chunksize=%d\n",newfilename,chunksize);
+ break;
+ }
+
+ dataout=ae->mem[slot*4];
+
+ if (slot*4+4>ae->snapRAMsize) ae->snapRAMsize=slot*4+4;
+
+ while (idx<65536 && src<srcmax) {
+ if (snapdata[src]==0xE5) {
+ src++;
+ for (i=0;i<snapdata[src] && idx<65536;i++) {
+ dataout[idx++]=snapdata[src+1];
+ }
+ src+=2;
+ } else {
+ dataout[idx++]=snapdata[src++];
+ }
+ }
+ if (src!=srcmax) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"file [%s] invalid chunk in snapshot (overrun)\n",newfilename);
+ break;
+ }
+ } else {
+ // skip non memory chunk
+ src+=8+chunksize;
+ }
+ }
+ // replicate bankset in memory to be ok with bankset rebuilding
+ memcpy(ae->mem[1],ae->mem[0],65536);
+ memcpy(ae->mem[2],ae->mem[0],65536);
+ memcpy(ae->mem[3],ae->mem[0],65536);
+ memcpy(ae->mem[5],ae->mem[4],65536);
+ memcpy(ae->mem[6],ae->mem[4],65536);
+ memcpy(ae->mem[7],ae->mem[4],65536);
+ MemFree(newfilename);
+ MemFree(snapdata);
}
-void __BUILDROM(struct s_assenv *ae) {
+
+
+void __BUILDSNA(struct s_assenv *ae) {
if (!ae->wl[ae->idx].t) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BUILDROM does not need a parameter\n");
+ if (strcmp(ae->wl[ae->idx+1].w,"V2")==0) {
+ ae->snapshot.version=2;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BUILDSNA unrecognized option\n");
+ }
}
- if (!ae->forcesnapshot && !ae->forcetape && !ae->forcezx && !ae->forcecpr) {
- ae->forceROM=1;
+ if (!ae->forcecpr && !ae->forcetape && !ae->forcezx && !ae->forceROM) {
+ ae->forcesnapshot=1;
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot select Amstrad ROM output when already in snapshot/tape/zx/cartridge output\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot select snapshot output when already in ZX/ROM/cartridge/tape output\n");
}
}
void __BUILDTAPE(struct s_assenv *ae) {
if (!ae->wl[ae->idx].t) {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BUILDTAPE does not need a parameter\n");
}
- if (!ae->forcesnapshot && !ae->forcecpr && !ae->forcezx) {
+ if (!ae->forcesnapshot && !ae->forcecpr && !ae->forcezx && !ae->forceROM) {
ae->forcetape=1;
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot select tape output when already in snapshot/cartridge output\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot select tape output when already in ZX/ROM/snapshot/cartridge output\n");
}
}
+void __LZSA1(struct s_assenv *ae) {
+ struct s_lz_section curlz={0};
+
+ if (!ae->wl[ae->idx].t) {
+ ae->idx++;
+ curlz.minmatch=atoi(ae->wl[ae->idx].w);
+ if (!ae->wl[ae->idx].t) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LZSA1 directive may only have 1 parameter\n");
+ }
+ }
+ #ifdef NO_3RD_PARTIES
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot use 3rd parties cruncher with this version of RASM\n");
+ FreeAssenv(ae);
+ exit(-5);
+ #endif
+
+ if (ae->lz>=0 && ae->lz<ae->ilz && ae->lzsection[ae->ilz-1].lzversion) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",ae->lz);
+ FreeAssenv(ae);
+ exit(-5);
+ }
+ curlz.version=1;
+ curlz.iw=ae->idx;
+ curlz.iorgzone=ae->io-1;
+ curlz.ibank=ae->activebank;
+ curlz.memstart=ae->outputadr;
+ curlz.memend=-1;
+ curlz.lzversion=18;
+ ae->lz=ae->ilz;
+ ObjectArrayAddDynamicValueConcat((void**)&ae->lzsection,&ae->ilz,&ae->mlz,&curlz,sizeof(curlz));
+}
+void __LZSA2(struct s_assenv *ae) {
+ struct s_lz_section curlz={0};
+
+ if (!ae->wl[ae->idx].t) {
+ ae->idx++;
+ curlz.minmatch=atoi(ae->wl[ae->idx].w);
+ if (!ae->wl[ae->idx].t) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LZSA2 directive may only have 1 parameter\n");
+ }
+ }
+ #ifdef NO_3RD_PARTIES
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot use 3rd parties cruncher with this version of RASM\n");
+ FreeAssenv(ae);
+ exit(-5);
+ #endif
+
+ if (ae->lz>=0 && ae->lz<ae->ilz && ae->lzsection[ae->ilz-1].lzversion) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",ae->lz);
+ FreeAssenv(ae);
+ exit(-5);
+ }
+ curlz.version=2;
+ curlz.iw=ae->idx;
+ curlz.iorgzone=ae->io-1;
+ curlz.ibank=ae->activebank;
+ curlz.memstart=ae->outputadr;
+ curlz.memend=-1;
+ curlz.lzversion=18;
+ ae->lz=ae->ilz;
+ ObjectArrayAddDynamicValueConcat((void**)&ae->lzsection,&ae->ilz,&ae->mlz,&curlz,sizeof(curlz));
+}
+void __LZAPU(struct s_assenv *ae) {
+ struct s_lz_section curlz;
+
+ if (!ae->wl[ae->idx].t) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LZ directive does not need any parameter\n");
+ return;
+ }
+ #ifdef NO_3RD_PARTIES
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot use 3rd parties cruncher with this version of RASM\n");
+ FreeAssenv(ae);
+ exit(-5);
+ #endif
+
+ if (ae->lz>=0 && ae->lz<ae->ilz && ae->lzsection[ae->ilz-1].lzversion) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",ae->lz);
+ FreeAssenv(ae);
+ exit(-5);
+ }
+ curlz.iw=ae->idx;
+ curlz.iorgzone=ae->io-1;
+ curlz.ibank=ae->activebank;
+ curlz.memstart=ae->outputadr;
+ curlz.memend=-1;
+ curlz.lzversion=17;
+ ae->lz=ae->ilz;
+ ObjectArrayAddDynamicValueConcat((void**)&ae->lzsection,&ae->ilz,&ae->mlz,&curlz,sizeof(curlz));
+}
void __LZ4(struct s_assenv *ae) {
struct s_lz_section curlz;
@@ -9657,13 +12644,13 @@ void __LZ4(struct s_assenv *ae) {
return;
}
#ifdef NO_3RD_PARTIES
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot use 3rd parties cruncher with this version of RASM\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot use 3rd parties cruncher with this version of RASM\n");
FreeAssenv(ae);
exit(-5);
#endif
- if (ae->lz>=0 && ae->lz<ae->ilz) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->lz);
+ if (ae->lz>=0 && ae->lz<ae->ilz && ae->lzsection[ae->ilz-1].lzversion) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",ae->lz);
FreeAssenv(ae);
exit(-5);
}
@@ -9676,6 +12663,62 @@ void __LZ4(struct s_assenv *ae) {
ae->lz=ae->ilz;
ObjectArrayAddDynamicValueConcat((void**)&ae->lzsection,&ae->ilz,&ae->mlz,&curlz,sizeof(curlz));
}
+void __LZX0(struct s_assenv *ae) {
+ struct s_lz_section curlz;
+
+ if (!ae->wl[ae->idx].t) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LZ directive does not need any parameter\n");
+ return;
+ }
+ #ifdef NO_3RD_PARTIES
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot use 3rd parties cruncher with this version of RASM\n");
+ FreeAssenv(ae);
+ exit(-5);
+ #endif
+
+ if (ae->lz>=0 && ae->lz<ae->ilz && ae->lzsection[ae->ilz-1].lzversion) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",ae->lz);
+ FreeAssenv(ae);
+ exit(-5);
+ }
+ curlz.version=MAX_OFFSET_ZX0;
+ curlz.iw=ae->idx;
+ curlz.iorgzone=ae->io-1;
+ curlz.ibank=ae->activebank;
+ curlz.memstart=ae->outputadr;
+ curlz.memend=-1;
+ curlz.lzversion=70;
+ ae->lz=ae->ilz;
+ ObjectArrayAddDynamicValueConcat((void**)&ae->lzsection,&ae->ilz,&ae->mlz,&curlz,sizeof(curlz));
+}
+void __LZX0B(struct s_assenv *ae) {
+ struct s_lz_section curlz;
+
+ if (!ae->wl[ae->idx].t) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LZ directive does not need any parameter\n");
+ return;
+ }
+ #ifdef NO_3RD_PARTIES
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot use 3rd parties cruncher with this version of RASM\n");
+ FreeAssenv(ae);
+ exit(-5);
+ #endif
+
+ if (ae->lz>=0 && ae->lz<ae->ilz && ae->lzsection[ae->ilz-1].lzversion) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",ae->lz);
+ FreeAssenv(ae);
+ exit(-5);
+ }
+ curlz.version=MAX_OFFSET_ZX0;
+ curlz.iw=ae->idx;
+ curlz.iorgzone=ae->io-1;
+ curlz.ibank=ae->activebank;
+ curlz.memstart=ae->outputadr;
+ curlz.memend=-1;
+ curlz.lzversion=71;
+ ae->lz=ae->ilz;
+ ObjectArrayAddDynamicValueConcat((void**)&ae->lzsection,&ae->ilz,&ae->mlz,&curlz,sizeof(curlz));
+}
void __LZX7(struct s_assenv *ae) {
struct s_lz_section curlz;
@@ -9684,13 +12727,13 @@ void __LZX7(struct s_assenv *ae) {
return;
}
#ifdef NO_3RD_PARTIES
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot use 3rd parties cruncher with this version of RASM\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot use 3rd parties cruncher with this version of RASM\n");
FreeAssenv(ae);
exit(-5);
#endif
- if (ae->lz>=0 && ae->lz<ae->ilz) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->lz);
+ if (ae->lz>=0 && ae->lz<ae->ilz && ae->lzsection[ae->ilz-1].lzversion) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",ae->lz);
FreeAssenv(ae);
exit(-5);
}
@@ -9711,13 +12754,13 @@ void __LZEXO(struct s_assenv *ae) {
return;
}
#ifdef NO_3RD_PARTIES
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot use 3rd parties cruncher with this version of RASM\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot use 3rd parties cruncher with this version of RASM\n");
FreeAssenv(ae);
exit(-5);
#endif
- if (ae->lz>=0 && ae->lz<ae->ilz) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->lz);
+ if (ae->lz>=0 && ae->lz<ae->ilz && ae->lzsection[ae->ilz-1].lzversion) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",ae->lz);
FreeAssenv(ae);
exit(-5);
}
@@ -9737,8 +12780,8 @@ void __LZ48(struct s_assenv *ae) {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LZ directive does not need any parameter\n");
return;
}
- if (ae->lz>=0 && ae->lz<ae->ilz) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->lz);
+ if (ae->lz>=0 && ae->lz<ae->ilz && ae->lzsection[ae->ilz-1].lzversion) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",ae->lz);
FreeAssenv(ae);
exit(-5);
}
@@ -9758,8 +12801,8 @@ void __LZ49(struct s_assenv *ae) {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LZ directive does not need any parameter\n");
return;
}
- if (ae->lz>=0 && ae->lz<ae->ilz) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ae->lz);
+ if (ae->lz>=0 && ae->lz<ae->ilz && ae->lzsection[ae->ilz-1].lzversion) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot start a new LZ section inside another one (%d)\n",ae->lz);
FreeAssenv(ae);
exit(-5);
}
@@ -9774,6 +12817,8 @@ void __LZ49(struct s_assenv *ae) {
ObjectArrayAddDynamicValueConcat((void**)&ae->lzsection,&ae->ilz,&ae->mlz,&curlz,sizeof(curlz));
}
void __LZCLOSE(struct s_assenv *ae) {
+ struct s_lz_section curlz;
+
if (!ae->ilz || ae->lz==-1) {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot close LZ section as it wasn't opened\n");
return;
@@ -9782,8 +12827,17 @@ void __LZCLOSE(struct s_assenv *ae) {
ae->lzsection[ae->ilz-1].memend=ae->outputadr;
ae->lzsection[ae->ilz-1].ilabel=ae->il;
ae->lzsection[ae->ilz-1].iexpr=ae->ie;
- //ae->lz=ae->ilz;
- ae->lz=-1;
+ // commentaire
+ curlz.iw=ae->idx;
+ curlz.iorgzone=ae->io-1;
+ curlz.ibank=ae->activebank;
+ curlz.memstart=ae->outputadr;
+ curlz.memend=-1;
+ curlz.lzversion=0; // intermediate zone
+ ae->lz=ae->ilz;
+ ObjectArrayAddDynamicValueConcat((void**)&ae->lzsection,&ae->ilz,&ae->mlz,&curlz,sizeof(curlz));
+
+ //ae->lz=-1;
}
void __LIMIT(struct s_assenv *ae) {
@@ -9840,7 +12894,10 @@ void ___new_memory_space(struct s_assenv *ae)
ae->orgzone[ae->io-1].memend=ae->outputadr;
}
if (ae->lz>=0) {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: LZ section wasn't closed before a new memory space directive\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: LZ section wasn't closed before a new memory space directive\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (ae->erronwarn) MaxError(ae);
+ }
__LZCLOSE(ae);
}
ae->activebank=ae->nbbank;
@@ -9853,6 +12910,7 @@ void ___new_memory_space(struct s_assenv *ae)
orgzone.memstart=0;
orgzone.ibank=ae->activebank;
orgzone.nocode=ae->nocode=0;
+ orgzone.inplace=1;
ObjectArrayAddDynamicValueConcat((void**)&ae->orgzone,&ae->io,&ae->mo,&orgzone,sizeof(orgzone));
OverWriteCheck(ae);
@@ -9874,6 +12932,7 @@ void __BANK(struct s_assenv *ae) {
}
ae->bankmode=1;
+ /* using BANK without build mode will select cartridge output as default */
if (!ae->forceROM && !ae->forcecpr && !ae->forcesnapshot && !ae->forcezx) ae->forcecpr=1;
if (ae->wl[ae->idx+1].t!=2) {
@@ -9889,20 +12948,24 @@ 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)) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - Bank selection must be from 0 to 31 in cartridge mode\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (ae->forcecpr && (ae->activebank<0 || ae->activebank>31) && !ae->extendedCPR) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - Bank selection must be from 0 to 31 in cartridge mode\n");
+ FreeAssenv(ae);
+ exit(2);
+ } else if (ae->extendedCPR && (ae->activebank<0 || ae->activebank>256) && !ae->extendedCPR) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - Bank selection must be from 0 to 256 in extended cartridge mode\n");
FreeAssenv(ae);
exit(2);
} else if (ae->forcezx && (ae->activebank<0 || ae->activebank>7)) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - Bank selection must be from 0 to 7 in ZX Spectrum mode\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - Bank selection must be from 0 to 7 in ZX Spectrum mode\n");
FreeAssenv(ae);
exit(2);
} else if (ae->forceROM && (ae->activebank<0 || ae->activebank>=256)) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - Bank selection must be from 0 to 255 in ROM mode\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - Bank selection must be from 0 to 255 in ROM mode\n");
FreeAssenv(ae);
exit(2);
} else if (ae->forcesnapshot && (ae->activebank<0 || ae->activebank>=260)) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - Bank selection must be from 0 to 259 in snapshot mode\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - Bank selection must be from 0 to 259 in snapshot mode\n");
FreeAssenv(ae);
exit(2);
}
@@ -9920,7 +12983,10 @@ void __BANK(struct s_assenv *ae) {
return;
}
if (ae->lz>=0) {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: LZ section wasn't closed before a new BANK directive\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: LZ section wasn't closed before a new BANK directive\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (ae->erronwarn) MaxError(ae);
+ }
__LZCLOSE(ae);
}
@@ -9945,11 +13011,11 @@ void __BANK(struct s_assenv *ae) {
void __BANKSET(struct s_assenv *ae) {
struct s_orgzone orgzone={0};
- int ibank;
+ int ibank,i;
__internal_UpdateLZBlockIfAny(ae);
- if (!ae->forcesnapshot && !ae->forcecpr && !ae->forcezx) ae->forcesnapshot=1;
+ if (!ae->forcesnapshot && !ae->forcecpr && !ae->forcezx && !ae->forceROM) ae->forcesnapshot=1;
if (!ae->forcesnapshot) {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BANKSET directive is specific to snapshot output\n");
return;
@@ -9965,26 +13031,37 @@ void __BANKSET(struct s_assenv *ae) {
ae->activebank=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0);
ae->activebank*=4;
if (ae->forcesnapshot && (ae->activebank<0 || ae->activebank>=260)) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - Bank set selection must be from 0 to 64 in snapshot mode\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"FATAL - Bank set selection must be from 0 to 64 in snapshot mode\n");
FreeAssenv(ae);
exit(2);
}
/* control */
ibank=ae->activebank;
- if (ae->bankused[ibank] || ae->bankused[ibank+1]|| ae->bankused[ibank+2]|| ae->bankused[ibank+3]) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot BANKSET because bank %d was already selected in single page mode\n",ibank);
- ae->idx++;
- return;
- } else {
- ae->bankset[ae->activebank/4]=1; /* pas très heureux mais bon... */
- }
+ if (!ae->bankset[ibank>>2]) {
+ if (ae->bankused[ibank] || ae->bankused[ibank+1]|| ae->bankused[ibank+2]|| ae->bankused[ibank+3]) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot BANKSET because bank %d was already selected in single page mode\n",ibank);
+ ae->idx++;
+ return;
+ } else {
+ /* in case of EMURAM, rebuild bankset with existing data (this is done only once) */
+ ae->bankset[ibank>>2]=1;
+ for (i=16384;i<32768;i++) {
+ ae->mem[ibank][i]=ae->mem[ibank+1][i];
+ ae->mem[ibank][i+16384]=ae->mem[ibank+2][i+16384];
+ ae->mem[ibank][i+32768]=ae->mem[ibank+3][i+32768];
+ }
+ }
+ }
ae->idx++;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BANKSET directive need one integer parameter\n");
return;
}
if (ae->lz>=0) {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: LZ section wasn't closed before a new BANKSET directive\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: LZ section wasn't closed before a new BANKSET directive\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (ae->erronwarn) MaxError(ae);
+ }
__LZCLOSE(ae);
}
@@ -10052,7 +13129,10 @@ void __WRITE(struct s_assenv *ae) {
__BANK(ae);
ok=1;
} else {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: WRITE DIRECT lower ROM ignored (value %d out of bounds 0-7)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,lower);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: WRITE DIRECT lower ROM ignored (value %d out of bounds 0-7)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,lower);
+ if (ae->erronwarn) MaxError(ae);
+ }
}
} else if (upper!=-1) {
if (upper>=0 && ((ae->forcecpr && upper<32) || (ae->forcesnapshot && upper<BANK_MAX_NUMBER))) {
@@ -10061,15 +13141,24 @@ void __WRITE(struct s_assenv *ae) {
ok=1;
} else {
if (!ae->forcecpr && !ae->forcesnapshot) {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: WRITE DIRECT select a ROM without cartridge output\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: WRITE DIRECT select a ROM without cartridge output\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (ae->erronwarn) MaxError(ae);
+ }
} else {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: WRITE DIRECT upper ROM ignored (value %d out of bounds 0-31)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,upper);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: WRITE DIRECT upper ROM ignored (value %d out of bounds 0-31)\n",GetCurrentFile(ae),ae->wl[ae->idx].l,upper);
+ if (ae->erronwarn) MaxError(ae);
+ }
}
}
} else if (bank!=-1) {
/* selection de bank on ouvre un nouvel espace */
} else {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: meaningless WRITE DIRECT\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: meaningless WRITE DIRECT\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (ae->erronwarn) MaxError(ae);
+ }
}
}
while (!ae->wl[ae->idx].t) ae->idx++;
@@ -10094,7 +13183,7 @@ void __CHARSET(struct s_assenv *ae) {
i=1;
while (ae->wl[ae->idx+1].w[i] && ae->wl[ae->idx+1].w[i]!=tquote) {
if (ae->wl[ae->idx+1].w[i]=='\\') i++;
- ae->charset[(int)ae->wl[ae->idx+1].w[i]]=(unsigned char)v++;
+ ae->charset[(unsigned int)ae->wl[ae->idx+1].w[i]&0xFF]=(unsigned char)v++;
i++;
}
} else {
@@ -10123,13 +13212,48 @@ void __CHARSET(struct s_assenv *ae) {
ae->charset[i]=(unsigned char)v++;
}
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CHARSET winape directive wrong interval value\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CHARSET Winape directive wrong interval value\n");
}
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CHARSET winape directive wrong parameter count\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CHARSET Winape directive wrong parameter count\n");
}
}
+void PushGlobal(struct s_assenv *ae) {
+ char *zelast;
+ if (ae->lastgloballabel) zelast=TxtStrDup(ae->lastgloballabel); else zelast=NULL;
+ ObjectArrayAddDynamicValueConcat((void **)&ae->globalstack,&ae->igs,&ae->mgs,&zelast,sizeof(char *));
+
+#if TRACE_LABEL
+printf("==> PushGlobal on Stack [%s] igs=%d\n",zelast,ae->igs);
+#endif
+}
+
+void PopGlobal(struct s_assenv *ae) {
+ if (ae->igs) {
+ ae->igs--;
+#if TRACE_LABEL
+printf("<== PopGlobal on Stack [%s] igs=%d\n",ae->globalstack[ae->igs],ae->igs+1);
+#endif
+ if (ae->lastglobalalloc) MemFree(ae->lastgloballabel);
+
+ if (ae->globalstack[ae->igs]) {
+ ae->lastgloballabel=TxtStrDup(ae->globalstack[ae->igs]);
+ ae->lastgloballabellen=strlen(ae->lastgloballabel);
+ ae->lastglobalalloc=1;
+ } else {
+ ae->lastgloballabel=NULL;
+ ae->lastgloballabellen=0;
+ ae->lastglobalalloc=0;
+ }
+
+ if (ae->globalstack[ae->igs]) MemFree(ae->globalstack[ae->igs]);
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"PopGlobal INTERNAL ERROR / Please report\n");
+ }
+}
+
+
void __MACRO(struct s_assenv *ae) {
struct s_macro curmacro={0};
char *referentfilename,*zeparam;
@@ -10144,9 +13268,27 @@ void __MACRO(struct s_assenv *ae) {
getparam=0;
}
/* overload forbidden */
+ /* macro, keywords and directives forbidden */
if (SearchMacro(ae,curmacro.crc,curmacro.mnemo)>=0) {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Macro already defined with this name\n");
+ } else {
+ if ((SearchDico(ae,ae->wl[ae->idx+1].w,curmacro.crc))!=NULL) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Macro definition: There is already a variable with this name\n");
+ } else {
+ if ((SearchLabel(ae,ae->wl[ae->idx+1].w,curmacro.crc))!=NULL) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Macro definition: There is already a label with this name\n");
+ } else {
+ if ((SearchAlias(ae,curmacro.crc,ae->wl[ae->idx+1].w))!=-1) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Macro definition: There is already an alias with this name\n");
+ } else {
+ if (IsRegister(curmacro.mnemo)) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Macro definition: Cannot choose a register as macro name\n");
+ }
+ }
+ }
+ }
}
+
idx=ae->idx+2;
while (ae->wl[idx].t!=2 && (GetCRC(ae->wl[idx].w)!=CRC_MEND || strcmp(ae->wl[idx].w,"MEND")!=0) && (GetCRC(ae->wl[idx].w)!=CRC_ENDM || strcmp(ae->wl[idx].w,"ENDM")!=0)) {
if (GetCRC(ae->wl[idx].w)==CRC_MACRO || strcmp(ae->wl[idx].w,"MACRO")==0) {
@@ -10190,7 +13332,7 @@ void __MACRO(struct s_assenv *ae) {
if (ae->wl[idx].t==2) idx--;
ae->idx=idx;
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"MACRO definition need at least one parameter\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"MACRO definition need at least one parameter for the name of the macro\n");
}
}
@@ -10219,10 +13361,6 @@ struct s_wordlist *__MACRO_EXECUTE(struct s_assenv *ae, int imacro) {
} else {
if (ae->macrovoid) {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"MACRO [%s] used without (void) and option -void used!\n",ae->macro[imacro].mnemo);
- while (!ae->wl[ae->idx].t) {
- ae->idx++;
- }
- ae->idx++;
}
}
}
@@ -10280,10 +13418,26 @@ struct s_wordlist *__MACRO_EXECUTE(struct s_assenv *ae, int imacro) {
for (i=0;i<nbparam;i++) {
cpybackup[i]=ae->wl[ae->idx+1+i];
}
- /* insert macro position */
+ /************************
+ insert macro position
+ *************************/
curmacropos.start=ae->idx;
curmacropos.end=ae->idx+ae->macro[imacro].nbword;
curmacropos.value=ae->macrocounter;
+ /* which level? */
+ curmacropos.pushed=0;
+ if (!ae->imacropos) {
+ curmacropos.level=1;
+ } else {
+ if (ae->macropos[ae->imacropos-1].end<=curmacropos.start) {
+ /* same level */
+ curmacropos.level=ae->macropos[ae->imacropos-1].level;
+ } else {
+ /* inception */
+ curmacropos.level=ae->macropos[ae->imacropos-1].level+1;
+ }
+ }
+
ObjectArrayAddDynamicValueConcat((void**)&ae->macropos,&ae->imacropos,&ae->mmacropos,&curmacropos,sizeof(curmacropos));
/* are we in a repeat/while block? */
@@ -10333,11 +13487,32 @@ struct s_wordlist *__MACRO_EXECUTE(struct s_assenv *ae, int imacro) {
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]);
}
}
+//printf("MACRO_EXECUTE word[%d]=[%s] param[%d]=[%s] cpybackup[%d]=[%s]\n",j,ae->wl[j].w,i,ae->macro[imacro].param[i],i,cpybackup[i].w);
ae->wl[j].w=TxtReplace(ae->wl[j].w,ae->macro[imacro].param[i],cpybackup[i].w,0);
}
MemFree(cpybackup[i].w);
}
MemFree(cpybackup);
+
+ /* look for specific tags */
+ for (j=idx;j<idx+ae->macro[imacro].nbword;j++) {
+ switch (GetCRC(ae->wl[j].w)) {
+ case CRC_AF_HIGH:if (strcmp(ae->wl[j].w,"AF.HIGH")==0) strcpy(ae->wl[j].w,"A");break;
+ case CRC_AF_LOW: if (strcmp(ae->wl[j].w,"AF.LOW")==0) strcpy(ae->wl[j].w,"F");break;
+ case CRC_BC_HIGH:if (strcmp(ae->wl[j].w,"BC.HIGH")==0) strcpy(ae->wl[j].w,"B");break;
+ case CRC_BC_LOW: if (strcmp(ae->wl[j].w,"BC.LOW")==0) strcpy(ae->wl[j].w,"C");break;
+ case CRC_DE_HIGH:if (strcmp(ae->wl[j].w,"DE.HIGH")==0) strcpy(ae->wl[j].w,"D");break;
+ case CRC_DE_LOW: if (strcmp(ae->wl[j].w,"DE.LOW")==0) strcpy(ae->wl[j].w,"E");break;
+ case CRC_HL_HIGH:if (strcmp(ae->wl[j].w,"HL.HIGH")==0) strcpy(ae->wl[j].w,"H");break;
+ case CRC_HL_LOW: if (strcmp(ae->wl[j].w,"HL.LOW")==0) strcpy(ae->wl[j].w,"L");break;
+ case CRC_IX_HIGH:if (strcmp(ae->wl[j].w,"IX.HIGH")==0) strcpy(ae->wl[j].w,"XH");break;
+ case CRC_IX_LOW: if (strcmp(ae->wl[j].w,"IX.LOW")==0) strcpy(ae->wl[j].w,"XL");break;
+ case CRC_IY_HIGH:if (strcmp(ae->wl[j].w,"IY.HIGH")==0) strcpy(ae->wl[j].w,"YH");break;
+ case CRC_IY_LOW: if (strcmp(ae->wl[j].w,"IY.LOW")==0) strcpy(ae->wl[j].w,"YL");break;
+ default:break;
+ }
+ }
+
/* macro replaced, need to rollback index */
//ae->idx--;
}
@@ -10373,7 +13548,8 @@ void __TICKER(struct s_assenv *ae) {
ObjectArrayAddDynamicValueConcat((void **)&ae->ticker,&ae->iticker,&ae->mticker,&ticker,sizeof(struct s_ticker));
}
ae->ticker[i].nopstart=ae->nop;
- } else if (strcmp(ae->wl[ae->idx+1].w,"STOP")==0) {
+ ae->ticker[i].tickerstart=ae->tick;
+ } else if (strncmp(ae->wl[ae->idx+1].w,"STOP",4)==0) {
for (i=0;i<ae->iticker;i++) {
if (ae->ticker[i].crc==crc && strcmp(ae->wl[ae->idx+2].w,ae->ticker[i].varname)==0) {
break;
@@ -10383,20 +13559,22 @@ void __TICKER(struct s_assenv *ae) {
/* set var */
if ((tvar=SearchDico(ae,ae->wl[ae->idx+2].w,crc))!=NULL) {
/* compute nop count */
- tvar->v=ae->nop-ae->ticker[i].nopstart;
+ if (ae->wl[ae->idx+1].w[4]=='Z') tvar->v=ae->tick-ae->ticker[i].tickerstart;
+ else tvar->v=ae->nop-ae->ticker[i].nopstart;
} else {
/* create var with nop count */
- ExpressionSetDicoVar(ae,ae->wl[ae->idx+2].w,ae->nop-ae->ticker[i].nopstart);
+ if (ae->wl[ae->idx+1].w[4]=='Z') ExpressionSetDicoVar(ae,ae->wl[ae->idx+2].w,ae->tick-ae->ticker[i].tickerstart,0);
+ else ExpressionSetDicoVar(ae,ae->wl[ae->idx+2].w,ae->nop-ae->ticker[i].nopstart,0);
}
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"TICKER not found\n");
}
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is TICKER start/stop,<variable>\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is TICKER start/stop(z),<variable>\n");
}
ae->idx+=2;
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is TICKER start/stop,<variable>\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is TICKER start/stop(z),<variable>\n");
}
}
@@ -10406,7 +13584,7 @@ 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 {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LET useless winape directive need one expression\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LET useless Winape directive need one expression\n");
}
}
@@ -10416,13 +13594,13 @@ void __RUN(struct s_assenv *ae) {
if (!ae->wl[ae->idx].t) {
ae->current_run_idx=ae->idx+1;
if (ae->forcezx) {
+ PushExpression(ae,ae->idx+1,E_EXPRESSION_ZXRUN); // delayed RUN value
+ ae->idx++;
if (!ae->wl[ae->idx].t) {
- PushExpression(ae,ae->idx+1,E_EXPRESSION_ZXRUN); // delayed RUN value
- PushExpression(ae,ae->idx+2,E_EXPRESSION_ZXSTACK); // delayed STACK value
- ae->idx+=2;
- } else {
+ PushExpression(ae,ae->idx+1,E_EXPRESSION_ZXSTACK); // delayed STACK value
ae->idx++;
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is RUN <adress>,<stack> (ZX mode)\n");
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is RUN <address>,<stack> (ZX mode, you must set address+stack)\n");
}
} else {
PushExpression(ae,ae->idx+1,E_EXPRESSION_RUN); // delayed RUN value
@@ -10432,16 +13610,23 @@ void __RUN(struct s_assenv *ae) {
ramconf=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0);
ae->idx++;
if (ramconf<0xC0 || ramconf>0xFF) {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: ram configuration out of bound %X forced to #C0\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ramconf);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: ram configuration out of bound %X forced to #C0\n",GetCurrentFile(ae),ae->wl[ae->idx].l,ramconf);
+ if (ae->erronwarn) MaxError(ae);
+ }
+ ramconf=0xC0;
}
+ ae->snapshot.ramconfiguration=ramconf;
}
}
} else {
- if (ae->forcezx) MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is RUN <adress>,<stack> (ZX mode)\n");
- else MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is RUN <adress>[,<ppi>]\n");
+ if (ae->forcezx) MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is RUN <address>,<stack> (ZX mode)\n");
+ else MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is RUN <address>[,<ppi>]\n");
+ }
+ if (ae->rundefined && !ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: run address redefinition\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (ae->erronwarn) MaxError(ae);
}
- ae->snapshot.ramconfiguration=ramconf;
- if (ae->rundefined && !ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: run adress redefinition\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
ae->rundefined=1;
}
void __BREAKPOINT(struct s_assenv *ae) {
@@ -10455,16 +13640,224 @@ void __BREAKPOINT(struct s_assenv *ae) {
breakpoint.address=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0);
ObjectArrayAddDynamicValueConcat((void **)&ae->breakpoint,&ae->ibreakpoint,&ae->maxbreakpoint,&breakpoint,sizeof(struct s_breakpoint));
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is BREAKPOINT [adress]\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"syntax is BREAKPOINT [address]\n");
+ }
+}
+
+void __SNASET(struct s_assenv *ae) {
+ int myvalue,idx;
+
+ if (!ae->forcecpr && !ae->forcetape && !ae->forcezx && !ae->forceROM) {
+ ae->forcesnapshot=1;
+ } else {
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: Cannot SNASET when already in ZX/ROM/cartridge/tape output\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (ae->erronwarn) MaxError(ae);
+ }
+ }
+
+ if (!ae->wl[ae->idx].t) {
+ ae->idx++;
+ /* TWO parameters */
+ if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) {
+ /* parameter value */
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0);
+ myvalue=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0);
+
+ /* Z80 register/value */
+ if (strcmp(ae->wl[ae->idx].w,"Z80_AF")==0) {
+ ae->snapshot.registers.general.F=myvalue&0xFF;
+ ae->snapshot.registers.general.A=(myvalue>>8)&0xFF;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_F")==0) {
+ ae->snapshot.registers.general.F=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_A")==0) {
+ ae->snapshot.registers.general.A=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_BC")==0) {
+ ae->snapshot.registers.general.C=myvalue&0xFF;
+ ae->snapshot.registers.general.B=(myvalue>>8)&0xFF;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_C")==0) {
+ ae->snapshot.registers.general.C=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_B")==0) {
+ ae->snapshot.registers.general.B=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_DE")==0) {
+ ae->snapshot.registers.general.E=myvalue&0xFF;
+ ae->snapshot.registers.general.D=(myvalue>>8)&0xFF;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_E")==0) {
+ ae->snapshot.registers.general.E=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_D")==0) {
+ ae->snapshot.registers.general.D=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_HL")==0) {
+ ae->snapshot.registers.general.L=myvalue&0xFF;
+ ae->snapshot.registers.general.H=(myvalue>>8)&0xFF;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_L")==0) {
+ ae->snapshot.registers.general.L=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_H")==0) {
+ ae->snapshot.registers.general.H=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_I")==0) {
+ ae->snapshot.registers.regI=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_R")==0) {
+ ae->snapshot.registers.R=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_IFF0")==0) {
+ ae->snapshot.registers.IFF0=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_IFF1")==0) {
+ ae->snapshot.registers.IFF1=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_IX")==0) {
+ ae->snapshot.registers.LX=myvalue&0xFF;
+ ae->snapshot.registers.HX=(myvalue>>8)&0xFF;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_IXL")==0) {
+ ae->snapshot.registers.LX=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_IXH")==0) {
+ ae->snapshot.registers.HX=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_IY")==0) {
+ ae->snapshot.registers.LY=myvalue&0xFF;
+ ae->snapshot.registers.HY=(myvalue>>8)&0xFF;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_IYL")==0) {
+ ae->snapshot.registers.LY=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_IYH")==0) {
+ ae->snapshot.registers.HY=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_SP")==0) {
+ ae->snapshot.registers.LSP=myvalue&0xFF;
+ ae->snapshot.registers.HSP=(myvalue>>8)&0xFF;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_PC")==0) {
+ ae->snapshot.registers.LPC=myvalue&0xFF;
+ ae->snapshot.registers.HPC=(myvalue>>8)&0xFF;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_IM")==0) {
+ ae->snapshot.registers.IM=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_AFX")==0) {
+ ae->snapshot.registers.alternate.F=myvalue&0xFF;
+ ae->snapshot.registers.alternate.A=(myvalue>>8)&0xFF;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_AX")==0) {
+ ae->snapshot.registers.alternate.A=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_FX")==0) {
+ ae->snapshot.registers.alternate.F=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_BCX")==0) {
+ ae->snapshot.registers.alternate.C=myvalue&0xFF;
+ ae->snapshot.registers.alternate.B=(myvalue>>8)&0xFF;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_CX")==0) {
+ ae->snapshot.registers.alternate.C=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_BX")==0) {
+ ae->snapshot.registers.alternate.B=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_DEX")==0) {
+ ae->snapshot.registers.alternate.E=myvalue&0xFF;
+ ae->snapshot.registers.alternate.D=(myvalue>>8)&0xFF;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_EX")==0) {
+ ae->snapshot.registers.alternate.E=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_DX")==0) {
+ ae->snapshot.registers.alternate.D=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_HLX")==0) {
+ ae->snapshot.registers.alternate.L=myvalue&0xFF;
+ ae->snapshot.registers.alternate.H=(myvalue>>8)&0xFF;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_LX")==0) {
+ ae->snapshot.registers.alternate.L=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"Z80_HX")==0) {
+ ae->snapshot.registers.alternate.H=myvalue;
+ /* Gate Array / CRTC / PPI / FDD */
+ } else if (strcmp(ae->wl[ae->idx].w,"GA_PEN")==0) {
+ ae->snapshot.gatearray.selectedpen=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"GA_ROMCFG")==0) {
+ ae->snapshot.gatearray.multiconfiguration=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"GA_RAMCFG")==0) {
+ ae->snapshot.ramconfiguration=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"CRTC_SEL")==0) {
+ ae->snapshot.crtc.selectedregister=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"ROM_UP")==0) {
+ ae->snapshot.romselect=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"PPI_A")==0) {
+ ae->snapshot.ppi.portA=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"PPI_B")==0) {
+ ae->snapshot.ppi.portB=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"PPI_C")==0) {
+ ae->snapshot.ppi.portC=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"PPI_CTL")==0) {
+ ae->snapshot.ppi.control=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"PSG_SEL")==0) {
+ ae->snapshot.psg.selectedregister=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"CPC_TYPE")==0) {
+ ae->snapshot.CPCType=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"INT_NUM")==0) {
+ ae->snapshot.interruptnumber=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"FDD_MOTOR")==0) {
+ ae->snapshot.fdd.motorstate=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"FDD_TRACK")==0) {
+ ae->snapshot.fdd.physicaltrack=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"PRNT_DATA")==0) {
+ ae->snapshot.printerstrobe=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"CRTC_TYPE")==0) {
+ ae->snapshot.crtcstate.model=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"CRTC_HCC")==0) {
+ ae->snapshot.crtcstate.HCC=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"CRTC_CLC")==0) {
+ ae->snapshot.crtcstate.CLC=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"CRTC_RLC")==0) {
+ ae->snapshot.crtcstate.RLC=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"CRTC_VAC")==0) { // Vertical Total Adjust Counter
+ ae->snapshot.crtcstate.VTC=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"CRTC_HSWC")==0) {
+ ae->snapshot.crtcstate.HSC=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"CRTC_VSWC")==0) {
+ ae->snapshot.crtcstate.VSC=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"CRTC_STATE")==0) {
+ ae->snapshot.crtcstate.flags=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"GA_VSC")==0) {
+ ae->snapshot.vsyncdelay=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"GA_ISC")==0) {
+ ae->snapshot.interruptscanlinecounter=myvalue;
+ } else if (strcmp(ae->wl[ae->idx].w,"INT_REQ")==0) {
+ ae->snapshot.interruptrequestflag=myvalue;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SNASET directive unknown non array settings\n");
+ }
+ } else if (!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) {
+ /* index value */
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0);
+ idx=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0);
+
+ /* parameter value */
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx+2].w,0);
+ myvalue=RoundComputeExpression(ae,ae->wl[ae->idx+2].w,ae->codeadr,0,0);
+
+ if (strcmp(ae->wl[ae->idx].w,"GA_PAL")==0) {
+ if (idx>=0 && idx<17) {
+ ae->snapshot.gatearray.palette[idx]=myvalue;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SNASET directive needs [0-16] index for GA_PAL\n");
+ }
+ } else if (strcmp(ae->wl[ae->idx].w,"CRTC_REG")==0) {
+ if (idx>=0 && idx<18) {
+ ae->snapshot.crtc.registervalue[idx]=myvalue;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SNASET directive needs [0-17] index for CRTC_REG\n");
+ }
+ } else if (strcmp(ae->wl[ae->idx].w,"PSG_REG")==0) {
+ if (idx>=0 && idx<16) {
+ ae->snapshot.psg.registervalue[idx]=myvalue;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SNASET directive needs [0-15] index for PSG_REG\n");
+ }
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SNASET directive unknown array settings\n");
+ }
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SNASET directive need 2 or 3 parameters (see documentation for more informations)\n");
+ }
}
+
+
}
+
+
void __SETCPC(struct s_assenv *ae) {
int mycpc;
- if (!ae->forcecpr) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: SETCPC is deprecated, use SNASET CPC_TYPE,<type> instead\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+
+ if (!ae->forcecpr && !ae->forceROM && !ae->forcezx) {
ae->forcesnapshot=1;
} else {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: Cannot SETCPC when already in cartridge output\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: Cannot SETCPC when already in ZX/ROM/cartridge output\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (ae->erronwarn) MaxError(ae);
+ }
}
if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) {
@@ -10490,10 +13883,15 @@ void __SETCPC(struct s_assenv *ae) {
void __SETCRTC(struct s_assenv *ae) {
int mycrtc;
- if (!ae->forcecpr) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: SETCRTC is deprecated, use SNASET CRTC_TYPE,<type> instead\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+
+ if (!ae->forcecpr && !ae->forcezx && !ae->forceROM) {
ae->forcesnapshot=1;
} else {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: Cannot SETCRTC when already in cartridge output\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: Cannot SETCRTC when already in ZX/ROM/cartridge output\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (ae->erronwarn) MaxError(ae);
+ }
}
if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) {
@@ -10502,6 +13900,7 @@ void __SETCRTC(struct s_assenv *ae) {
ae->idx++;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"SETCRTC directive need one integer parameter\n");
+ mycrtc=0;
}
switch (mycrtc) {
case 0:
@@ -10519,18 +13918,21 @@ void __SETCRTC(struct s_assenv *ae) {
void __LIST(struct s_assenv *ae) {
if (!ae->wl[ae->idx].t) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LIST winape directive do not need parameter\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"LIST Winape directive does not need parameter\n");
}
}
void __NOLIST(struct s_assenv *ae) {
if (!ae->wl[ae->idx].t) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"NOLIST winape directive do not need parameter\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"NOLIST Winape directive does not need parameter\n");
}
}
void __BRK(struct s_assenv *ae) {
if (!ae->wl[ae->idx].t) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BRK winape directive do not need parameter\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BRK Winape directive does not need parameter\n");
+ } else {
+ ___output(ae,0xED);
+ ___output(ae,0xFF);
}
}
@@ -10541,6 +13943,14 @@ void __STOP(struct s_assenv *ae) {
ae->stop=1;
}
+void __DELAYED_PRINT(struct s_assenv *ae) {
+ IntArrayAddDynamicValueConcat(&ae->dprint_idx,&ae->idprint,&ae->mdprint,ae->idx);
+ /* skip parameters */
+ while (ae->wl[ae->idx].t!=1) {
+ ae->idx++;
+ }
+}
+
void __PRINT(struct s_assenv *ae) {
while (ae->wl[ae->idx].t!=1) {
if (!StringIsQuote(ae->wl[ae->idx+1].w)) {
@@ -10574,6 +13984,13 @@ void __PRINT(struct s_assenv *ae) {
} else if (strncmp(ae->wl[ae->idx+1].w,"{INT}",5)==0) {
string2print=TxtStrDup(ae->wl[ae->idx+1].w+5);
entier=1;
+ } else if (strncmp(ae->wl[ae->idx+1].w,"{INT",4)==0 && ae->wl[ae->idx+1].w[4] && ae->wl[ae->idx+1].w[5]=='}') {
+ string2print=TxtStrDup(ae->wl[ae->idx+1].w+6);
+ entier=ae->wl[ae->idx+1].w[4]-'0';
+ if (entier<2 || entier>5) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"invalid prefix, must be from INT2 to INT5\n");
+ entier=5;
+ }
} else {
string2print=TxtStrDup(ae->wl[ae->idx+1].w);
}
@@ -10617,7 +14034,7 @@ void __PRINT(struct s_assenv *ae) {
}
rasm_printf(ae," ");
} else if (entier) {
- rasm_printf(ae,"%d ",(int)RoundComputeExpressionCore(ae,string2print,ae->codeadr,0));
+ rasm_printf(ae,"%0*d ",entier,(int)RoundComputeExpressionCore(ae,string2print,ae->codeadr,0));
} else {
rasm_printf(ae,"%.2lf ",ComputeExpressionCore(ae,string2print,ae->codeadr,0));
}
@@ -10656,6 +14073,54 @@ void __FAIL(struct s_assenv *ae) {
MaxError(ae);
}
+void __CONFINE(struct s_assenv *ae) {
+ int aval,ifill=0,warning=0,enforce=0;
+
+ if (ae->io) {
+ ae->orgzone[ae->io-1].memend=ae->outputadr; // mandatory but why???
+ }
+ 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)-1;
+ ae->idx++;
+ while (!ae->wl[ae->idx].t) {
+ if (strcmp(ae->wl[ae->idx+1].w,"ENFORCE")==0) {
+ warning=1;
+ } else if (strcmp(ae->wl[ae->idx+1].w,"WARNING")==0) {
+ warning=1;
+ } else /* confine with fill ? */ {
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0);
+ ifill=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->codeadr,0,0);
+ if (ifill<0 || ifill>255) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"ALIGN fill value must be 0 to 255\n");
+ ifill=0;
+ }
+ }
+ ae->idx++;
+ }
+ if (aval<1 || aval>256) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CONFINE size must be in [2-256] interval\n");
+ aval=1;
+ }
+ /* touch codeadr only if needed */
+ if (((ae->codeadr+aval)&0xFF00)!=(ae->codeadr&0xFF00)) {
+ if (!ae->nowarning || warning || enforce) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: confinement overflows %d byte%s, loss of %d byte%s\n",GetCurrentFile(ae),ae->wl[ae->idx].l,
+ ((ae->codeadr+aval)&0xFF)+1,(((ae->codeadr+aval)&0xFF)+1)>1?"s":"",
+ aval-((ae->codeadr+aval)&0xFF)-1,aval-((ae->codeadr+aval)&0xFF)-1>1?"s":"");
+ if (ae->erronwarn || enforce) MaxError(ae);
+ }
+ /* physical ALIGN fill bytes */
+ while ((ae->codeadr&0xFF)!=0) {
+ ___output(ae,ifill);
+ ae->nop+=1;
+ }
+ }
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CONFINE <confined size>[,fill] directive need one or two integers parameters\n");
+ }
+}
+
void __ALIGN(struct s_assenv *ae) {
int aval,ifill=-1;
@@ -10682,7 +14147,7 @@ void __ALIGN(struct s_assenv *ae) {
aval=1;
}
- /* touch codeadr only if adress is misaligned */
+ /* touch codeadr only if address is misaligned */
if (ae->codeadr%aval) {
if (ifill==-1) {
/* virtual ALIGN is moving outputadr the same value as codeadr move */
@@ -10767,6 +14232,12 @@ void __WHILE(struct s_assenv *ae) {
___internal_skip_loop_block(ae,E_LOOPSTYLE_WHILE);
return;
} else {
+
+ /*************************************************/
+ /********* PUSH Global on Stack ******************/
+ /*************************************************/
+ PushGlobal(ae);
+
ae->idx++;
whilewend.start=ae->idx;
whilewend.cpt=0;
@@ -10788,6 +14259,12 @@ void __WEND(struct s_assenv *ae) {
if (ae->wl[ae->idx].t==1) {
if (ComputeExpression(ae,ae->wl[ae->whilewend[ae->iw-1].start].w,ae->codeadr,0,2)) {
if (ae->whilewend[ae->iw-1].while_counter>65536) {
+
+ /*************************************************/
+ /********* POP Global on Stack *******************/
+ /*************************************************/
+ PopGlobal(ae);
+
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Bypass infinite WHILE loop\n");
ae->iw--;
/* refresh macro check index */
@@ -10800,6 +14277,12 @@ void __WEND(struct s_assenv *ae) {
ae->imacropos=ae->whilewend[ae->iw-1].maxim;
}
} else {
+
+ /*************************************************/
+ /********* POP Global on Stack *******************/
+ /*************************************************/
+ PopGlobal(ae);
+
ae->iw--;
/* refresh macro check index */
if (ae->iw) ae->imacropos=ae->whilewend[ae->iw-1].maxim;
@@ -10812,17 +14295,32 @@ void __WEND(struct s_assenv *ae) {
}
}
+void __STARTINGINDEX(struct s_assenv *ae) {
+ if (ae->wl[ae->idx].t==0) {
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0);
+ ae->repeat_start=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,0,0,0);
+ ae->idx++;
+ if (ae->wl[ae->idx].t==0) {
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0);
+ ae->repeat_increment=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,0,0,0);
+ ae->idx++;
+ }
+ } else {
+ ae->repeat_start=1;
+ ae->repeat_increment=1;
+ }
+}
+
void __REPEAT(struct s_assenv *ae) {
struct s_repeat currepeat={0};
struct s_expr_dico *rvar;
- int *loopstyle;
- int iloop,mloop;
- int cidx,crc;
+ int crc;
if (ae->wl[ae->idx+1].t!=2) {
if (ae->wl[ae->idx].t==0) {
ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0);
currepeat.cpt=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,0,0,0);
+
if (!currepeat.cpt) {
/* skip repeat block */
___internal_skip_loop_block(ae,E_LOOPSTYLE_REPEATN);
@@ -10833,28 +14331,48 @@ void __REPEAT(struct s_assenv *ae) {
return;
}
ae->idx++;
- currepeat.start=ae->idx;
if (ae->wl[ae->idx].t==0) {
+ double vstart;
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);
+
+ // default
+ currepeat.varincrement=ae->repeat_increment;
+ vstart=ae->repeat_start;
+
+ /* additionnal options */
+ if (ae->wl[ae->idx].t==0) {
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0);
+ vstart=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,0,0,0);
+ if (ae->wl[ae->idx+1].t==0) {
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx+2].w,0);
+ currepeat.varincrement=RoundComputeExpression(ae,ae->wl[ae->idx+2].w,0,0,0);
}
- currepeat.repeatvar=ae->wl[ae->idx].w;
- currepeat.repeatcrc=crc;
+ }
+
+ /* 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=vstart;
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"extended syntax is REPEAT <n>,<var>\n");
+ /* mais ne peut être un label ou un alias */
+ ExpressionSetDicoVar(ae,ae->wl[ae->idx].w,vstart,0);
}
+ currepeat.repeatvar=ae->wl[ae->idx].w;
+ currepeat.repeatcrc=crc;
+ // adjust
+ while (ae->wl[ae->idx].t==0) ae->idx++;
}
+ currepeat.start=ae->idx-1;
} else {
currepeat.start=ae->idx;
currepeat.cpt=-1;
}
+
+ /*************************************************/
+ /********* PUSH Global on Stack ******************/
+ /*************************************************/
+ PushGlobal(ae);
+
currepeat.value=ae->repeatcounter;
currepeat.repeat_counter=1;
ae->repeatcounter++;
@@ -10877,7 +14395,7 @@ void __REND(struct s_assenv *ae) {
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;
+ rvar->v+=ae->repeat[ae->ir-1].varincrement; // LEGACY rvar->v=ae->repeat[ae->ir-1].repeat_counter;
}
if (ae->repeat[ae->ir-1].cpt) {
ae->idx=ae->repeat[ae->ir-1].start;
@@ -10887,6 +14405,12 @@ void __REND(struct s_assenv *ae) {
ae->ir--;
/* refresh macro check index */
if (ae->ir) ae->imacropos=ae->repeat[ae->ir-1].maxim;
+
+ /*************************************************/
+ /********* POP Global on Stack *******************/
+ /*************************************************/
+ PopGlobal(ae);
+
}
}
} else {
@@ -10904,6 +14428,12 @@ 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) {
+
+ /*************************************************/
+ /********* POP Global on Stack *******************/
+ /*************************************************/
+ PopGlobal(ae);
+
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Bypass infinite REPEAT loop\n");
ae->ir--;
/* refresh macro check index */
@@ -10915,6 +14445,12 @@ void __UNTIL(struct s_assenv *ae) {
ae->imacropos=ae->repeat[ae->ir-1].maxim;
}
} else {
+
+ /*************************************************/
+ /********* POP Global on Stack *******************/
+ /*************************************************/
+ PopGlobal(ae);
+
ae->ir--;
/* refresh macro check index */
if (ae->ir) ae->imacropos=ae->repeat[ae->ir-1].maxim;
@@ -10976,7 +14512,7 @@ void __IF_light(struct s_assenv *ae) {
struct s_ifthen ifthen={0};
if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) {
- /* do not need to compute the value in shadow execution */
+ /* does not need to compute the value in shadow execution */
ifthen.v=0;
ifthen.filename=GetCurrentFile(ae);
ifthen.line=ae->wl[ae->idx].l;
@@ -10998,15 +14534,24 @@ void __IFUSED(struct s_assenv *ae) {
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) {
+ char *labelmodule=NULL;
+ // first look for module label!
+ if (ae->module) {
+ labelmodule=MemMalloc(ae->modulen+2+strlen(ae->wl[ae->idx+1].w));
+ strcpy(labelmodule,ae->module);
+ strcat(labelmodule,ae->module_separator);
+ strcat(labelmodule,ae->wl[ae->idx+1].w);
+ }
+ if (ae->module && (SearchLabel(ae,labelmodule,GetCRC(labelmodule)))!=NULL) {
+ rexpr=1;
+ } else if ((SearchLabel(ae,ae->wl[ae->idx+1].w,crc))!=NULL) {
+ rexpr=1;
+ } else if ((SearchAlias(ae,crc,ae->wl[ae->idx+1].w))!=-1) {
rexpr=1;
} else {
- if ((SearchAlias(ae,crc,ae->wl[ae->idx+1].w))!=-1) {
- rexpr=1;
- } else {
- rexpr=SearchUsed(ae,ae->wl[ae->idx+1].w,crc);
- }
+ rexpr=SearchUsed(ae,ae->wl[ae->idx+1].w,crc);
}
+ if (labelmodule) MemFree(labelmodule);
}
ifthen.v=rexpr;
ifthen.filename=GetCurrentFile(ae);
@@ -11052,19 +14597,26 @@ void __IFDEF(struct s_assenv *ae) {
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) {
+ char *labelmodule=NULL;
+ // first look for module label!
+ if (ae->module) {
+ labelmodule=MemMalloc(ae->modulen+2+strlen(ae->wl[ae->idx+1].w));
+ strcpy(labelmodule,ae->module);
+ strcat(labelmodule,ae->module_separator);
+ strcat(labelmodule,ae->wl[ae->idx+1].w);
+ }
+ if (labelmodule && (SearchLabel(ae,labelmodule,GetCRC(labelmodule)))!=NULL) {
rexpr=1;
- } else {
- if ((SearchAlias(ae,crc,ae->wl[ae->idx+1].w))!=-1) {
+ } else if ((SearchLabel(ae,ae->wl[ae->idx+1].w,crc))!=NULL) {
+ rexpr=1;
+ } else if ((SearchAlias(ae,crc,ae->wl[ae->idx+1].w))!=-1) {
rexpr=1;
- } else {
- if (SearchMacro(ae,crc,ae->wl[ae->idx+1].w)>=0) {
- rexpr=1;
- } else {
- rexpr=0;
- }
- }
+ } else if (SearchMacro(ae,crc,ae->wl[ae->idx+1].w)>=0) {
+ rexpr=1;
+ } else {
+ rexpr=0;
}
+ if (labelmodule) MemFree(labelmodule);
}
ifthen.v=rexpr;
ifthen.filename=GetCurrentFile(ae);
@@ -11087,12 +14639,10 @@ void __IFDEF_light(struct s_assenv *ae) {
ObjectArrayAddDynamicValueConcat((void **)&ae->ifthen,&ae->ii,&ae->mi,&ifthen,sizeof(ifthen));
ae->idx++;
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"GetCurrentFile(ae),ae->wl[ae->idx].l[%s:%d] FATAL - IFDEF need one variable or label\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IFDEF need one variable or label\n");
}
}
void __IFNDEF(struct s_assenv *ae) {
- struct s_expr_dico *curdic=NULL;
- struct s_label *curlabel=NULL;
struct s_ifthen ifthen={0};
int rexpr,crc;
@@ -11101,19 +14651,26 @@ void __IFNDEF(struct s_assenv *ae) {
if ((SearchDico(ae,ae->wl[ae->idx+1].w,crc))!=NULL) {
rexpr=0;
} else {
- if ((SearchLabel(ae,ae->wl[ae->idx+1].w,crc))!=NULL) {
+ char *labelmodule=NULL;
+ // first look for module label!
+ if (ae->module) {
+ labelmodule=MemMalloc(ae->modulen+2+strlen(ae->wl[ae->idx+1].w));
+ strcpy(labelmodule,ae->module);
+ strcat(labelmodule,ae->module_separator);
+ strcat(labelmodule,ae->wl[ae->idx+1].w);
+ }
+ if (ae->module && (SearchLabel(ae,labelmodule,GetCRC(labelmodule)))!=NULL) {
rexpr=0;
- } else {
- if ((SearchAlias(ae,crc,ae->wl[ae->idx+1].w))!=-1) {
+ } else if ((SearchLabel(ae,ae->wl[ae->idx+1].w,crc))!=NULL) {
+ rexpr=0;
+ } else if ((SearchAlias(ae,crc,ae->wl[ae->idx+1].w))!=-1) {
rexpr=0;
- } else {
- if (SearchMacro(ae,crc,ae->wl[ae->idx+1].w)>=0) {
- rexpr=0;
- } else {
- rexpr=1;
- }
- }
+ } else if (SearchMacro(ae,crc,ae->wl[ae->idx+1].w)>=0) {
+ rexpr=0;
+ } else {
+ rexpr=1;
}
+ if (labelmodule) MemFree(labelmodule);
}
ifthen.v=rexpr;
ifthen.filename=GetCurrentFile(ae);
@@ -11126,9 +14683,8 @@ void __IFNDEF(struct s_assenv *ae) {
}
}
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;
@@ -11138,7 +14694,7 @@ void __IFNDEF_light(struct s_assenv *ae) {
ObjectArrayAddDynamicValueConcat((void **)&ae->ifthen,&ae->ii,&ae->mi,&ifthen,sizeof(ifthen));
ae->idx++;
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IFNDEF need one variable or label\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"IFNDEF need one variable or label\n");
}
}
@@ -11196,7 +14752,7 @@ void __DEFAULT(struct s_assenv *ae) {
ae->switchcase[ae->isw-1].execute=1;
}
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFAULT do not need parameter\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFAULT does not need parameter\n");
}
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DEFAULT encounter whereas there is no referent SWITCH\n");
@@ -11208,7 +14764,7 @@ void __BREAK(struct s_assenv *ae) {
if (ae->wl[ae->idx].t==1) {
ae->switchcase[ae->isw-1].execute=0;
} else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BREAK do not need parameter\n");
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BREAK does not need parameter\n");
}
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"BREAK encounter whereas there is no referent SWITCH\n");
@@ -11390,7 +14946,7 @@ void __PROTECT(struct s_assenv *ae) {
}
void ___org_close(struct s_assenv *ae) {
- if (ae->lz>=0) {
+ if (ae->lz>=0 && ae->lzsection[ae->ilz-1].lzversion) {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Cannot ORG inside a LZ section\n");
return;
}
@@ -11447,9 +15003,17 @@ void __ORG(struct s_assenv *ae) {
if (ae->wl[ae->idx+1].t!=2) {
ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,0);
ae->codeadr=RoundComputeExpression(ae,ae->wl[ae->idx+1].w,ae->outputadr,0,0);
+ if (ae->codeadr<0 || ae->codeadr>0xFFFF) {
+ ae->codeadr=0;
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"[%s:%d] cannot ORG outside memory!\n");
+ }
if (!ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t!=2) {
ExpressionFastTranslate(ae,&ae->wl[ae->idx+2].w,0);
ae->outputadr=RoundComputeExpression(ae,ae->wl[ae->idx+2].w,ae->outputadr,0,0);
+ if (ae->outputadr<0 || ae->outputadr>0xFFFF) {
+ ae->outputadr=0;
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"[%s:%d] cannot ORG outside memory!\n");
+ }
ae->idx+=2;
} else {
ae->outputadr=ae->codeadr;
@@ -11461,6 +15025,8 @@ void __ORG(struct s_assenv *ae) {
}
___org_new(ae,ae->nocode);
+
+ if (ae->outputadr==ae->codeadr) ae->orgzone[ae->io-1].inplace=1;
}
void __NOCODE(struct s_assenv *ae) {
if (ae->wl[ae->idx].t==1) {
@@ -11500,7 +15066,6 @@ void __STRUCT(struct s_assenv *ae) {
int crc,i,j,irs;
/* filler */
int localsize,cursize;
- double zeval;
if (!ae->wl[ae->idx].t) {
if (ae->wl[ae->idx+1].t) {
@@ -11532,6 +15097,7 @@ void __STRUCT(struct s_assenv *ae) {
instruction[ICRC_DEFB].makemnemo=_DEFB_struct;instruction[ICRC_DB].makemnemo=_DEFB_struct;
instruction[ICRC_DEFW].makemnemo=_DEFW_struct;instruction[ICRC_DW].makemnemo=_DEFW_struct;
instruction[ICRC_DEFI].makemnemo=_DEFI_struct;
+ instruction[ICRC_DEFF].makemnemo=_DEFF_struct;instruction[ICRC_DF].makemnemo=_DEFF_struct;
instruction[ICRC_DEFR].makemnemo=_DEFR_struct;instruction[ICRC_DR].makemnemo=_DEFR_struct;
instruction[ICRC_DEFS].makemnemo=_DEFS_struct;instruction[ICRC_DS].makemnemo=_DEFS_struct;
}
@@ -11595,6 +15161,8 @@ printf("EVOL 119 - tableau! %d elem(s)\n",nbelem);
/* create label for global struct ptr */
curlabel.iw=-1;
curlabel.ptr=ae->codeadr;
+ curlabel.fileidx=ae->wl[ae->idx+2].ifile;
+
if (!ae->getstruct) {
if (ae->wl[ae->idx+2].w[0]=='@') curlabel.name=MakeLocalLabel(ae,ae->wl[ae->idx+2].w,NULL); else curlabel.name=TxtStrDup(ae->wl[ae->idx+2].w);
curlabel.crc=GetCRC(curlabel.name);
@@ -11625,6 +15193,7 @@ printf("create subfields\n");
#endif
curlabel.iw=-1;
curlabel.ptr=ae->codeadr;
+ curlabel.ibank=ae->activebank<BANK_MAX_NUMBER?ae->activebank:0;
for (i=0;i<ae->rasmstruct[irs].irasmstructfield;i++) {
curlabel.ptr=ae->codeadr+ae->rasmstruct[irs].rasmstructfield[i].offset;
if (!ae->getstruct) {
@@ -11654,6 +15223,9 @@ printf("create subfields\n");
curlabel.crc=GetCRC(curlabel.name);
PushLabelLight(ae,&curlabel);
}
+#if TRACE_STRUCT
+printf("pushLight [%s] %d:%X\n",curlabel.name,curlabel.ibank,curlabel.ptr);
+#endif
}
/* is there any filler in the declaration? */
@@ -11749,23 +15321,35 @@ void __ENDSTRUCT(struct s_assenv *ae) {
curlabel.crc=ae->rasmstruct[ae->irasmstruct-1].crc;
curlabel.iw=-1;
curlabel.ptr=ae->rasmstruct[ae->irasmstruct-1].size;
+ //curlabel.fileidx wont be used
PushLabelLight(ae,&curlabel);
/* compute size for each field */
+#if TRACE_STRUCT
+ printf("compute field size\n");
+#endif
newlen=strlen(ae->rasmstruct[ae->irasmstruct-1].name)+2;
- for (i=0;i<ae->rasmstruct[ae->irasmstruct-1].irasmstructfield-1;i++) {
- ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].size=ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i+1].offset-ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].offset;
+ if (ae->rasmstruct[ae->irasmstruct-1].irasmstructfield) {
+ for (i=0;i<ae->rasmstruct[ae->irasmstruct-1].irasmstructfield-1;i++) {
+ ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].size=ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i+1].offset-ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].offset;
+ ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].fullname=MemMalloc(newlen+strlen(ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].name));
+ sprintf(ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].fullname,"%s.%s",ae->rasmstruct[ae->irasmstruct-1].name,ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].name);
+ ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].crc=GetCRC(ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].fullname);
+ }
+ ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].size=ae->rasmstruct[ae->irasmstruct-1].size-ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].offset;
ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].fullname=MemMalloc(newlen+strlen(ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].name));
sprintf(ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].fullname,"%s.%s",ae->rasmstruct[ae->irasmstruct-1].name,ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].name);
ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].crc=GetCRC(ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].fullname);
+ } else {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: empty structure [%s]\n",GetCurrentFile(ae),ae->wl[ae->idx].l,curlabel.name);
+ if (ae->erronwarn) MaxError(ae);
}
- ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].size=ae->rasmstruct[ae->irasmstruct-1].size-ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].offset;
- ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].fullname=MemMalloc(newlen+strlen(ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].name));
- sprintf(ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].fullname,"%s.%s",ae->rasmstruct[ae->irasmstruct-1].name,ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].name);
- ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].crc=GetCRC(ae->rasmstruct[ae->irasmstruct-1].rasmstructfield[i].fullname);
/* unwrap data capture */
- if (ae->as80==1) {/* not for UZ80 */
+#if TRACE_STRUCT
+ printf("unwrap data capture\n");
+#endif
+ if (ae->as80==1 || ae->pasmo) {/* not for UZ80 */
instruction[ICRC_DEFB].makemnemo=_DEFB_as80;instruction[ICRC_DB].makemnemo=_DEFB_as80;
instruction[ICRC_DEFW].makemnemo=_DEFW_as80;instruction[ICRC_DW].makemnemo=_DEFW_as80;
instruction[ICRC_DEFI].makemnemo=_DEFI_as80;
@@ -11774,6 +15358,7 @@ void __ENDSTRUCT(struct s_assenv *ae) {
instruction[ICRC_DEFW].makemnemo=_DEFW;instruction[ICRC_DW].makemnemo=_DEFW;
instruction[ICRC_DEFI].makemnemo=_DEFI;
}
+ instruction[ICRC_DEFF].makemnemo=_DEFF;instruction[ICRC_DF].makemnemo=_DEFF;
instruction[ICRC_DEFR].makemnemo=_DEFR;instruction[ICRC_DR].makemnemo=_DEFR;
instruction[ICRC_DEFS].makemnemo=_DEFS;instruction[ICRC_DS].makemnemo=_DEFS;
@@ -11802,34 +15387,45 @@ int (*_internal_getsample)(unsigned char *data, int *idx);
#define FUNC "_internal_AudioGetSampleValue"
int __internal_getsample8(unsigned char *data, int *idx) {
- unsigned char v;
+ int v;
v=data[*idx]-128;*idx=*idx+1;return v;
}
int __internal_getsample16little(unsigned char *data, int *idx) {
int cursample;
- cursample=data[*idx+1]-0x80;*idx=*idx+2;
+ char *sdata=(char *)data;
+ cursample=sdata[*idx+1];*idx=*idx+2;
return cursample;
}
int __internal_getsample24little(unsigned char *data, int *idx) {
int cursample;
- cursample=data[*idx+2-0x80];*idx=*idx+3;
+ char *sdata=(char *)data;
+ cursample=sdata[*idx+2];*idx=*idx+3;
return cursample;
}
/* big-endian */
int __internal_getsample16big(unsigned char *data, int *idx) {
int cursample;
- cursample=data[*idx]-0x80;*idx=*idx+2;
+ char *sdata=(char *)data;
+ cursample=sdata[*idx];*idx=*idx+2;
return cursample;
}
int __internal_getsample24big(unsigned char *data, int *idx) {
int cursample;
- cursample=data[*idx]-0x80;*idx=*idx+3;
+ char *sdata=(char *)data;
+ cursample=sdata[*idx];*idx=*idx+3;
return cursample;
}
/* float & endian shit */
int _isLittleEndian() /* from lz4.h */
{
- const union { U32 u; BYTE c[4]; } one = { 1 };
+#ifdef NO_3RD_PARTIES
+ #if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
+ typedef uint32_t U32;
+ #else
+ typedef unsigned int U32;
+ #endif
+#endif
+ const union { U32 u; unsigned char c[4]; } one = { 1 };
return one.c[0];
}
@@ -11863,7 +15459,7 @@ int __internal_getsample32biglittle(unsigned char *data, int *idx) {
#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)
+void _AudioLoadSample(struct s_assenv *ae, unsigned char *data, unsigned int filesize, enum e_audio_sample_type sample_type, float normalize)
{
#undef FUNC
#define FUNC "AudioLoadSample"
@@ -11871,10 +15467,11 @@ void _AudioLoadSample(struct s_assenv *ae, unsigned char *data, int filesize, en
struct s_wav_header *wav_header;
int i,j,n,idx,controlsize;
int nbchannel,bitspersample,nbsample;
- int bigendian=0,cursample;
+ int bigendian=0,cursample,wFormat;
+ double frequency;
double accumulator;
unsigned char samplevalue=0, sampleprevious=0;
- int samplerepeat=0,ipause;
+ int samplerepeat=0,ipause,mypsgreg;
unsigned char *subchunk;
int subchunksize;
@@ -11915,7 +15512,7 @@ printf("AudioLoadSample filesize=%d st=%d normalize=%.2lf\n",filesize,sample_typ
printf("AudioLoadSample getsubchunk\n");
#endif
subchunk=(unsigned char *)&wav_header->SubChunk2ID;
- while (strncmp(subchunk,"data",4)) {
+ while (strncmp((char *)subchunk,"data",4)) {
subchunksize=8+subchunk[4]+subchunk[5]*256+subchunk[6]*65536+subchunk[7]*256*65536;
if (subchunksize>=filesize) {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"WAV import - data subchunk not found\n");
@@ -11931,28 +15528,54 @@ printf("AudioLoadSample getsubchunk\n");
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"WAV import - invalid number of audio channel\n");
return;
}
+
+ wFormat=wav_header->AudioFormat[0]+wav_header->AudioFormat[1]*256;
+ if (wFormat!=1 && wFormat!=3) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"WAV import - invalid or unsupported wFormatTag (%04X)\n",wFormat);
+ return;
+ }
+
+ frequency=wav_header->SampleRate[0]+wav_header->SampleRate[1]*256+wav_header->SampleRate[2]*65536+wav_header->SampleRate[3]*256*65536;
+ switch (sample_type) {
+ case AUDIOSAMPLE_DMAA:
+ case AUDIOSAMPLE_DMAB:
+ case AUDIOSAMPLE_DMAC:
+ if (fabs(frequency/15125.0-1.0)>0.2) {
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: WAV sample frequency (%dHz) is very different from 15KHz DMA frequency\n",GetCurrentFile(ae),ae->wl[ae->idx].l,(int)frequency);
+ if (ae->erronwarn) MaxError(ae);
+ }
+ }
+ default:break;
+ }
+
bitspersample=wav_header->BitsPerSample[0]+wav_header->BitsPerSample[1]*256;
#if TRACE_HEXBIN
-printf("AudioLoadSample bitpersample=%d\n",bitspersample);
+printf("AudioLoadSample bitpersample=%d | Format=%s\n",bitspersample,wFormat==1?"PCM":"IEEE Float");
#endif
switch (bitspersample) {
case 8:_internal_getsample=__internal_getsample8;break;
case 16:if (!bigendian) _internal_getsample=__internal_getsample16little; else _internal_getsample=__internal_getsample16big;break;
case 24:if (!bigendian) _internal_getsample=__internal_getsample24little; else _internal_getsample=__internal_getsample24big;break;
- case 32:if (!bigendian) {
- if (_isLittleEndian()) {
- _internal_getsample=__internal_getsample32littlelittle;
- } else {
- _internal_getsample=__internal_getsample32littlebig;
- }
- } else {
- if (_isLittleEndian()) {
- _internal_getsample=__internal_getsample32biglittle;
+ case 32:if (wFormat==3) {
+ if (!bigendian) {
+ if (_isLittleEndian()) {
+ _internal_getsample=__internal_getsample32littlelittle;
+ } else {
+ _internal_getsample=__internal_getsample32littlebig;
+ }
} else {
- _internal_getsample=__internal_getsample32bigbig;
+ if (_isLittleEndian()) {
+ _internal_getsample=__internal_getsample32biglittle;
+ } else {
+ _internal_getsample=__internal_getsample32bigbig;
+ }
}
- }
- break;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"WAV import - unsupported 32bits PCM\n",wFormat);
+ return;
+ }
+ break;
default:
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"WAV import - unsupported bits per sample (%d)\n",bitspersample);
return;
@@ -11965,7 +15588,7 @@ printf("AudioLoadSample bitpersample=%d\n",bitspersample);
}
#if TRACE_HEXBIN
-printf("nbsample=%d (sze=%d,chn=%d,bps=%d) st=%c\n",nbsample,controlsize,nbchannel,bitspersample,sample_type);
+printf("nbsample=%d (sze=%d,chn=%d,bps=%d) st=%d\n",nbsample,controlsize,nbchannel,bitspersample,sample_type);
#endif
idx=subchunk-data;
@@ -12033,9 +15656,25 @@ printf("nbsample=%d (sze=%d,chn=%d,bps=%d) st=%c\n",nbsample,controlsize,nbchann
___output(ae,samplevalue);
}
break;
- case AUDIOSAMPLE_DMA:
- sampleprevious=255;
- for (i=0;i<nbsample;i++) {
+ case AUDIOSAMPLE_DMAA:
+ case AUDIOSAMPLE_DMAB:
+ case AUDIOSAMPLE_DMAC:
+ switch (sample_type) {
+ case AUDIOSAMPLE_DMAA:mypsgreg=0x8;break;
+ case AUDIOSAMPLE_DMAB:mypsgreg=0x9;break;
+ case AUDIOSAMPLE_DMAC:mypsgreg=0xA;break;
+ default:printf("warning remover\n");
+ }
+ /* downmixing */
+ accumulator=0.0;
+ for (n=0;n<nbchannel;n++) {
+ accumulator+=_internal_getsample(data,&idx);
+ }
+ /* normalize */
+ cursample=MinMaxInt(floor(((accumulator/nbchannel)*normalize)+0.5)+128,0,255);
+ /* PSG levels */
+ sampleprevious=ae->psgtab[cursample];
+ for (i=1;i<nbsample;i++) {
/* downmixing */
accumulator=0.0;
for (n=0;n<nbchannel;n++) {
@@ -12047,17 +15686,17 @@ printf("nbsample=%d (sze=%d,chn=%d,bps=%d) st=%c\n",nbsample,controlsize,nbchann
/* PSG levels */
samplevalue=ae->psgtab[cursample];
- if (samplevalue==sampleprevious) {
+ if (samplevalue==sampleprevious && i+1<nbsample) {
samplerepeat++;
} else {
if (!samplerepeat) {
/* DMA output */
___output(ae,sampleprevious);
- ___output(ae,0x0A); /* volume canal C */
+ ___output(ae,mypsgreg); /* volume canal A/B/C */
} else {
/* DMA pause */
___output(ae,sampleprevious);
- ___output(ae,0x0A); /* volume canal C */
+ ___output(ae,mypsgreg); /* volume canal A/B/C */
while (samplerepeat) {
ipause=samplerepeat<4096?samplerepeat:4095;
___output(ae,ipause&0xFF);
@@ -12070,31 +15709,61 @@ printf("nbsample=%d (sze=%d,chn=%d,bps=%d) st=%c\n",nbsample,controlsize,nbchann
sampleprevious=samplevalue;
}
}
- if (samplerepeat) {
- /* DMA pause */
+ /* if last sample is alone */
+ if (!samplerepeat) {
___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,mypsgreg); /* volume canal A/B/C */
}
- ___output(ae,0);
- ___output(ae,0x0A); /* volume canal C */
- ___output(ae,0x20);
- ___output(ae,0x40); /* stop or reloop? */
break;
}
}
+
+#ifdef NOAPULTRA
+ int LZSA_crunch(unsigned char *input_data,int input_size,unsigned char **lzdata,int *lzlen) {
+ lzdata=MemMalloc(4);
+ *lzlen=0;
+
+printf("no LZSA support in this version!\n");
+fprintf(stderr,"no LZSA support in this version!\n");
+
+ return 0;
+ }
+ int APULTRA_crunch(unsigned char *input_data,int input_size,unsigned char **lzdata,int *lzlen) {
+ lzdata=MemMalloc(4);
+ *lzlen=0;
+
+printf("no AP-Ultra support in this version!\n");
+fprintf(stderr,"no AP-Ultra support in this version!\n");
+
+ return 0;
+ }
+#endif
+
/*
meta fonction qui gère le INCBIN standard plus les variantes SMP et DMA
*/
+void __READ(struct s_assenv *ae) {
+ if (!ae->wl[ae->idx].t) {
+ int idx;
+
+ idx=atoi(ae->wl[ae->idx+1].w);
+ ae->idx++;
+
+ if (idx>=0 && idx<ae->ih) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"File to include was not found [%s]\n",ae->hexbin[idx].filename);
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"internal error with text file import (index out of bounds)\n");
+ }
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"READ directive need a proper filename as argument\n");
+ }
+}
+
void __HEXBIN(struct s_assenv *ae) {
+ #undef FUNC
+ #define FUNC "__HEXBIN"
+
int hbinidx,overwritecheck=1,crc;
struct s_expr_dico *rvar;
unsigned int idx;
@@ -12102,12 +15771,15 @@ void __HEXBIN(struct s_assenv *ae) {
float amplification=1.0;
int deload=0;
int vtiles=0,remap=0,revert=0;
- int itiles=0,tilex;
+ int itiles=0,tilex=0,gtiles=0;
+ struct s_hexbin *curhexbin;
+ unsigned char *newdata=NULL;
+ int fileok=0,incwav=0;
if (!ae->wl[ae->idx].t) {
ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,1);
hbinidx=RoundComputeExpressionCore(ae,ae->wl[ae->idx+1].w,ae->codeadr,0);
- if (hbinidx>ae->ih) {
+ if (hbinidx>=ae->ih) {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"internal error with binary file import (index out of bounds)\n");
return;
}
@@ -12118,29 +15790,12 @@ printf("Hexbin idx=[%s] filename=[%s]\n",ae->wl[ae->idx+1].w,ae->hexbin[hbinidx]
if (!ae->wl[ae->idx+1].t) {
if (strcmp("DSK",ae->wl[ae->idx+2].w)==0) {
/* import binary from DSK */
- } else if (strchr("SD",ae->wl[ae->idx+2].w[0]) && ae->wl[ae->idx+2].w[1]=='M' &&
- strchr("P24A",ae->wl[ae->idx+2].w[2]) && !ae->wl[ae->idx+2].w[3]) {
+ } else if (strchr("SD",ae->wl[ae->idx+2].w[0]) && ae->wl[ae->idx+2].w[1]=='M' && strchr("P24A",ae->wl[ae->idx+2].w[2]) && !ae->wl[ae->idx+2].w[3]) {
/* SMP,SM2,SM4,DMA */
-
#if TRACE_HEXBIN
-printf("Hexbin -> %s\n",ae->wl[ae->idx+2].w);
+printf("Hexbin for WAV-> %s (no operation until delayed load)\n",ae->wl[ae->idx+2].w);
#endif
- if (!ae->wl[ae->idx+2].t) {
- amplification=ComputeExpressionCore(ae,ae->wl[ae->idx+3].w,ae->codeadr,0);
-#if TRACE_HEXBIN
-printf("sample amplification=%.2lf\n",amplification);
-#endif
- }
-
- switch (ae->wl[ae->idx+2].w[2]) {
- case 'P':_AudioLoadSample(ae,ae->hexbin[hbinidx].data,ae->hexbin[hbinidx].datalen, AUDIOSAMPLE_SMP,amplification);break;
- case '2':_AudioLoadSample(ae,ae->hexbin[hbinidx].data,ae->hexbin[hbinidx].datalen, AUDIOSAMPLE_SM2,amplification);break;
- case '4':_AudioLoadSample(ae,ae->hexbin[hbinidx].data,ae->hexbin[hbinidx].datalen, AUDIOSAMPLE_SM4,amplification);break;
- case 'A':_AudioLoadSample(ae,ae->hexbin[hbinidx].data,ae->hexbin[hbinidx].datalen, AUDIOSAMPLE_DMA,amplification);break;
- default:printf("warning remover\n");break;
- }
- ae->idx+=2;
- return;
+ incwav=1;
} else {
/* legacy binary file */
#if TRACE_HEXBIN
@@ -12172,6 +15827,21 @@ printf(" -> REMAP loading\n");
offset=size=0; // full file
ae->idx+=2;
+ } else if (strcmp("GTILES",ae->wl[ae->idx+2].w)==0) {
+ /*** entrelace les tiles, besoin de hauteur et largeur de la tile ***/
+ if (!ae->wl[ae->idx+2].t) {
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx+3].w,1);
+ tilex=RoundComputeExpressionCore(ae,ae->wl[ae->idx+3].w,ae->codeadr,0);
+ gtiles=1;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is INCBIN'file',GTILES,width\n");
+ tilex=0;
+ }
+#if TRACE_HEXBIN
+printf(" -> GTILES loading\n");
+#endif
+ offset=size=0; // full file
+ ae->idx+=2;
} else if (strcmp("ITILES",ae->wl[ae->idx+2].w)==0) {
/*** entrelace les tiles, besoin de hauteur et largeur de la tile ***/
if (!ae->wl[ae->idx+2].t) {
@@ -12180,6 +15850,7 @@ printf(" -> REMAP loading\n");
itiles=1;
} else {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is INCBIN'file',ITILES,width\n");
+ tilex=0;
}
#if TRACE_HEXBIN
printf(" -> ITILES loading\n");
@@ -12249,7 +15920,7 @@ printf(" -> VTILES loading\n");
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);
+ ExpressionSetDicoVar(ae,ae->wl[ae->idx+6].w,ae->hexbin[hbinidx].rawlen,0);
}
ae->idx+=6;
} else {
@@ -12270,18 +15941,17 @@ printf(" -> VTILES loading\n");
ae->idx++;
}
+ curhexbin=&ae->hexbin[hbinidx];
+
/* preprocessor cannot manage variables so here is the delayed load */
if (ae->hexbin[hbinidx].datalen<0) {
- struct s_hexbin *curhexbin;
char *newfilename;
int lm,touched;
- unsigned char *newdata=NULL;
#if TRACE_HEXBIN
printf("Hexbin -> as only the assembler know how to deal with var,\n");
printf("we look for tags in the name of a file which were not found\n");
#endif
- curhexbin=&ae->hexbin[hbinidx];
newfilename=TxtStrDup(curhexbin->filename);
@@ -12291,8 +15961,26 @@ printf("we look for tags in the name of a file which were not found\n");
}
/* on essaie d'interpréter le nom du fichier en dynamique */
newfilename=TranslateTag(ae,newfilename,&touched,1,E_TAGOPTION_REMOVESPACE);
- /* load */
- if (FileExists(newfilename)) {
+
+ /* Where is the file to load? */
+ if (!FileExists(newfilename)) {
+ int ilookfile;
+ char *filename_toread;
+
+ /* on cherche dans les include */
+ for (ilookfile=0;ilookfile<ae->ipath && !fileok;ilookfile++) {
+ filename_toread=MergePath(ae,ae->includepath[ilookfile],newfilename);
+ if (FileExists(filename_toread)) {
+ fileok=1;
+ MemFree(newfilename);
+ newfilename=TxtStrDup(filename_toread); // Merge renvoie un static
+ }
+ }
+ } else {
+ fileok=1;
+ }
+
+ if (fileok) {
#if TRACE_HEXBIN
printf("Hexbin -> surprise! we found the file!\n");
#endif
@@ -12300,70 +15988,104 @@ printf("Hexbin -> surprise! we found the file!\n");
curhexbin->data=MemMalloc(curhexbin->datalen*1.3+10);
if (FileReadBinary(newfilename,(char*)curhexbin->data,curhexbin->datalen)!=curhexbin->datalen) {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"read error on file [%s]\n",newfilename);
+ MemFree(curhexbin->data);
+ MemFree(newfilename);
return;
}
FileReadBinaryClose(newfilename);
-
- switch (curhexbin->crunch) {
- #ifndef NO_3RD_PARTIES
- case 4:
- newdata=LZ4_crunch(curhexbin->data,curhexbin->datalen,&curhexbin->datalen);
- MemFree(curhexbin->data);
- curhexbin->data=newdata;
- #if TRACE_PREPRO
- rasm_printf(ae,KVERBOSE"crunched with LZ4 into %d byte(s)\n",curhexbin->datalen);
- #endif
- break;
- case 7:
- {
- size_t slzlen;
- newdata=ZX7_compress(optimize(curhexbin->data, curhexbin->datalen), curhexbin->data, curhexbin->datalen, &slzlen);
- curhexbin->datalen=slzlen;
- MemFree(curhexbin->data);
- curhexbin->data=newdata;
- #if TRACE_PREPRO
- rasm_printf(ae,KVERBOSE"crunched with ZX7 into %d byte(s)\n",curhexbin->datalen);
- #endif
- }
- break;
- case 8:
- rasm_printf(ae,KWARNING"Exomizer is crunching %.1fkb this may take a while, be patient...\n",curhexbin->datalen/1024.0);
- newdata=Exomizer_crunch(curhexbin->data,curhexbin->datalen,&curhexbin->datalen);
- MemFree(curhexbin->data);
- curhexbin->data=newdata;
- #if TRACE_PREPRO
- rasm_printf(ae,KVERBOSE"crunched with Exomizer into %d byte(s)\n",curhexbin->datalen);
- #endif
- break;
- #endif
- case 48:
- newdata=LZ48_crunch(curhexbin->data,curhexbin->datalen,&curhexbin->datalen);
- MemFree(curhexbin->data);
- curhexbin->data=newdata;
- #if TRACE_PREPRO
- rasm_printf(ae,KVERBOSE"crunched with LZ48 into %d byte(s)\n",curhexbin->datalen);
- #endif
- break;
- case 49:
- newdata=LZ49_crunch(curhexbin->data,curhexbin->datalen,&curhexbin->datalen);
- MemFree(curhexbin->data);
- curhexbin->data=newdata;
- #if TRACE_PREPRO
- rasm_printf(ae,KVERBOSE"crunched with LZ49 into %d byte(s)\n",curhexbin->datalen);
- #endif
- break;
- default:break;
- }
deload=1;
} else {
/* still not found */
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"file not found [%s]\n",newfilename);
+ MemFree(newfilename);
return;
}
+ MemFree(newfilename);
}
+
+ if (incwav) {
+ /* SMP,SM2,SM4,DMA */
+ int dma_args=3;
+ int dma_channel=AUDIOSAMPLE_DMAC;
+ int dma_int=0,dma_repeat=0;
+ int mypsgreg=0xA;
+#if TRACE_HEXBIN
+printf("Hexbin -> %s\n",ae->wl[ae->idx+2].w);
+#endif
+ switch (ae->wl[ae->idx+2].w[2]) {
+ case 'P':case '2':case '4':
+ if (!ae->wl[ae->idx+2].t) {
+ amplification=ComputeExpressionCore(ae,ae->wl[ae->idx+3].w,ae->codeadr,0);
+#if TRACE_HEXBIN
+ printf("sample amplification=%.2lf\n",amplification);
+#endif
+ }
+ default:break;
+ }
+
+ switch (ae->wl[ae->idx+2].w[2]) {
+ case 'P':_AudioLoadSample(ae,ae->hexbin[hbinidx].data,ae->hexbin[hbinidx].datalen, AUDIOSAMPLE_SMP,amplification);break;
+ case '2':_AudioLoadSample(ae,ae->hexbin[hbinidx].data,ae->hexbin[hbinidx].datalen, AUDIOSAMPLE_SM2,amplification);break;
+ case '4':_AudioLoadSample(ae,ae->hexbin[hbinidx].data,ae->hexbin[hbinidx].datalen, AUDIOSAMPLE_SM4,amplification);break;
+ case 'A':/* DMA options */
+ if (!ae->wl[ae->idx+2].t) {
+ while (!ae->wl[ae->idx+dma_args].t) {
+ dma_args++;
+ if (strcmp(ae->wl[ae->idx+dma_args].w,"DMA_INT")==0) {
+ dma_int=1;
+ } else if (strcmp(ae->wl[ae->idx+dma_args].w,"DMA_REPEAT")==0) {
+ if (!ae->wl[ae->idx+dma_args].t) {
+ dma_args++;
+ dma_repeat=ComputeExpressionCore(ae,ae->wl[ae->idx+dma_args].w,ae->codeadr,0);
+ if (dma_repeat<1 || dma_repeat>4095) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DMA_REPEAT value out of bounds (1-4095)\n");
+ dma_repeat=0;
+ }
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"DMA_REPEAT must be followed by another parameter\n");
+ }
+ } else if (strcmp(ae->wl[ae->idx+dma_args].w,"DMA_CHANNEL_A")==0) {
+ dma_channel=AUDIOSAMPLE_DMAA;
+ mypsgreg=0x8;
+ } else if (strcmp(ae->wl[ae->idx+dma_args].w,"DMA_CHANNEL_B")==0) {
+ dma_channel=AUDIOSAMPLE_DMAB;
+ mypsgreg=0x9;
+ } else if (strcmp(ae->wl[ae->idx+dma_args].w,"DMA_CHANNEL_C")==0) {
+ dma_channel=AUDIOSAMPLE_DMAC;
+ mypsgreg=0xA;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Unrecognized DMA option [%s]\n",ae->wl[ae->idx+dma_args].w);
+ }
+ }
+ }
+ if (dma_repeat) {
+ ___output(ae,dma_repeat&0xFF);
+ ___output(ae,0x20|((dma_repeat>>8)&0xF));
+ }
+ _AudioLoadSample(ae,ae->hexbin[hbinidx].data,ae->hexbin[hbinidx].datalen, dma_channel,amplification);
+ if (dma_repeat) {
+ ___output(ae,0x01);
+ ___output(ae,0x40); /* LOOP */
+ }
+ ___output(ae,0);
+ ___output(ae,mypsgreg); /* volume to zero */
+ if (dma_int) {
+ ___output(ae,0x10);
+ ___output(ae,0x40); /* INT */
+ }
+ ___output(ae,0x20);
+ ___output(ae,0x40); /* Mandatory STOP */
+ break;
+
+ default:printf("warning remover\n");break;
+ }
+ ae->idx+=2;
+ return;
+ }
if (ae->hexbin[hbinidx].datalen>0) {
if (hbinidx<ae->ih && hbinidx>=0) {
+ /* pre-parametres OK (longueur+IDX struct) */
if (size<0) {
#if TRACE_HEXBIN
printf("taille négative %d -> conversion en %d\n",size,ae->hexbin[hbinidx].datalen+size);
@@ -12396,35 +16118,60 @@ printf("taille nulle et offset=%d -> conversion en %d\n",offset,size);
if (size+offset>ae->hexbin[hbinidx].datalen) {
MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INCBIN size+offset is greater than filesize\n");
} else {
+ /* OUTPUT DATA */
+ unsigned char *outputdata;
+ int outputidx=0;
+ outputdata=MemMalloc(ae->hexbin[hbinidx].datalen);
+#if TRACE_HEXBIN
+printf("output fictif pour réorganiser les données\n");
+#endif
+
if (revert) {
int p;
p=size-1;
while (p>=0) {
- ___output(ae,ae->hexbin[hbinidx].data[p--]);
+ outputdata[outputidx++]=ae->hexbin[hbinidx].data[p--];
}
- } else if (itiles) {
+ } else if (itiles || gtiles) {
/* tiles data reordering */
- int tx,ty,it,width;
+ int tx,it;
if (size % (tilex*8)) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INCBIN ITILES cannot reorder tiles %d bytewidth with file of size %d\n",tilex,size);
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"INCBIN ITILES/GTILES cannot reorder tiles %d bytewidth with file of size %d\n",tilex,size);
} else {
- it=0;
- while (it<size) {
- for (tx=0;tx<tilex;tx++) ___output(ae,ae->hexbin[hbinidx].data[it+tx+0*tilex]);
- for (tx=tilex-1;tx>=0;tx--) ___output(ae,ae->hexbin[hbinidx].data[it+tx+1*tilex]);
- for (tx=0;tx<tilex;tx++) ___output(ae,ae->hexbin[hbinidx].data[it+tx+3*tilex]);
- for (tx=tilex-1;tx>=0;tx--) ___output(ae,ae->hexbin[hbinidx].data[it+tx+2*tilex]);
- for (tx=0;tx<tilex;tx++) ___output(ae,ae->hexbin[hbinidx].data[it+tx+6*tilex]);
- for (tx=tilex-1;tx>=0;tx--) ___output(ae,ae->hexbin[hbinidx].data[it+tx+7*tilex]);
- for (tx=0;tx<tilex;tx++) ___output(ae,ae->hexbin[hbinidx].data[it+tx+5*tilex]);
- for (tx=tilex-1;tx>=0;tx--) ___output(ae,ae->hexbin[hbinidx].data[it+tx+4*tilex]);
- it+=tilex*8;
+ if (itiles) {
+ /* zigzag with regular gray coding */
+ it=0;
+ while (it<size) {
+ for (tx=0;tx<tilex;tx++) outputdata[outputidx++]=ae->hexbin[hbinidx].data[it+tx+0*tilex];
+ for (tx=tilex-1;tx>=0;tx--) outputdata[outputidx++]=ae->hexbin[hbinidx].data[it+tx+1*tilex];
+ for (tx=0;tx<tilex;tx++) outputdata[outputidx++]=ae->hexbin[hbinidx].data[it+tx+3*tilex];
+ for (tx=tilex-1;tx>=0;tx--) outputdata[outputidx++]=ae->hexbin[hbinidx].data[it+tx+2*tilex];
+ for (tx=0;tx<tilex;tx++) outputdata[outputidx++]=ae->hexbin[hbinidx].data[it+tx+6*tilex];
+ for (tx=tilex-1;tx>=0;tx--) outputdata[outputidx++]=ae->hexbin[hbinidx].data[it+tx+7*tilex];
+ for (tx=0;tx<tilex;tx++) outputdata[outputidx++]=ae->hexbin[hbinidx].data[it+tx+5*tilex];
+ for (tx=tilex-1;tx>=0;tx--) outputdata[outputidx++]=ae->hexbin[hbinidx].data[it+tx+4*tilex];
+ it+=tilex*8;
+ }
+ } else {
+ /* only reorder lines with regular gray coding */
+ it=0;
+ while (it<size) {
+ for (tx=0;tx<tilex;tx++) outputdata[outputidx++]=ae->hexbin[hbinidx].data[it+tx+0*tilex];
+ for (tx=0;tx<tilex;tx++) outputdata[outputidx++]=ae->hexbin[hbinidx].data[it+tx+1*tilex];
+ for (tx=0;tx<tilex;tx++) outputdata[outputidx++]=ae->hexbin[hbinidx].data[it+tx+3*tilex];
+ for (tx=0;tx<tilex;tx++) outputdata[outputidx++]=ae->hexbin[hbinidx].data[it+tx+2*tilex];
+ for (tx=0;tx<tilex;tx++) outputdata[outputidx++]=ae->hexbin[hbinidx].data[it+tx+6*tilex];
+ for (tx=0;tx<tilex;tx++) outputdata[outputidx++]=ae->hexbin[hbinidx].data[it+tx+7*tilex];
+ for (tx=0;tx<tilex;tx++) outputdata[outputidx++]=ae->hexbin[hbinidx].data[it+tx+5*tilex];
+ for (tx=0;tx<tilex;tx++) outputdata[outputidx++]=ae->hexbin[hbinidx].data[it+tx+4*tilex];
+ it+=tilex*8;
+ }
}
}
} else if (remap) {
/* tiles data reordering */
- int tx,ty,it,width;
+ int tx,it,width;
width=size/remap;
@@ -12433,7 +16180,7 @@ printf("taille nulle et offset=%d -> conversion en %d\n",offset,size);
} else {
for (it=0;it<remap;it++) {
for (tx=0;tx<width;tx++) {
- ___output(ae,ae->hexbin[hbinidx].data[it+tx*remap]);
+ outputdata[outputidx++]=ae->hexbin[hbinidx].data[it+tx*remap];
}
}
}
@@ -12451,7 +16198,7 @@ printf("taille nulle et offset=%d -> conversion en %d\n",offset,size);
printf("Hexbin -> re-tiling MAP! width=%d\n",width);
#endif
for (idx=tilex=tiley=0;idx<size;idx++) {
- ___output(ae,ae->hexbin[hbinidx].data[tilex+tiley*width]);
+ outputdata[outputidx++]=ae->hexbin[hbinidx].data[tilex+tiley*width];
tiley++;
if (tiley>=vtiles) {
tiley=0;
@@ -12460,23 +16207,147 @@ printf("Hexbin -> re-tiling MAP! width=%d\n",width);
}
}
} else {
- /* legacy HEXBIN */
- if (overwritecheck) {
- for (idx=offset;idx<size+offset;idx++) {
- ___output(ae,ae->hexbin[hbinidx].data[idx]);
- }
- } else {
- ___org_close(ae);
- ___org_new(ae,0);
- for (idx=offset;idx<size+offset;idx++) {
- ___output(ae,ae->hexbin[hbinidx].data[idx]);
- }
- /* hack to disable overwrite check */
- ae->orgzone[ae->io-1].nocode=2;
- ___org_close(ae);
- ___org_new(ae,0);
+#if TRACE_HEXBIN
+printf("Hexbin -> Legacy output from %d to %d\n",offset,size+offset);
+if (curhexbin->crunch) printf("CRUNCHED! (%d)\n",curhexbin->crunch);
+#endif
+ /* only from offset to size+offset */
+ for (idx=offset;idx<size+offset;idx++) {
+ outputdata[outputidx++]=ae->hexbin[hbinidx].data[idx];
}
+
+ switch (curhexbin->crunch) {
+ #ifndef NO_3RD_PARTIES
+ case 4:
+ newdata=LZ4_crunch(outputdata,outputidx,&outputidx);
+ MemFree(outputdata);
+ outputdata=newdata;
+ #if TRACE_PREPRO
+ rasm_printf(ae,KVERBOSE"crunched with LZ4 into %d byte(s)\n",outputidx);
+ #endif
+ break;
+
+ case 70:
+ {
+ int delta,slzlen;
+
+ if (outputidx>=1024 && MAX_OFFSET_ZX0>5000) rasm_printf(ae,KWARNING"ZX0 is crunching %.1fkb this may take a while, be patient...\n",outputidx/1024.0);
+ newdata=zx0_compress(zx0_optimize(outputdata, outputidx, 0, MAX_OFFSET_ZX0), outputdata, outputidx, 0, 0, 1, &slzlen, &delta);
+ outputidx=slzlen;
+ MemFree(outputdata);
+ outputdata=newdata;
+ #if TRACE_PREPRO
+ rasm_printf(ae,KVERBOSE"crunched with ZX0 into %d byte(s) delta=%d\n",outputidx,delta);
+ #endif
+ }
+ break;
+ case 71:
+ {
+ int delta,slzlen;
+
+ if (outputidx>=1024 && MAX_OFFSET_ZX0>5000) rasm_printf(ae,KWARNING"ZX0 is crunching %.1fkb this may take a while, be patient...\n",outputidx/1024.0);
+ zx0_reverse(outputdata,outputdata+outputidx-1);
+ newdata=zx0_compress(zx0_optimize(outputdata, outputidx, 0, MAX_OFFSET_ZX0), outputdata, outputidx, 0, 1, 0,&slzlen, &delta);
+ zx0_reverse(newdata,newdata+slzlen-1);
+ outputidx=slzlen;
+ MemFree(outputdata);
+ outputdata=newdata;
+ #if TRACE_PREPRO
+ rasm_printf(ae,KVERBOSE"crunched with ZX0 backward into %d byte(s) delta=%d\n",outputidx,delta);
+ #endif
+ }
+ break;
+ case 7:
+ {
+ int slzlen;
+ newdata=ZX7_compress(zx7_optimize(outputdata, outputidx), outputdata, outputidx, &slzlen);
+ outputidx=slzlen;
+ MemFree(outputdata);
+ outputdata=newdata;
+ #if TRACE_PREPRO
+ rasm_printf(ae,KVERBOSE"crunched with ZX7 into %d byte(s)\n",outputidx);
+ #endif
+ }
+ break;
+ case 8:
+ if (outputidx>=1024) rasm_printf(ae,KWARNING"Exomizer is crunching %.1fkb this may take a while, be patient...\n",outputidx/1024.0);
+ newdata=Exomizer_crunch(outputdata,outputidx,&outputidx);
+ MemFree(outputdata);
+ outputdata=newdata;
+ #if TRACE_PREPRO
+ rasm_printf(ae,KVERBOSE"crunched with Exomizer into %d byte(s)\n",outputidx);
+ #endif
+ break;
+ case 17:
+ if (outputidx>=1024) rasm_printf(ae,KWARNING"AP-Ultra is crunching %.1fkb this may take a while, be patient...\n",outputidx/1024.0);
+ {
+ int nnewlen;
+ APULTRA_crunch(outputdata,outputidx,&newdata,&nnewlen);
+ outputidx=nnewlen;
+ }
+ MemFree(outputdata);
+ outputdata=newdata;
+ #if TRACE_PREPRO
+ rasm_printf(ae,KVERBOSE"crunched with AP-Ultra into %d byte(s)\n",outputidx);
+ #endif
+ break;
+ case 18:
+ if (outputidx>=16384 && curhexbin->version==2) rasm_printf(ae,KWARNING"LZSA2 is crunching %.1fkb this may take a while, be patient...\n",outputidx/1024.0);
+ {
+ int nnewlen;
+ LZSA_crunch(outputdata,outputidx,&newdata,&nnewlen,curhexbin->version,curhexbin->minmatch);
+ outputidx=nnewlen;
+ }
+ MemFree(outputdata);
+ outputdata=newdata;
+ #if TRACE_PREPRO
+ rasm_printf(ae,KVERBOSE"crunched with LZSA%d into %d byte(s)\n",curhexbin->version,outputidx);
+ #endif
+ break;
+ #endif
+ case 48:
+ newdata=LZ48_crunch(outputdata,outputidx,&outputidx);
+ MemFree(outputdata);
+ outputdata=newdata;
+ #if TRACE_PREPRO
+ rasm_printf(ae,KVERBOSE"crunched with LZ48 into %d byte(s)\n",outputidx);
+ #endif
+ break;
+ case 49:
+ newdata=LZ49_crunch(outputdata,outputidx,&outputidx);
+ MemFree(outputdata);
+ outputdata=newdata;
+ #if TRACE_PREPRO
+ rasm_printf(ae,KVERBOSE"crunched with LZ49 into %d byte(s)\n",outputidx);
+ #endif
+ break;
+ default:break;
+ }
+
+
+ if (!overwritecheck) {
+ rasm_printf(ae,KWARNING"INCBIN without overwrite check still not working...\n");
+ if (ae->erronwarn) MaxError(ae);
+ }
+ }
+
+ if (overwritecheck) {
+ for (idx=0;idx<outputidx;idx++) {
+ ___output(ae,outputdata[idx]);
+ }
+ } else {
+ ___org_close(ae);
+ ___org_new(ae,0);
+ /* hack to disable overwrite check */
+ for (idx=0;idx<outputidx;idx++) {
+ ___output(ae,outputdata[idx]);
+ }
+ ae->orgzone[ae->io-1].nocode=2;
+ ___org_close(ae);
+ ___org_new(ae,0);
}
+
+ MemFree(outputdata);
}
}
} else {
@@ -12500,7 +16371,7 @@ printf("Hexbin -> re-tiling MAP! width=%d\n",width);
/*
save "nom",start,size -> save binary
-save "nom",start,size,TAPE -> save tape file
+save "nom",start,size,TAPE,"cdtname" -> save tape file
save "nom",start,size,AMSDOS -> save binary with Amsdos header
save "nom",start,size,DSK,"dskname" -> save binary on DSK data format
save "nom",start,size,DSK,"dskname",B -> select face
@@ -12508,9 +16379,12 @@ save "nom",start,size,DSK,B -> current DSK, choose face
save "nom",start,size,DSK -> current DSK, current face
*/
void __SAVE(struct s_assenv *ae) {
+ #undef FUNC
+ #define FUNC "__SAVE"
+
struct s_save cursave={0};
- unsigned int offset=0,size=0;
- int ko=1;
+ int ko=1,touched,lm;
+ char *filename;
if (!ae->wl[ae->idx].t) {
/* nom de fichier entre quotes ou bien mot clef DSK */
@@ -12519,17 +16393,31 @@ void __SAVE(struct s_assenv *ae) {
ko=0;
} else {
if (!ae->wl[ae->idx+1].t) {
+ filename=TxtStrDup(ae->wl[ae->idx+1].w);
+ /* need to upper case tags */
+ for (lm=touched=0;filename[lm];lm++) {
+ if (filename[lm]=='{') touched++; else if (filename[lm]=='}') touched--; else if (touched) filename[lm]=toupper(filename[lm]);
+ }
+ filename=TranslateTag(ae,filename,&touched,1,E_TAGOPTION_REMOVESPACE);
+ if (!touched) MemFree(filename);
+
if (!ae->wl[ae->idx+2].t && ae->wl[ae->idx+3].t!=2) {
cursave.ibank=ae->activebank;
cursave.ioffset=ae->idx+2;
ExpressionFastTranslate(ae,&ae->wl[ae->idx+2].w,1); // si on utilise des variables ça évite la grouille post traitement...
cursave.isize=ae->idx+3;
ExpressionFastTranslate(ae,&ae->wl[ae->idx+3].w,1); // idem
- cursave.iw=ae->idx+1;
+ if (!touched) cursave.iw=ae->idx+1; else cursave.filename=filename;
cursave.irun=ae->current_run_idx;
if (!ae->wl[ae->idx+3].t) {
if (strcmp(ae->wl[ae->idx+4].w,"TAPE")==0) {
cursave.tape=1;
+ if (!ae->wl[ae->idx+4].t) {
+ cursave.iwdskname=ae->idx+5;
+ } else {
+ cursave.iwdskname=-1;
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"cannot autoselect TAPE, please specify a filename after TAPE arg\n");
+ }
} else if (strcmp(ae->wl[ae->idx+4].w,"AMSDOS")==0) {
cursave.amsdos=1;
} else if (strcmp(ae->wl[ae->idx+4].w,"HOBETA")==0) {
@@ -12583,28 +16471,217 @@ void __SAVE(struct s_assenv *ae) {
void __MODULE(struct s_assenv *ae) {
+ #undef FUNC
+ #define FUNC "__MODULE"
+
if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) {
- if (StringIsQuote(ae->wl[ae->idx+1].w)) {
+ if (strcmp(ae->wl[ae->idx+1].w,"OFF")==0) {
+ if (ae->module || ae->modulen) MemFree(ae->module);
+ ae->module=NULL;
+ ae->modulen=0;
+ } else {
if (ae->modulen || ae->module) {
MemFree(ae->module);
}
ae->modulen=strlen(ae->wl[ae->idx+1].w);
- ae->module=MemMalloc(ae->modulen);
- /* duplicate and remove quotes */
- strcpy(ae->module,ae->wl[ae->idx+1].w+1);
- ae->module[--ae->modulen]=0;
- } else {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"MODULE directive need one text parameter\n");
+ ae->module=TxtStrDup(ae->wl[ae->idx+1].w);
}
ae->idx++;
} else {
- if (ae->module) MemFree(ae->module);
+ if (ae->module || ae->modulen) MemFree(ae->module);
ae->module=NULL;
+ ae->modulen=0;
}
}
+void __ENDMODULE(struct s_assenv *ae) {
+ #undef FUNC
+ #define FUNC "__ENDMODULE"
-void __TIMESTR(struct s_assenv *ae) {
+ if (!ae->wl[ae->idx].t && ae->wl[ae->idx+1].t==1) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"ENDMODULE does not need any parameter\n");
+ } else {
+ __MODULE(ae);
+ }
+}
+void __SUMMEM(struct s_assenv *ae) {
+ struct s_poker poker={0};
+
+ if (!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) {
+ /* no poke in a NOCODE section */
+ if (!ae->nocode) {
+ poker.method=E_POKER_SUM8;
+ poker.istart=ae->idx+1;
+ poker.iend=ae->idx+2;
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,1);
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx+2].w,1);
+ poker.outputadr=ae->outputadr;
+ poker.ibank=ae->activebank;
+ poker.ipoker=ae->idx;
+ ObjectArrayAddDynamicValueConcat((void**)&ae->poker,&ae->nbpoker,&ae->maxpoker,&poker,sizeof(poker));
+ }
+ ___output(ae,0);
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is SUMMEM start,end\n");
+ }
+}
+
+void __XORMEM(struct s_assenv *ae) {
+ struct s_poker poker={0};
+
+ if (!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t && ae->wl[ae->idx+2].t==1) {
+ /* no poke in a NOCODE section */
+ if (!ae->nocode) {
+ poker.method=E_POKER_XOR8;
+ poker.istart=ae->idx+1;
+ poker.iend=ae->idx+2;
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,1);
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx+2].w,1);
+ poker.outputadr=ae->outputadr;
+ poker.ibank=ae->activebank;
+ poker.ipoker=ae->idx;
+ ObjectArrayAddDynamicValueConcat((void**)&ae->poker,&ae->nbpoker,&ae->maxpoker,&poker,sizeof(poker));
+ }
+ ___output(ae,0);
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is XORMEM start,end\n");
+ }
+}
+
+void __CIPHERMEM(struct s_assenv *ae) {
+ struct s_poker poker={0};
+ int ciphermode;
+
+ if (!ae->wl[ae->idx].t && !ae->wl[ae->idx+1].t) {
+ /* cipher memory */
+ if (!ae->nocode) {
+ if (!ae->wl[ae->idx+2].t) {
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx+3].w,1);
+ ciphermode=RoundComputeExpression(ae,ae->wl[ae->idx+3].w,ae->outputadr,0,0);
+ switch (ciphermode) {
+ default:
+ case 0:
+ case 1:poker.method=E_POKER_CIPHER001;break;
+ case 2:poker.method=E_POKER_CIPHER002;break;
+ case 3:poker.method=E_POKER_CIPHER003; break;
+ case 4:poker.method=E_POKER_CIPHER004;
+ if (!ae->wl[ae->idx+3].t) {
+ poker.istring=ae->idx+4;
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is CIPHERMEM start,end,4,'keystring'\n");
+ }
+ break;
+ }
+ switch (ciphermode) {
+ default:
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ if (!ae->wl[ae->idx+3].t) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: keystring parameter will be ignored\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (ae->erronwarn) MaxError(ae);
+ }
+ case 4:
+ break;
+ }
+ if (!ae->wl[ae->idx+3].t && !ae->wl[ae->idx+4].t) {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Too many parameters! Usage is CIPHERMEM start,end[,method[,'keystring']]\n");
+ }
+ } else {
+ poker.method=E_POKER_CIPHER001;
+ }
+ poker.istart=ae->idx+1;
+ poker.iend=ae->idx+2;
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx+1].w,1);
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx+2].w,1);
+ poker.outputadr=ae->outputadr;
+ poker.ibank=ae->activebank;
+ poker.ipoker=ae->idx;
+ ObjectArrayAddDynamicValueConcat((void**)&ae->poker,&ae->nbpoker,&ae->maxpoker,&poker,sizeof(poker));
+ }
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"usage is CIPHERMEM start,end[,method[,'keystring']]\n");
+ }
+}
+
+void __TIMESTAMP(struct s_assenv *ae) {
+ char Ltimestamp[32];
+ char LTMP[64];
+ struct tm *local;
+ char *timestr;
+ time_t now;
+ int idx=0;
+ int cpt;
+
+ time(&now);
+ local=localtime(&now);
+
+ if (!ae->wl[ae->idx].t) {
+ ae->idx++;
+ timestr=ae->wl[ae->idx].w+1;
+ } else {
+ timestr=Ltimestamp;
+ strcpy(timestr,"[Y-M-D h:m]");
+ }
+
+ while (timestr[idx]) {
+ switch (timestr[idx]) {
+ case 'Y':
+ cpt=0;
+ while (timestr[idx]=='Y') {idx++;cpt++;}
+ sprintf(LTMP,"%04d",local->tm_year+1900);
+ switch (cpt) {
+ case 2: //___output(ae,LTMP[2]);
+ ___output(ae,ae->charset[(unsigned int)LTMP[2]]);
+ ___output(ae,ae->charset[(unsigned int)LTMP[3]]);
+ break;
+ case 1:
+ case 4: //___output(ae,LTMP[0]);
+ ___output(ae,ae->charset[(unsigned int)LTMP[0]]);
+ ___output(ae,ae->charset[(unsigned int)LTMP[1]]);
+ ___output(ae,ae->charset[(unsigned int)LTMP[2]]);
+ ___output(ae,ae->charset[(unsigned int)LTMP[3]]);
+ break;
+ }
+ break;
+ case 'M':
+ while (timestr[idx]=='M') idx++;
+ sprintf(LTMP,"%02d",local->tm_mon+1);
+ ___output(ae,ae->charset[(unsigned int)LTMP[0]]);
+ ___output(ae,ae->charset[(unsigned int)LTMP[1]]);
+ break;
+ case 'D':
+ while (timestr[idx]=='D') idx++;
+ sprintf(LTMP,"%02d",local->tm_mday);
+ ___output(ae,ae->charset[(unsigned int)LTMP[0]]);
+ ___output(ae,ae->charset[(unsigned int)LTMP[1]]);
+ break;
+ case 'h':
+ while (timestr[idx]=='h') idx++;
+ sprintf(LTMP,"%02d",local->tm_hour);
+ ___output(ae,ae->charset[(unsigned int)LTMP[0]]);
+ ___output(ae,ae->charset[(unsigned int)LTMP[1]]);
+ break;
+ case 'm':
+ while (timestr[idx]=='m') idx++;
+ sprintf(LTMP,"%02d",local->tm_min);
+ ___output(ae,ae->charset[(unsigned int)LTMP[0]]);
+ ___output(ae,ae->charset[(unsigned int)LTMP[1]]);
+ break;
+ case 's':
+ while (timestr[idx]=='s') idx++;
+ sprintf(LTMP,"%02d",local->tm_sec);
+ ___output(ae,ae->charset[(unsigned int)LTMP[0]]);
+ ___output(ae,ae->charset[(unsigned int)LTMP[1]]);
+ break;
+ default:
+ if ((timestr[idx]=='\'' || timestr[idx]=='"') && !timestr[idx+1]) {} else ___output(ae,ae->charset[(unsigned int)timestr[idx]&0xFF]);
+ idx++;
+ break;
+
+ }
+ }
}
struct s_asm_keyword instruction[]={
@@ -12648,9 +16725,11 @@ struct s_asm_keyword instruction[]={
{"DI",0,_DI},
{"EI",0,_EI},
{"NOP",0,_NOP},
+{"DEFF",0,_DEFF},
{"DEFR",0,_DEFR},
{"DEFB",0,_DEFB},
{"DEFM",0,_DEFB},
+{"DF",0,_DEFF},
{"DR",0,_DEFR},
{"DM",0,_DEFB},
{"DB",0,_DEFB},
@@ -12691,6 +16770,7 @@ struct s_asm_keyword instruction[]={
{"INDR",0,_INDR},
{"INIR",0,_INIR},
{"REPEAT",0,__REPEAT},
+{"STARTINGINDEX",0,__STARTINGINDEX},
{"REND",0,__REND},
{"ENDREPEAT",0,__REND},
{"ENDREP",0,__REND},
@@ -12699,8 +16779,11 @@ struct s_asm_keyword instruction[]={
{"PROTECT",0,__PROTECT},
{"WHILE",0,__WHILE},
{"WEND",0,__WEND},
+{"READ",0,__READ},
+{"INCLUDE",0,__READ}, // anti-label
{"HEXBIN",0,__HEXBIN},
{"ALIGN",0,__ALIGN},
+{"CONFINE",0,__CONFINE},
{"ELSEIF",0,__ELSEIF},
{"ELSE",0,__ELSE},
{"IF",0,__IF},
@@ -12732,6 +16815,7 @@ struct s_asm_keyword instruction[]={
{"LIST",0,__LIST},
{"STOP",0,__STOP},
{"PRINT",0,__PRINT},
+{"DELAYED_PRINT",0,__DELAYED_PRINT},
{"FAIL",0,__FAIL},
{"BREAKPOINT",0,__BREAKPOINT},
{"BANK",0,__BANK},
@@ -12740,11 +16824,19 @@ struct s_asm_keyword instruction[]={
{"LIMIT",0,__LIMIT},
{"LZEXO",0,__LZEXO},
{"LZX7",0,__LZX7},
+{"LZX0",0,__LZX0},
+{"LZX0B",0,__LZX0B},
+{"LZAPU",0,__LZAPU},
+{"LZSA1",0,__LZSA1},
+{"LZSA2",0,__LZSA2},
{"LZ4",0,__LZ4},
{"LZ48",0,__LZ48},
{"LZ49",0,__LZ49},
{"LZCLOSE",0,__LZCLOSE},
+{"SNASET",0,__SNASET},
+{"SNAPINIT",0,__SNAPINIT},
{"BUILDZX",0,__BUILDZX},
+{"BUILDOBJ",0,__BUILDOBJ},
{"BUILDCPR",0,__BUILDCPR},
{"BUILDSNA",0,__BUILDSNA},
{"BUILDROM",0,__BUILDROM},
@@ -12761,9 +16853,28 @@ struct s_asm_keyword instruction[]={
{"ENDS",0,__ENDSTRUCT},
{"NOEXPORT",0,__NOEXPORT},
{"ENOEXPORT",0,__ENOEXPORT},
+{"MODULE",0,__MODULE},
+{"ENDMODULE",0,__ENDMODULE},
+{"TIMESTAMP",0,__TIMESTAMP},
+{"SUMMEM",0,__SUMMEM},
+{"XORMEM",0,__XORMEM},
+{"CIPHERMEM",0,__CIPHERMEM},
+{"EXTERNAL",0,__EXTERNAL},
+{"PROCEDURE",0,__PROCEDURE},
{"",0,NULL}
};
+int IsDirective(char *zeexpression)
+{
+ int i,crc;
+
+ crc=GetCRC(zeexpression);
+
+ for (i=0;instruction[i].mnemo[0];i++) if (instruction[i].crc==crc && !strcmp(instruction[i].mnemo,zeexpression)) return 1;
+
+ return 0;
+}
+
int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout, struct s_rasm_info **debug)
{
#undef FUNC
@@ -12772,16 +16883,17 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout, struct s
unsigned char *AmsdosHeader;
struct s_expression curexp={0};
struct s_wordlist *wordlist;
- struct s_expr_dico curdico={0};
struct s_label *curlabel;
int icrc,curcrc,i,j,k;
unsigned char *lzdata=NULL;
int lzlen,lzshift,input_size;
- size_t slzlen;
+ int slzlen,delta;
unsigned char *input_data;
struct s_orgzone orgzone={0};
- int iorgzone,ibank,offset,endoffset;
- int il,maxrom;
+ int iorgzone,ibank,offset,endoffset,morgzone,saveorgzone;
+ int AutomateCharStop[256];
+ int AutomateChar[256];
+ int il,jl,maxrom;
char *TMP_filename=NULL;
int minmem=65536,maxmem=0,lzmove;
char symbol_line[1024];
@@ -12790,9 +16902,17 @@ int Assemble(struct s_assenv *ae, unsigned char **dataout, int *lenout, struct s
int curii,inhibe;
int ok;
+
+ for (i=0;i<256;i++) {
+ if (i==0 || (i>='a' && i<='z') || (i>='A' && i<='Z')) AutomateCharStop[i]=1; else AutomateCharStop[i]=0;
+ if ((i>='a' && i<='z') || (i>='A' && i<='Z')) AutomateChar[i]=1; else AutomateChar[i]=0;
+ }
+ AutomateChar['@']=AutomateCharStop['@']=1;
+ AutomateChar['_']=AutomateCharStop['_']=1;
+
rasm_printf(ae,KAYGREEN"Assembling\n");
#if TRACE_ASSEMBLE
-printf("assembling\n");
+printf("assembling (nberr=%d)\n",ae->nberr);
#endif
#if TRACE_GENERALE
printf("*** assembling ***\n");
@@ -12809,16 +16929,17 @@ printf("*** assembling ***\n");
/* default orgzone */
orgzone.ibank=BANK_MAX_NUMBER;
+ orgzone.inplace=1;
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);
+ InitAutomate(ae->AutomateHexa,(unsigned char *)AutomateHexaDefinition);
+ InitAutomate(ae->AutomateDigit,(unsigned char *)AutomateDigitDefinition);
+ InitAutomate(ae->AutomateValidLabel,(unsigned char *)AutomateValidLabelDefinition);
+ InitAutomate(ae->AutomateValidLabelFirst,(unsigned char *)AutomateValidLabelFirstDefinition);
+ InitAutomate(ae->AutomateExpressionValidCharExtended,(unsigned char *)AutomateExpressionValidCharExtendedDefinition);
+ InitAutomate(ae->AutomateExpressionValidCharFirst,(unsigned char *)AutomateExpressionValidCharFirstDefinition);
+ InitAutomate(ae->AutomateExpressionValidChar,(unsigned char *)AutomateExpressionValidCharDefinition);
ae->AutomateExpressionDecision['<']='<';
ae->AutomateExpressionDecision['>']='>';
ae->AutomateExpressionDecision['=']='=';
@@ -12829,6 +16950,7 @@ printf("*** assembling ***\n");
/* set operator precedence */
if (!ae->maxam) {
for (i=0;i<256;i++) {
+ ae->AutomateElement[i].string=NULL;
switch (i) {
/* priority 0 */
case '(':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_OPEN;ae->AutomateElement[i].priority=0;break;
@@ -12867,6 +16989,7 @@ printf("*** assembling ***\n");
}
} else {
for (i=0;i<256;i++) {
+ ae->AutomateElement[i].string=NULL;
switch (i) {
/* priority 0 */
case '(':ae->AutomateElement[i].operator=E_COMPUTE_OPERATION_OPEN;ae->AutomateElement[i].priority=0;break;
@@ -12930,8 +17053,8 @@ printf("*** assembling ***\n");
}
/* default var */
ae->autorise_export=1;
- ExpressionSetDicoVar(ae,"PI",3.1415926545);
- ExpressionSetDicoVar(ae,"ASSEMBLER_RASM",1);
+ ExpressionSetDicoVar(ae,"PI",3.1415926545,0);
+ ExpressionSetDicoVar(ae,"ASSEMBLER_RASM",1,0);
/* add a fictive expression to simplify test when parsing expressions */
ObjectArrayAddDynamicValueConcat((void **)&ae->expression,&ae->ie,&ae->me,&curexp,sizeof(curexp));
@@ -12940,7 +17063,7 @@ printf("*** assembling ***\n");
for (icrc=0;instruction[icrc].mnemo[0];icrc++) instruction[icrc].crc=GetCRC(instruction[icrc].mnemo);
for (icrc=0;math_keyword[icrc].mnemo[0];icrc++) math_keyword[icrc].crc=GetCRC(math_keyword[icrc].mnemo);
- if (ae->as80==1) { /* not for UZ80 */
+ if (ae->as80==1 || ae->pasmo) { /* not for UZ80 */
for (icrc=0;instruction[icrc].mnemo[0];icrc++) {
if (strcmp(instruction[icrc].mnemo,"DEFB")==0 || strcmp(instruction[icrc].mnemo,"DB")==0) {
instruction[icrc].makemnemo=_DEFB_as80;
@@ -12950,6 +17073,17 @@ printf("*** assembling ***\n");
instruction[icrc].makemnemo=_DEFI_as80;
}
}
+ } else {
+ /* for multiple configurations with rasm embedded */
+ for (icrc=0;instruction[icrc].mnemo[0];icrc++) {
+ if (strcmp(instruction[icrc].mnemo,"DEFB")==0 || strcmp(instruction[icrc].mnemo,"DB")==0) {
+ instruction[icrc].makemnemo=_DEFB;
+ } else if (strcmp(instruction[icrc].mnemo,"DEFW")==0 || strcmp(instruction[icrc].mnemo,"DW")==0) {
+ instruction[icrc].makemnemo=_DEFW;
+ } else if (strcmp(instruction[icrc].mnemo,"DEFI")==0) {
+ instruction[icrc].makemnemo=_DEFI;
+ }
+ }
}
for (icrc=0;instruction[icrc].mnemo[0];icrc++) {
@@ -12962,6 +17096,10 @@ printf("*** assembling ***\n");
ICRC_DEFW=icrc;
} else if (strcmp(instruction[icrc].mnemo,"DW")==0) {
ICRC_DW=icrc;
+ } else if (strcmp(instruction[icrc].mnemo,"DEFF")==0) {
+ ICRC_DEFF=icrc;
+ } else if (strcmp(instruction[icrc].mnemo,"DF")==0) {
+ ICRC_DF=icrc;
} else if (strcmp(instruction[icrc].mnemo,"DEFR")==0) {
ICRC_DEFR=icrc;
} else if (strcmp(instruction[icrc].mnemo,"DR")==0) {
@@ -13099,22 +17237,43 @@ printf("-loop\n");
}
}
}
+ /*****************************************
+ m a c r o p o s i t i o n s
+ *****************************************/
if (ae->imacropos) {
+ int icheckm;
+
+ /*
+ printf("===== Macro positions idx=%d =====\n",ae->idx);
+ for (icheckm=0;icheckm<ae->imacropos;icheckm++) {
+ printf("macro[%d] start=%3d end=%3d level=%d \n",icheckm,ae->macropos[icheckm].start,ae->macropos[icheckm].end,ae->macropos[icheckm].level);
+ }
+ printf("---------------------------\n");
+ */
+
+ /* we must close */
+ for (icheckm=0;icheckm<ae->imacropos;icheckm++) {
+ if (ae->idx==ae->macropos[icheckm].end) {
+ /* contiguous macro management... */
+ if (ae->macropos[icheckm].pushed) {
+ PopGlobal(ae);
+ ae->macropos[icheckm].pushed=0;
+ }
+ }
+ }
+ /* before opening */
+ for (icheckm=0;icheckm<ae->imacropos;icheckm++) {
+ if (ae->idx==ae->macropos[icheckm].start) {
+ PushGlobal(ae);
+ ae->macropos[icheckm].pushed=1;
+ }
+ }
+
/* are we still in a macro? */
if (ae->idx>=ae->macropos[0].end) {
/* are we out of all repetition blocks? */
if (!ae->ir && !ae->iw) {
ae->imacropos=0;
-
- /* quand on sort du local, on récupère le dernier label global */
- if (ae->lastsuperglobal!=ae->lastgloballabel && ae->lastsuperglobal) {
- if (ae->lastglobalalloc) {
- MemFree(ae->lastgloballabel);
- ae->lastglobalalloc=0;
- }
- ae->lastgloballabel=ae->lastsuperglobal;
- ae->lastgloballabellen=strlen(ae->lastgloballabel);
- }
}
}
}
@@ -13228,102 +17387,254 @@ printf("-check ORG\n");
}
}
#if TRACE_ASSEMBLE
-printf("crunch if any\n");
+printf("crunch if any %d blocks\n",ae->ilz);
#endif
/***************************************************
c r u n c h L Z s e c t i o n s
***************************************************/
if (!ae->stop || !ae->nberr) {
+
+ /* all EQU values are computed in order to be STATIC values until the end
+ * at this point, there is a lot of expressions (in or outside lz sections)
+ * to be computed.
+ */
+ for (i=0;i<ae->ialias;i++) {
+ char alias_value[128];
+ double v;
+ // compute EQU defined in crunched sections
+ if (ae->alias[i].lz>=0) {
+ ae->idx=ae->alias[i].iw; // expression core hack
+ v=ComputeExpressionCore(ae,ae->alias[i].translation,ae->alias[i].ptr,0);
+ sprintf(alias_value,"%.8lf",v);
+ MemFree(ae->alias[i].translation);
+ ae->alias[i].translation=TxtStrDup(alias_value);
+ ae->alias[i].len=strlen(ae->alias[i].translation);
+ }
+ }
+
for (i=0;i<ae->ilz;i++) {
- /* compute labels and expression inside crunched blocks */
- PopAllExpression(ae,i);
-
- ae->curlz=i;
- iorgzone=ae->lzsection[i].iorgzone;
- ibank=ae->lzsection[i].ibank;
- input_data=&ae->mem[ae->lzsection[i].ibank][ae->lzsection[i].memstart];
- input_size=ae->lzsection[i].memend-ae->lzsection[i].memstart;
-//printf("grouik (%d) %s\n",ae->lzsection[i].lzversion,ae->lzsection[i].lzversion==8?"mizou":"");
- if (!input_size) {
- rasm_printf(ae,KWARNING"[%s:%d] Warning: crunched section is empty\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
- } else {
- switch (ae->lzsection[i].lzversion) {
- case 7:
- #ifndef NO_3RD_PARTIES
- lzdata=ZX7_compress(optimize(input_data, input_size), input_data, input_size, &slzlen);
- lzlen=slzlen;
- #endif
- break;
- case 4:
- #ifndef NO_3RD_PARTIES
- lzdata=LZ4_crunch(input_data,input_size,&lzlen);
- #endif
- break;
- case 8:
- #ifndef NO_3RD_PARTIES
- rasm_printf(ae,KWARNING"Exomizer is crunching %.1fkb this may take a while, be patient...\n",input_size/1024.0);
+ /* on dépile les symboles dans l'ordre mais on ne reloge pas sur les zones intermédiaires ou post-crunched */
+ if (ae->lzsection[i].lzversion!=0) {
+#if TRACE_ASSEMBLE
+printf("Crunch LZ[%d] (%d) %s\n",i,ae->lzsection[i].lzversion,ae->lzsection[i].lzversion==8?"mizou":"");
+#endif
- lzdata=Exomizer_crunch(input_data,input_size,&lzlen);
- #endif
- break;
- case 48:
- lzdata=LZ48_crunch(input_data,input_size,&lzlen);
- break;
- case 49:
- lzdata=LZ49_crunch(input_data,input_size,&lzlen);
- break;
- default:
- rasm_printf(ae,"Internal error - unknown crunch method %d\n",ae->lzsection[i].lzversion);
- exit(-12);
- }
- }
- //rasm_printf(ae,"lzsection[%d] type=%d start=%04X end=%04X crunched size=%d\n",i,ae->lzsection[i].lzversion,ae->lzsection[i].memstart,ae->lzsection[i].memend,lzlen);
-
- if (input_size<lzlen) {
- MakeError(ae,ae->filename[ae->wl[ae->lzsection[i].iw].ifile],ae->wl[ae->lzsection[i].iw].l,"As the LZ section cannot crunch data, Rasm may not guarantee assembled file!\n");
- }
-
- lzshift=lzlen-(ae->lzsection[i].memend-ae->lzsection[i].memstart);
- if (lzshift>0) {
- MemMove(ae->mem[ae->lzsection[i].ibank]+ae->lzsection[i].memend+lzshift,ae->mem[ae->lzsection[i].ibank]+ae->lzsection[i].memend,65536-ae->lzsection[i].memend-lzshift);
- } else if (lzshift<0) {
- lzmove=ae->orgzone[iorgzone].memend-ae->lzsection[i].memend;
- if (lzmove) {
- MemMove(ae->mem[ae->lzsection[i].ibank]+ae->lzsection[i].memend+lzshift,ae->mem[ae->lzsection[i].ibank]+ae->lzsection[i].memend,lzmove);
- }
- }
- memcpy(ae->mem[ae->lzsection[i].ibank]+ae->lzsection[i].memstart,lzdata,lzlen);
- MemFree(lzdata);
- /*******************************************************************
- l a b e l a n d e x p r e s s i o n r e l o c a t i o n
- *******************************************************************/
- /* relocate labels in the same ORG zone AND after the current crunched section */
- il=ae->lzsection[i].ilabel;
- while (il<ae->il && ae->label[il].iorgzone==iorgzone && ae->label[il].ibank==ibank) {
- curlabel=SearchLabel(ae,ae->label[il].iw!=-1?wordlist[ae->label[il].iw].w:ae->label[il].name,ae->label[il].crc);
- /* CANNOT be NULL */
- curlabel->ptr+=lzshift;
- //printf("label [%s] shifte de %d valeur #%04X -> #%04X\n",curlabel->iw!=-1?wordlist[curlabel->iw].w:curlabel->name,lzshift,curlabel->ptr-lzshift,curlabel->ptr);
- il++;
- }
- /* relocate expressions in the same ORG zone AND after the current crunched section */
- il=ae->lzsection[i].iexpr;
- while (il<ae->ie && ae->expression[il].iorgzone==iorgzone && ae->expression[il].ibank==ibank) {
- ae->expression[il].wptr+=lzshift;
- ae->expression[il].ptr+=lzshift;
- //printf("expression [%s] shiftee ptr=#%04X wptr=#%04X\n", ae->expression[il].reference?ae->expression[il].reference:wordlist[ae->expression[il].iw].w, ae->expression[il].ptr, ae->expression[il].wptr);
- il++;
- }
- /* relocate crunched sections in the same ORG zone AND after the current crunched section */
- il=i+1;
- while (il<ae->ilz && ae->lzsection[il].iorgzone==iorgzone && ae->lzsection[il].ibank==ibank) {
- //rasm_printf(ae,"reloger lzsection[%d] O%d B%d\n",il,ae->lzsection[il].iorgzone,ae->lzsection[il].ibank);
- ae->lzsection[il].memstart+=lzshift;
- ae->lzsection[il].memend+=lzshift;
- il++;
- }
- /* relocate current ORG zone */
- ae->orgzone[iorgzone].memend+=lzshift;
+ if (ae->lzsection[i].memend==-1) {
+ /* patch idx */
+ ae->idx=ae->lzsection[i].iw;
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"Crunched section was not closed\n");
+ continue;
+ }
+
+ /* compute labels and expression inside crunched blocks */
+ PopAllExpression(ae,i);
+
+ ae->curlz=i;
+ iorgzone=ae->lzsection[i].iorgzone;
+ ibank=ae->lzsection[i].ibank;
+ input_data=&ae->mem[ae->lzsection[i].ibank][ae->lzsection[i].memstart];
+ input_size=ae->lzsection[i].memend-ae->lzsection[i].memstart;
+ if (!input_size) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: crunched section is empty\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (ae->erronwarn) MaxError(ae);
+ } else {
+ switch (ae->lzsection[i].lzversion) {
+
+ case 70:
+ #ifndef NO_3RD_PARTIES
+ if (input_size>=1024 && MAX_OFFSET_ZX0>5000) rasm_printf(ae,KWARNING"ZX0 is crunching %.1fkb this may take a while, be patient...\n",input_size/1024.0);
+ lzdata=zx0_compress(zx0_optimize(input_data, input_size, 0, MAX_OFFSET_ZX0), input_data, input_size, 0, 0, 1,&slzlen, &delta);
+ lzlen=slzlen;
+ #endif
+ break;
+ case 71:
+ #ifndef NO_3RD_PARTIES
+ if (input_size>=1024 && MAX_OFFSET_ZX0>5000) rasm_printf(ae,KWARNING"ZX0 is crunching %.1fkb this may take a while, be patient...\n",input_size/1024.0);
+ zx0_reverse(input_data,input_data+input_size-1);
+ lzdata=zx0_compress(zx0_optimize(input_data, input_size, 0, MAX_OFFSET_ZX0), input_data, input_size, 0, 1, 0,&slzlen, &delta);
+ zx0_reverse(lzdata,lzdata+slzlen-1);
+ lzlen=slzlen;
+ #endif
+ break;
+ case 7:
+ #ifndef NO_3RD_PARTIES
+ lzdata=ZX7_compress(zx7_optimize(input_data, input_size), input_data, input_size, &slzlen);
+ lzlen=slzlen;
+ #endif
+ break;
+ case 4:
+ #ifndef NO_3RD_PARTIES
+ lzdata=LZ4_crunch(input_data,input_size,&lzlen);
+ #endif
+ break;
+ case 8:
+ #ifndef NO_3RD_PARTIES
+ if (input_size>=1024) rasm_printf(ae,KWARNING"Exomizer is crunching %.1fkb this may take a while, be patient...\n",input_size/1024.0);
+ lzdata=Exomizer_crunch(input_data,input_size,&lzlen);
+ #endif
+ break;
+ case 17:
+ #ifndef NO_3RD_PARTIES
+ if (input_size>=1024) rasm_printf(ae,KWARNING"AP-Ultra is crunching %.1fkb this may take a while, be patient...\n",input_size/1024.0);
+ APULTRA_crunch(input_data,input_size,&lzdata,&lzlen);
+ #endif
+ break;
+ case 18:
+#if TRACE_ASSEMBLE
+ printf("crunching bank %d ptr=%d lng=%d version=%d minmatch=%d\n",ae->lzsection[i].ibank,ae->lzsection[i].memstart,input_size,ae->lzsection[i].version,ae->lzsection[i].minmatch);
+#endif
+ #ifndef NO_3RD_PARTIES
+ if (input_size>=16384 && ae->lzsection[i].version==2) rasm_printf(ae,KWARNING"LZSA is crunching %.1fkb this may take a while, be patient...\n",input_size/1024.0);
+ LZSA_crunch(input_data,input_size,&lzdata,&lzlen,ae->lzsection[i].version,ae->lzsection[i].minmatch);
+ #endif
+ break;
+ case 48:
+ lzdata=LZ48_crunch(input_data,input_size,&lzlen);
+ break;
+ case 49:
+ lzdata=LZ49_crunch(input_data,input_size,&lzlen);
+ break;
+ default:
+ rasm_printf(ae,"Internal error - unknown crunch method %d\n",ae->lzsection[i].lzversion);
+ exit(-12);
+ }
+ }
+
+#if TRACE_ASSEMBLE
+ printf("lzsection[%d] type=%d start=%04X end=%04X crunched size=%d\n",i,ae->lzsection[i].lzversion,ae->lzsection[i].memstart,ae->lzsection[i].memend,lzlen);
+#endif
+
+ if (input_size<lzlen) {
+ //MakeError(ae,ae->filename[ae->wl[ae->lzsection[i].iw].ifile],ae->wl[ae->lzsection[i].iw].l,"As the LZ section cannot crunch data, Rasm may not guarantee assembled file!\n");
+ rasm_printf(ae,KWARNING"Warning: LZ section is bigger than original\n");
+ if (ae->erronwarn) MaxError(ae);
+ }
+
+ lzshift=lzlen-(ae->lzsection[i].memend-ae->lzsection[i].memstart);
+#if TRACE_ASSEMBLE
+printf("lzshift=%d\n",lzshift);
+#endif
+
+ /*******************************************************************************
+ r e l o c a t e d a t a u n t i l n o n c o n t i g u o u s O R G
+ *******************************************************************************/
+ morgzone=iorgzone;
+ if (lzshift>0) {
+ /* positif => plus gros @@TODO */
+ //MemMove(ae->mem[ae->lzsection[i].ibank]+ae->lzsection[i].memend+lzshift,ae->mem[ae->lzsection[i].ibank]+ae->lzsection[i].memend,65536-ae->lzsection[i].memend-lzshift);
+ } else if (lzshift<0) {
+ /* when crunched we may have to move more than 1 ORG */
+ while (morgzone+1<ae->io) {
+ /* if next ORG zone is contiguous */
+ if (ae->orgzone[morgzone+1].memstart==ae->orgzone[morgzone].memend && ae->orgzone[morgzone+1].ibank==ae->orgzone[morgzone].ibank) {
+ morgzone++;
+ } else break;
+ }
+ lzmove=ae->orgzone[morgzone].memend-ae->lzsection[i].memend;
+#if TRACE_ASSEMBLE
+printf("include %d other ORG for the memove size=%d\n",morgzone-iorgzone,lzmove);
+#endif
+ if (lzmove) {
+ MemMove(ae->mem[ae->lzsection[i].ibank]+ae->lzsection[i].memend+lzshift,ae->mem[ae->lzsection[i].ibank]+ae->lzsection[i].memend,lzmove);
+ }
+ }
+ memcpy(ae->mem[ae->lzsection[i].ibank]+ae->lzsection[i].memstart,lzdata,lzlen);
+ MemFree(lzdata);
+ /*******************************************************************
+ l a b e l a n d e x p r e s s i o n r e l o c a t i o n
+ *******************************************************************/
+ /* relocate labels in the same ORG zone AND contiguous ORG when they are "in place" */
+ il=ae->lzsection[i].ilabel;
+ saveorgzone=iorgzone;
+ do {
+ while (il<ae->il && ae->label[il].iorgzone<iorgzone) il++;
+
+ while (il<ae->il && ae->label[il].iorgzone==iorgzone) {
+ curlabel=SearchLabel(ae,ae->label[il].iw!=-1?wordlist[ae->label[il].iw].w:ae->label[il].name,ae->label[il].crc);
+ /* CANNOT be NULL */
+ curlabel->ptr+=lzshift;
+#if TRACE_ASSEMBLE
+ printf("label [%s] shifte de %d valeur #%04X -> #%04X\n",curlabel->iw!=-1?wordlist[curlabel->iw].w:curlabel->name,lzshift,curlabel->ptr-lzshift,curlabel->ptr);
+#endif
+ il++;
+ }
+ iorgzone++;
+ /* jump over contiguous ORG not "in place" */
+ while (iorgzone<ae->io && !ae->orgzone[iorgzone].inplace && iorgzone<=morgzone) {
+ //printf("label reallocation jump over ORG %d\n",iorgzone);
+ iorgzone++;
+ }
+ } while (iorgzone<=morgzone);
+
+ /* relocate mapping after the same ORG zone and inside contiguous ORG
+ * there is no check for outside/inside crunched section because this
+ * was already done during mapping declaration but we must avoid to
+ * shift before crunched section inside the same ORG */
+ iorgzone=saveorgzone;
+ do {
+ for (il=0;il<ae->nexternal;il++) {
+ for (jl=0;jl<ae->external[il].nmapping;jl++) {
+ if (ae->external[il].mapping[jl].iorgzone==iorgzone && ae->external[il].mapping[jl].ptr>ae->lzsection[i].memstart) {
+ //printf("shift mapping ptr=%d => %d\n",ae->external[il].mapping[jl].ptr,ae->external[il].mapping[jl].ptr+lzshift);
+ ae->external[il].mapping[jl].ptr+=lzshift;
+ }
+ }
+ }
+ iorgzone++;
+ } while (iorgzone<=morgzone);
+
+ /* relocate expressions in the same ORG zone AND contiguous ORG */
+ iorgzone=saveorgzone;
+ il=ae->lzsection[i].iexpr;
+ do {
+ while (il<ae->il && ae->label[il].iorgzone<iorgzone) il++;
+
+ while (il<ae->ie && ae->expression[il].iorgzone==iorgzone) {
+ ae->expression[il].wptr+=lzshift;
+ /* relocate only "in place" contiguous ORG */
+ if (ae->orgzone[iorgzone].inplace) ae->expression[il].ptr+=lzshift;
+#if TRACE_ASSEMBLE
+ printf("expression [%s] shiftee ptr(%s)=#%04X wptr=#%04X\n", ae->expression[il].reference?ae->expression[il].reference:wordlist[ae->expression[il].iw].w, ae->orgzone[iorgzone].inplace?"relocated":"untouched",ae->expression[il].ptr, ae->expression[il].wptr);
+#endif
+ il++;
+ }
+ iorgzone++;
+ } while (iorgzone<=morgzone);
+
+ /* relocate crunched sections in the same ORG zone AND contiguous ORG */
+ iorgzone=saveorgzone;
+ il=i+1;
+ do {
+ while (il<ae->ilz && ae->lzsection[il].iorgzone==iorgzone && ae->lzsection[il].ibank==ibank) {
+
+#if TRACE_ASSEMBLE
+ rasm_printf(ae,"reloger lzsection[%d] O%d B%d shift=%d\n",il,ae->lzsection[il].iorgzone,ae->lzsection[il].ibank,lzshift);
+#endif
+ ae->lzsection[il].memstart+=lzshift;
+ ae->lzsection[il].memend+=lzshift;
+ il++;
+ }
+ iorgzone++;
+ } while (iorgzone<=morgzone);
+
+ iorgzone=saveorgzone;
+ /* relocate ORG zone(s) */
+ ae->orgzone[iorgzone].memend+=lzshift;
+ while (iorgzone<morgzone) {
+ iorgzone++;
+ ae->orgzone[iorgzone].memstart+=lzshift;
+ ae->orgzone[iorgzone].memend+=lzshift;
+ }
+ }
+ }
+ for (i=0;i<ae->ilz;i++) {
+ if (ae->lzsection[i].lzversion==0) {
+#if TRACE_ASSEMBLE
+//printf("PopAllExpr on intermediate section[%d] (%d) %s\n",i,ae->lzsection[i].lzversion,ae->lzsection[i].lzversion==8?"mizou":"");
+#endif
+ /* compute labels and expression outside crunched blocks BUT after crunched */
+ PopAllExpression(ae,i);
+ }
}
if (ae->ilz) {
/* compute expression placed after the last crunched block */
@@ -13333,6 +17644,101 @@ printf("crunch if any\n");
PopAllExpression(ae,-1);
}
+ /*******************************************************************************
+ p o k e r
+ *******************************************************************************/
+ for (i=0;i<ae->nbpoker;i++) {
+ int istart=-1,iend=-1;
+ unsigned char xorval,sumval;
+
+ /* start/end */
+ ae->idx=ae->poker[i].istart; /* exp hack */
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx].w,0);
+ istart=RoundComputeExpression(ae,ae->wl[ae->idx].w,0,0,0);
+ ae->idx=ae->poker[i].iend; /* exp hack */
+ ExpressionFastTranslate(ae,&ae->wl[ae->idx].w,0);
+ iend=RoundComputeExpression(ae,ae->wl[ae->idx].w,0,0,0);
+
+ switch (ae->poker[i].method) {
+ case E_POKER_XOR8:
+ xorval=0;
+ for (j=istart;j<iend;j++) {
+ xorval=xorval^ae->mem[ae->poker[i].ibank][j];
+ }
+ ae->mem[ae->poker[i].ibank][ae->poker[i].outputadr]=xorval;
+ //printf("poker XOR from #%04X to #%04X at #%04X\n",istart,iend,ae->poker[i].outputadr);
+ break;
+ case E_POKER_SUM8:
+ sumval=0;
+ for (j=istart;j<iend;j++) {
+ sumval+=ae->mem[ae->poker[i].ibank][j];
+ }
+ ae->mem[ae->poker[i].ibank][ae->poker[i].outputadr]=sumval;
+ break;
+ case E_POKER_CIPHER001:
+ case E_POKER_CIPHER002:
+ if (ae->poker[i].method==E_POKER_CIPHER001) {
+ xorval=ae->mem[ae->poker[i].ibank][istart];
+ istart++;
+ } else if (ae->poker[i].method==E_POKER_CIPHER002) {
+ xorval=istart&0xFF; // xor start value depends on memory location!
+ }
+ for (j=istart;j<iend;j++) {
+ ae->mem[ae->poker[i].ibank][j]=xorval=ae->mem[ae->poker[i].ibank][j]^xorval;
+ }
+ break;
+ case E_POKER_CIPHER003:
+ for (j=istart;j<iend;j++) {
+ xorval=j&0xFF;
+ ae->mem[ae->poker[i].ibank][j]=ae->mem[ae->poker[i].ibank][j]^xorval;
+ }
+ break;
+ case E_POKER_CIPHER004:
+ {
+ char *zekey;
+ int zelen,ikey=0;
+ zekey=TxtStrDup(ae->wl[ae->poker[i].istring].w+1);
+ zelen=strlen(zekey)-1;
+ if (zelen>1) {
+ zekey[zelen]=0;
+ for (j=istart;j<iend;j++) {
+ xorval=zekey[ikey++];if (ikey>=zelen) ikey=0;
+ ae->mem[ae->poker[i].ibank][j]=ae->mem[ae->poker[i].ibank][j]^xorval;
+ }
+ } else {
+ MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"CIPHER needs a string of one char or more to run properly\n");
+ }
+ if (zekey) MemFree(zekey);
+ }
+ break;
+ default:printf("warning remover\n");break;
+ }
+
+ for (j=0;j<ae->nbpoker;j++) {
+ if (ae->poker[i].ibank==ae->poker[j].ibank) {
+ if (ae->poker[j].outputadr>=istart && ae->poker[j].outputadr<iend) {
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: %s poker result is inside another %s poker calculation",GetCurrentFile(ae),ae->wl[ae->idx].l,
+ ae->poker[i].method<E_POKER_END?strpoker[ae->poker[i].method]:"???",
+ ae->poker[j].method<E_POKER_END?strpoker[ae->poker[j].method]:"???");
+ ae->idx=ae->poker[j].istart;
+ rasm_printf(ae,KWARNING"[%s:%d]\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (ae->erronwarn) MaxError(ae);
+ }
+ }
+ }
+ }
+
+ }
+
+ /*******************************************************************************
+ d e l a y e d p r i n t s
+ *******************************************************************************/
+ for (i=0;i<ae->idprint;i++) {
+ ae->idx=ae->dprint_idx[i];
+ __PRINT(ae);
+ }
+
/***************************************************************************************************************************************************************************************
****************************************************************************************************************************************************************************************
W R I T E O U T P U T F I L E S
@@ -13353,40 +17759,104 @@ printf("output files\n");
/* enregistrement des fichiers programmes par la commande SAVE */
PopAllSave(ae);
- if (ae->nbsave==0 || ae->forcecpr || ae->forcesnapshot) {
+ if (ae->nbsave==0 || ae->forcecpr || ae->forcesnapshot || ae->forceROM || ae->forcetape) {
+ /*********************************************
+ ROM LABEL EXPORT
+ *********************************************/
+ char cprinfo_filename[PATH_MAX];
+ char cprinfo_line[1024];
+
+ if (ae->cprinfo_export) {
+ for (i=maxrom=0;i<ae->io;i++) {
+ if (ae->orgzone[i].ibank<256 && ae->orgzone[i].ibank>maxrom) maxrom=ae->orgzone[i].ibank;
+ }
+ if (ae->cprinfo_filename) {
+ sprintf(cprinfo_filename,"%s",ae->cprinfo_filename);
+ } else {
+ sprintf(cprinfo_filename,"%s.rom_labels",ae->outputfilename);
+ }
+ FileRemoveIfExists(cprinfo_filename);
+ rasm_printf(ae,KIO"Write ROM label file %s\n",cprinfo_filename);
+
+ for (i=0;i<=maxrom && i<BANK_MAX_NUMBER;i++) {
+ int lm;
+ if (ae->iwnamebank[i]>0) {
+ lm=strlen(ae->wl[ae->iwnamebank[i]].w)-2;
+ if (lm) {
+ snprintf(cprinfo_line,sizeof(cprinfo_line),"%d: %-*.*s\n",i,lm,lm,ae->wl[ae->iwnamebank[i]].w+1);
+ FileWriteLine(cprinfo_filename,cprinfo_line);
+ }
+ } else {
+ sprintf(cprinfo_line,"%d:\n",i);
+ FileWriteLine(cprinfo_filename,cprinfo_line);
+ }
+ }
+ FileWriteLineClose(cprinfo_filename);
+ }
+
/*********************************************
**********************************************
- C A R T R I D G E
+ C A R T R I D G E
**********************************************
*********************************************/
if (ae->forcecpr) {
char ChunkName[32];
int ChunkSize;
- int do_it=1;
unsigned char chunk_endian;
-
+
if (ae->cartridge_name) {
sprintf(TMP_filename,"%s",ae->cartridge_name);
} else {
- sprintf(TMP_filename,"%s.cpr",ae->outputfilename);
+ if (!ae->extendedCPR) sprintf(TMP_filename,"%s.cpr",ae->outputfilename);
+ else sprintf(TMP_filename,"%s.xpr",ae->outputfilename);
}
FileRemoveIfExists(TMP_filename);
- rasm_printf(ae,KIO"Write cartridge file %s\n",TMP_filename);
+ rasm_printf(ae,KIO"Write %scartridge file %s\n",ae->extendedCPR?"extended ":"",TMP_filename);
for (i=maxrom=0;i<ae->io;i++) {
- if (ae->orgzone[i].ibank<32 && ae->orgzone[i].ibank>maxrom) maxrom=ae->orgzone[i].ibank;
+ if (ae->orgzone[i].ibank<256 && ae->orgzone[i].ibank>maxrom) maxrom=ae->orgzone[i].ibank;
}
/* construction du CPR */
/* header blablabla */
strcpy(ChunkName,"RIFF");
FileWriteBinary(TMP_filename,ChunkName,4);
- ChunkSize=(maxrom+1)*(16384+8)+4;
- chunk_endian=ChunkSize&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1);
- chunk_endian=(ChunkSize>>8)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1);
- chunk_endian=(ChunkSize>>16)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1);
- chunk_endian=(ChunkSize>>24)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1);
- sprintf(ChunkName,"AMS!");
- FileWriteBinary(TMP_filename,ChunkName,4);
+
+ if (!ae->extendedCPR) {
+ ChunkSize=(maxrom+1)*(16384+8)+4;
+ chunk_endian=ChunkSize&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1);
+ chunk_endian=(ChunkSize>>8)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1);
+ chunk_endian=(ChunkSize>>16)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1);
+ chunk_endian=(ChunkSize>>24)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1);
+ sprintf(ChunkName,"AMS!");
+ FileWriteBinary(TMP_filename,ChunkName,4);
+ } else {
+ for (i=0;i<=maxrom;i+=32) {
+ char xproutputname[256];
+ sprintf(xproutputname,"xpr%02d.rom",i>>5);
+ FileRemoveIfExists(xproutputname);
+ }
+
+ ChunkSize=(maxrom+1)*(16384+8)+4+10;
+ chunk_endian=ChunkSize&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1);
+ chunk_endian=(ChunkSize>>8)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1);
+ chunk_endian=(ChunkSize>>16)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1);
+ chunk_endian=(ChunkSize>>24)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1);
+ sprintf(ChunkName,"CXME");
+ FileWriteBinary(TMP_filename,ChunkName,4);
+ ChunkName[0]='N';
+ ChunkName[1]='B';
+ ChunkName[2]='B';
+ ChunkName[3]='K';
+ FileWriteBinary(TMP_filename,ChunkName,4);
+ ChunkSize=2;
+ chunk_endian=ChunkSize&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1);
+ chunk_endian=(ChunkSize>>8)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1);
+ chunk_endian=(ChunkSize>>16)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1);
+ chunk_endian=(ChunkSize>>24)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1);
+ ChunkName[0]=0;
+ ChunkName[1]=32;
+ FileWriteBinary(TMP_filename,ChunkName,2);
+ }
// for (j=0;j<ae->io;j++) {
//printf("ORG[%03d]=B%02d/#%04X/#%04X\n",j,ae->orgzone[j].ibank,ae->orgzone[j].memstart,ae->orgzone[j].memend);
@@ -13407,24 +17877,31 @@ printf("output files\n");
if (ae->iwnamebank[i]>0) {
lm=strlen(ae->wl[ae->iwnamebank[i]].w)-2;
}
- rasm_printf(ae,KVERBOSE"WriteCPR bank %2d of %5d byte%s start at #%04X",i,endoffset-offset,endoffset-offset>1?"s":" ",offset);
+ if (ae->cprinfo) rasm_printf(ae,KVERBOSE"WriteCPR bank %2d of %5d byte%s start at #%04X",i,endoffset-offset,endoffset-offset>1?"s":" ",offset);
if (endoffset-offset>16384) {
- rasm_printf(ae,"\nROM is too big!!!\n");
+ rasm_printf(ae,"\nROM %d is too big!!!\n",i);
FileWriteBinaryClose(TMP_filename);
FileRemoveIfExists(TMP_filename);
FreeAssenv(ae);
exit(ABORT_ERROR);
}
- if (lm) {
- rasm_printf(ae," (%-*.*s)\n",lm,lm,ae->wl[ae->iwnamebank[i]].w+1);
- } else {
- rasm_printf(ae,"\n");
+ if (ae->cprinfo) {
+ if (lm) {
+ rasm_printf(ae," (%-*.*s)\n",lm,lm,ae->wl[ae->iwnamebank[i]].w+1);
+ } else {
+ rasm_printf(ae,"\n");
+ }
}
} else {
- rasm_printf(ae,KVERBOSE"WriteCPR bank %2d (empty)\n",i);
+ if (ae->cprinfo) rasm_printf(ae,KVERBOSE"WriteCPR bank %2d (empty)\n",i);
}
ChunkSize=16384;
- sprintf(ChunkName,"cb%02d",i);
+ if (ae->extendedCPR) {
+ ChunkName[0]='C';
+ ChunkName[1]='X';
+ ChunkName[2]=i>>8;
+ ChunkName[3]=i&255;
+ } else sprintf(ChunkName,"cb%02d",i);
FileWriteBinary(TMP_filename,ChunkName,4);
chunk_endian=ChunkSize&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1);
chunk_endian=(ChunkSize>>8)&0xFF;FileWriteBinary(TMP_filename,(char*)&chunk_endian,1);
@@ -13436,14 +17913,93 @@ printf("output files\n");
if (ChunkSize) FileWriteBinary(TMP_filename,(char*)ae->mem[i]+offset,ChunkSize);
/* ADD zeros until the end of the bank */
FileWriteBinary(TMP_filename,(char*)filler,16384-ChunkSize);
+ if (ae->xpr) {
+ char xproutputname[256];
+ sprintf(xproutputname,"xpr%02d.rom",i>>5);
+ if (ChunkSize) FileWriteBinary(xproutputname,(char*)ae->mem[i]+offset,ChunkSize);
+ FileWriteBinary(xproutputname,(char*)filler,16384-ChunkSize);
+ }
} else {
FileWriteBinary(TMP_filename,(char*)ae->mem[i]+offset,ChunkSize);
+ if (ae->xpr) {
+ char xproutputname[256];
+ sprintf(xproutputname,"xpr%02d.rom",i>>5);
+ FileWriteBinary(xproutputname,(char*)ae->mem[i]+offset,ChunkSize);
+ }
}
}
FileWriteBinaryClose(TMP_filename);
rasm_printf(ae,"Total %d bank%s (%dK)\n",maxrom+1,maxrom+1>1?"s":"",(maxrom+1)*16);
/*********************************************
**********************************************
+ R O M
+ **********************************************
+ *********************************************/
+ } else if (ae->forceROM) {
+ unsigned char filler[16384]={0};
+ int noflood=0;
+
+ /* how many ROM? */
+ for (i=maxrom=0;i<ae->io;i++) {
+ if (ae->orgzone[i].ibank<256 && ae->orgzone[i].ibank>maxrom) maxrom=ae->orgzone[i].ibank;
+ }
+
+ for (i=0;i<=maxrom;i++) {
+ /* number the file */
+ if (i==0 || !ae->forceROMconcat) {
+ if (ae->rom_name) {
+ sprintf(TMP_filename,"%s%d.rom",ae->rom_name,i);
+ } else {
+ sprintf(TMP_filename,"%s%d.rom",ae->outputfilename,i);
+ }
+ FileRemoveIfExists(TMP_filename);
+ }
+
+ offset=65536;
+ endoffset=0;
+ for (j=0;j<ae->io;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].memstart<offset) offset=ae->orgzone[j].memstart;
+ if (ae->orgzone[j].memend>endoffset) endoffset=ae->orgzone[j].memend;
+ }
+ }
+ if (endoffset>offset) {
+ /* cannot be bigger than 16K */
+ if (endoffset-offset>16384) {
+ rasm_printf(ae,"\nROM is too big!!!\n");
+ FileRemoveIfExists(TMP_filename);
+ FreeAssenv(ae);
+ exit(ABORT_ERROR);
+ }
+ /* to avoid ROM smaller than 16K at the end of working memory */
+ if (offset>49152) offset=49152;
+
+ if (i<4 || i+4>maxrom) rasm_printf(ae,KVERBOSE"WriteROM bank %3d of %5d byte%s start at #%04X\n",i,endoffset-offset,endoffset-offset>1?"s":" ",offset);
+ else if (!noflood) {rasm_printf(ae,KVERBOSE"[...]\n");noflood=1;}
+
+ FileWriteBinary(TMP_filename,(char *)(ae->mem[i]+offset),endoffset-offset);
+ if (endoffset-offset<16384) FileWriteBinary(TMP_filename,(char*)filler,16384-(endoffset-offset));
+ if (!ae->forceROMconcat) {
+ FileWriteBinaryClose(TMP_filename);
+ }
+ } else {
+ rasm_printf(ae,KVERBOSE"WriteROM bank %3d is empty\n",i);
+ /* with flat output we must fill with zeroes empty banks */
+ if (ae->forceROMconcat) {
+ FileWriteBinary(TMP_filename,(char*)filler,16384);
+ }
+ }
+ }
+ if (ae->forceROMconcat) {
+ FileWriteBinaryClose(TMP_filename);
+ }
+
+ rasm_printf(ae,"Total %d rom%s (%dK)\n",maxrom+1,maxrom+1>1?"s":"",(maxrom+1)*16);
+
+ /*********************************************
+ **********************************************
S N A P S H O T
**********************************************
*********************************************/
@@ -13488,22 +18044,27 @@ printf("output files\n");
unsigned char *rlebank=NULL;
char ChunkName[16];
int ChunkSize;
- int do_it=1;
int bankset;
int noflood=0;
- if (ae->snapshot.version==2 && ae->snapshot.CPCType>2) {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"[%s:%d] Warning: V2 snapshot cannot select a Plus model (forced to 6128)\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
- ae->snapshot.CPCType=2; /* 6128 */
- }
-
- if (ae->snapshot_name) {
- sprintf(TMP_filename,"%s",ae->snapshot_name);
- } else {
- sprintf(TMP_filename,"%s.sna",ae->outputfilename);
+ if (!ae->flux) {
+ if (ae->snapshot.version==2 && ae->snapshot.CPCType>2) {
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"[%s:%d] Warning: V2 snapshot cannot select a Plus model (forced to 6128)\n",GetCurrentFile(ae),ae->wl[ae->idx].l);
+ if (ae->erronwarn) MaxError(ae);
+ }
+ ae->snapshot.CPCType=2; /* 6128 */
+ }
+
+ if (ae->snapshot_name) {
+ sprintf(TMP_filename,"%s",ae->snapshot_name);
+ } else {
+ sprintf(TMP_filename,"%s.sna",ae->outputfilename);
+ }
+ FileRemoveIfExists(TMP_filename);
}
- FileRemoveIfExists(TMP_filename);
-
+
+ // we use part of SNAPSHOT code for emulator in-place output
maxrom=-1;
for (i=0;i<ae->io;i++) {
if (ae->orgzone[i].ibank<BANK_MAX_NUMBER && ae->orgzone[i].ibank>maxrom && ae->orgzone[i].memstart!=ae->orgzone[i].memend) {
@@ -13511,7 +18072,6 @@ printf("output files\n");
}
}
- //printf("maxrom=%d\n",maxrom);
/* construction du SNA */
if (ae->snapshot.version==2) {
if (maxrom>=4) {
@@ -13519,14 +18079,21 @@ printf("output files\n");
} else if (maxrom>=0) {
ae->snapshot.dumpsize[0]=64;
}
+ } else {
+ ae->snapshot.dumpsize[0]=0;
}
+
+ // enforce snapshot input size (if any) even we do not write everywhere in memory
+ if (ae->snapRAMsize-1>maxrom) maxrom=ae->snapRAMsize-1;
+
if (maxrom==-1) {
rasm_printf(ae,KWARNING"Warning: No byte were written in snapshot memory\n");
+ if (ae->erronwarn) MaxError(ae);
} else {
rasm_printf(ae,KIO"Write snapshot v%d file %s\n",ae->snapshot.version,TMP_filename);
/* header */
- FileWriteBinary(TMP_filename,(char *)&ae->snapshot,0x100);
+ if (!ae->flux) FileWriteBinary(TMP_filename,(char *)&ae->snapshot,0x100);
/* write all memory crunched */
for (i=0;i<=maxrom;i+=4) {
bankset=i>>2;
@@ -13549,10 +18116,12 @@ printf("output files\n");
}
if (endoffset-offset>16384) {
rasm_printf(ae,KERROR"\nBANK is too big!!!\n");
- FileWriteBinaryClose(TMP_filename);
- FileRemoveIfExists(TMP_filename);
- FreeAssenv(ae);
- exit(ABORT_ERROR);
+ if (!ae->flux) {
+ FileWriteBinaryClose(TMP_filename);
+ FileRemoveIfExists(TMP_filename);
+ FreeAssenv(ae);
+ exit(ABORT_ERROR);
+ } //@@TODO renvoyer erreur quand meme?
}
/* banks are gathered in the 64K block */
if (offset>0xC000) {
@@ -13571,10 +18140,12 @@ printf("output files\n");
else if (!noflood) {rasm_printf(ae,KVERBOSE"[...]\n");noflood=1;}
if (endoffset-offset>16384) {
rasm_printf(ae,KERROR"\nRAM block is too big!!!\n");
- FileWriteBinaryClose(TMP_filename);
- FileRemoveIfExists(TMP_filename);
- FreeAssenv(ae);
- exit(ABORT_ERROR);
+ if (!ae->flux) {
+ FileWriteBinaryClose(TMP_filename);
+ FileRemoveIfExists(TMP_filename);
+ FreeAssenv(ae);
+ exit(ABORT_ERROR);
+ } // @@TODO aussi
}
if (lm) {
if (i<4 || i+4>maxrom) rasm_printf(ae,KVERBOSE" (%-*.*s)\n",lm,lm,ae->wl[ae->iwnamebank[i+k]].w+1);
@@ -13590,7 +18161,7 @@ printf("output files\n");
if (ae->snapshot.version==2) {
/* snapshot v2 */
- FileWriteBinary(TMP_filename,(char*)&packed,65536);
+ if (!ae->flux) FileWriteBinary(TMP_filename,(char*)&packed,65536);
if (bankset) {
/* v2 snapshot is 128K maximum */
maxrom=7;
@@ -13609,14 +18180,16 @@ printf("output files\n");
MakeError(ae,"(core)",0,"internal error during snapshot write, please report (%d)\n",bankset);
}
- FileWriteBinary(TMP_filename,ChunkName,4);
- if (rlebank!=NULL) {
+ if (!ae->flux) {
+ FileWriteBinary(TMP_filename,ChunkName,4);
FileWriteBinary(TMP_filename,(char*)&ChunkSize,4);
- FileWriteBinary(TMP_filename,(char*)rlebank,ChunkSize);
- MemFree(rlebank);
- } else {
- ChunkSize=65536;
- FileWriteBinary(TMP_filename,(char*)&packed,ChunkSize);
+ if (rlebank!=NULL) {
+ FileWriteBinary(TMP_filename,(char*)rlebank,ChunkSize);
+ MemFree(rlebank);
+ } else {
+ // write unpacked data
+ FileWriteBinary(TMP_filename,(char*)&packed,ChunkSize);
+ }
}
}
}
@@ -13624,12 +18197,12 @@ printf("output files\n");
/**************************************************************
snapshot additional chunks in v3+ only
**************************************************************/
- if (ae->snapshot.version>=3) {
+ if (!ae->flux && ae->snapshot.version>=3) {
/* export breakpoint */
if (ae->export_snabrk) {
/* BRKS chunk for Winape emulator (unofficial)
- 2 bytes - adress
+ 2 bytes - address
1 byte - 0=base 64K / 1=extended
2 bytes - condition (zeroed)
*/
@@ -13640,13 +18213,13 @@ printf("output files\n");
/* add labels and local labels to breakpoint pool (if any) */
for (i=0;i<ae->il;i++) {
if (!ae->label[i].name) {
- if (strncmp(ae->wl[ae->label[i].iw].w,"BRK",3)==0) {
+ if (strncmp(ae->wl[ae->label[i].iw].w,"BRK",3)==0 || strncmp(ae->wl[ae->label[i].iw].w,"@BRK",4)==0 || strstr(ae->wl[ae->label[i].iw].w,".BRK")!=NULL) {
breakpoint.address=ae->label[i].ptr;
if (ae->label[i].ibank>3) breakpoint.bank=1; else breakpoint.bank=0;
ObjectArrayAddDynamicValueConcat((void **)&ae->breakpoint,&ae->ibreakpoint,&ae->maxbreakpoint,&breakpoint,sizeof(struct s_breakpoint));
}
} else {
- if (strncmp(ae->label[i].name,"@BRK",4)==0 || strstr(ae->label[i].name,".BRK")) {
+ if (strncmp(ae->label[i].name,"BRK",3)==0 || 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));
@@ -13709,7 +18282,7 @@ printf("output files\n");
1 byte - name size
n bytes - name (without 0 to end the string)
6 bytes - reserved for future use
- 2 bytes - shitty big endian adress for the symbol
+ 2 bytes - shitty big endian address for the symbol
*/
unsigned char *symbchunk=NULL;
@@ -13782,14 +18355,20 @@ printf("output files\n");
}
} else {
if (ae->export_snabrk) {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"Warning: breakpoint export is not supported with snapshot version 2\n");
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"Warning: breakpoint export is not supported with snapshot version 2\n");
+ if (ae->erronwarn) MaxError(ae);
+ }
}
if (ae->export_sna) {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"Warning: symbol export is not supported with snapshot version 2\n");
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"Warning: symbol export is not supported with snapshot version 2\n");
+ if (ae->erronwarn) MaxError(ae);
+ }
}
}
- FileWriteBinaryClose(TMP_filename);
+ if (!ae->flux) FileWriteBinaryClose(TMP_filename);
maxrom=(maxrom>>2)*4+4;
rasm_printf(ae,KAYGREEN"Total %d bank%s (%dK)\n",maxrom,maxrom>1?"s":"",(maxrom)*16);
}
@@ -13828,30 +18407,128 @@ printf("output files\n");
}
if (maxmem-minmem<=0) {
if (!ae->stop) {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"Warning: Not a single byte to output\n");
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"Warning: Not a single byte to output\n");
+ if (ae->erronwarn) MaxError(ae);
+ }
}
if (ae->flux) {
*lenout=0;
}
} else {
if (!ae->flux) {
- rasm_printf(ae,KIO"Write binary file %s (%d byte%s)\n",TMP_filename,maxmem-minmem,maxmem-minmem>1?"s":"");
- if (ae->amsdos) {
- AmsdosHeader=MakeAMSDOSHeader(minmem,minmem,maxmem,TMP_filename); //@@TODO
- FileWriteBinary(TMP_filename,(char *)AmsdosHeader,128);
- }
- if (maxmem-minmem>0) {
- FileWriteBinary(TMP_filename,(char*)ae->mem[lastspaceid]+minmem,maxmem-minmem);
- FileWriteBinaryClose(TMP_filename);
+ /***************************************************************
+ * T A P E o u t p u t *
+ ***************************************************************/
+ if (ae->forcetape) {
+ int run;
+ if (ae->tape_name) {
+ sprintf(TMP_filename,"%s",ae->tape_name);
+ } else {
+ sprintf(TMP_filename,"%s.cdt",ae->outputfilename);
+ }
+ run=ae->snapshot.registers.LPC+(ae->snapshot.registers.HPC<<8);
+ if (run<0x100) run=minmem;
+ __output_CDT(ae,TMP_filename,"TAPE.BIN",(char*)ae->mem[lastspaceid]+minmem,maxmem-minmem,minmem,run);
} else {
- if (ae->amsdos) {
+ /***************************************************************
+ * O B J o u t p u t *
+ ***************************************************************/
+ if (ae->buildobj) {
+ struct s_label *curlabel;
+ char objtmp[1024];
+ int iex,jex;
+
+ sprintf(TMP_filename,"%s.obj",ae->outputfilename);
+ FileRemoveIfExists(TMP_filename);
+ rasm_printf(ae,KIO"Write OBJ file %s\n",TMP_filename,maxmem-minmem);
+
+ for (i=0;i<ae->nprocedurename;i++) {
+ curlabel=SearchLabel(ae,ae->procedurename[i],GetCRC(ae->procedurename[i]));
+ if (!curlabel) {
+ rasm_printf(ae,KERROR" INTERNAL ERROR: procedure [%s] not found in label pool\n");
+ MaxError(ae);
+ } else {
+ strcpy(objtmp,"PROCEDURE ");
+ FileWriteBinary(TMP_filename,(char *)objtmp,strlen(objtmp));
+ FileWriteBinary(TMP_filename,(char *)ae->procedurename[i],strlen(ae->procedurename[i]));
+ sprintf(objtmp," 0x%04X\n",curlabel->ptr);
+ FileWriteBinary(TMP_filename,(char *)objtmp,strlen(objtmp));
+ }
+ }
+ for (i=0;i<ae->nexternal;i++) {
+ for (j=0;j<ae->external[i].nmapping;j++) {
+ strcpy(objtmp,"EXTERNAL ");
+ FileWriteBinary(TMP_filename,(char *)objtmp,strlen(objtmp));
+ FileWriteBinary(TMP_filename,(char *)ae->external[i].name,strlen(ae->external[i].name));
+ sprintf(objtmp," 0x%04X %d\n",ae->external[i].mapping[j].ptr,ae->external[i].mapping[j].size);
+ FileWriteBinary(TMP_filename,(char *)objtmp,strlen(objtmp));
+ }
+ }
+ for (i=0;i<ae->nrelocation;i++) {
+ if (ae->relocation[i].value>=minmem && ae->relocation[i].value<maxmem) {
+ sprintf(objtmp,"RELOCATION 0x%04X\n",ae->relocation[i].ptr);
+ FileWriteBinary(TMP_filename,(char *)objtmp,strlen(objtmp));
+ }
+ }
+ for (i=0;i<ae->nrelocation;i++) {
+ if (ae->relocation[i].value>=minmem && ae->relocation[i].value<maxmem) {
+ } else {
+ sprintf(objtmp,"LONGJUMP 0x%04X ; CALL or JP outside scope\n",ae->relocation[i].ptr);
+ FileWriteBinary(TMP_filename,(char *)objtmp,strlen(objtmp));
+ }
+ }
+ sprintf(objtmp,"DATA START=0x%04X LEN=0x%04X\n",minmem,maxmem-minmem);
+ FileWriteBinary(TMP_filename,(char *)objtmp,strlen(objtmp));
+ j=0;
+ for (i=minmem;i<maxmem;i++) {
+ if (!j) {
+ strcpy(objtmp,"BYTE ");
+ } else {
+ strcpy(objtmp,",");
+ }
+ FileWriteBinary(TMP_filename,(char *)objtmp,strlen(objtmp));
+ /* data */
+ sprintf(objtmp,"0x%02X",ae->mem[lastspaceid][i]);
+ FileWriteBinary(TMP_filename,(char *)objtmp,strlen(objtmp));
+ j++;
+ if (j==16) {
+ strcpy(objtmp,"\n");
+ FileWriteBinary(TMP_filename,(char *)objtmp,strlen(objtmp));
+ j=0;
+ }
+ }
+ strcpy(objtmp,"\n");
+ FileWriteBinary(TMP_filename,(char *)objtmp,strlen(objtmp));
FileWriteBinaryClose(TMP_filename);
+ } else {
+ /***************************************************************
+ * F I L E o u t p u t *
+ ***************************************************************/
+ rasm_printf(ae,KIO"Write binary file %s (%d byte%s)",TMP_filename,maxmem-minmem,maxmem-minmem>1?"s":"");
+ if (ae->amsdos) {
+ AmsdosHeader=MakeAMSDOSHeader(minmem,minmem,maxmem,TMP_filename); //@@TODO
+ FileWriteBinary(TMP_filename,(char *)AmsdosHeader,128);
+ rasm_printf(ae," (automatic Amsdos header)\n");
+ } else {
+ rasm_printf(ae,"\n");
+ }
+ if (maxmem-minmem>0) {
+ FileWriteBinary(TMP_filename,(char*)ae->mem[lastspaceid]+minmem,maxmem-minmem);
+ FileWriteBinaryClose(TMP_filename);
+ } else {
+ if (ae->amsdos) {
+ FileWriteBinaryClose(TMP_filename);
+ }
+ }
}
}
} else {
- *dataout=MemMalloc(maxmem-minmem+1);
- memcpy(*dataout,ae->mem[lastspaceid]+minmem,maxmem-minmem);
- *lenout=maxmem-minmem;
+ if (dataout) {
+ *dataout=MemMalloc(maxmem-minmem+1);
+ memcpy(*dataout,ae->mem[lastspaceid]+minmem,maxmem-minmem);
+ *lenout=maxmem-minmem;
+ }
}
}
}
@@ -13866,6 +18543,7 @@ printf("output files\n");
if (strcmp(ae->alias[i].alias,"IX") && strcmp(ae->alias[i].alias,"IY")) {
if (!ae->alias[i].used) {
rasm_printf(ae,KWARNING"[%s:%d] Warning: alias %s declared but not used\n",ae->filename[ae->wl[ae->alias[i].iw].ifile],ae->wl[ae->alias[i].iw].l,ae->alias[i].alias);
+ if (ae->erronwarn) MaxError(ae);
}
}
}
@@ -13901,7 +18579,74 @@ printf("output files\n");
} else {
rasm_printf(ae,KIO"Write symbol file %s\n",TMP_filename);
}
-
+
+ /****************************
+ case export hack
+ ****************************/
+ if (ae->enforce_symbol_case) {
+ char *casefound;
+ int ilocal=0;
+
+ for (i=0;i<ae->il;i++) {
+ if (ae->label[i].autorise_export) {
+ if (!ae->label[i].name) {
+ if ((casefound=_internal_stristr(ae->rawfile[ae->label[i].fileidx],ae->rawlen[ae->label[i].fileidx],ae->wl[ae->label[i].iw].w))!=NULL) {
+ memcpy(ae->wl[ae->label[i].iw].w,casefound,strlen(ae->wl[ae->label[i].iw].w));
+ }
+ } else if (ae->export_local || !ae->label[i].local) {
+ char splitlabel[256];
+ char casecharbackup;
+ int caseidx;
+ int istart,iend,ilen,isplit,icopy;
+
+ ilen=strlen(ae->label[i].name);
+
+ if (ae->label[i].name[0]=='@') {
+ // remove radix
+ while (ae->label[i].name[ilen]!='R') ilen--;
+ ae->label[i].name[ilen]=0;
+ }
+
+ iend=0;
+ do {
+ istart=iend;
+ while (!AutomateCharStop[ae->label[i].name[istart]]) istart++;
+ if (istart>=ilen) break;
+
+ iend=istart;
+ while (AutomateChar[ae->label[i].name[iend]]) iend++;
+
+ isplit=0;
+ icopy=istart;
+ while (icopy<iend && isplit<255) splitlabel[isplit++]=ae->label[i].name[icopy++];
+ splitlabel[isplit]=0;
+
+ if (isplit>1) {
+ casefound=_internal_stristr(ae->rawfile[ae->label[i].fileidx],ae->rawlen[ae->label[i].fileidx],splitlabel);
+ if (casefound) {
+ memcpy(ae->label[i].name+istart,casefound,isplit);
+ }
+ }
+ } while (istart<ilen && iend<ilen);
+
+ if (ae->label[i].name[0]=='@') {
+ // put simplified radix back
+ ae->label[i].name[ilen]='_';
+ sprintf(ae->label[i].name+ilen+1,"%x",ilocal++);
+ }
+ }
+ }
+ }
+ // translate alias only if there are exported
+ if (ae->export_equ) {
+ for (i=0;i<ae->ialias;i++) {
+ if ((casefound=_internal_stristr(ae->rawfile[ae->wl[ae->alias[i].iw].ifile],ae->rawlen[ae->wl[ae->alias[i].iw].ifile],ae->alias[i].alias))!=NULL) {
+ memcpy(ae->alias[i].alias,casefound,strlen(ae->alias[i].alias));
+ }
+ }
+ }
+ }
+
switch (ae->export_sym) {
case 5:
/* ZX export */
@@ -13980,7 +18725,7 @@ printf("output files\n");
FileWriteLineClose(TMP_filename);
break;
case 3:
- /* winape */
+ /* Winape */
for (i=0;i<ae->il;i++) {
if (ae->label[i].autorise_export) {
if (ae->export_multisym) {
@@ -14068,7 +18813,7 @@ printf("output files\n");
sprintf(symbol_line,"%s #%X B%d\n",ae->wl[ae->label[i].iw].w,ae->label[i].ptr,ae->label[i].ibank>31?0:ae->label[i].ibank);
FileWriteLine(TMP_filename,symbol_line);
} else {
- if (ae->export_local) {
+ if (ae->export_local || !ae->label[i].local) {
sprintf(symbol_line,"%s #%X B%d\n",ae->label[i].name,ae->label[i].ptr,ae->label[i].ibank>31?0:ae->label[i].ibank);
FileWriteLine(TMP_filename,symbol_line);
}
@@ -14113,13 +18858,13 @@ printf("output files\n");
/* add labels and local labels to breakpoint pool (if any) */
for (i=0;i<ae->il;i++) {
if (!ae->label[i].name) {
- if (strncmp(ae->wl[ae->label[i].iw].w,"BRK",3)==0) {
+ if (strncmp(ae->wl[ae->label[i].iw].w,"BRK",3)==0 || strncmp(ae->wl[ae->label[i].iw].w,"@BRK",4)==0 || strstr(ae->wl[ae->label[i].iw].w,".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));
}
} else {
- if (strncmp(ae->label[i].name,"@BRK",4)==0) {
+ if (strncmp(ae->label[i].name,"BRK",3)==0 || 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));
@@ -14135,8 +18880,26 @@ printf("output files\n");
}
FileWriteLineClose(TMP_filename);
} else {
- if (!ae->nowarning) rasm_printf(ae,KWARNING"Warning: no breakpoint to output (previous file [%s] deleted anyway)\n",TMP_filename);
+ if (!ae->nowarning) {
+ rasm_printf(ae,KWARNING"Warning: no breakpoint to output\n",TMP_filename);
+ if (ae->erronwarn) MaxError(ae);
+ /* empty file */
+ FileTruncate(TMP_filename);
+ }
+ }
+ }
+ /*********************************
+ **********************************
+ DEBUG INFO
+ **********************************
+ *********************************/
+ if (ae->retdebug) {
+ if (ae->rundefined) {
+ ae->debug.run=ae->snapshot.registers.LPC+(ae->snapshot.registers.HPC<<8);
+ } else {
+ ae->debug.run=-1;
}
+ ae->debug.start=minmem;
}
} else {
@@ -14175,7 +18938,8 @@ printf("dependencies\n");
/*******************************************************************************************
V E R B O S E S H I T
*******************************************************************************************/
-#if TRACE_ASSEMBLE
+ if (ae->display_stats) {
+ int parsed_size=0;
rasm_printf(ae,KVERBOSE"------ statistics ------------------\n");
rasm_printf(ae,KVERBOSE"%d file%s\n",ae->ifile,ae->ifile>1?"s":"");
rasm_printf(ae,KVERBOSE"%d binary include%s\n",ae->ih,ae->ih>1?"s":"");
@@ -14188,8 +18952,10 @@ printf("dependencies\n");
rasm_printf(ae,KVERBOSE"%d alias%s\n",ae->ialias,ae->ialias>1?"s":"");
rasm_printf(ae,KVERBOSE"%d ORG zone%s\n",ae->io-1,ae->io>2?"s":"");
rasm_printf(ae,KVERBOSE"%d virtual space%s\n",ae->nbbank,ae->nbbank>1?"s":"");
-#endif
-
+ rasm_printf(ae,KVERBOSE"\n");
+ for (i=0;i<ae->nbword;i++) parsed_size+=strlen(ae->wl[i].w);
+ rasm_printf(ae,KVERBOSE"%d byte%s of pure code\n",parsed_size,parsed_size>1?"s":"");
+ }
/*******************************************************************************************
C L E A N U P
*******************************************************************************************/
@@ -14211,9 +18977,34 @@ printf("-cleanup\n");
ok=0;
}
+ /*********************************************************************
+ *
+ * assembling into emulator memory
+ *
+ * ******************************************************************/
+ /* get back memory if requested */
+ if (ae->retdebug && ae->debug.emuram && ae->debug.lenram) {
+ int ramidx,ramend,maxbank;
+
+ maxbank=ae->debug.lenram>>14;
+ ramidx=0;
+ for (i=0;i<maxbank;i+=4) {
+ if (ae->bankset[i>>2]) {
+ if (ramidx+65536<=ae->debug.lenram) ramend=65536; else ramend=ae->debug.lenram-ramidx;
+ for (j=0;j<ramend;j++) {
+ ae->debug.emuram[ramidx++]=ae->mem[i][j];
+ }
+ } else {
+ printf("@@@ simple banking unsupported => todo\n");
+ /* unsupported now => @@TODO */
+ }
+ }
+ }
+
FreeAssenv(ae);
#if TRACE_ASSEMBLE
printf("end of assembling\n");
+printf("-end ok=%d\n",ok);
#endif
#if TRACE_GENERALE
printf("-end ok=%d\n",ok);
@@ -14235,70 +19026,97 @@ void EarlyPrepSrc(struct s_assenv *ae, char **listing, char *filename) {
l++;
idx=0;
continue;
- } else if (!quote_type) {
- /* upper case */
- if (c>='a' && c<='z') {
- listing[l][idx-1]=c=c-'a'+'A';
- }
+ } else {
+ if (!quote_type) {
- if (c=='\'' && idx>2 && strncmp(&listing[l][idx-3],"AF'",3)==0) {
- /* il ne faut rien faire */
- } else if (c=='"' || c=='\'') {
- quote_type=c;
- } else if (c==';' || (c=='/' && listing[l][idx]=='/')) {
- idx--;
- while (listing[l][idx] && listing[l][idx]!=0x0D && listing[l][idx]!=0x0A) listing[l][idx++]=':';
- idx--;
- } else if (c=='>' && listing[l][idx]=='>' && !quote_type) {
- listing[l][idx-1]=']';
- listing[l][idx++]=' ';
- continue;
- } else if (c=='<' && listing[l][idx]=='<' && !quote_type) {
- listing[l][idx-1]='[';
- listing[l][idx++]=' ';
- continue;
- } else if (c=='/' && listing[l][idx]=='*' && !quote_type) {
- /* multi-line comment */
- mlc_start=l;
- mlc_idx=idx-1;
- idx++;
- while (1) {
- c=listing[l][idx++];
- if (!c) {
- idx=0;
- l++;
- if (!listing[l]) {
- MakeError(ae,GetCurrentFile(ae),ae->wl[ae->idx].l,"opened comment to the end of the file\n",filename,l+1);
- return;
+ /* upper case */
+ if (c>='a' && c<='z') {
+ listing[l][idx-1]=c=c-'a'+'A';
+ }
+
+ if (c=='\'') {
+ if (idx>2 && strncmp(&listing[l][idx-3],"AF'",3)==0) {
+ /* il ne faut rien faire */
+ } else {
+ quote_type=c;
+ }
+ } else if (c=='"') {
+ quote_type=c;
+ } else if (c==';' || (c=='/' && listing[l][idx]=='/')) {
+ idx--;
+ while (listing[l][idx] && listing[l][idx]!=0x0D && listing[l][idx]!=0x0A) listing[l][idx++]=':';
+ idx--;
+ } else if (c=='>' && listing[l][idx]=='>' && !quote_type) {
+ listing[l][idx-1]=']';
+ listing[l][idx++]=' ';
+ continue;
+ } else if (c=='<' && listing[l][idx]=='<' && !quote_type) {
+ listing[l][idx-1]='[';
+ listing[l][idx++]=' ';
+ continue;
+ } else if (c=='/' && listing[l][idx]=='*' && !quote_type) {
+ /* multi-line comment */
+ mlc_start=l;
+ mlc_idx=idx-1;
+ idx++;
+ while (1) {
+ c=listing[l][idx++];
+ if (!c) {
+ idx=0;
+ l++;
+ if (!listing[l]) {
+ MakeError(ae,filename,l+1,"opened comment to the end of the file\n");
+ return;
+ }
+ } else if (c=='*' && listing[l][idx]=='/') {
+ idx++;
+ break;
}
- } else if (c=='*' && listing[l][idx]=='/') {
- idx++;
- break;
+ }
+ /* merge */
+ if (mlc_start==l) {
+ /* on the same line */
+ while (mlc_idx<idx) listing[l][mlc_idx++]=' '; /* raz with spaces */
+ } else {
+ /* multi-line */
+ listing[mlc_start][mlc_idx]=0; /* raz EOL */
+ mlc_start++;
+ while (mlc_start<l) listing[mlc_start++][0]=0; /* raz line */
+ mlc_idx=0;
+ while (mlc_idx<idx) listing[l][mlc_idx++]=' '; /* raz beginning of the line */
}
}
- /* merge */
- if (mlc_start==l) {
- /* on the same line */
- while (mlc_idx<idx) listing[l][mlc_idx++]=' '; /* raz with spaces */
- } else {
- /* multi-line */
- listing[mlc_start][mlc_idx]=0; /* raz EOL */
- mlc_start++;
- while (mlc_start<l) listing[mlc_start++][0]=0; /* raz line */
- mlc_idx=0;
- while (mlc_idx<idx) listing[l][mlc_idx++]=' '; /* raz beginning of the line */
+ } else {
+ /* in quote */
+ if (c=='\\') {
+ if (listing[l][idx]) {
+ idx++;
+ }
+ } else if (c==quote_type) {
+ quote_type=0;
}
}
- } else {
- /* in quote */
- if (c=='\\') {
- if (listing[l][idx]) {
- idx++;
- }
- } else if (c==quote_type) {
- quote_type=0;
+ }
+ }
+ l-=2;
+ if (l>0)
+ while (l>=0) {
+ /* patch merge line with '\' only outside quotes */
+ idx=strlen(listing[l])-1;
+
+ if (idx>0) {
+ while (idx && (listing[l][idx]==' ' || listing[l][idx]==0x0D || listing[l][idx]==0x0A || listing[l][idx]==0x0B)) {
+ idx--;
+ }
+
+ if (listing[l][idx]=='\\') {
+ /* fusion avec la ligne suivante qui est obligatoirement présente */
+ listing[l]=MemRealloc(listing[l],strlen(listing[l])+strlen(listing[l+1])+1);
+ strcpy(listing[l]+idx,listing[l+1]);
+ strcpy(listing[l+1],"");
}
}
+ l--;
}
}
@@ -14380,9 +19198,9 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int
char **listing_include=NULL;
int i,j,l=0,idx=0,c=0,li,le;
char Automate[256]={0};
+ char AutomatePrepro[256]={0};
struct s_hexbin curhexbin;
char *newlistingline=NULL;
- unsigned char *newdata;
struct s_label curlabel={0};
char *labelsep1;
char **labelines=NULL;
@@ -14401,7 +19219,7 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int
int nri=0,mri=0,ri=0;
int nwi=0,mwi=0,wi=0;
/* state machine trigger */
- int waiting_quote=0,lquote;
+ int waiting_quote=0,lquote=0;
int macro_trigger=0;
int escape_code=0;
int quote_type=0;
@@ -14410,6 +19228,12 @@ struct s_assenv *PreProcessing(char *filename, int flux, const char *datain, int
int nbinstruction;
int ifast,texpr;
int ispace=0;
+ char opassign=0;
+ /* incbin bug */
+ int incstartL=0;
+ char *original_filename=NULL;
+
+
#if TRACE_GENERALE
printf("*** preprocessing ***\n");
@@ -14425,14 +19249,12 @@ printf("start prepro, alloc assenv\n");
rindex.cidx=-1;
#if TRACE_PREPRO
-printf("malloc\n");
+printf("malloc+memset\n");
#endif
ae=MemMalloc(sizeof(struct s_assenv));
-#if TRACE_PREPRO
-printf("memset\n");
-#endif
memset(ae,0,sizeof(struct s_assenv));
+ ae->module_separator[0]='_';
#if TRACE_PREPRO
printf("paramz 1\n");
#endif
@@ -14448,9 +19270,11 @@ printf("paramz 1\n");
}
ae->export_brk=param->export_brk;
ae->warn_unused=param->warn_unused;
+ ae->display_stats=param->display_stats;
ae->edskoverwrite=param->edskoverwrite;
ae->rough=param->rough;
ae->as80=param->as80;
+ ae->pasmo=param->pasmo;
ae->dams=param->dams;
ae->macrovoid=param->macrovoid;
if (param->v2) {
@@ -14459,16 +19283,28 @@ printf("paramz 1\n");
} else {
ae->snapshot.version=3;
}
+ ae->xpr=param->xpr;
+ ae->cprinfo=param->cprinfo;
+ ae->cprinfo_export=param->cprinfoexport;
+ ae->cprinfo_filename=param->cprinfo_name;
ae->maxerr=param->maxerr;
ae->extended_error=param->extended_error;
ae->nowarning=param->nowarning;
+ ae->erronwarn=param->erronwarn;
+ ae->utf8enable=param->utf8enable;
+ ae->freequote=param->freequote;
ae->breakpoint_name=param->breakpoint_name;
ae->symbol_name=param->symbol_name;
ae->binary_name=param->binary_name;
ae->flexible_export=param->flexible_export;
ae->cartridge_name=param->cartridge_name;
ae->snapshot_name=param->snapshot_name;
+ ae->tape_name=param->tape_name;
+ ae->rom_name=param->rom_name;
ae->checkmode=param->checkmode;
+ ae->noampersand=param->noampersand;
+ ae->module_separator[0]=param->module_separator;
+ ae->enforce_symbol_case=param->enforce_symbol_case;
if (param->rough) ae->maxam=0; else ae->maxam=1;
/* additional symbols */
for (i=0;i<param->nsymb;i++) {
@@ -14476,7 +19312,7 @@ printf("paramz 1\n");
sep=strchr(param->symboldef[i],'=');
if (sep) {
*sep=0;
- ExpressionSetDicoVar(ae,param->symboldef[i],atof(sep+1));
+ ExpressionSetDicoVar(ae,param->symboldef[i],atof(sep+1),0); // not external as default
}
}
if (param->msymb) {
@@ -14491,7 +19327,7 @@ printf("paramz 1\n");
ae->dependencies=param->dependencies;
}
#if TRACE_PREPRO
-printf("init 0\n");
+printf("init 0 amper=%d\n",ae->noampersand);
#endif
#if TRACE_GENERALE
printf("-init\n");
@@ -14546,7 +19382,7 @@ printf("-init\n");
ae->snapshot.CPCType=2; /* 6128 */
ae->snapshot.crtcstate.model=0; /* CRTC 0 */
ae->snapshot.vsyncdelay=2;
- strcpy((char *)ae->snapshot.unused6+3+0x20+8,RASM_VERSION);
+ strncpy((char *)ae->snapshot.unused6+3+0x20,RASM_VERSION,sizeof(ae->snapshot.unused6)-1-(3+0x20));
/* CRTC default registers */
ae->snapshot.crtc.registervalue[0]=0x3F;
ae->snapshot.crtc.registervalue[1]=40;
@@ -14563,8 +19399,11 @@ printf("-init\n");
/* standard stack */
ae->snapshot.registers.HSP=0xC0;
+ ae->repeat_start=1;
+ ae->repeat_increment=1;
+
/*
- winape sprintf(symbol_line,"%s #%4X\n",ae->label[i].name,ae->label[i].ptr);
+ Winape sprintf(symbol_line,"%s #%4X\n",ae->label[i].name,ae->label[i].ptr);
pasmo sprintf(symbol_line,"%s EQU 0%4XH\n",ae->label[i].name,ae->label[i].ptr);
rasm sprintf(symbol_line,"%s #%X B%d\n",ae->wl[ae->label[i].iw].w,ae->label[i].ptr,ae->label[i].ibank>31?0:ae->label[i].ibank);
*/
@@ -14576,11 +19415,23 @@ printf("paramz\n");
rasm_printf(ae,"Label import from [%s]\n",param->labelfilename[j]);
ae->label_filename=param->labelfilename[j];
ae->label_line=1;
- labelines=FileReadLines(param->labelfilename[j]);
+ labelines=FileReadLines(ae,param->labelfilename[j]);
+
+ curlabel.fileidx=ae->ifile;
+ FieldArrayAddDynamicValueConcat(&ae->filename,&ae->ifile,&ae->maxfile,filename); // besoin de la casse
+
+ if (ae->enforce_symbol_case) {
+ ae->rawfile=MemRealloc(ae->rawfile,sizeof(char **)*ae->ifile);
+ ae->rawlen=MemRealloc(ae->rawlen,sizeof(int)*ae->ifile);
+ ae->rawfile[ae->ifile-1]=ae->source_bigbuffer;
+ ae->rawlen[ae->ifile-1]=ae->source_bigbuffer_len;
+ }
+
i=0;
while (labelines[i]) {
+ int k;
/* upper case */
- for (j=0;labelines[i][j];j++) labelines[i][j]=toupper(labelines[i][j]);
+ for (k=0;labelines[i][k];k++) labelines[i][k]=toupper(labelines[i][k]);
if ((labelsep1=strstr(labelines[i],": EQU 0"))!=NULL) {
/* sjasm */
@@ -14600,7 +19451,7 @@ printf("paramz\n");
//ObjectArrayAddDynamicValueConcat((void **)&ae->label,&ae->il,&ae->ml,&curlabel,sizeof(curlabel));
PushLabelLight(ae,&curlabel);
} else if ((labelsep1=strstr(labelines[i]," "))!=NULL) {
- /* winape / rasm */
+ /* Winape / rasm */
if (*(labelsep1+1)=='#') {
*labelsep1=0;
curlabel.name=labelines[i];
@@ -14654,28 +19505,75 @@ printf("nbbank=%d initialised\n",ae->nbbank);
}
/* si on est en ligne de commande ET que le fichier n'est pas trouvé */
if (param && param->filename && !FileExists(param->filename)) {
- char *LTryExtension[]={".asm",".z80",".o",".dam",".mxm",".txt",
- ".ASM",".Z80",".O",".DAM",".MXM",".TXT",NULL};
+ char *LTryExtension[]={".asm",".z80",".inc",".src",".dam",".mxm",".txt",
+ ".ASM",".Z80",".INC",".SRC",".DAM",".MXM",".TXT",".o",".s",".O",".S","",NULL};
int iguess=1;
+#if TRACE_PREPRO
+ printf("TRY EXT\n");
+#endif
+ original_filename=TxtStrDup(param->filename);
l=strlen(param->filename);
- filename=MemRealloc(param->filename,l+6);
- /* si le nom du fichier termine par un . on n'ajoute que l'extension, sinon on l'ajoute avec le . */
- if (param->filename[l-1]=='.') strcat(param->filename,"asm"); else strcat(param->filename,".asm");
+ param->filename=MemRealloc(param->filename,l+6);
+ /* add fake filetype without dot if not present but a dot */
+ if (param->filename[l-1]=='.') {
+ strcat(param->filename,"asm");
+ } else {
+ /* if no filetype at all and no dot, add it */
+ int eidx=l-1;
+
+ while (eidx) {
+ if (param->filename[eidx]=='.') {
+ param->filename[eidx]=0;
+ break;
+ } else if (param->filename[eidx]=='/' || param->filename[eidx]=='\\') {
+ break;
+ } else {
+ eidx--;
+ }
+ }
+ strcat(param->filename,".asm");
+ }
while (!FileExists(param->filename) && LTryExtension[iguess]!=NULL) {
- TxtReplace(param->filename,LTryExtension[iguess-1],LTryExtension[iguess],0); /* no realloc with this */
+ /* no realloc with this BECAUSE every replace is equal or smaller than the previous one */
+ TxtReplace(param->filename,LTryExtension[iguess-1],LTryExtension[iguess],0);
+#if TRACE_PREPRO
+ printf("TRY [%s]\n",param->filename);
+#endif
if (!FileExists(param->filename)) {
param->filename[l]=0;
}
iguess++;
}
+ filename=param->filename;
}
if (param && param->filename && !FileExists(param->filename)) {
- rasm_printf(ae,"Cannot find file [%s]\n",param->filename);
- exit(-1802);
+ char *filename_toread;
+ int fileok=0,ilookfile;
+#if TRACE_PREPRO
+ printf("TRY %d include path(s)\n",ae->ipath);
+#endif
+ /* search the very first file into include paths */
+ for (ilookfile=0;ilookfile<ae->ipath && !fileok;ilookfile++) {
+ filename_toread=MergePath(ae,ae->includepath[ilookfile],original_filename);
+#if TRACE_PREPRO
+ printf("TRY [%s]\n",filename_toread);
+#endif
+ if (FileExists(filename_toread)) {
+ fileok=1;
+ }
+ }
+ if (fileok) {
+ filename=TxtStrDup(filename_toread); // overwrite original filename
+ } else {
+ // we tried, we tried, but hey, nothing found!
+ rasm_printf(ae,"Cannot find file [%s]\n",param->filename);
+ exit(-1802);
+ }
}
+ if (original_filename) MemFree(original_filename);
if (param) rasm_printf(ae,KAYGREEN"Pre-processing [%s]\n",param->filename);
for (nbinstruction=0;instruction[nbinstruction].mnemo[0];nbinstruction++);
@@ -14683,6 +19581,9 @@ printf("nbbank=%d initialised\n",ae->nbbank);
for (i=0;i<256;i++) { ae->fastmatch[i]=-1; }
for (i=0;i<nbinstruction;i++) { if (ae->fastmatch[(int)instruction[i].mnemo[0]]==-1) ae->fastmatch[(int)instruction[i].mnemo[0]]=i; }
for (i=0;CharWord[i];i++) {Automate[((int)CharWord[i])&0xFF]=1;}
+ for (i=0;i<256;i++) {
+ if (((i>='A' && i<='Z') || (i>='0' && i<='9') || i=='@' || i=='_') && !quote_type) AutomatePrepro[i]=1; else AutomatePrepro[i]=0;
+ }
/* separators */
Automate[' ']=2;
Automate[',']=2;
@@ -14710,8 +19611,14 @@ printf("-read/flux\n");
#endif
if (!ae->flux) {
- zelines=FileReadLines(filename);
+ zelines=FileReadLines(ae,filename);
FieldArrayAddDynamicValueConcat(&ae->filename,&ae->ifile,&ae->maxfile,filename);
+ if (ae->enforce_symbol_case) {
+ ae->rawfile=MemRealloc(ae->rawfile,sizeof(char **)*ae->ifile);
+ ae->rawlen=MemRealloc(ae->rawlen,sizeof(int)*ae->ifile);
+ ae->rawfile[ae->ifile-1]=ae->source_bigbuffer;
+ ae->rawlen[ae->ifile-1]=ae->source_bigbuffer_len;
+ }
} else {
int flux_nblines=0;
int flux_curpos;
@@ -14747,7 +19654,7 @@ if (flux_nblines<50) printf("%02d[%s]\n",flux_nblines,zelines[flux_nblines]);
/* terminator */
zelines[flux_nblines]=NULL;
- /* en mode flux on prend le repertoire courant en reference */
+ /* with embedded Rasm we set the current directory of the caller as reference */
FieldArrayAddDynamicValueConcat(&ae->filename,&ae->ifile,&ae->maxfile,CURRENT_DIR);
}
@@ -14776,22 +19683,49 @@ printf("-comz/include\n");
}
waiting_quote=quote_type=0;
+
+ /************************************************************************************/
+ /************************************************************************************/
+ /* simplify case, carriage return and some tricky quotes ****************************/
+ /* also do all sources and binaries includes ****************************************/
+ /************************************************************************************/
+ /************************************************************************************/
l=idx=0;
while (l<ilisting) {
+
+#if TRACE_PREPRO
+if (!idx) printf("[%s]\n",listing[l].listing);
+#endif
+
c=listing[l].listing[idx++];
if (!c) {
l++;
idx=0;
continue;
- } else if (c=='\\' && !waiting_quote) {
+ }
+ if (c=='\\' && !waiting_quote) {
idx++;
continue;
- } else if (c==0x0D || c==0x0A) {
+ }
+
+ if (c==0x0D || c==0x0A) {
listing[l].listing[idx-1]=':';
c=':';
- } else if (c=='\'' && idx>2 && strncmp(&listing[l].listing[idx-3],"AF'",3)==0) {
- /* rien */
- } else if (c=='"' || c=='\'') {
+ } else if (c=='\'') {
+ // test this only if there is a single quote
+ if (idx>2 && strncmp(&listing[l].listing[idx-3],"AF'",3)==0) {
+ /* nothing */
+ } else {
+ if (!quote_type) {
+ quote_type=c;
+ lquote=l;
+ } else {
+ if (c==quote_type) {
+ quote_type=0;
+ }
+ }
+ }
+ } else if (c=='"') {
if (!quote_type) {
quote_type=c;
lquote=l;
@@ -14803,10 +19737,18 @@ printf("-comz/include\n");
}
if (waiting_quote) {
- /* expecting quote and nothing else */
+ /* expecting quote and NOTHING else */
switch (waiting_quote) {
case 1:
- if (c==quote_type) waiting_quote=2;
+ if (c==quote_type) waiting_quote=2; else {
+ /* enforce there is only spaces or tabs between READ/INC and string */
+ if (c!=' ' && c!=0x9) {
+ MakeError(ae,ae->filename[listing[l].ifile],listing[l].iline,"A quoted string must follow INCLUDE/READ directive\n");
+ waiting_quote=0;
+ idx--;
+ continue;
+ }
+ }
break;
case 2:
if (!quote_type) {
@@ -14833,101 +19775,76 @@ printf("-comz/include\n");
}
}
}
-
curhexbin.filename=TxtStrDup(filename_toread);
curhexbin.crunch=crunch;
- if (fileok) {
- /* lecture */
- curhexbin.rawlen=curhexbin.datalen=FileGetSize(filename_toread);
- curhexbin.data=MemMalloc(curhexbin.datalen*1.3+10);
- #if TRACE_PREPRO
- switch (crunch) {
- case 0:rasm_printf(ae,KBLUE"incbin [%s] size=%d\n",filename_toread,curhexbin.datalen);break;
- case 4:rasm_printf(ae,KBLUE"inclz4 [%s] size=%d\n",filename_toread,curhexbin.datalen);break;
- case 7:rasm_printf(ae,KBLUE"incsx7 [%s] size=%d\n",filename_toread,curhexbin.datalen);break;
- case 8:rasm_printf(ae,KBLUE"incexo [%s] size=%d\n",filename_toread,curhexbin.datalen);break;
- case 88:rasm_printf(ae,KBLUE"incexb [%s] size=%d\n",filename_toread,curhexbin.datalen);break;
- case 48:rasm_printf(ae,KBLUE"incl48 [%s] size=%d\n",filename_toread,curhexbin.datalen);break;
- case 49:rasm_printf(ae,KBLUE"incl49 [%s] size=%d\n",filename_toread,curhexbin.datalen);break;
- default:rasm_printf(ae,KBLUE"invalid crunch state!\n");exit(-42);
- }
- #endif
- if (FileReadBinary(filename_toread,(char*)curhexbin.data,curhexbin.datalen)!=curhexbin.datalen) {
- rasm_printf(ae,"read error on %s",filename_toread);
- exit(2);
+ switch (crunch) {
+ case 18:
+ curhexbin.version=1;
+ curhexbin.minmatch=5;
+ break;
+ case 19:
+ curhexbin.crunch=18;
+ curhexbin.version=2;
+ curhexbin.minmatch=2;
+ break;
+ default:break;
+ }
+
+ /* TAG + info */
+ curhexbin.datalen=-1;
+ curhexbin.data=NULL;
+ /* not yet an error, we will know later when executing the code */
+ ObjectArrayAddDynamicValueConcat((void**)&ae->hexbin,&ae->ih,&ae->mh,&curhexbin,sizeof(curhexbin));
+
+ /* v0.130 handling error case with filename on multiple lines */
+ if (incstartL!=l) {
+ int iconcat=incstartL;
+ int ilen;
+
+ MakeError(ae,ae->filename[listing[incstartL].ifile],listing[incstartL].iline,"INCBIN filename cannot be on multiple lines\n");
+
+ ilen=strlen(listing[iconcat].listing)+1;
+ idx+=ilen-rewrite;
+ while (iconcat<l) {
+ int tlen;
+ iconcat++;
+ tlen=strlen(listing[iconcat].listing);
+ ilen+=tlen;
+ if (iconcat<l) idx+=tlen;
}
- FileReadBinaryClose(filename_toread);
- switch (crunch) {
- #ifndef NO_3RD_PARTIES
- case 4:
- newdata=LZ4_crunch(curhexbin.data,curhexbin.datalen,&curhexbin.datalen);
- MemFree(curhexbin.data);
- curhexbin.data=newdata;
- #if TRACE_PREPRO
- rasm_printf(ae,KVERBOSE"crunched with LZ4 into %d byte(s)\n",curhexbin.datalen);
- #endif
- break;
- case 7:
- {
- size_t slzlen;
- newdata=ZX7_compress(optimize(curhexbin.data, curhexbin.datalen), curhexbin.data, curhexbin.datalen, &slzlen);
- curhexbin.datalen=slzlen;
- MemFree(curhexbin.data);
- curhexbin.data=newdata;
- #if TRACE_PREPRO
- rasm_printf(ae,KVERBOSE"crunched with ZX7 into %d byte(s)\n",curhexbin.datalen);
- #endif
- }
- break;
- case 8:
- rasm_printf(ae,KWARNING"Exomizer is crunching %.1fkb this may take a while, be patient...\n",curhexbin.datalen/1024.0);
- newdata=Exomizer_crunch(curhexbin.data,curhexbin.datalen,&curhexbin.datalen);
- MemFree(curhexbin.data);
- curhexbin.data=newdata;
- #if TRACE_PREPRO
- rasm_printf(ae,KVERBOSE"crunched with Exomizer into %d byte(s)\n",curhexbin.datalen);
- #endif
- break;
- #endif
- case 48:
- newdata=LZ48_crunch(curhexbin.data,curhexbin.datalen,&curhexbin.datalen);
- MemFree(curhexbin.data);
- curhexbin.data=newdata;
- #if TRACE_PREPRO
- rasm_printf(ae,KVERBOSE"crunched with LZ48 into %d byte(s)\n",curhexbin.datalen);
- #endif
- break;
- case 49:
- newdata=LZ49_crunch(curhexbin.data,curhexbin.datalen,&curhexbin.datalen);
- MemFree(curhexbin.data);
- curhexbin.data=newdata;
- #if TRACE_PREPRO
- rasm_printf(ae,KVERBOSE"crunched into with LZ49 %d byte(s)\n",curhexbin.datalen);
- #endif
- break;
- default:break;
+
+ iconcat=incstartL;
+ listing[iconcat].listing=MemRealloc(listing[iconcat].listing,ilen);
+ while (iconcat<l) {
+ iconcat++;
+ strcat(listing[incstartL].listing,listing[iconcat].listing);
+ listing[iconcat].listing[0]=0;
}
+ l=incstartL;
+
+ /* patch data to remain Assembler silent about this */
+ for (i=rewrite;i<idx;i++) listing[incstartL].listing[i]=' ';
+ /* delete entry */
+ MemFree(curhexbin.filename);
+ ae->ih--;
} else {
- /* TAG + info */
- curhexbin.datalen=-1;
- curhexbin.data=MemMalloc(2);
- /* not yet an error, we will know later when executing the code */
+ /* insertion */
+ le=strlen(listing[l].listing);
+
+ newlistingline=MemMalloc(le+32);
+ memcpy(newlistingline,listing[l].listing,rewrite);
+ rewrite+=sprintf(newlistingline+rewrite,"HEXBIN #%X",ae->ih-1);
+ strcat(newlistingline+rewrite,listing[l].listing+idx);
+ idx=rewrite;
+ MemFree(listing[l].listing);
+ listing[l].listing=newlistingline;
}
- ObjectArrayAddDynamicValueConcat((void**)&ae->hexbin,&ae->ih,&ae->mh,&curhexbin,sizeof(curhexbin));
- /* insertion */
- le=strlen(listing[l].listing);
-
- newlistingline=MemMalloc(le+32);
- memcpy(newlistingline,listing[l].listing,rewrite);
- rewrite+=sprintf(newlistingline+rewrite,"HEXBIN #%X",ae->ih-1);
- strcat(newlistingline+rewrite,listing[l].listing+idx);
- idx=rewrite;
- MemFree(listing[l].listing);
- listing[l].listing=newlistingline;
incbin=0;
} else if (include) {
/* qval contient le nom du fichier a lire */
int fileok=0,ilookfile;
+ /* cette notion n'existe pas dans le cas normal */
+ curhexbin.datalen=0;
/* qval contient le nom du fichier a lire */
filename_toread=MergePath(ae,ae->filename[listing[l].ifile],qval);
if (FileExists(filename_toread)) {
@@ -14940,43 +19857,78 @@ printf("-comz/include\n");
}
}
}
-
- if (fileok) {
- int newi,newj;
- #if TRACE_PREPRO
- rasm_printf(ae,KBLUE"include [%s]\n",filename_toread);
- #endif
-
- /* lecture */
- listing_include=FileReadLines(filename_toread);
- FieldArrayAddDynamicValueConcat(&ae->filename,&ae->ifile,&ae->maxfile,filename_toread);
- /* virer les commentaires + pré-traitement */
- EarlyPrepSrc(ae,listing_include,ae->filename[ae->ifile-1]);
-
- /* split de la ligne en cours + suppression de l'instruction include */
- PreProcessingSplitListing(&listing,&ilisting,&maxlisting,l,rewrite,idx);
- /* insertion des nouvelles lignes + reference fichier + numeros de ligne */
- PreProcessingInsertListing(&listing,&ilisting,&maxlisting,l,listing_include,ae->ifile-1);
-
- MemFree(listing_include); /* free le tableau mais pas les lignes */
- listing_include=NULL;
- idx=0; /* on reste sur la meme ligne mais on se prepare a relire du caractere 0! */
+
+ /* v0.130 handling error case with filename on multiple lines */
+ if (incstartL!=l) {
+ int iconcat=incstartL;
+ int ilen;
+
+ MakeError(ae,ae->filename[listing[incstartL].ifile],listing[incstartL].iline,"INCLUDE filename cannot be on multiple lines\n");
+ ilen=strlen(listing[iconcat].listing)+1;
+ idx+=ilen-rewrite;
+ while (iconcat<l) {
+ int tlen;
+ iconcat++;
+ tlen=strlen(listing[iconcat].listing);
+ ilen+=tlen;
+ if (iconcat<l) idx+=tlen;
+ }
+
+ iconcat=incstartL;
+ listing[iconcat].listing=MemRealloc(listing[iconcat].listing,ilen);
+ while (iconcat<l) {
+ iconcat++;
+ strcat(listing[incstartL].listing,listing[iconcat].listing);
+ listing[iconcat].listing[0]=0;
+ }
+ l=incstartL;
+
} else {
- /* TAG + info */
- curhexbin.filename=TxtStrDup(filename_toread);
- curhexbin.datalen=-2;
- curhexbin.data=MemMalloc(2);
- /* not yet an error, we will know later when executing the code */
- ObjectArrayAddDynamicValueConcat((void**)&ae->hexbin,&ae->ih,&ae->mh,&curhexbin,sizeof(curhexbin));
- /* insertion */
- le=strlen(listing[l].listing);
- newlistingline=MemMalloc(le+32);
- memcpy(newlistingline,listing[l].listing,rewrite);
- rewrite+=sprintf(newlistingline+rewrite,"HEXBIN #%X",ae->ih-1);
- strcat(newlistingline+rewrite,listing[l].listing+idx);
- idx=rewrite;
- MemFree(listing[l].listing);
- listing[l].listing=newlistingline;
+ if (fileok) {
+ #if TRACE_PREPRO
+ rasm_printf(ae,KBLUE"include [%s]\n",filename_toread);
+ #endif
+
+ /* lecture */
+ listing_include=FileReadLines(ae,filename_toread);
+ FieldArrayAddDynamicValueConcat(&ae->filename,&ae->ifile,&ae->maxfile,filename_toread);
+ if (ae->enforce_symbol_case) {
+ ae->rawfile=MemRealloc(ae->rawfile,sizeof(char **)*ae->ifile);
+ ae->rawlen=MemRealloc(ae->rawlen,sizeof(int)*ae->ifile);
+ ae->rawfile[ae->ifile-1]=ae->source_bigbuffer;
+ ae->rawlen[ae->ifile-1]=ae->source_bigbuffer_len;
+ }
+ /* virer les commentaires + pré-traitement */
+ EarlyPrepSrc(ae,listing_include,ae->filename[ae->ifile-1]);
+
+ /* split de la ligne en cours + suppression de l'instruction include */
+ PreProcessingSplitListing(&listing,&ilisting,&maxlisting,l,rewrite,idx);
+ /* insertion des nouvelles lignes + reference fichier + numeros de ligne */
+ PreProcessingInsertListing(&listing,&ilisting,&maxlisting,l,listing_include,ae->ifile-1);
+
+ MemFree(listing_include); /* free le tableau mais pas les lignes */
+ listing_include=NULL;
+ idx=0; /* on reste sur la meme ligne mais on se prepare a relire du caractere 0! */
+ } else {
+ /********************************************
+ * E R R O R M a n a g e m e n t *
+ ********************************************/
+ char tmp_insert[128];
+
+ for (i=rewrite;i<idx;i++) listing[incstartL].listing[i]=' ';
+ sprintf(tmp_insert,"READ %d",ae->ih);
+ memcpy(listing[incstartL].listing+rewrite,tmp_insert,strlen(tmp_insert));
+
+ filename_toread=MergePath(ae,ae->filename[listing[l].ifile],qval);
+ curhexbin.filename=TxtStrDup(filename_toread);
+ curhexbin.crunch=crunch;
+
+ /* TAG + info */
+ curhexbin.datalen=-2;
+ curhexbin.data=NULL;
+ /* not yet an error, we will know later when executing the code */
+ ObjectArrayAddDynamicValueConcat((void**)&ae->hexbin,&ae->ih,&ae->mh,&curhexbin,sizeof(curhexbin));
+ }
}
include=0;
}
@@ -14988,144 +19940,244 @@ printf("-comz/include\n");
/* classic behaviour */
/* looking for include/incbin */
- if (((c>='A' && c<='Z') || (c>='0' && c<='9') || c=='@' || c=='_')&& !quote_type) {
+ //if (((c>='A' && c<='Z') || (c>='0' && c<='9') || c=='@' || c=='_')&& !quote_type) {
+ if (AutomatePrepro[((int)c)&0xFF] && !quote_type) {
bval[ival++]=c;
StateMachineResizeBuffer(&bval,ival,&sval);
bval[ival]=0;
} else {
- if (strcmp(bval,"INCLUDE")==0) {
- include=1;
- waiting_quote=1;
- rewrite=idx-7-1;
- /* quote right after keyword */
- if (c==quote_type) {
- waiting_quote=2;
- }
- } else if (strcmp(bval,"READ")==0) {
- include=1;
- waiting_quote=1;
- rewrite=idx-4-1;
- /* quote right after keyword */
- if (c==quote_type) {
- waiting_quote=2;
- }
- } else if (strcmp(bval,"INCLZ4")==0) {
- incbin=1;
- crunch=4;
- waiting_quote=1;
- rewrite=idx-6-1;
- /* quote right after keyword */
- if (c==quote_type) {
- waiting_quote=2;
- }
- } else if (strcmp(bval,"INCEXB")==0) {
- incbin=1;
- crunch=88;
- waiting_quote=1;
- rewrite=idx-6-1;
- /* quote right after keyword */
- if (c==quote_type) {
- waiting_quote=2;
- }
- } else if (strcmp(bval,"INCEXO")==0) {
- incbin=1;
- crunch=8;
- waiting_quote=1;
- rewrite=idx-6-1;
- /* quote right after keyword */
- if (c==quote_type) {
- waiting_quote=2;
- }
- } else if (strcmp(bval,"INCZX7")==0) {
- incbin=1;
- crunch=7;
- waiting_quote=1;
- rewrite=idx-6-1;
- /* quote right after keyword */
- if (c==quote_type) {
- waiting_quote=2;
- }
- } else if (strcmp(bval,"INCL48")==0) {
- incbin=1;
- crunch=48;
- waiting_quote=1;
- rewrite=idx-6-1;
- /* quote right after keyword */
- if (c==quote_type) {
- waiting_quote=2;
- }
- } else if (strcmp(bval,"INCL49")==0) {
- incbin=1;
- crunch=49;
- waiting_quote=1;
- rewrite=idx-6-1;
- /* quote right after keyword */
- if (c==quote_type) {
- waiting_quote=2;
- }
- } else if (strcmp(bval,"INCBIN")==0) {
- incbin=1;
- crunch=0;
- waiting_quote=1;
- rewrite=idx-6-1;
- /* quote right after keyword */
- if (c==quote_type) {
- waiting_quote=2;
- }
- } else if (strcmp(bval,"INCWAV")==0) {
- incbin=1;
- crunch=0;
- waiting_quote=1;
- rewrite=idx-6-1;
- /* quote right after keyword */
- if (c==quote_type) {
- waiting_quote=2;
- }
- } else if (strcmp(bval,"WHILE")==0) {
- /* remplir la structure repeat_index */
- windex.ol=listing[l].iline;
- windex.oidx=idx;
- windex.ifile=ae->ifile-1;
- ObjectArrayAddDynamicValueConcat((void**)&TABwindex,&nwi,&mwi,&windex,sizeof(windex));
- } else if (strcmp(bval,"REPEAT")==0) {
- /* remplir la structure repeat_index */
- rindex.ol=listing[l].iline;
- rindex.oidx=idx;
- rindex.ifile=ae->ifile-1;
- ObjectArrayAddDynamicValueConcat((void**)&TABrindex,&nri,&mri,&rindex,sizeof(rindex));
- } else if (strcmp(bval,"WEND")==0) {
- /* retrouver la structure repeat_index correspondant a l'ouverture */
- for (wi=nwi-1;wi>=0;wi--) {
- if (TABwindex[wi].cl==-1) {
- TABwindex[wi].cl=c;
- TABwindex[wi].cidx=idx;
- break;
+ switch (bval[0]) {
+ case 'I':
+ if (bval[1]=='N' && bval[2]=='C') {
+ if (strcmp(bval,"INCLUDE")==0) {
+ incstartL=l;
+ include=1;
+ waiting_quote=1;
+ rewrite=idx-7-1;
+ /* quote right after keyword */
+ if (c==quote_type) {
+ waiting_quote=2;
+ }
+ } else if (strcmp(bval,"INCLZSA2")==0) {
+ incstartL=l;
+ incbin=1;
+ crunch=19;
+ waiting_quote=1;
+ rewrite=idx-8-1;
+ /* quote right after keyword */
+ if (c==quote_type) {
+ waiting_quote=2;
+ }
+ } else if (strcmp(bval,"INCLZSA1")==0) {
+ incstartL=l;
+ incbin=1;
+ crunch=18;
+ waiting_quote=1;
+ rewrite=idx-8-1;
+ /* quote right after keyword */
+ if (c==quote_type) {
+ waiting_quote=2;
+ }
+ } else if (strcmp(bval,"INCAPU")==0) {
+ incstartL=l;
+ incbin=1;
+ crunch=17;
+ waiting_quote=1;
+ rewrite=idx-6-1;
+ /* quote right after keyword */
+ if (c==quote_type) {
+ waiting_quote=2;
+ }
+ } else if (strcmp(bval,"INCLZ4")==0) {
+ incstartL=l;
+ incbin=1;
+ crunch=4;
+ waiting_quote=1;
+ rewrite=idx-6-1;
+ /* quote right after keyword */
+ if (c==quote_type) {
+ waiting_quote=2;
+ }
+ } else if (strcmp(bval,"INCEXO")==0) {
+ incstartL=l;
+ incbin=1;
+ crunch=8;
+ waiting_quote=1;
+ rewrite=idx-6-1;
+ /* quote right after keyword */
+ if (c==quote_type) {
+ waiting_quote=2;
+ }
+ } else if (strcmp(bval,"INCZX0")==0) {
+ incstartL=l;
+ incbin=1;
+ crunch=70;
+ waiting_quote=1;
+ rewrite=idx-6-1;
+ /* quote right after keyword */
+ if (c==quote_type) {
+ waiting_quote=2;
+ }
+ } else if (strcmp(bval,"INCZX0B")==0) {
+ incstartL=l;
+ incbin=1;
+ crunch=71;
+ waiting_quote=1;
+ rewrite=idx-7-1;
+ /* quote right after keyword */
+ if (c==quote_type) {
+ waiting_quote=2;
+ }
+ } else if (strcmp(bval,"INCZX7")==0) {
+ incstartL=l;
+ incbin=1;
+ crunch=7;
+ waiting_quote=1;
+ rewrite=idx-6-1;
+ /* quote right after keyword */
+ if (c==quote_type) {
+ waiting_quote=2;
+ }
+ } else if (strcmp(bval,"INCL48")==0) {
+ incstartL=l;
+ incbin=1;
+ crunch=48;
+ waiting_quote=1;
+ rewrite=idx-6-1;
+ /* quote right after keyword */
+ if (c==quote_type) {
+ waiting_quote=2;
+ }
+ } else if (strcmp(bval,"INCL49")==0) {
+ incstartL=l;
+ incbin=1;
+ crunch=49;
+ waiting_quote=1;
+ rewrite=idx-6-1;
+ /* quote right after keyword */
+ if (c==quote_type) {
+ waiting_quote=2;
+ }
+ } else if (strcmp(bval,"INCBIN")==0) {
+ incstartL=l;
+ incbin=1;
+ crunch=0;
+ waiting_quote=1;
+ rewrite=idx-6-1;
+ /* quote right after keyword */
+ if (c==quote_type) {
+ waiting_quote=2;
+ }
+ } else if (strcmp(bval,"INCWAV")==0) {
+ incstartL=l;
+ incbin=1;
+ crunch=0;
+ waiting_quote=1;
+ rewrite=idx-6-1;
+ /* quote right after keyword */
+ if (c==quote_type) {
+ waiting_quote=2;
+ }
+ }
}
- }
- if (wi==-1) {
- MakeError(ae,ae->filename[listing[l].ifile],listing[l].iline,"WEND refers to unknown WHILE\n");
- //exit(1);
- }
- } else if (strcmp(bval,"REND")==0 || strcmp(bval,"UNTIL")==0) {
- /* retrouver la structure repeat_index correspondant a l'ouverture */
- for (ri=nri-1;ri>=0;ri--) {
- if (TABrindex[ri].cl==-1) {
- TABrindex[ri].cl=c;
- TABrindex[ri].cidx=idx;
- break;
+ break;
+
+ case 'U':
+ /* code dupliqué du REND */
+ if (strcmp(bval,"UNTIL")==0) {
+ /* retrouver la structure repeat_index correspondant a l'ouverture */
+ for (ri=nri-1;ri>=0;ri--) {
+ if (TABrindex[ri].cl==-1) {
+ TABrindex[ri].cl=c;
+ TABrindex[ri].cidx=idx;
+ break;
+ }
+ }
+ if (ri==-1) {
+ MakeError(ae,ae->filename[listing[l].ifile],listing[l].iline,"%s refers to unknown REPEAT\n",bval);
+ //exit(1);
+ }
}
- }
- if (ri==-1) {
- MakeError(ae,ae->filename[listing[l].ifile],listing[l].iline,"%s refers to unknown REPEAT\n",bval);
- //exit(1);
- }
-
+ break;
+
+ case 'R':
+ if (strcmp(bval,"READ")==0) {
+ incstartL=l;
+ include=1;
+ waiting_quote=1;
+ rewrite=idx-4-1;
+ /* quote right after keyword */
+ if (c==quote_type) {
+ waiting_quote=2;
+ }
+ /* code dupliqué du UNTIL */
+ } else if (strcmp(bval,"REND")==0) {
+ /* retrouver la structure repeat_index correspondant a l'ouverture */
+ for (ri=nri-1;ri>=0;ri--) {
+ if (TABrindex[ri].cl==-1) {
+ TABrindex[ri].cl=c;
+ TABrindex[ri].cidx=idx;
+ break;
+ }
+ }
+ if (ri==-1) {
+ MakeError(ae,ae->filename[listing[l].ifile],listing[l].iline,"%s refers to unknown REPEAT\n",bval);
+ //exit(1);
+ }
+ } else if (strcmp(bval,"REPEAT")==0) {
+ /* remplir la structure repeat_index */
+ rindex.ol=listing[l].iline;
+ rindex.oidx=idx;
+ rindex.ifile=ae->ifile-1;
+ ObjectArrayAddDynamicValueConcat((void**)&TABrindex,&nri,&mri,&rindex,sizeof(rindex));
+ }
+ break;
+
+ case 'W':
+ if (strcmp(bval,"WHILE")==0) {
+ /* remplir la structure repeat_index */
+ windex.ol=listing[l].iline;
+ windex.oidx=idx;
+ windex.ifile=ae->ifile-1;
+ ObjectArrayAddDynamicValueConcat((void**)&TABwindex,&nwi,&mwi,&windex,sizeof(windex));
+ } else if (strcmp(bval,"WEND")==0) {
+ /* retrouver la structure repeat_index correspondant a l'ouverture */
+ for (wi=nwi-1;wi>=0;wi--) {
+ if (TABwindex[wi].cl==-1) {
+ TABwindex[wi].cl=c;
+ TABwindex[wi].cidx=idx;
+ break;
+ }
+ }
+ if (wi==-1) {
+ MakeError(ae,ae->filename[listing[l].ifile],listing[l].iline,"WEND refers to unknown WHILE\n");
+ //exit(1);
+ }
+
+ }
+ break;
+
+ default: if (ae->noampersand && c=='&') {
+ listing[l].listing[idx-1]='#';
+#if TRACE_PREPRO
+printf("patch & => #\n");
+#endif
+ }
+ break;
}
+
+#if TRACE_PREPRO
+printf("bval=[%s]\n",bval);
+#endif
bval[0]=0;
ival=0;
}
}
}
+ if (waiting_quote && ilisting) {
+ MakeError(ae,ae->filename[listing[ilisting-1].ifile],listing[ilisting-1].iline,"A quoted string must follow INCLUDE/READ directive\n");
+ }
+
#if TRACE_PREPRO
printf("check quotes and repeats\n");
#endif
@@ -15190,25 +20242,40 @@ printf("-build wordlist\n");
#if TRACE_PREPRO
printf("c='%c' automate[c]=%d\n",c>31?c:'.',Automate[((int)c)&0xFF]);
#endif
- exit(0);
+ exit(1);
break;
case 1:
- if (c=='\'' && idx>2 && strncmp(&listing[l].listing[idx-3],"AF'",3)==0) {
- w[lw++]=c;
- StateMachineResizeBuffer(&w,lw,&mw);
- w[lw]=0;
- break;
- } else if (c=='\'' || c=='"') {
- quote_type=c;
- /* debut d'une quote, on finalise le mot -> POURQUOI DONC? */
- //idx--;
+ if (c=='\'') {
+ if (idx>2 && strncmp(&listing[l].listing[idx-3],"AF'",3)==0) {
+ w[lw++]=c;
+ StateMachineResizeBuffer(&w,lw,&mw);
+ w[lw]=0;
+ break;
+ }
+#if TRACE_PREPRO
+printf("quote\n");
+#endif
+ /* on finalise le mot si on est en début d'une nouvelle instruction ET que c'est un SAVE */
+ if (strcmp(w,"SAVE")==0) {
+ // on ne break pas pour passer dans le case 2 (separator)
+ idx--;
+ } else {
+ quote_type=c;
+ w[lw++]=c;
+ StateMachineResizeBuffer(&w,lw,&mw);
+ w[lw]=0;
+ break;
+ }
+ } else if (c=='"') {
#if TRACE_PREPRO
printf("quote\n");
#endif
/* on finalise le mot si on est en début d'une nouvelle instruction ET que c'est un SAVE */
if (strcmp(w,"SAVE")==0) {
+ // on ne break pas pour passer dans le case 2 (separator)
idx--;
} else {
+ quote_type=c;
w[lw++]=c;
StateMachineResizeBuffer(&w,lw,&mw);
w[lw]=0;
@@ -15222,7 +20289,7 @@ printf("quote\n");
} else {
/* Winape/Maxam operator compatibility on expressions */
#if TRACE_PREPRO
-printf("1/2 winape maxam operator test for [%s]\n",w+ispace);
+printf("1/2 Winape maxam operator test for [%s]\n",w+ispace);
#endif
if (texpr) {
if (strcmp(w+ispace,"AND")==0) {
@@ -15261,9 +20328,9 @@ printf("*** separator='%c'\n",c);
if (lw) {
w[lw]=0;
if (texpr && !wordlist[nbword-1].t && wordlist[nbword-1].e && !hadcomma) {
- /* pour compatibilite winape avec AND,OR,XOR */
+ /* pour compatibilite Winape avec AND,OR,XOR */
#if TRACE_PREPRO
-printf("2/2 winape maxam operator test for expression [%s]\n",w+ispace);
+printf("2/2 Winape maxam operator test for expression [%s]\n",w+ispace);
#endif
if (strcmp(w,"AND")==0) {
wtmp=TxtStrDup("&");
@@ -15477,6 +20544,22 @@ printf("expr operator=%c\n",c);
#endif
/* expression/condition */
texpr=1;
+
+ /* patch operator assignment with useless spacing v121 */
+ if (lw==1 && c=='=') {
+ switch (w[0]) {
+ case '[':case ']':case '+':case '*':case '-':case '/':case '|':case '&':
+#if TRACE_PREPRO
+printf("*** patch prepro operator assignment + useless spacing\n");
+#endif
+ opassign=w[0];lw=0;
+ break;
+ default:opassign=0;break;
+ }
+ } else {
+ opassign=0;
+ }
+
if (lw) {
Automate[' ']=1;
Automate['\t']=1;
@@ -15493,7 +20576,7 @@ printf("expr operator=%c\n",c);
} else {
/* 2018.06.06 évolution sur le ! (not) */
#if TRACE_PREPRO
-printf("*** operateur commence le mot\n");
+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=='!') {
@@ -15535,6 +20618,14 @@ printf("mot precedent=[%s] t=%d\n",wordlist[nbword-1].w,wordlist[nbword-1].t);
}
MemFree(wordlist[nbword].w);
/* on ajoute l'egalite ou comparaison! */
+ if (opassign) {
+ #if TRACE_PREPRO
+ printf("*** patch opassign en finalisation de mot\n");
+ #endif
+ w[lw++]=opassign;
+ StateMachineResizeBuffer(&w,lw,&mw);
+ w[lw]=0;
+ }
curw.e=lw+1;
}
w[lw++]=c;
@@ -15553,21 +20644,95 @@ printf("mot precedent=[%s] t=%d\n",wordlist[nbword-1].w,wordlist[nbword-1].t);
exit(-1);
}
} else {
- /* lecture inconditionnelle de la quote */
#if TRACE_PREPRO
-printf("quote[%d]=%c\n",lw,c);
+printf("quote start with %c\n",c);
#endif
+ /* quoted string always starts with a single or a double quote */
w[lw++]=c;
StateMachineResizeBuffer(&w,lw,&mw);
+ if (c=='\\') {
+ escape_code=1;
+ } else if (c==quote_type) {
+ quote_type=0;
+ }
+
+ if (quote_type) // should not happend but...
+ do {
+ c=listing[l].listing[idx++];
+ if (!c) {
+ MakeError(ae,ae->filename[listing[l].ifile],listing[l].iline,"Quoted string must be on a single line!\n");
+ idx=0;
+ l++;
+ lw=0; // to avoid side effects
+ quote_type=0; // leave anyway
+ } else {
+ w[lw++]=c;
+ StateMachineResizeBuffer(&w,lw,&mw);
+
+ // string is stored with quotes
+ if (!escape_code) {
+ if (c=='\\') {
+ escape_code=1;
+ } else if (c==quote_type) {
+ quote_type=0;
+ }
+ } else {
+ // if previous char is an escape char, do not take care about ending quote
+ escape_code=0;
+ }
+ }
+ } while (quote_type);
+ // EOL for new word!
w[lw]=0;
- if (!escape_code) {
- if (c=='\\') escape_code=1;
- if (lw>1 && c==quote_type) {
- quote_type=0;
+
+ if (ae->utf8enable) {
+ int utidx;
+ for (utidx=0;w[utidx];utidx++) {
+ if ((unsigned char)w[utidx]>126) {
+ switch ((unsigned char)w[utidx]) {
+ case 0xC2:
+ if ((unsigned char)w[utidx+1]==0xBF) w[utidx]=174; else // ¿
+ if ((unsigned char)w[utidx+1]==0xA1) w[utidx]=175; else // ¡
+ MakeError(ae,ae->filename[listing[l].ifile],listing[l].iline,"Unsupported UTF8 char for quoted string\n");
+ break;
+ case 0xC3:
+ if ((unsigned char)w[utidx+1]==0xB9) w[utidx]=124; else // ù
+ if ((unsigned char)w[utidx+1]==0xA9) w[utidx]=123; else // é
+ if ((unsigned char)w[utidx+1]==0xA8) w[utidx]=125; else // è
+ if ((unsigned char)w[utidx+1]==0xA0) w[utidx]=64; else // à
+ if ((unsigned char)w[utidx+1]==0x91) w[utidx]=161; else // Ñ
+ if ((unsigned char)w[utidx+1]==0xB1) w[utidx]=171; else // ñ
+ if ((unsigned char)w[utidx+1]==0xA7) { // ç
+ w[utidx]=92;
+ w[utidx+1]=92;
+ } else
+ MakeError(ae,ae->filename[listing[l].ifile],listing[l].iline,"Unsupported UTF8 char for quoted string\n");
+ break;
+ default:
+ MakeError(ae,ae->filename[listing[l].ifile],listing[l].iline,"Unsupported UTF8 char for quoted string\n");
+ }
+ // shift string bytes except for \ char
+ if (w[utidx+1] && w[utidx+1]!=92) {
+ int utshift;
+ utshift=utidx+1; do { w[utshift]=w[utshift+1]; utshift++; } while (w[utshift]);
+ }
+ }
+ }
+ } else if (!ae->freequote) {
+ // control special chars except in freequote mode
+ int utidx;
+ for (utidx=0;w[utidx];utidx++) {
+ if ((w[utidx]>=32 && w[utidx]<127) || w[utidx]=='\t') {
+ // is ok
+ } else {
+ MakeError(ae,ae->filename[listing[l].ifile],listing[l].iline,"Invalid char for quoted string\n");
+ }
}
- } else {
- escape_code=0;
}
+
+#if TRACE_PREPRO
+printf("quote end w=%s\n",w);
+#endif
}
}
@@ -15575,6 +20740,10 @@ printf("quote[%d]=%c\n",lw,c);
printf("END\n");
#endif
+ // fix error in previous instruction
+ if (nbword && !wordlist[nbword-1].t) {
+ wordlist[nbword-1].t=1;
+ }
curw.w="END";
curw.l=0;
curw.t=2;
@@ -15650,8 +20819,11 @@ int Rasm(struct s_parameter *param)
int RasmAssemble(const char *datain, int lenin, unsigned char **dataout, int *lenout)
{
+ static int cpt=0;
struct s_assenv *ae=NULL;
+ if (datain==NULL && lenin==0) return cpt; else cpt++;
+
if (lenout) *lenout=0;
ae=PreProcessing(NULL,1,datain,lenin,NULL);
return Assemble(ae,dataout,lenout,NULL);
@@ -15659,19 +20831,77 @@ int RasmAssemble(const char *datain, int lenin, unsigned char **dataout, int *le
int RasmAssembleInfo(const char *datain, int lenin, unsigned char **dataout, int *lenout, struct s_rasm_info **debug)
{
+ static int cpt=0;
struct s_assenv *ae=NULL;
int ret;
-
+
+ if (datain==NULL && lenin==0) return cpt; else cpt++;
+
ae=PreProcessing(NULL,1,datain,lenin,NULL);
ret=Assemble(ae,dataout,lenout,debug);
return ret;
}
+int RasmAssembleInfoIntoRAM(const char *datain, int lenin, struct s_rasm_info **debug, unsigned char *emuram, int ramsize)
+{
+ static int cpt=0;
+ struct s_assenv *ae=NULL;
+ int ret;
+ int i,j,maxbank,ramidx;
+
+ if (datain==NULL && lenin==0) return cpt; else cpt++;
+
+ ae=PreProcessing(NULL,1,datain,lenin,NULL);
+
+ /* extension 4Mo = 256 slots + 4 slots 64K de RAM par défaut => 260 */
+ maxbank=ramsize>>14;
+ for (i=0;i<maxbank;i++) {
+ ramidx=i*16384;
+ for (j=0;j<16384;j++) {
+ ae->mem[i][j+16384*(i&3)]=emuram[ramidx++];
+ }
+ }
+ /* remaining bytes, if any */
+ ramidx=i*16384;
+ for (j=0;j<ramsize-ramidx;j++) {
+ ae->mem[i][j+16384*(i&3)]=emuram[ramidx++];
+ }
+
+ ae->debug.emuram=emuram;
+ ae->debug.lenram=ramsize;
+
+ ret=Assemble(ae,NULL,NULL,debug);
+
+ return ret;
+}
+
+int RasmAssembleInfoParam(const char *datain, int lenin, unsigned char **dataout, int *lenout, struct s_rasm_info **debug, struct s_parameter *param)
+{
+ static int cpt=0;
+ struct s_assenv *ae=NULL;
+ int ret;
+
+ if (datain==NULL && lenin==0) return cpt; else cpt++;
+
+ ae=PreProcessing(NULL,1,datain,lenin,param);
+ ret=Assemble(ae,dataout,lenout,debug);
+ return ret;
+}
+
+#define AUTOTEST_ACCENT "defb 'grouiké'"
+
+#define AUTOTEST_QUOTELAST "nop : save'grouik"
#define AUTOTEST_PAGELABELGEN "buildsna: bank: cpt=5: ld bc,{page}miam{cpt}: bank cpt: nop: miam{cpt} nop: assert {page}miam{cpt}==0x7FC5 "
#define AUTOTEST_NOINCLUDE "truc equ 0:if truc:include'bite':endif:nop"
+#define AUTOTEST_BADINCLUDE "include 'truc\n .bin' \n nop nop"
+
+#define AUTOTEST_BADINCBIN "incl49 'truc\n .bin' \n nop nop"
+
+#define AUTOTEST_BADINCLUDE02 "read: ldir : cp ';'"
+
#define AUTOTEST_SETINSIDE "ld hl,0=0xC9FB"
#define AUTOTEST_OPERATOR_CONVERSION "ld hl,10 OR 20:ld a,40 and 10:ld bc,5 MOD 2:ld a,(ix+45 xor 45)"
@@ -15858,6 +21088,9 @@ int RasmAssembleInfo(const char *datain, int lenin, unsigned char **dataout, int
#define AUTOTEST_EQUNUM "mavar = 9:monlabel{mavar+5}truc:unalias{mavar+5}heu equ 50:autrelabel{unalias14heu}:ld hl,autrelabel50"
+#define AUTOTEST_EQUDOLLAR " ld hl,une_equ: ld de,deux_equ: ldir: une_equ equ $+2: deux_equ equ $+4: defw 1: preums: defw 2: deuze: defw 3,4,5,6: assert une_equ == preums: assert deux_equ == deuze"
+
+
#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"
@@ -15901,6 +21134,18 @@ int RasmAssembleInfo(const char *datain, int lenin, unsigned char **dataout, int
#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_MULTILZ "bank: jr suivant: lz48: defs 100,#FF: lzclose: suivant jr lafin: lz49: defs 100,#FF: lzclose: lafin: bank: jr preums: " \
+ " preums jr suivant2: lzapu: defs 100,#FF: lzclose: suivant2 jr lafin2: lzexo: defs 100,#FF: lzclose: lafin2 "
+
+#define AUTOTEST_MULTILZORG " tabeul: defw script0: defw script1: defw script2: " \
+ "script0: org #4000,$: lz48: start1: jr end1: defs 100: djnz start1: end1: lzclose: " \
+ "org $: script1: org #4000,$: lz49: start2: jr end2: defs 100: djnz start2: end2: lzclose: " \
+ "org $: script2: org #4000,$: lz49: start3: jr end3: defs 100: djnz start3: end3: lzclose: " \
+ "org $: ei: ret "
+
+#define AUTOTEST_LZDEFERED "lz48:defs 20:lzclose:defb $"
+
+
#define AUTOTEST_PAGETAG "bankset 0:org #5000:label1:bankset 1:org #9000:label2:bankset 2:" \
"assert {page}label1==0x7FC0:assert {page}label2==0x7FC6:assert {pageset}label1==#7FC0:assert {pageset}label2==#7FC2:nop"
@@ -15945,6 +21190,12 @@ int RasmAssembleInfo(const char *datain, int lenin, unsigned char **dataout, int
#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_ALIGN "org 0:nop: align 64: defb 64: align 128: defb 128: align 256: defb 255 "
+
+#define AUTOTEST_CONFINE "org 0: nop: org 250: confine 10: defb #aa: org 500: confine 12: defb #bb: assert $<512 "
+
+#define AUTOTEST_SAVEINVALID0 "repeat 256,x : defb x-1 : rend : save 'rasmoutput.bin',0,$"
+
#define AUTOTEST_SAVEINVALID1 "nop : save'gruik',20,-100"
#define AUTOTEST_SAVEINVALID2 "nop : save'gruik',-20,100"
@@ -15953,6 +21204,11 @@ int RasmAssembleInfo(const char *datain, int lenin, unsigned char **dataout, int
#define AUTOTEST_MACROPROX " macro unemacro: nop: endm: global_label: ld hl, .table: .table"
+#define AUTOTEST_MACRO_CONF01 " nop: macro label1: nop: mend: macro label1: nop: mend:"
+#define AUTOTEST_MACRO_CONF02 " label1=0: macro label1: nop: mend: nop:"
+#define AUTOTEST_MACRO_CONF03 " label1 equ #100: macro label1: nop: mend: nop:"
+#define AUTOTEST_MACRO_CONF04 " label1 nop: macro label1: nop: mend: nop"
+
#define AUTOTEST_PROXBACK " macro grouik: @truc djnz @truc: .unprox djnz .unprox: mend:" \
"ld b,2: unglobal nop: djnz unglobal: ld b,2: .unprox nop: djnz .unprox: beforelocal=$ :" \
"repeat 2: @unlocal: ld b,2: .unprox nop: djnz .unprox: grouik : djnz .unprox : rend: assert .unprox < beforelocal : nop"
@@ -15970,6 +21226,8 @@ int RasmAssembleInfo(const char *datain, int lenin, unsigned char **dataout, int
#define AUTOTEST_FRAC "mavar=frac(5.5):assert mavar==0.5:assert frac(6.6)==0.6:assert frac(1.1)==0.1:assert frac(1)==0:assert frac(100000)==0:nop"
+#define AUTOTEST_RND "repeat:glop=rnd(20):until glop==10:nop"
+
/* test override control between bank and bankset in snapshot mode + temp workspace */
#define AUTOTEST_BANKSET "buildsna:bank 0:nop:bank 1:nop:bank:nop:bank 2:nop:bank 3:nop:bankset 1:nop:bank 8:nop:bank 9:nop:bank 10:nop:bank 11:nop"
@@ -15980,7 +21238,7 @@ int RasmAssembleInfo(const char *datain, int lenin, unsigned char **dataout, int
#define AUTOTEST_DEFS "defs 256,0"
#define AUTOTEST_LIMIT03 "limit -1 : nop"
-#define AUTOTEST_LIMIT04 "limit #10000 : nop"
+#define AUTOTEST_LIMIT04 "limit #10001 : nop"
#define AUTOTEST_LIMIT05 "org #FFFF : ldir"
#define AUTOTEST_LIMIT06 "org #FFFF : nop"
@@ -15992,8 +21250,87 @@ int RasmAssembleInfo(const char *datain, int lenin, unsigned char **dataout, int
#define AUTOTEST_LZ4 "lz4:repeat 10:nop:rend:defb 'roudoudoudouoneatxkjhgfdskljhsdfglkhnopnopnopnop':lzclose"
+#define AUTOTEST_INCBIN1 "incbin 'autotest_include.raw'"
+#define AUTOTEST_INCBIN2 "incbin 'autotest_include.raw',1000"
+#define AUTOTEST_INCBIN3 "incbin 'autotest_include.raw',0,1000"
+
+#define AUTOTEST_LZ4_A "lz4 : incbin 'autotest_include.raw' : lzclose"
+#define AUTOTEST_LZ4_B "inclz4 'autotest_include.raw'"
+#define AUTOTEST_LZ4_C "inclz4 'autotest_include.raw',100"
+#define AUTOTEST_LZ4_D "lz4 : incbin 'autotest_include.raw',100 : lzclose"
+#define AUTOTEST_LZ4_E "inclz4 'autotest_include.raw',0,1000"
+#define AUTOTEST_LZ4_F "lz4 : incbin'autotest_include.raw',0,1000 : lzclose"
+
+#define AUTOTEST_LZ48_A "lz48 : incbin 'autotest_include.raw' : lzclose"
+#define AUTOTEST_LZ48_B "incl48 'autotest_include.raw'"
+#define AUTOTEST_LZ48_C "incl48 'autotest_include.raw',100"
+#define AUTOTEST_LZ48_D "lz48 : incbin 'autotest_include.raw',100 : lzclose"
+#define AUTOTEST_LZ48_E "incl48 'autotest_include.raw',0,1000"
+#define AUTOTEST_LZ48_F "lz48 : incbin'autotest_include.raw',0,1000 : lzclose"
+
+#define AUTOTEST_LZ49_A "lz49 : incbin 'autotest_include.raw' : lzclose"
+#define AUTOTEST_LZ49_B "incl49 'autotest_include.raw'"
+#define AUTOTEST_LZ49_C "incl49 'autotest_include.raw',100"
+#define AUTOTEST_LZ49_D "lz49 : incbin 'autotest_include.raw',100 : lzclose"
+#define AUTOTEST_LZ49_E "incl49 'autotest_include.raw',0,1000"
+#define AUTOTEST_LZ49_F "lz49 : incbin'autotest_include.raw',0,1000 : lzclose"
+
+#define AUTOTEST_LZAPU_A "lzapu : incbin 'autotest_include.raw' : lzclose"
+#define AUTOTEST_LZAPU_B "incapu 'autotest_include.raw'"
+#define AUTOTEST_LZAPU_C "incapu 'autotest_include.raw',100"
+#define AUTOTEST_LZAPU_D "lzapu : incbin 'autotest_include.raw',100 : lzclose"
+#define AUTOTEST_LZAPU_E "incapu 'autotest_include.raw',0,1000"
+#define AUTOTEST_LZAPU_F "lzapu : incbin'autotest_include.raw',0,1000 : lzclose"
+
+#define AUTOTEST_LZSA2_A "lzsa2 : incbin 'autotest_include.raw' : lzclose"
+#define AUTOTEST_LZSA2_Abis "lzsa2 2 : incbin 'autotest_include.raw' : lzclose"
+#define AUTOTEST_LZSA2_B "inclzsa2 'autotest_include.raw'"
+#define AUTOTEST_LZSA2_C "inclzsa2 'autotest_include.raw',100"
+#define AUTOTEST_LZSA2_D "lzsa2 : incbin 'autotest_include.raw',100 : lzclose"
+#define AUTOTEST_LZSA2_E "inclzsa2 'autotest_include.raw',0,1000"
+#define AUTOTEST_LZSA2_F "lzsa2 : incbin'autotest_include.raw',0,1000 : lzclose"
+
+#define AUTOTEST_LZSA1_A "lzsa1 : incbin 'autotest_include.raw' : lzclose"
+#define AUTOTEST_LZSA1_Abis "lzsa1 2 : incbin 'autotest_include.raw' : lzclose"
+#define AUTOTEST_LZSA1_B "inclzsa1 'autotest_include.raw'"
+#define AUTOTEST_LZSA1_C "inclzsa1 'autotest_include.raw',100"
+#define AUTOTEST_LZSA1_D "lzsa1 : incbin 'autotest_include.raw',100 : lzclose"
+#define AUTOTEST_LZSA1_E "inclzsa1 'autotest_include.raw',0,1000"
+#define AUTOTEST_LZSA1_F "lzsa1 : incbin'autotest_include.raw',0,1000 : lzclose"
+
+#define AUTOTEST_LZEXO_A "lzexo : incbin 'autotest_include.raw' : lzclose"
+#define AUTOTEST_LZEXO_B "incexo 'autotest_include.raw'"
+#define AUTOTEST_LZEXO_C "incexo 'autotest_include.raw',100"
+#define AUTOTEST_LZEXO_D "lzexo : incbin 'autotest_include.raw',100 : lzclose"
+#define AUTOTEST_LZEXO_E "incexo 'autotest_include.raw',0,1000"
+#define AUTOTEST_LZEXO_F "lzexo : incbin'autotest_include.raw',0,1000 : lzclose"
+
+#define AUTOTEST_LZX7_A "lzx7 : incbin 'autotest_include.raw' : lzclose"
+#define AUTOTEST_LZX7_B "inczx7 'autotest_include.raw'"
+#define AUTOTEST_LZX7_C "inczx7 'autotest_include.raw',100"
+#define AUTOTEST_LZX7_D "lzx7 : incbin 'autotest_include.raw',100 : lzclose"
+#define AUTOTEST_LZX7_E "inczx7 'autotest_include.raw',0,1000"
+#define AUTOTEST_LZX7_F "lzx7 : incbin'autotest_include.raw',0,1000 : lzclose"
+
+#define AUTOTEST_LZX0_A "lzx0 : incbin 'autotest_include.raw' : lzclose"
+#define AUTOTEST_LZX0_B "inczx0 'autotest_include.raw'"
+#define AUTOTEST_LZX0_C "inczx0 'autotest_include.raw',100"
+#define AUTOTEST_LZX0_D "lzx0 : incbin 'autotest_include.raw',100 : lzclose"
+#define AUTOTEST_LZX0_E "inczx0 'autotest_include.raw',0,1000"
+#define AUTOTEST_LZX0_F "lzx0 : incbin'autotest_include.raw',0,1000 : lzclose"
+
+#define AUTOTEST_LZX0B_A "lzx0b : incbin 'autotest_include.raw' : lzclose"
+#define AUTOTEST_LZX0B_B "inczx0b 'autotest_include.raw'"
+#define AUTOTEST_LZX0B_C "inczx0b 'autotest_include.raw',100"
+#define AUTOTEST_LZX0B_D "lzx0b : incbin 'autotest_include.raw',100 : lzclose"
+#define AUTOTEST_LZX0B_E "inczx0b 'autotest_include.raw',0,1000"
+#define AUTOTEST_LZX0B_F "lzx0b : incbin'autotest_include.raw',0,1000 : lzclose"
+
+
#define AUTOTEST_MAXERROR "repeat 20:aglapi:rend:nop"
+#define AUTOTEST_REAL "defr 0,0.5,-0.5,43.375,3.14159265,-0.25,0.9994433,0.9994434,-0.9994433,-0.9994434,0.1234567,1.2345678,0.00007"
+
#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)"
@@ -16004,6 +21341,10 @@ int RasmAssembleInfo(const char *datain, int lenin, unsigned char **dataout, int
#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_ENHANCED_LD3 "ld bc,ix : ld bc,iy : ld de,ix : ld de,iy : ld ix,bc : ld ix,de : ld iy,bc : ld iy,de:"\
+ "ld b,hx : ld c,lx : ld b,hy : ld c,ly : ld d,hx : ld e,lx : ld d,hy : ld e,ly :"\
+ "ld hx,b : ld lx,c : ld hx,d : ld lx,e : ld hy,b : ld ly,c : ld hy,d : ld ly,e"
+
#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'"
@@ -16041,7 +21382,617 @@ int RasmAssembleInfo(const char *datain, int lenin, unsigned char **dataout, int
"a>>=1 : assert a==20 : nop"
#define AUTOTEST_OPERATORASSIGN2 "a=1 : a+=2 : assert a==3 : repeat 2 : a+=10 : rend : assert a==23: a=1 : a-=2 : assert a==-1 : repeat 2 : a-=10 : rend : assert a==-21: " \
"a=3 : a*=2 : assert a==6 : repeat 2 : a*=10 : rend : assert a==600: a=600 : a/=2 : assert a==300 : repeat 2 : a/=10 : rend : assert a==3 : nop"
-
+#define AUTOTEST_OPERATORASSIGN3 "a=1 : a += 2 : assert a==3 : repeat 2 : a += 10 : rend : assert a==23: a=1 : a -= 2 : assert a==-1 : repeat 2 : a -= 10 : rend : assert a==-21: " \
+ "a=3 : a *= 2 : assert a==6 : repeat 2 : a *= 10 : rend : assert a==600: a=600 : a /= 2 : assert a==300 : repeat 2 : a /= 10 : rend : assert a==3 : nop"
+
+#define AUTOTEST_MODULE01 "org 0: nop: preums nop : .prox1 : djnz preums : djnz .prox1 : defs 200 : djnz gourni_preums: djnz gourni_preums.prox1: djnz grouik_preums: " \
+ "djnz grouik_preums.prox1: module grouik: preums nop: .prox1: djnz preums: djnz .prox1: djnz gourni_preums: module gourni: ld (.prox1),a: ld (preums.prox1),a: " \
+ "preums nop: .prox1: djnz preums: djnz .prox1: djnz grouik_preums: assert preums!=1: module : plop: : module quatre: : jp plop: bip: jr bip: " \
+ " : assert preums==1: module OFF: : assert preums==1 "
+
+#define AUTOTEST_PUSHPOPGLOBAL "unglobal: nop: repeat 2: @unlocal: .prox nop: rend: .prox nop: apres=$: macro unemacro: @inside: nop: .prox: nop: assert .prox>@inside: djnz .prox: " \
+ "mend: macro deuxmacros: @inside: nop: .prox: nop: unemacro: nop: djnz .prox: assert .prox>@inside: mend: unemacro (void): assert .prox<apres: " \
+ "djnz .prox: deuxmacros (void): djnz .prox: assert .prox<apres "
+#define AUTOTEST_MODULE02 "unglobal: nop: .prox: nop: module un: deuxglobal: nop: .prox: nop: djnz .prox: nop: doublon: nop: module deux: troisglobal: nop: " \
+ " .prox: nop: djnz .prox: nop: doublon: nop: assert doublon>troisglobal: module: jr un_doublon: jr deux_doublon: jr un_deuxglobal.prox: jr deux_troisglobal.prox "
+
+#define AUTOTEST_MODULE03 "unglobal: nop: .prox: nop: module un: deuxglobal: nop: .prox: nop: djnz .prox: nop: doublon: nop: module deux: troisglobal: nop: " \
+ " .prox: nop: djnz .prox: nop: doublon: nop: assert doublon>troisglobal: endmodule: jr un_doublon: jr deux_doublon: jr un_deuxglobal.prox: jr deux_troisglobal.prox "
+
+#define AUTOTEST_GETNOP_LD "ticker start,testouille:"\
+ "ld a,1: ld a,b: ld b,a: ld a,i: ld i,a: ld a,r: ld r,a:"\
+ "ld a,(5): ld a,(hl): ld a,(de): ld (de),a: ld (hl),h: ld a,lx: ld lx,c:"\
+ "ld (1234),a: ld hl,1234: ld bc,1234: ld ix,1234: ld hl,(123): ld bc,(123): ld ix,(123): ld sp,(123):"\
+ "ld (123),hl: ld (123),de: ld (123),iy: ld (123),sp: ld yh,45: ld sp,hl: ld sp,ix:"\
+ "ticker stop,testouille:"\
+ "v1=getnop('ld a,1: ld a,b: ld b,a: ld a,i: ld i,a: ld a,r: ld r,a'):"\
+ "v1+=getnop('ld a,(5): ld a,(hl): ld a,(de): ld (de),a: ld (hl),h: ld a,lx: ld lx,c'):"\
+ "v1+=getnop('ld (1234),a: ld hl,1234: ld bc,1234: ld ix,1234: ld hl,(123): ld bc,(123): ld ix,(123): ld sp,(123)'):"\
+ "v1+=getnop('ld (123),hl: ld (123),de: ld (123),iy: ld (123),sp: ld yh,45: ld sp,hl: ld sp,ix'):"\
+ "assert v1==testouille"
+
+#define AUTOTEST_DELAYED_EQU "ld (ix + PLY_AKM_Data_OffsetPtStartTrack + 1),h:PLY_AKM_Track1_Data::" \
+ "PLY_AKM_Track1_PtStartTrack defw 0:PLY_AKM_Data_OffsetPtStartTrack "\
+ " equ PLY_AKM_Track1_PtStartTrack - PLY_AKM_Track1_Data"
+
+#define AUTOTEST_TICKERNOP_FULL "ticker start,v1 : rla: rlca: rrca: rra: nop: ccf: daa: scf: cpl: exx: ei: di : ticker stop,v1:"\
+"ticker start,v2 :im 0: neg : rst #10: retn : reti:ticker stop,v2:"\
+"ticker start,v3 :cpir : cpdr : cpd : cpi : outi : outd : ldd :ldi :ldir:lddr:inir:indr:otir:otdr:ind:ini:ticker stop,v3:"\
+"ticker start,v4 :rld:rrd:cp (hl):cp #12:cp a:cp c:cp (ix+0):cp (iy+5):cp ly:cp xl:ticker stop,v4:"\
+"assert v1==getnop('rla: rlca: rrca: rra: nop: ccf: daa: scf: cpl: exx: ei: di'):"\
+"assert v2==getnop('im : neg : rst : retn : reti'):"\
+"assert v3==getnop('cpir : cpdr : cpd : cpi : outi : outd : ldd :ldi :ldir:lddr:inir:indr:otir:otdr:ind:ini'):"\
+"assert v4==getnop('rld:rrd:cp (hl):cp #12:cp a:cp c:cp (ix+0):cp (iy+5):cp ly:cp xl'):"\
+"ticker start,v5 : ex af,af' : ex hl,de : ex de,hl : ex (sp),hl : ex hl,(sp) : ex (sp),ix : ex ix,(sp) : exx : ticker stop,v5:"\
+"assert v5==getnop(\"ex af,af' : ex hl,de : ex de,hl : ex (sp),hl : ex hl,(sp) : ex (sp),ix : ex ix,(sp) : exx\"):"\
+"ticker start,v6 : push af : push bc : push ix : pop ix : pop bc : pop af : ticker stop,v6:"\
+"ticker start,v7 : sla a : sla b : sla (hl) : sla (ix+5) : sla (ix-20),b : ticker stop,v7:"\
+"assert v7==getnop('sla a : sla b : sla (hl) : sla (ix+5) : sla (ix-20),b'):"\
+"ticker start,v8 : sll a : sll b : sll (hl) : sll (ix+5) : sll (ix-20),b : ticker stop,v8:"\
+"assert v8==getnop('sll a : sll b : sll (hl) : sll (ix+5) : sll (ix-20),b'):"\
+"ticker start,v9 : sra a : sra b : sra (hl) : sra (ix+5) : sra (ix-20),b : ticker stop,v9:"\
+"assert v9==getnop('sra a : sra b : sra (hl) : sra (ix+5) : sra (ix-20),b'):"\
+"ticker start,v10 : srl a : srl b : srl (hl) : srl (ix+5) : srl (ix-20),b : ticker stop,v10:"\
+"assert v10==getnop('srl a : srl b : srl (hl) : srl (ix+5) : srl (ix-20),b'):"\
+"ticker start,v11 : rl a : rl b : rl (hl) : rl (ix+5) : rl (ix-20),b : ticker stop,v11:"\
+"assert v11==getnop('rl a : rl b : rl (hl) : rl (ix+5) : rl (ix-20),b'):"\
+"ticker start,v12 : rlc a : rlc b : rlc (hl) : rlc (ix+5) : rlc (ix-20),b : ticker stop,v12:"\
+"assert v12==getnop('rlc a : rlc b : rlc (hl) : rlc (ix+5) : rlc (ix-20),b'):"\
+"ticker start,v13 : rr a : rr b : rr (hl) : rr (ix+5) : rr (ix-20),b : ticker stop,v13:"\
+"assert v13==getnop('rr a : rr b : rr (hl) : rr (ix+5) : rr (ix-20),b'):"\
+"ticker start,v14 : rrc a : rrc b : rrc (hl) : rrc (ix+5) : rrc (ix-20),b : ticker stop,v14:"\
+"assert v14==getnop('rrc a : rrc b : rrc (hl) : rrc (ix+5) : rrc (ix-20),b'):"\
+"ticker start,v20 : out (c),a : out (c),c : out (0),a : out (c),0 : in a,(c) : in f,(c) : in a,(0) : ticker stop,v20:"\
+"assert v20==getnop('out (c),a : out (c),c : out (0),a : out (c),0 : in a,(c) : in f,(c) : in a,(0) '):"\
+"ticker start,v21 : add a,a : add b : add ix,bc : add iy,sp : add hl,de : add (hl) : add xl : add (ix+3) : add #12 : ticker stop,v21:"\
+"assert v21==getnop('add a,a : add b : add ix,bc : add iy,sp : add hl,de : add (hl) : add xl : add (ix+3) : add #12'):"\
+"ticker start,v22 : adc hl,bc : adc hl,hl : sbc hl,hl : sbc hl,sp : sbc hl,bc : adc hl,sp : ticker stop,v22:"\
+"assert v22==getnop('adc hl,bc : adc hl,hl : sbc hl,hl : sbc hl,sp : sbc hl,bc : adc hl,sp'):"\
+"ticker start,v23 : sub a : sub a,b : sub c : sub #44 : sub (hl) : sub xl : sub (ix+20) : ticker stop,v23:"\
+"assert v23==getnop('sub a : sub a,b : sub c : sub #44 : sub (hl) : sub xl : sub (ix+20)'):"\
+"ticker start,v24 : xor a : xor b : xor c : xor #44 : xor (hl) : xor xl : xor (ix+20) : ticker stop,v24:"\
+"assert v24==getnop('xor a : xor b : xor c : xor #44 : xor (hl) : xor xl : xor (ix+20)'):"\
+"ticker start,v25 : and a : and b : and c : and #44 : and (hl) : and xl : and (ix+20) : ticker stop,v25:"\
+"assert v25==getnop('and a : and b : and c : and #44 : and (hl) : and xl : and (ix+20)'):"\
+"ticker start,v26 : or a : or b : or c : or #44 : or (hl) : or xl : or (ix+20) : ticker stop,v26:"\
+"assert v26==getnop('or a : or b : or c : or #44 : or (hl) : or xl : or (ix+20)'):"\
+"ticker start,v27 : bit 0,a : bit 1,b : bit 2,c : bit 3,d : bit 4,(hl) : bit 5,(ix+0) : bit 6,(ix+0),e : ticker stop,v27:"\
+"assert v27==getnop('bit 0,a : bit 1,b : bit 2,c : bit 3,d : bit 4,(hl) : bit 5,(ix+0) : bit 6,(ix+0),e'):"\
+"ticker start,v28 : res 0,a : res 1,b : res 2,c : res 3,d : res 4,(hl) : res 5,(ix+0) : res 6,(ix+0),e : ticker stop,v28:"\
+"assert v28==getnop('res 0,a : res 1,b : res 2,c : res 3,d : res 4,(hl) : res 5,(ix+0) : res 6,(ix+0),e'):"\
+"ticker start,v29 : set 0,a : set 1,b : set 2,c : set 3,d : set 4,(hl) : set 5,(ix+0) : set 6,(ix+0),e : ticker stop,v29:"\
+"assert v29==getnop('set 0,a : set 1,b : set 2,c : set 3,d : set 4,(hl) : set 5,(ix+0) : set 6,(ix+0),e'):"\
+"ticker start,v30 : dec a : dec b : dec lx : dec bc : dec hl : dec sp : dec ix : dec (hl) : dec (ix+100) : ticker stop,v30:"\
+"assert v30==getnop('dec a : dec b : dec lx : dec bc : dec hl : dec sp : dec ix : dec (hl) : dec (ix+100) '):"\
+"ticker start,v31 : inc a : inc b : inc lx : inc bc : inc hl : inc sp : inc ix : inc (hl) : inc (ix+100) : ticker stop,v31:"\
+"assert v31==getnop('inc a : inc b : inc lx : inc bc : inc hl : inc sp : inc ix : inc (hl) : inc (ix+100) '):"\
+"ticker start,v32 : jp 0 : jp c,0 : jp pe,0 : jp (ix) : jp (hl) : djnz $ : ticker stop,v32:"\
+"assert v32==getnop('jp 0 : jp c,0 : jp pe,0 : jp (ix) : jp (hl) : djnz $'):"\
+"ticker start,v40 : ld a,i : ld a,r : ld r,a : ld i,a : ld a,a : ld b,c : ld d,e : ld a,yl : ld d,yh : ld a,(bc) : ticker stop,v40:"\
+"assert v40==getnop('ld a,i : ld a,r : ld r,a : ld i,a : ld a,a : ld b,c : ld d,e : ld a,yl : ld d,yh : ld a,(bc)'):"\
+"ticker start,v41 : ld a,(de) : ld a,(hl) : ld l,(hl) : ld (hl),d : ld (hl),a : ld a,#12 : ld b,#12 : ld a,(#1234) : ld (#1234),a : ticker stop,v41:"\
+"assert v41==getnop('ld a,(de) : ld a,(hl) : ld l,(hl) : ld (hl),d : ld (hl),a : ld a,#12 : ld b,#12 : ld a,(#1234) : ld (#1234),a'):"\
+"ticker start,v42 : ld bc,123 : ld hl,123 : ld sp,123 : ld bc,(123) : ld hl,(123) : ld sp,(123) : ld ix,123 : ld ix,(123) : ticker stop,v42:"\
+"assert v42==getnop('ld bc,123 : ld hl,123 : ld sp,123 : ld bc,(123) : ld hl,(123) : ld sp,(123) : ld ix,123 : ld ix,(123)'):"\
+"ticker start,v43 : ld (123),bc : ld (123),hl : ld (123),ix : ld (123),sp : ld hy,#12 : ld ly,b : ld sp,hl : ld sp,ix : ticker stop,v43:"\
+"assert v43==getnop('ld (123),bc : ld (123),hl : ld (123),ix : ld (123),sp : ld hy,#12 : ld ly,b : ld sp,hl : ld sp,ix'):"\
+"ticker start,v44 : ld a,(ix+0) : ld h,(ix+0) : ld (ix+0),a : ld (ix+0),l : ld (ix+0),#12 : ticker stop,v44:"\
+"assert v44==getnop('ld a,(ix+0) : ld h,(ix+0) : ld (ix+0),a : ld (ix+0),l : ld (ix+0),#12')"
+
+#define AUTOTEST_TICKER_FULL "ticker start,v1 : rla: rlca: rrca: rra: nop: ccf: daa: scf: cpl: exx: ei: di : ticker stopzx,v1:"\
+"ticker start,v2 :im 0: neg : rst #10: retn : reti:ticker stopzx,v2:"\
+"ticker start,v3 :cpir : cpdr : cpd : cpi : outi : outd : ldd :ldi :ldir:lddr:inir:indr:otir:otdr:ind:ini:ticker stopzx,v3:"\
+"ticker start,v4 :rld:rrd::cp (hl):cp #12:cp a:cp c:cp (ix+0):cp (iy+5):cp ly:cp xl:ticker stopzx,v4:"\
+"assert v1==gettick('rla: rlca: rrca: rra: nop: ccf: daa: scf: cpl: exx: ei: di'):"\
+"assert v2==gettick('im : neg : rst : retn : reti'):"\
+"assert v3==gettick('cpir : cpdr : cpd : cpi : outi : outd : ldd :ldi :ldir:lddr:inir:indr:otir:otdr:ind:ini'):"\
+"assert v4==gettick('rld:rrd:cp (hl):cp #12:cp a:cp c:cp (ix+0):cp (iy+5):cp ly:cp xl'):"\
+"ticker start,v5 : ex af,af' : ex hl,de : ex de,hl : ex (sp),hl : ex hl,(sp) : ex (sp),ix : ex ix,(sp) : exx : ticker stopzx,v5:"\
+"assert v5==gettick(\"ex af,af' : ex hl,de : ex de,hl : ex (sp),hl : ex hl,(sp) : ex (sp),ix : ex ix,(sp) : exx\"):"\
+"ticker start,v6 : push af : push bc : push ix : pop ix : pop bc : pop af : ticker stopzx,v6:"\
+"ticker start,v7 : sla a : sla b : sla (hl) : sla (ix+5) : sla (ix-20),b : ticker stopzx,v7:"\
+"assert v7==gettick('sla a : sla b : sla (hl) : sla (ix+5) : sla (ix-20),b'):"\
+"ticker start,v8 : sll a : sll b : sll (hl) : sll (ix+5) : sll (ix-20),b : ticker stopzx,v8:"\
+"assert v8==gettick('sll a : sll b : sll (hl) : sll (ix+5) : sll (ix-20),b'):"\
+"ticker start,v9 : sra a : sra b : sra (hl) : sra (ix+5) : sra (ix-20),b : ticker stopzx,v9:"\
+"assert v9==gettick('sra a : sra b : sra (hl) : sra (ix+5) : sra (ix-20),b'):"\
+"ticker start,v10 : srl a : srl b : srl (hl) : srl (ix+5) : srl (ix-20),b : ticker stopzx,v10:"\
+"assert v10==gettick('srl a : srl b : srl (hl) : srl (ix+5) : srl (ix-20),b'):"\
+"ticker start,v11 : rl a : rl b : rl (hl) : rl (ix+5) : rl (ix-20),b : ticker stopzx,v11:"\
+"assert v11==gettick('rl a : rl b : rl (hl) : rl (ix+5) : rl (ix-20),b'):"\
+"ticker start,v12 : rlc a : rlc b : rlc (hl) : rlc (ix+5) : rlc (ix-20),b : ticker stopzx,v12:"\
+"assert v12==gettick('rlc a : rlc b : rlc (hl) : rlc (ix+5) : rlc (ix-20),b'):"\
+"ticker start,v13 : rr a : rr b : rr (hl) : rr (ix+5) : rr (ix-20),b : ticker stopzx,v13:"\
+"assert v13==gettick('rr a : rr b : rr (hl) : rr (ix+5) : rr (ix-20),b'):"\
+"ticker start,v14 : rrc a : rrc b : rrc (hl) : rrc (ix+5) : rrc (ix-20),b : ticker stopzx,v14:"\
+"assert v14==gettick('rrc a : rrc b : rrc (hl) : rrc (ix+5) : rrc (ix-20),b'):"\
+"ticker start,v20 : out (c),a : out (c),c : out (0),a : out (c),0 : in a,(c) : in f,(c) : in a,(0) : ticker stopzx,v20:"\
+"assert v20==gettick('out (c),a : out (c),c : out (0),a : out (c),0 : in a,(c) : in f,(c) : in a,(0) '):"\
+"ticker start,v21 : add a,a : add b : add ix,bc : add iy,sp : add hl,de : add (hl) : add xl : add (ix+3) : add #12 : ticker stopzx,v21:"\
+"assert v21==gettick('add a,a : add b : add ix,bc : add iy,sp : add hl,de : add (hl) : add xl : add (ix+3) : add #12'):"\
+"ticker start,v22 : adc hl,bc : adc hl,hl : sbc hl,hl : sbc hl,sp : sbc hl,bc : adc hl,sp : ticker stopzx,v22:"\
+"assert v22==gettick('adc hl,bc : adc hl,hl : sbc hl,hl : sbc hl,sp : sbc hl,bc : adc hl,sp'):"\
+"ticker start,v23 : sub a : sub a,b : sub c : sub #44 : sub (hl) : sub xl : sub (ix+20) : ticker stopzx,v23:"\
+"assert v23==gettick('sub a : sub a,b : sub c : sub #44 : sub (hl) : sub xl : sub (ix+20)'):"\
+"ticker start,v24 : xor a : xor b : xor c : xor #44 : xor (hl) : xor xl : xor (ix+20) : ticker stopzx,v24:"\
+"assert v24==gettick('xor a : xor b : xor c : xor #44 : xor (hl) : xor xl : xor (ix+20)'):"\
+"ticker start,v25 : and a : and b : and c : and #44 : and (hl) : and xl : and (ix+20) : ticker stopzx,v25:"\
+"assert v25==gettick('and a : and b : and c : and #44 : and (hl) : and xl : and (ix+20)'):"\
+"ticker start,v26 : or a : or b : or c : or #44 : or (hl) : or xl : or (ix+20) : ticker stopzx,v26:"\
+"assert v26==gettick('or a : or b : or c : or #44 : or (hl) : or xl : or (ix+20)'):"\
+"ticker start,v27 : bit 0,a : bit 1,b : bit 2,c : bit 3,d : bit 4,(hl) : bit 5,(ix+0) : bit 6,(ix+0),e : ticker stopzx,v27:"\
+"assert v27==gettick('bit 0,a : bit 1,b : bit 2,c : bit 3,d : bit 4,(hl) : bit 5,(ix+0) : bit 6,(ix+0),e'):"\
+"ticker start,v28 : res 0,a : res 1,b : res 2,c : res 3,d : res 4,(hl) : res 5,(ix+0) : res 6,(ix+0),e : ticker stopzx,v28:"\
+"assert v28==gettick('res 0,a : res 1,b : res 2,c : res 3,d : res 4,(hl) : res 5,(ix+0) : res 6,(ix+0),e'):"\
+"ticker start,v29 : set 0,a : set 1,b : set 2,c : set 3,d : set 4,(hl) : set 5,(ix+0) : set 6,(ix+0),e : ticker stopzx,v29:"\
+"assert v29==gettick('set 0,a : set 1,b : set 2,c : set 3,d : set 4,(hl) : set 5,(ix+0) : set 6,(ix+0),e'):"\
+"ticker start,v30 : dec a : dec b : dec lx : dec bc : dec hl : dec sp : dec ix : dec (hl) : dec (ix+100) : ticker stopzx,v30:"\
+"assert v30==gettick('dec a : dec b : dec lx : dec bc : dec hl : dec sp : dec ix : dec (hl) : dec (ix+100) '):"\
+"ticker start,v31 : inc a : inc b : inc lx : inc bc : inc hl : inc sp : inc ix : inc (hl) : inc (ix+100) : ticker stopzx,v31:"\
+"assert v31==gettick('inc a : inc b : inc lx : inc bc : inc hl : inc sp : inc ix : inc (hl) : inc (ix+100) '):"\
+"ticker start,v32 : jp 0 : jp c,0 : jp pe,0 : jp (ix) : jp (hl) : djnz $ : ticker stopzx,v32:"\
+"assert v32==gettick('jp 0 : jp c,0 : jp pe,0 : jp (ix) : jp (hl) : djnz $'):"\
+"ticker start,v40 : ld a,i : ld a,r : ld r,a : ld i,a : ld a,a : ld b,c : ld d,e : ld a,yl : ld d,yh : ld a,(bc) : ticker stopzx,v40:"\
+"assert v40==gettick('ld a,i : ld a,r : ld r,a : ld i,a : ld a,a : ld b,c : ld d,e : ld a,yl : ld d,yh : ld a,(bc)'):"\
+"ticker start,v41 : ld a,(de) : ld a,(hl) : ld l,(hl) : ld (hl),d : ld (hl),a : ld a,#12 : ld b,#12 : ld a,(#1234) : ld (#1234),a : ticker stopzx,v41:"\
+"assert v41==gettick('ld a,(de) : ld a,(hl) : ld l,(hl) : ld (hl),d : ld (hl),a : ld a,#12 : ld b,#12 : ld a,(#1234) : ld (#1234),a'):"\
+"ticker start,v42 : ld bc,123 : ld hl,123 : ld sp,123 : ld bc,(123) : ld hl,(123) : ld sp,(123) : ld ix,123 : ld ix,(123) : ticker stopzx,v42:"\
+"assert v42==gettick('ld bc,123 : ld hl,123 : ld sp,123 : ld bc,(123) : ld hl,(123) : ld sp,(123) : ld ix,123 : ld ix,(123)'):"\
+"ticker start,v43 : ld (123),bc : ld (123),hl : ld (123),ix : ld (123),sp : ld hy,#12 : ld ly,b : ld sp,hl : ld sp,ix : ticker stopzx,v43:"\
+"assert v43==gettick('ld (123),bc : ld (123),hl : ld (123),ix : ld (123),sp : ld hy,#12 : ld ly,b : ld sp,hl : ld sp,ix'):"\
+"ticker start,v44 : ld a,(ix+0) : ld h,(ix+0) : ld (ix+0),a : ld (ix+0),l : ld (ix+0),#12 : ticker stopzx,v44:"\
+"assert v44==gettick('ld a,(ix+0) : ld h,(ix+0) : ld (ix+0),a : ld (ix+0),l : ld (ix+0),#12')"
+
+#define AUTOTEST_GETSIZE "bank:push de:assert $==getsize('push de'):bank:sub #12:assert $==getsize('sub #12'):bank:rst #10:assert $==getsize('rst #10'):" \
+"bank:ret c:assert $==getsize('ret c'):bank:exx:assert $==getsize('exx'):bank:jp c,#1234:assert $==getsize('jp c,#1234')" \
+":bank:in a,(#12):assert $==getsize('in a,(#12)'):bank:call c,#1234:assert $==getsize('call c,#1234'):bank:nop:assert $==getsize('nop')" \
+":bank:sbc #12:assert $==getsize('sbc #12'):bank:rst #18:assert $==getsize('rst #18'):bank:ret po:assert $==getsize('ret po')" \
+":bank:pop hl:assert $==getsize('pop hl'):bank:jp po,#1234:assert $==getsize('jp po,#1234'):bank:ex (sp),hl:assert $==getsize('ex (sp),hl')" \
+":bank:call po,#1234:assert $==getsize('call po,#1234'):bank:push hl:assert $==getsize('push hl'):bank:and #12:assert $==getsize('and #12')" \
+":bank:rst #20:assert $==getsize('rst #20'):bank:ret pe:assert $==getsize('ret pe'):bank:jp (hl):assert $==getsize('jp (hl)')" \
+":bank:jp pe,#1234:assert $==getsize('jp pe,#1234'):bank:ex de,hl:assert $==getsize('ex de,hl'):bank:call pe,#1234:assert $==getsize('call pe,#1234')" \
+":bank:nop:assert $==getsize('nop'):bank:xor #12:assert $==getsize('xor #12'):bank:rst #28:assert $==getsize('rst #28')" \
+":bank:ret p:assert $==getsize('ret p'):bank:pop af:assert $==getsize('pop af'):bank:jp p,#1234:assert $==getsize('jp p,#1234')" \
+":bank:di:assert $==getsize('di'):bank:call p,#1234:assert $==getsize('call p,#1234'):bank:push af:assert $==getsize('push af')" \
+":bank:or #12:assert $==getsize('or #12'):bank:rst #30:assert $==getsize('rst #30'):bank:ret m:assert $==getsize('ret m')" \
+":bank:ld sp,hl:assert $==getsize('ld sp,hl'):bank:jp m,#1234:assert $==getsize('jp m,#1234'):bank:ei:assert $==getsize('ei')" \
+":bank:call m,#1234:assert $==getsize('call m,#1234'):bank:nop:assert $==getsize('nop'):bank:cp #12:assert $==getsize('cp #12')" \
+":bank:rst #38:assert $==getsize('rst #38'):bank:in b,(c):assert $==getsize('in b,(c)'):bank:out (c),b:assert $==getsize('out (c),b')" \
+":bank:sbc hl,bc:assert $==getsize('sbc hl,bc'):bank:ld (#1234),bc:assert $==getsize('ld (#1234),bc'):bank:neg:assert $==getsize('neg')" \
+":bank:retn:assert $==getsize('retn'):bank:im 0:assert $==getsize('im 0'):bank:ld i,a:assert $==getsize('ld i,a')" \
+":bank:in c,(c):assert $==getsize('in c,(c)'):bank:out (c),c:assert $==getsize('out (c),c'):bank:adc hl,bc:assert $==getsize('adc hl,bc')" \
+":bank:ld bc,(#1234):assert $==getsize('ld bc,(#1234)'):bank:reti:assert $==getsize('reti'):bank:ld r,a:assert $==getsize('ld r,a')" \
+":bank:in d,(c):assert $==getsize('in d,(c)'):bank:out (c),d:assert $==getsize('out (c),d'):bank:sbc hl,de:assert $==getsize('sbc hl,de')" \
+":bank:ld (#1234),de:assert $==getsize('ld (#1234),de'):bank:retn:assert $==getsize('retn'):bank:im 1:assert $==getsize('im 1')" \
+":bank:ld a,i:assert $==getsize('ld a,i'):bank:in e,(c):assert $==getsize('in e,(c)'):bank:out (c),e:assert $==getsize('out (c),e')" \
+":bank:adc hl,de:assert $==getsize('adc hl,de'):bank:ld de,(#1234):assert $==getsize('ld de,(#1234)'):bank:im 2:assert $==getsize('im 2')" \
+":bank:ld a,r:assert $==getsize('ld a,r'):bank:in h,(c):assert $==getsize('in h,(c)'):bank:out (c),h:assert $==getsize('out (c),h')" \
+":bank:sbc hl,hl:assert $==getsize('sbc hl,hl'):bank:rrd:assert $==getsize('rrd'):bank:in l,(c):assert $==getsize('in l,(c)')" \
+":bank:out (c),l:assert $==getsize('out (c),l'):bank:adc hl,hl:assert $==getsize('adc hl,hl'):bank:rld:assert $==getsize('rld')" \
+":bank:in 0,(c):assert $==getsize('in 0,(c)'):bank:out (c),0:assert $==getsize('out (c),0'):bank:sbc hl,sp:assert $==getsize('sbc hl,sp')" \
+":bank:ld (#1234),sp:assert $==getsize('ld (#1234),sp'):bank:in a,(c):assert $==getsize('in a,(c)'):bank:out (c),a:assert $==getsize('out (c),a')" \
+":bank:adc hl,sp:assert $==getsize('adc hl,sp'):bank:ld sp,(#1234):assert $==getsize('ld sp,(#1234)'):bank:ldi:assert $==getsize('ldi')" \
+":bank:cpi:assert $==getsize('cpi'):bank:ini:assert $==getsize('ini'):bank:outi:assert $==getsize('outi')" \
+":bank:ldd:assert $==getsize('ldd'):bank:cpd:assert $==getsize('cpd'):bank:ind:assert $==getsize('ind')" \
+":bank:outd:assert $==getsize('outd'):bank:ldir:assert $==getsize('ldir'):bank:cpir:assert $==getsize('cpir')" \
+":bank:inir:assert $==getsize('inir'):bank:otir:assert $==getsize('otir'):bank:lddr:assert $==getsize('lddr')" \
+":bank:cpdr:assert $==getsize('cpdr'):bank:indr:assert $==getsize('indr'):bank:otdr:assert $==getsize('otdr')" \
+":bank:rlc b:assert $==getsize('rlc b'):bank:rlc c:assert $==getsize('rlc c'):bank:rlc d:assert $==getsize('rlc d')" \
+":bank:rlc e:assert $==getsize('rlc e'):bank:rlc h:assert $==getsize('rlc h'):bank:rlc l:assert $==getsize('rlc l')" \
+":bank:rlc (hl):assert $==getsize('rlc (hl)'):bank:rlc a:assert $==getsize('rlc a'):bank:rrc b:assert $==getsize('rrc b')" \
+":bank:rrc c:assert $==getsize('rrc c'):bank:rrc d:assert $==getsize('rrc d'):bank:rrc e:assert $==getsize('rrc e')" \
+":bank:rrc h:assert $==getsize('rrc h'):bank:rrc l:assert $==getsize('rrc l'):bank:rrc (hl):assert $==getsize('rrc (hl)')" \
+":bank:rrc a:assert $==getsize('rrc a'):bank:rl b:assert $==getsize('rl b'):bank:rl c:assert $==getsize('rl c')" \
+":bank:rl d:assert $==getsize('rl d'):bank:rl e:assert $==getsize('rl e'):bank:rl h:assert $==getsize('rl h')" \
+":bank:rl l:assert $==getsize('rl l'):bank:rl (hl):assert $==getsize('rl (hl)'):bank:rl a:assert $==getsize('rl a')" \
+":bank:rr b:assert $==getsize('rr b'):bank:rr c:assert $==getsize('rr c'):bank:rr d:assert $==getsize('rr d')" \
+":bank:rr e:assert $==getsize('rr e'):bank:rr h:assert $==getsize('rr h'):bank:rr l:assert $==getsize('rr l')" \
+":bank:rr (hl):assert $==getsize('rr (hl)'):bank:rr a:assert $==getsize('rr a'):bank:sla b:assert $==getsize('sla b')" \
+":bank:sla c:assert $==getsize('sla c'):bank:sla d:assert $==getsize('sla d'):bank:sla e:assert $==getsize('sla e')" \
+":bank:sla h:assert $==getsize('sla h'):bank:sla l:assert $==getsize('sla l'):bank:sla (hl):assert $==getsize('sla (hl)')" \
+":bank:sla a:assert $==getsize('sla a'):bank:sra b:assert $==getsize('sra b'):bank:sra c:assert $==getsize('sra c')" \
+":bank:sra d:assert $==getsize('sra d'):bank:sra e:assert $==getsize('sra e'):bank:sra h:assert $==getsize('sra h')" \
+":bank:sra l:assert $==getsize('sra l'):bank:sra (hl):assert $==getsize('sra (hl)'):bank:sra a:assert $==getsize('sra a')" \
+":bank:sll b:assert $==getsize('sll b'):bank:sll c:assert $==getsize('sll c'):bank:sll d:assert $==getsize('sll d')" \
+":bank:sll e:assert $==getsize('sll e'):bank:sll h:assert $==getsize('sll h'):bank:sll l:assert $==getsize('sll l')" \
+":bank:sll (hl):assert $==getsize('sll (hl)'):bank:sll a:assert $==getsize('sll a'):bank:srl b:assert $==getsize('srl b')" \
+":bank:srl c:assert $==getsize('srl c'):bank:srl d:assert $==getsize('srl d'):bank:srl e:assert $==getsize('srl e')" \
+":bank:srl h:assert $==getsize('srl h'):bank:srl l:assert $==getsize('srl l'):bank:srl (hl):assert $==getsize('srl (hl)')" \
+":bank:srl a:assert $==getsize('srl a'):bank:bit 0,b:assert $==getsize('bit 0,b'):bank:bit 0,c:assert $==getsize('bit 0,c')" \
+":bank:bit 0,d:assert $==getsize('bit 0,d'):bank:bit 0,e:assert $==getsize('bit 0,e'):bank:bit 0,h:assert $==getsize('bit 0,h')" \
+":bank:bit 0,l:assert $==getsize('bit 0,l'):bank:bit 0,(hl):assert $==getsize('bit 0,(hl)'):bank:bit 0,a:assert $==getsize('bit 0,a')" \
+":bank:bit 1,b:assert $==getsize('bit 1,b'):bank:bit 1,c:assert $==getsize('bit 1,c'):bank:bit 1,d:assert $==getsize('bit 1,d')" \
+":bank:bit 1,e:assert $==getsize('bit 1,e'):bank:bit 1,h:assert $==getsize('bit 1,h'):bank:bit 1,l:assert $==getsize('bit 1,l')" \
+":bank:bit 1,(hl):assert $==getsize('bit 1,(hl)'):bank:bit 1,a:assert $==getsize('bit 1,a'):bank:bit 2,b:assert $==getsize('bit 2,b')" \
+":bank:bit 2,c:assert $==getsize('bit 2,c'):bank:bit 2,d:assert $==getsize('bit 2,d'):bank:bit 2,e:assert $==getsize('bit 2,e')" \
+":bank:bit 2,h:assert $==getsize('bit 2,h'):bank:bit 2,l:assert $==getsize('bit 2,l'):bank:bit 2,(hl):assert $==getsize('bit 2,(hl)')" \
+":bank:bit 2,a:assert $==getsize('bit 2,a'):bank:bit 3,b:assert $==getsize('bit 3,b'):bank:bit 3,c:assert $==getsize('bit 3,c')" \
+":bank:bit 3,d:assert $==getsize('bit 3,d'):bank:bit 3,e:assert $==getsize('bit 3,e'):bank:bit 3,h:assert $==getsize('bit 3,h')" \
+":bank:bit 3,l:assert $==getsize('bit 3,l'):bank:bit 3,(hl):assert $==getsize('bit 3,(hl)'):bank:bit 3,a:assert $==getsize('bit 3,a')" \
+":bank:bit 4,b:assert $==getsize('bit 4,b'):bank:bit 4,c:assert $==getsize('bit 4,c'):bank:bit 4,d:assert $==getsize('bit 4,d')" \
+":bank:bit 4,e:assert $==getsize('bit 4,e'):bank:bit 4,h:assert $==getsize('bit 4,h'):bank:bit 4,l:assert $==getsize('bit 4,l')" \
+":bank:bit 4,(hl):assert $==getsize('bit 4,(hl)'):bank:bit 4,a:assert $==getsize('bit 4,a'):bank:bit 5,b:assert $==getsize('bit 5,b')" \
+":bank:bit 5,c:assert $==getsize('bit 5,c'):bank:bit 5,d:assert $==getsize('bit 5,d'):bank:bit 5,e:assert $==getsize('bit 5,e')" \
+":bank:bit 5,h:assert $==getsize('bit 5,h'):bank:bit 5,l:assert $==getsize('bit 5,l'):bank:bit 5,(hl):assert $==getsize('bit 5,(hl)')" \
+":bank:bit 5,a:assert $==getsize('bit 5,a'):bank:bit 6,b:assert $==getsize('bit 6,b'):bank:bit 6,c:assert $==getsize('bit 6,c')" \
+":bank:bit 6,d:assert $==getsize('bit 6,d'):bank:bit 6,e:assert $==getsize('bit 6,e'):bank:bit 6,h:assert $==getsize('bit 6,h')" \
+":bank:bit 6,l:assert $==getsize('bit 6,l'):bank:bit 6,(hl):assert $==getsize('bit 6,(hl)'):bank:bit 6,a:assert $==getsize('bit 6,a')" \
+":bank:bit 7,b:assert $==getsize('bit 7,b'):bank:bit 7,c:assert $==getsize('bit 7,c'):bank:bit 7,d:assert $==getsize('bit 7,d')" \
+":bank:bit 7,e:assert $==getsize('bit 7,e'):bank:bit 7,h:assert $==getsize('bit 7,h'):bank:bit 7,l:assert $==getsize('bit 7,l')" \
+":bank:bit 7,(hl):assert $==getsize('bit 7,(hl)'):bank:bit 7,a:assert $==getsize('bit 7,a'):bank:res 0,b:assert $==getsize('res 0,b')" \
+":bank:res 0,c:assert $==getsize('res 0,c'):bank:res 0,d:assert $==getsize('res 0,d'):bank:res 0,e:assert $==getsize('res 0,e')" \
+":bank:res 0,h:assert $==getsize('res 0,h'):bank:res 0,l:assert $==getsize('res 0,l'):bank:res 0,(hl):assert $==getsize('res 0,(hl)')" \
+":bank:res 0,a:assert $==getsize('res 0,a'):bank:res 1,b:assert $==getsize('res 1,b'):bank:res 1,c:assert $==getsize('res 1,c')" \
+":bank:res 1,d:assert $==getsize('res 1,d'):bank:res 1,e:assert $==getsize('res 1,e'):bank:res 1,h:assert $==getsize('res 1,h')" \
+":bank:res 1,l:assert $==getsize('res 1,l'):bank:res 1,(hl):assert $==getsize('res 1,(hl)'):bank:res 1,a:assert $==getsize('res 1,a')" \
+":bank:res 2,b:assert $==getsize('res 2,b'):bank:res 2,c:assert $==getsize('res 2,c'):bank:res 2,d:assert $==getsize('res 2,d')" \
+":bank:res 2,e:assert $==getsize('res 2,e'):bank:res 2,h:assert $==getsize('res 2,h'):bank:res 2,l:assert $==getsize('res 2,l')" \
+":bank:res 2,(hl):assert $==getsize('res 2,(hl)'):bank:res 2,a:assert $==getsize('res 2,a'):bank:res 3,b:assert $==getsize('res 3,b')" \
+":bank:res 3,c:assert $==getsize('res 3,c'):bank:res 3,d:assert $==getsize('res 3,d'):bank:res 3,e:assert $==getsize('res 3,e')" \
+":bank:res 3,h:assert $==getsize('res 3,h'):bank:res 3,l:assert $==getsize('res 3,l'):bank:res 3,(hl):assert $==getsize('res 3,(hl)')" \
+":bank:res 3,a:assert $==getsize('res 3,a'):bank:res 4,b:assert $==getsize('res 4,b'):bank:res 4,c:assert $==getsize('res 4,c')" \
+":bank:res 4,d:assert $==getsize('res 4,d'):bank:res 4,e:assert $==getsize('res 4,e'):bank:res 4,h:assert $==getsize('res 4,h')" \
+":bank:res 4,l:assert $==getsize('res 4,l'):bank:res 4,(hl):assert $==getsize('res 4,(hl)'):bank:res 4,a:assert $==getsize('res 4,a')" \
+":bank:res 5,b:assert $==getsize('res 5,b'):bank:res 5,c:assert $==getsize('res 5,c'):bank:res 5,d:assert $==getsize('res 5,d')" \
+":bank:res 5,e:assert $==getsize('res 5,e'):bank:res 5,h:assert $==getsize('res 5,h'):bank:res 5,l:assert $==getsize('res 5,l')" \
+":bank:res 5,(hl):assert $==getsize('res 5,(hl)'):bank:res 5,a:assert $==getsize('res 5,a'):bank:res 6,b:assert $==getsize('res 6,b')" \
+":bank:res 6,c:assert $==getsize('res 6,c'):bank:res 6,d:assert $==getsize('res 6,d'):bank:res 6,e:assert $==getsize('res 6,e')" \
+":bank:res 6,h:assert $==getsize('res 6,h'):bank:res 6,l:assert $==getsize('res 6,l'):bank:res 6,(hl):assert $==getsize('res 6,(hl)')" \
+":bank:res 6,a:assert $==getsize('res 6,a'):bank:res 7,b:assert $==getsize('res 7,b'):bank:res 7,c:assert $==getsize('res 7,c')" \
+":bank:res 7,d:assert $==getsize('res 7,d'):bank:res 7,e:assert $==getsize('res 7,e'):bank:res 7,h:assert $==getsize('res 7,h')" \
+":bank:res 7,l:assert $==getsize('res 7,l'):bank:res 7,(hl):assert $==getsize('res 7,(hl)'):bank:res 7,a:assert $==getsize('res 7,a')" \
+":bank:set 0,b:assert $==getsize('set 0,b'):bank:set 0,c:assert $==getsize('set 0,c'):bank:set 0,d:assert $==getsize('set 0,d')" \
+":bank:set 0,e:assert $==getsize('set 0,e'):bank:set 0,h:assert $==getsize('set 0,h'):bank:set 0,l:assert $==getsize('set 0,l')" \
+":bank:set 0,(hl):assert $==getsize('set 0,(hl)'):bank:set 0,a:assert $==getsize('set 0,a'):bank:set 1,b:assert $==getsize('set 1,b')" \
+":bank:set 1,c:assert $==getsize('set 1,c'):bank:set 1,d:assert $==getsize('set 1,d'):bank:set 1,e:assert $==getsize('set 1,e')" \
+":bank:set 1,h:assert $==getsize('set 1,h'):bank:set 1,l:assert $==getsize('set 1,l'):bank:set 1,(hl):assert $==getsize('set 1,(hl)')" \
+":bank:set 1,a:assert $==getsize('set 1,a'):bank:set 2,b:assert $==getsize('set 2,b'):bank:set 2,c:assert $==getsize('set 2,c')" \
+":bank:set 2,d:assert $==getsize('set 2,d'):bank:set 2,e:assert $==getsize('set 2,e'):bank:set 2,h:assert $==getsize('set 2,h')" \
+":bank:set 2,l:assert $==getsize('set 2,l'):bank:set 2,(hl):assert $==getsize('set 2,(hl)'):bank:set 2,a:assert $==getsize('set 2,a')" \
+":bank:set 3,b:assert $==getsize('set 3,b'):bank:set 3,c:assert $==getsize('set 3,c'):bank:set 3,d:assert $==getsize('set 3,d')" \
+":bank:set 3,e:assert $==getsize('set 3,e'):bank:set 3,h:assert $==getsize('set 3,h'):bank:set 3,l:assert $==getsize('set 3,l')" \
+":bank:set 3,(hl):assert $==getsize('set 3,(hl)'):bank:set 3,a:assert $==getsize('set 3,a'):bank:set 4,b:assert $==getsize('set 4,b')" \
+":bank:set 4,c:assert $==getsize('set 4,c'):bank:set 4,d:assert $==getsize('set 4,d'):bank:set 4,e:assert $==getsize('set 4,e')" \
+":bank:set 4,h:assert $==getsize('set 4,h'):bank:set 4,l:assert $==getsize('set 4,l'):bank:set 4,(hl):assert $==getsize('set 4,(hl)')" \
+":bank:set 4,a:assert $==getsize('set 4,a'):bank:set 5,b:assert $==getsize('set 5,b'):bank:set 5,c:assert $==getsize('set 5,c')" \
+":bank:set 5,d:assert $==getsize('set 5,d'):bank:set 5,e:assert $==getsize('set 5,e'):bank:set 5,h:assert $==getsize('set 5,h')" \
+":bank:set 5,l:assert $==getsize('set 5,l'):bank:set 5,(hl):assert $==getsize('set 5,(hl)'):bank:set 5,a:assert $==getsize('set 5,a')" \
+":bank:set 6,b:assert $==getsize('set 6,b'):bank:set 6,c:assert $==getsize('set 6,c'):bank:set 6,d:assert $==getsize('set 6,d')" \
+":bank:set 6,e:assert $==getsize('set 6,e'):bank:set 6,h:assert $==getsize('set 6,h'):bank:set 6,l:assert $==getsize('set 6,l')" \
+":bank:set 6,(hl):assert $==getsize('set 6,(hl)'):bank:set 6,a:assert $==getsize('set 6,a'):bank:set 7,b:assert $==getsize('set 7,b')" \
+":bank:set 7,c:assert $==getsize('set 7,c'):bank:set 7,d:assert $==getsize('set 7,d'):bank:set 7,e:assert $==getsize('set 7,e')" \
+":bank:set 7,h:assert $==getsize('set 7,h'):bank:set 7,l:assert $==getsize('set 7,l'):bank:set 7,(hl):assert $==getsize('set 7,(hl)')" \
+":bank:set 7,a:assert $==getsize('set 7,a'):bank:add ix,bc:assert $==getsize('add ix,bc'):bank:add ix,de:assert $==getsize('add ix,de')" \
+":bank:ld ix,#1234:assert $==getsize('ld ix,#1234'):bank:ld (#1234),ix:assert $==getsize('ld (#1234),ix'):bank:inc ix:assert $==getsize('inc ix')" \
+":bank:inc xh:assert $==getsize('inc xh'):bank:dec xh:assert $==getsize('dec xh'):bank:ld xh,#12:assert $==getsize('ld xh,#12')" \
+":bank:add ix,ix:assert $==getsize('add ix,ix'):bank:ld ix,(#1234):assert $==getsize('ld ix,(#1234)'):bank:dec ix:assert $==getsize('dec ix')" \
+":bank:inc xl:assert $==getsize('inc xl'):bank:dec xl:assert $==getsize('dec xl'):bank:ld xl,#12:assert $==getsize('ld xl,#12')" \
+":bank:inc (ix+#12):assert $==getsize('inc (ix+#12)'):bank:dec (ix+#12):assert $==getsize('dec (ix+#12)'):bank:ld (ix+#12),#34:assert $==getsize('ld (ix+#12),#34')" \
+":bank:add ix,sp:assert $==getsize('add ix,sp'):bank:ld b,xh:assert $==getsize('ld b,xh'):bank:ld b,xl:assert $==getsize('ld b,xl')" \
+":bank:ld b,(ix+#12):assert $==getsize('ld b,(ix+#12)'):bank:ld c,xh:assert $==getsize('ld c,xh'):bank:ld c,xl:assert $==getsize('ld c,xl')" \
+":bank:ld c,(ix+#12):assert $==getsize('ld c,(ix+#12)'):bank:ld d,xh:assert $==getsize('ld d,xh'):bank:ld d,xl:assert $==getsize('ld d,xl')" \
+":bank:ld d,(ix+#12):assert $==getsize('ld d,(ix+#12)'):bank:ld e,xh:assert $==getsize('ld e,xh'):bank:ld e,xl:assert $==getsize('ld e,xl')" \
+":bank:ld e,(ix+#12):assert $==getsize('ld e,(ix+#12)'):bank:ld xh,b:assert $==getsize('ld xh,b'):bank:ld xh,c:assert $==getsize('ld xh,c')" \
+":bank:ld xh,d:assert $==getsize('ld xh,d'):bank:ld xh,e:assert $==getsize('ld xh,e'):bank:ld xh,xh:assert $==getsize('ld xh,xh')" \
+":bank:ld xh,xl:assert $==getsize('ld xh,xl'):bank:ld h,(ix+#12):assert $==getsize('ld h,(ix+#12)'):bank:ld xh,a:assert $==getsize('ld xh,a')" \
+":bank:ld xl,b:assert $==getsize('ld xl,b'):bank:ld xl,c:assert $==getsize('ld xl,c'):bank:ld xl,d:assert $==getsize('ld xl,d')" \
+":bank:ld xl,e:assert $==getsize('ld xl,e'):bank:ld xl,xh:assert $==getsize('ld xl,xh'):bank:ld xl,xl:assert $==getsize('ld xl,xl')" \
+":bank:ld l,(ix+#12):assert $==getsize('ld l,(ix+#12)'):bank:ld xl,a:assert $==getsize('ld xl,a'):bank:ld (ix+#12),b:assert $==getsize('ld (ix+#12),b')" \
+":bank:ld (ix+#12),c:assert $==getsize('ld (ix+#12),c'):bank:ld (ix+#12),d:assert $==getsize('ld (ix+#12),d'):bank:ld (ix+#12),e:assert $==getsize('ld (ix+#12),e')" \
+":bank:ld (ix+#12),h:assert $==getsize('ld (ix+#12),h'):bank:ld (ix+#12),l:assert $==getsize('ld (ix+#12),l'):bank:ld (ix+#12),a:assert $==getsize('ld (ix+#12),a')" \
+":bank:ld a,xh:assert $==getsize('ld a,xh'):bank:ld a,xl:assert $==getsize('ld a,xl'):bank:ld a,(ix+#12):assert $==getsize('ld a,(ix+#12)')" \
+":bank:add xh:assert $==getsize('add xh'):bank:add xl:assert $==getsize('add xl'):bank:add (ix+#12):assert $==getsize('add (ix+#12)')" \
+":bank:adc xh:assert $==getsize('adc xh'):bank:adc xl:assert $==getsize('adc xl'):bank:adc (ix+#12):assert $==getsize('adc (ix+#12)')" \
+":bank:sub xh:assert $==getsize('sub xh'):bank:sub xl:assert $==getsize('sub xl'):bank:sub (ix+#12):assert $==getsize('sub (ix+#12)')" \
+":bank:sbc xh:assert $==getsize('sbc xh'):bank:sbc xl:assert $==getsize('sbc xl'):bank:sbc (ix+#12):assert $==getsize('sbc (ix+#12)')" \
+":bank:and xh:assert $==getsize('and xh'):bank:and xl:assert $==getsize('and xl'):bank:and (ix+#12):assert $==getsize('and (ix+#12)')" \
+":bank:xor xh:assert $==getsize('xor xh'):bank:xor xl:assert $==getsize('xor xl'):bank:xor (ix+#12):assert $==getsize('xor (ix+#12)')" \
+":bank:or xh:assert $==getsize('or xh'):bank:or xl:assert $==getsize('or xl'):bank:or (ix+#12):assert $==getsize('or (ix+#12)')" \
+":bank:cp xh:assert $==getsize('cp xh'):bank:cp xl:assert $==getsize('cp xl'):bank:cp (ix+#12):assert $==getsize('cp (ix+#12)')" \
+":bank:pop ix:assert $==getsize('pop ix'):bank:ex (sp),ix:assert $==getsize('ex (sp),ix'):bank:push ix:assert $==getsize('push ix')" \
+":bank:jp (ix):assert $==getsize('jp (ix)'):bank:ld sp,ix:assert $==getsize('ld sp,ix'):bank:rlc (ix+#12),b:assert $==getsize('rlc (ix+#12),b')" \
+":bank:rlc (ix+#12),c:assert $==getsize('rlc (ix+#12),c'):bank:rlc (ix+#12),d:assert $==getsize('rlc (ix+#12),d'):bank:rlc (ix+#12),e:assert $==getsize('rlc (ix+#12),e')" \
+":bank:rlc (ix+#12),h:assert $==getsize('rlc (ix+#12),h'):bank:rlc (ix+#12),l:assert $==getsize('rlc (ix+#12),l'):bank:rlc (ix+#12):assert $==getsize('rlc (ix+#12)')" \
+":bank:rlc (ix+#12),a:assert $==getsize('rlc (ix+#12),a'):bank:rrc (ix+#12),b:assert $==getsize('rrc (ix+#12),b'):bank:rrc (ix+#12),c:assert $==getsize('rrc (ix+#12),c')" \
+":bank:rrc (ix+#12),d:assert $==getsize('rrc (ix+#12),d'):bank:rrc (ix+#12),e:assert $==getsize('rrc (ix+#12),e'):bank:rrc (ix+#12),h:assert $==getsize('rrc (ix+#12),h')" \
+":bank:rrc (ix+#12),l:assert $==getsize('rrc (ix+#12),l'):bank:rrc (ix+#12):assert $==getsize('rrc (ix+#12)'):bank:rrc (ix+#12),a:assert $==getsize('rrc (ix+#12),a')" \
+":bank:rl (ix+#12),b:assert $==getsize('rl (ix+#12),b'):bank:rl (ix+#12),c:assert $==getsize('rl (ix+#12),c'):bank:rl (ix+#12),d:assert $==getsize('rl (ix+#12),d')" \
+":bank:rl (ix+#12),e:assert $==getsize('rl (ix+#12),e'):bank:rl (ix+#12),h:assert $==getsize('rl (ix+#12),h'):bank:rl (ix+#12),l:assert $==getsize('rl (ix+#12),l')" \
+":bank:rl (ix+#12):assert $==getsize('rl (ix+#12)'):bank:rl (ix+#12),a:assert $==getsize('rl (ix+#12),a'):bank:rr (ix+#12),b:assert $==getsize('rr (ix+#12),b')" \
+":bank:rr (ix+#12),c:assert $==getsize('rr (ix+#12),c'):bank:rr (ix+#12),d:assert $==getsize('rr (ix+#12),d'):bank:rr (ix+#12),e:assert $==getsize('rr (ix+#12),e')" \
+":bank:rr (ix+#12),h:assert $==getsize('rr (ix+#12),h'):bank:rr (ix+#12),l:assert $==getsize('rr (ix+#12),l'):bank:rr (ix+#12):assert $==getsize('rr (ix+#12)')" \
+":bank:rr (ix+#12),a:assert $==getsize('rr (ix+#12),a'):bank:sla (ix+#12),b:assert $==getsize('sla (ix+#12),b'):bank:sla (ix+#12),c:assert $==getsize('sla (ix+#12),c')" \
+":bank:sla (ix+#12),d:assert $==getsize('sla (ix+#12),d'):bank:sla (ix+#12),e:assert $==getsize('sla (ix+#12),e'):bank:sla (ix+#12),h:assert $==getsize('sla (ix+#12),h')" \
+":bank:sla (ix+#12),l:assert $==getsize('sla (ix+#12),l'):bank:sla (ix+#12):assert $==getsize('sla (ix+#12)'):bank:sla (ix+#12),a:assert $==getsize('sla (ix+#12),a')" \
+":bank:sra (ix+#12),b:assert $==getsize('sra (ix+#12),b'):bank:sra (ix+#12),c:assert $==getsize('sra (ix+#12),c'):bank:sra (ix+#12),d:assert $==getsize('sra (ix+#12),d')" \
+":bank:sra (ix+#12),e:assert $==getsize('sra (ix+#12),e'):bank:sra (ix+#12),h:assert $==getsize('sra (ix+#12),h'):bank:sra (ix+#12),l:assert $==getsize('sra (ix+#12),l')" \
+":bank:sra (ix+#12):assert $==getsize('sra (ix+#12)'):bank:sra (ix+#12),a:assert $==getsize('sra (ix+#12),a'):bank:sll (ix+#12),b:assert $==getsize('sll (ix+#12),b')" \
+":bank:sll (ix+#12),c:assert $==getsize('sll (ix+#12),c'):bank:sll (ix+#12),d:assert $==getsize('sll (ix+#12),d'):bank:sll (ix+#12),e:assert $==getsize('sll (ix+#12),e')" \
+":bank:sll (ix+#12),h:assert $==getsize('sll (ix+#12),h'):bank:sll (ix+#12),l:assert $==getsize('sll (ix+#12),l'):bank:sll (ix+#12):assert $==getsize('sll (ix+#12)')" \
+":bank:sll (ix+#12),a:assert $==getsize('sll (ix+#12),a'):bank:srl (ix+#12),b:assert $==getsize('srl (ix+#12),b'):bank:srl (ix+#12),c:assert $==getsize('srl (ix+#12),c')" \
+":bank:srl (ix+#12),d:assert $==getsize('srl (ix+#12),d'):bank:srl (ix+#12),e:assert $==getsize('srl (ix+#12),e'):bank:srl (ix+#12),h:assert $==getsize('srl (ix+#12),h')" \
+":bank:srl (ix+#12),l:assert $==getsize('srl (ix+#12),l'):bank:srl (ix+#12):assert $==getsize('srl (ix+#12)'):bank:srl (ix+#12),a:assert $==getsize('srl (ix+#12),a')" \
+":bank:bit 0,(ix+#12):assert $==getsize('bit 0,(ix+#12)'):bank:bit 1,(ix+#12):assert $==getsize('bit 1,(ix+#12)'):bank:bit 2,(ix+#12):assert $==getsize('bit 2,(ix+#12)')" \
+":bank:bit 3,(ix+#12):assert $==getsize('bit 3,(ix+#12)'):bank:bit 4,(ix+#12):assert $==getsize('bit 4,(ix+#12)'):bank:bit 5,(ix+#12):assert $==getsize('bit 5,(ix+#12)')" \
+":bank:bit 6,(ix+#12):assert $==getsize('bit 6,(ix+#12)'):bank:bit 7,(ix+#12):assert $==getsize('bit 7,(ix+#12)'):bank:bit 0,(ix+#12),d:assert $==getsize('bit 0,(ix+#12),d')" \
+":bank:bit 1,(ix+#12),b:assert $==getsize('bit 1,(ix+#12),b'):bank:bit 2,(ix+#12),c:assert $==getsize('bit 2,(ix+#12),c'):bank:bit 3,(ix+#12),d:assert $==getsize('bit 3,(ix+#12),d')" \
+":bank:bit 4,(ix+#12),e:assert $==getsize('bit 4,(ix+#12),e'):bank:bit 5,(ix+#12),h:assert $==getsize('bit 5,(ix+#12),h'):bank:bit 6,(ix+#12),l:assert $==getsize('bit 6,(ix+#12),l')" \
+":bank:bit 7,(ix+#12),a:assert $==getsize('bit 7,(ix+#12),a'):bank:res 0,(ix+#12),b:assert $==getsize('res 0,(ix+#12),b'):bank:res 0,(ix+#12),c:assert $==getsize('res 0,(ix+#12),c')" \
+":bank:res 0,(ix+#12),d:assert $==getsize('res 0,(ix+#12),d'):bank:res 0,(ix+#12),e:assert $==getsize('res 0,(ix+#12),e'):bank:res 0,(ix+#12),h:assert $==getsize('res 0,(ix+#12),h')" \
+":bank:res 0,(ix+#12),l:assert $==getsize('res 0,(ix+#12),l'):bank:res 0,(ix+#12):assert $==getsize('res 0,(ix+#12)'):bank:res 0,(ix+#12),a:assert $==getsize('res 0,(ix+#12),a')" \
+":bank:res 1,(ix+#12),b:assert $==getsize('res 1,(ix+#12),b'):bank:res 1,(ix+#12),c:assert $==getsize('res 1,(ix+#12),c'):bank:res 1,(ix+#12),d:assert $==getsize('res 1,(ix+#12),d')" \
+":bank:res 1,(ix+#12),e:assert $==getsize('res 1,(ix+#12),e'):bank:res 1,(ix+#12),h:assert $==getsize('res 1,(ix+#12),h'):bank:res 1,(ix+#12),l:assert $==getsize('res 1,(ix+#12),l')" \
+":bank:res 1,(ix+#12):assert $==getsize('res 1,(ix+#12)'):bank:res 1,(ix+#12),a:assert $==getsize('res 1,(ix+#12),a'):bank:res 2,(ix+#12),b:assert $==getsize('res 2,(ix+#12),b')" \
+":bank:res 2,(ix+#12),c:assert $==getsize('res 2,(ix+#12),c'):bank:res 2,(ix+#12),d:assert $==getsize('res 2,(ix+#12),d'):bank:res 2,(ix+#12),e:assert $==getsize('res 2,(ix+#12),e')" \
+":bank:res 2,(ix+#12),h:assert $==getsize('res 2,(ix+#12),h'):bank:res 2,(ix+#12),l:assert $==getsize('res 2,(ix+#12),l'):bank:res 2,(ix+#12):assert $==getsize('res 2,(ix+#12)')" \
+":bank:res 2,(ix+#12),a:assert $==getsize('res 2,(ix+#12),a'):bank:res 3,(ix+#12),b:assert $==getsize('res 3,(ix+#12),b'):bank:res 3,(ix+#12),c:assert $==getsize('res 3,(ix+#12),c')" \
+":bank:res 3,(ix+#12),d:assert $==getsize('res 3,(ix+#12),d'):bank:res 3,(ix+#12),e:assert $==getsize('res 3,(ix+#12),e'):bank:res 3,(ix+#12),h:assert $==getsize('res 3,(ix+#12),h')" \
+":bank:res 3,(ix+#12),l:assert $==getsize('res 3,(ix+#12),l'):bank:res 3,(ix+#12):assert $==getsize('res 3,(ix+#12)'):bank:res 3,(ix+#12),a:assert $==getsize('res 3,(ix+#12),a')" \
+":bank:res 4,(ix+#12),b:assert $==getsize('res 4,(ix+#12),b'):bank:res 4,(ix+#12),c:assert $==getsize('res 4,(ix+#12),c'):bank:res 4,(ix+#12),d:assert $==getsize('res 4,(ix+#12),d')" \
+":bank:res 4,(ix+#12),e:assert $==getsize('res 4,(ix+#12),e'):bank:res 4,(ix+#12),h:assert $==getsize('res 4,(ix+#12),h'):bank:res 4,(ix+#12),l:assert $==getsize('res 4,(ix+#12),l')" \
+":bank:res 4,(ix+#12):assert $==getsize('res 4,(ix+#12)'):bank:res 4,(ix+#12),a:assert $==getsize('res 4,(ix+#12),a'):bank:res 5,(ix+#12),b:assert $==getsize('res 5,(ix+#12),b')" \
+":bank:res 5,(ix+#12),c:assert $==getsize('res 5,(ix+#12),c'):bank:res 5,(ix+#12),d:assert $==getsize('res 5,(ix+#12),d'):bank:res 5,(ix+#12),e:assert $==getsize('res 5,(ix+#12),e')" \
+":bank:res 5,(ix+#12),h:assert $==getsize('res 5,(ix+#12),h'):bank:res 5,(ix+#12),l:assert $==getsize('res 5,(ix+#12),l'):bank:res 5,(ix+#12):assert $==getsize('res 5,(ix+#12)')" \
+":bank:res 5,(ix+#12),a:assert $==getsize('res 5,(ix+#12),a'):bank:res 6,(ix+#12),b:assert $==getsize('res 6,(ix+#12),b'):bank:res 6,(ix+#12),c:assert $==getsize('res 6,(ix+#12),c')" \
+":bank:res 6,(ix+#12),d:assert $==getsize('res 6,(ix+#12),d'):bank:res 6,(ix+#12),e:assert $==getsize('res 6,(ix+#12),e'):bank:res 6,(ix+#12),h:assert $==getsize('res 6,(ix+#12),h')" \
+":bank:res 6,(ix+#12),l:assert $==getsize('res 6,(ix+#12),l'):bank:res 6,(ix+#12):assert $==getsize('res 6,(ix+#12)'):bank:res 6,(ix+#12),a:assert $==getsize('res 6,(ix+#12),a')" \
+":bank:res 7,(ix+#12),b:assert $==getsize('res 7,(ix+#12),b'):bank:res 7,(ix+#12),c:assert $==getsize('res 7,(ix+#12),c'):bank:res 7,(ix+#12),d:assert $==getsize('res 7,(ix+#12),d')" \
+":bank:res 7,(ix+#12),e:assert $==getsize('res 7,(ix+#12),e'):bank:res 7,(ix+#12),h:assert $==getsize('res 7,(ix+#12),h'):bank:res 7,(ix+#12),l:assert $==getsize('res 7,(ix+#12),l')" \
+":bank:res 7,(ix+#12):assert $==getsize('res 7,(ix+#12)'):bank:res 7,(ix+#12),a:assert $==getsize('res 7,(ix+#12),a'):bank:set 0,(ix+#12),b:assert $==getsize('set 0,(ix+#12),b')" \
+":bank:set 0,(ix+#12),c:assert $==getsize('set 0,(ix+#12),c'):bank:set 0,(ix+#12),d:assert $==getsize('set 0,(ix+#12),d'):bank:set 0,(ix+#12),e:assert $==getsize('set 0,(ix+#12),e')" \
+":bank:set 0,(ix+#12),h:assert $==getsize('set 0,(ix+#12),h'):bank:set 0,(ix+#12),l:assert $==getsize('set 0,(ix+#12),l'):bank:set 0,(ix+#12):assert $==getsize('set 0,(ix+#12)')" \
+":bank:set 0,(ix+#12),a:assert $==getsize('set 0,(ix+#12),a'):bank:set 1,(ix+#12),b:assert $==getsize('set 1,(ix+#12),b'):bank:set 1,(ix+#12),c:assert $==getsize('set 1,(ix+#12),c')" \
+":bank:set 1,(ix+#12),d:assert $==getsize('set 1,(ix+#12),d'):bank:set 1,(ix+#12),e:assert $==getsize('set 1,(ix+#12),e'):bank:set 1,(ix+#12),h:assert $==getsize('set 1,(ix+#12),h')" \
+":bank:set 1,(ix+#12),l:assert $==getsize('set 1,(ix+#12),l'):bank:set 1,(ix+#12):assert $==getsize('set 1,(ix+#12)'):bank:set 1,(ix+#12),a:assert $==getsize('set 1,(ix+#12),a')" \
+":bank:set 2,(ix+#12),b:assert $==getsize('set 2,(ix+#12),b'):bank:set 2,(ix+#12),c:assert $==getsize('set 2,(ix+#12),c'):bank:set 2,(ix+#12),d:assert $==getsize('set 2,(ix+#12),d')" \
+":bank:set 2,(ix+#12),e:assert $==getsize('set 2,(ix+#12),e'):bank:set 2,(ix+#12),h:assert $==getsize('set 2,(ix+#12),h'):bank:set 2,(ix+#12),l:assert $==getsize('set 2,(ix+#12),l')" \
+":bank:set 2,(ix+#12):assert $==getsize('set 2,(ix+#12)'):bank:set 2,(ix+#12),a:assert $==getsize('set 2,(ix+#12),a'):bank:set 3,(ix+#12),b:assert $==getsize('set 3,(ix+#12),b')" \
+":bank:set 3,(ix+#12),c:assert $==getsize('set 3,(ix+#12),c'):bank:set 3,(ix+#12),d:assert $==getsize('set 3,(ix+#12),d'):bank:set 3,(ix+#12),e:assert $==getsize('set 3,(ix+#12),e')" \
+":bank:set 3,(ix+#12),h:assert $==getsize('set 3,(ix+#12),h'):bank:set 3,(ix+#12),l:assert $==getsize('set 3,(ix+#12),l'):bank:set 3,(ix+#12):assert $==getsize('set 3,(ix+#12)')" \
+":bank:set 3,(ix+#12),a:assert $==getsize('set 3,(ix+#12),a'):bank:set 4,(ix+#12),b:assert $==getsize('set 4,(ix+#12),b'):bank:set 4,(ix+#12),c:assert $==getsize('set 4,(ix+#12),c')" \
+":bank:set 4,(ix+#12),d:assert $==getsize('set 4,(ix+#12),d'):bank:set 4,(ix+#12),e:assert $==getsize('set 4,(ix+#12),e'):bank:set 4,(ix+#12),h:assert $==getsize('set 4,(ix+#12),h')" \
+":bank:set 4,(ix+#12),l:assert $==getsize('set 4,(ix+#12),l'):bank:set 4,(ix+#12):assert $==getsize('set 4,(ix+#12)'):bank:set 4,(ix+#12),a:assert $==getsize('set 4,(ix+#12),a')" \
+":bank:set 5,(ix+#12),b:assert $==getsize('set 5,(ix+#12),b'):bank:set 5,(ix+#12),c:assert $==getsize('set 5,(ix+#12),c'):bank:set 5,(ix+#12),d:assert $==getsize('set 5,(ix+#12),d')" \
+":bank:set 5,(ix+#12),e:assert $==getsize('set 5,(ix+#12),e'):bank:set 5,(ix+#12),h:assert $==getsize('set 5,(ix+#12),h'):bank:set 5,(ix+#12),l:assert $==getsize('set 5,(ix+#12),l')" \
+":bank:set 5,(ix+#12):assert $==getsize('set 5,(ix+#12)'):bank:set 5,(ix+#12),a:assert $==getsize('set 5,(ix+#12),a'):bank:set 6,(ix+#12),b:assert $==getsize('set 6,(ix+#12),b')" \
+":bank:set 6,(ix+#12),c:assert $==getsize('set 6,(ix+#12),c'):bank:set 6,(ix+#12),d:assert $==getsize('set 6,(ix+#12),d'):bank:set 6,(ix+#12),e:assert $==getsize('set 6,(ix+#12),e')" \
+":bank:set 6,(ix+#12),h:assert $==getsize('set 6,(ix+#12),h'):bank:set 6,(ix+#12),l:assert $==getsize('set 6,(ix+#12),l'):bank:set 6,(ix+#12):assert $==getsize('set 6,(ix+#12)')" \
+":bank:set 6,(ix+#12),a:assert $==getsize('set 6,(ix+#12),a'):bank:set 7,(ix+#12),b:assert $==getsize('set 7,(ix+#12),b'):bank:set 7,(ix+#12),c:assert $==getsize('set 7,(ix+#12),c')" \
+":bank:set 7,(ix+#12),d:assert $==getsize('set 7,(ix+#12),d'):bank:set 7,(ix+#12),e:assert $==getsize('set 7,(ix+#12),e'):bank:set 7,(ix+#12),h:assert $==getsize('set 7,(ix+#12),h')" \
+":bank:set 7,(ix+#12),l:assert $==getsize('set 7,(ix+#12),l'):bank:set 7,(ix+#12):assert $==getsize('set 7,(ix+#12)'):bank:set 7,(ix+#12),a:assert $==getsize('set 7,(ix+#12),a')" \
+":bank:add iy,bc:assert $==getsize('add iy,bc'):bank:add iy,de:assert $==getsize('add iy,de'):bank:ld iy,#1234:assert $==getsize('ld iy,#1234')" \
+":bank:ld (#1234),iy:assert $==getsize('ld (#1234),iy'):bank:inc iy:assert $==getsize('inc iy'):bank:inc yh:assert $==getsize('inc yh')" \
+":bank:dec yh:assert $==getsize('dec yh'):bank:ld yh,#12:assert $==getsize('ld yh,#12'):bank:add iy,iy:assert $==getsize('add iy,iy')" \
+":bank:ld iy,(#1234):assert $==getsize('ld iy,(#1234)'):bank:dec iy:assert $==getsize('dec iy'):bank:inc yl:assert $==getsize('inc yl')" \
+":bank:dec yl:assert $==getsize('dec yl'):bank:ld yl,#12:assert $==getsize('ld yl,#12'):bank:inc (iy+#12):assert $==getsize('inc (iy+#12)')" \
+":bank:dec (iy+#12):assert $==getsize('dec (iy+#12)'):bank:ld (iy+#12),#34:assert $==getsize('ld (iy+#12),#34'):bank:add iy,sp:assert $==getsize('add iy,sp')" \
+":bank:ld b,yh:assert $==getsize('ld b,yh'):bank:ld b,yl:assert $==getsize('ld b,yl'):bank:ld b,(iy+#12):assert $==getsize('ld b,(iy+#12)')" \
+":bank:ld c,yh:assert $==getsize('ld c,yh'):bank:ld c,yl:assert $==getsize('ld c,yl'):bank:ld c,(iy+#12):assert $==getsize('ld c,(iy+#12)')" \
+":bank:ld d,yh:assert $==getsize('ld d,yh'):bank:ld d,yl:assert $==getsize('ld d,yl'):bank:ld d,(iy+#12):assert $==getsize('ld d,(iy+#12)')" \
+":bank:ld e,yh:assert $==getsize('ld e,yh'):bank:ld e,yl:assert $==getsize('ld e,yl'):bank:ld e,(iy+#12):assert $==getsize('ld e,(iy+#12)')" \
+":bank:ld yh,b:assert $==getsize('ld yh,b'):bank:ld yh,c:assert $==getsize('ld yh,c'):bank:ld yh,d:assert $==getsize('ld yh,d')" \
+":bank:ld yh,e:assert $==getsize('ld yh,e'):bank:ld yh,yh:assert $==getsize('ld yh,yh'):bank:ld yh,yl:assert $==getsize('ld yh,yl')" \
+":bank:ld h,(iy+#12):assert $==getsize('ld h,(iy+#12)'):bank:ld yh,a:assert $==getsize('ld yh,a'):bank:ld yl,b:assert $==getsize('ld yl,b')" \
+":bank:ld yl,c:assert $==getsize('ld yl,c'):bank:ld yl,d:assert $==getsize('ld yl,d'):bank:ld yl,e:assert $==getsize('ld yl,e')" \
+":bank:ld yl,yh:assert $==getsize('ld yl,yh'):bank:ld yl,yl:assert $==getsize('ld yl,yl'):bank:ld l,(iy+#12):assert $==getsize('ld l,(iy+#12)')" \
+":bank:ld yl,a:assert $==getsize('ld yl,a'):bank:ld (iy+#12),b:assert $==getsize('ld (iy+#12),b'):bank:ld (iy+#12),c:assert $==getsize('ld (iy+#12),c')" \
+":bank:ld (iy+#12),d:assert $==getsize('ld (iy+#12),d'):bank:ld (iy+#12),e:assert $==getsize('ld (iy+#12),e'):bank:ld (iy+#12),h:assert $==getsize('ld (iy+#12),h')" \
+":bank:ld (iy+#12),l:assert $==getsize('ld (iy+#12),l'):bank:ld (iy+#12),a:assert $==getsize('ld (iy+#12),a'):bank:ld a,yh:assert $==getsize('ld a,yh')" \
+":bank:ld a,yl:assert $==getsize('ld a,yl'):bank:ld a,(iy+#12):assert $==getsize('ld a,(iy+#12)'):bank:add yh:assert $==getsize('add yh')" \
+":bank:add yl:assert $==getsize('add yl'):bank:add (iy+#12):assert $==getsize('add (iy+#12)'):bank:adc yh:assert $==getsize('adc yh')" \
+":bank:adc yl:assert $==getsize('adc yl'):bank:adc (iy+#12):assert $==getsize('adc (iy+#12)'):bank:sub yh:assert $==getsize('sub yh')" \
+":bank:sub yl:assert $==getsize('sub yl'):bank:sub (iy+#12):assert $==getsize('sub (iy+#12)'):bank:sbc yh:assert $==getsize('sbc yh')" \
+":bank:sbc yl:assert $==getsize('sbc yl'):bank:sbc (iy+#12):assert $==getsize('sbc (iy+#12)'):bank:and yh:assert $==getsize('and yh')" \
+":bank:and yl:assert $==getsize('and yl'):bank:and (iy+#12):assert $==getsize('and (iy+#12)'):bank:xor yh:assert $==getsize('xor yh')" \
+":bank:xor yl:assert $==getsize('xor yl'):bank:xor (iy+#12):assert $==getsize('xor (iy+#12)'):bank:or yh:assert $==getsize('or yh')" \
+":bank:or yl:assert $==getsize('or yl'):bank:or (iy+#12):assert $==getsize('or (iy+#12)'):bank:cp yh:assert $==getsize('cp yh')" \
+":bank:cp yl:assert $==getsize('cp yl'):bank:cp (iy+#12):assert $==getsize('cp (iy+#12)'):bank:pop iy:assert $==getsize('pop iy')" \
+":bank:ex (sp),iy:assert $==getsize('ex (sp),iy'):bank:push iy:assert $==getsize('push iy'):bank:jp (iy):assert $==getsize('jp (iy)')" \
+":bank:ld sp,iy:assert $==getsize('ld sp,iy'):bank:rlc (iy+#12),b:assert $==getsize('rlc (iy+#12),b'):bank:rlc (iy+#12),c:assert $==getsize('rlc (iy+#12),c')" \
+":bank:rlc (iy+#12),d:assert $==getsize('rlc (iy+#12),d'):bank:rlc (iy+#12),e:assert $==getsize('rlc (iy+#12),e'):bank:rlc (iy+#12),h:assert $==getsize('rlc (iy+#12),h')" \
+":bank:rlc (iy+#12),l:assert $==getsize('rlc (iy+#12),l'):bank:rlc (iy+#12):assert $==getsize('rlc (iy+#12)'):bank:rlc (iy+#12),a:assert $==getsize('rlc (iy+#12),a')" \
+":bank:rrc (iy+#12),b:assert $==getsize('rrc (iy+#12),b'):bank:rrc (iy+#12),c:assert $==getsize('rrc (iy+#12),c'):bank:rrc (iy+#12),d:assert $==getsize('rrc (iy+#12),d')" \
+":bank:rrc (iy+#12),e:assert $==getsize('rrc (iy+#12),e'):bank:rrc (iy+#12),h:assert $==getsize('rrc (iy+#12),h'):bank:rrc (iy+#12),l:assert $==getsize('rrc (iy+#12),l')" \
+":bank:rrc (iy+#12):assert $==getsize('rrc (iy+#12)'):bank:rrc (iy+#12),a:assert $==getsize('rrc (iy+#12),a'):bank:rl (iy+#12),b:assert $==getsize('rl (iy+#12),b')" \
+":bank:rl (iy+#12),c:assert $==getsize('rl (iy+#12),c'):bank:rl (iy+#12),d:assert $==getsize('rl (iy+#12),d'):bank:rl (iy+#12),e:assert $==getsize('rl (iy+#12),e')" \
+":bank:rl (iy+#12),h:assert $==getsize('rl (iy+#12),h'):bank:rl (iy+#12),l:assert $==getsize('rl (iy+#12),l'):bank:rl (iy+#12):assert $==getsize('rl (iy+#12)')" \
+":bank:rl (iy+#12),a:assert $==getsize('rl (iy+#12),a'):bank:rr (iy+#12),b:assert $==getsize('rr (iy+#12),b'):bank:rr (iy+#12),c:assert $==getsize('rr (iy+#12),c')" \
+":bank:rr (iy+#12),d:assert $==getsize('rr (iy+#12),d'):bank:rr (iy+#12),e:assert $==getsize('rr (iy+#12),e'):bank:rr (iy+#12),h:assert $==getsize('rr (iy+#12),h')" \
+":bank:rr (iy+#12),l:assert $==getsize('rr (iy+#12),l'):bank:rr (iy+#12):assert $==getsize('rr (iy+#12)'):bank:rr (iy+#12),a:assert $==getsize('rr (iy+#12),a')" \
+":bank:sla (iy+#12),b:assert $==getsize('sla (iy+#12),b'):bank:sla (iy+#12),c:assert $==getsize('sla (iy+#12),c'):bank:sla (iy+#12),d:assert $==getsize('sla (iy+#12),d')" \
+":bank:sla (iy+#12),e:assert $==getsize('sla (iy+#12),e'):bank:sla (iy+#12),h:assert $==getsize('sla (iy+#12),h'):bank:sla (iy+#12),l:assert $==getsize('sla (iy+#12),l')" \
+":bank:sla (iy+#12):assert $==getsize('sla (iy+#12)'):bank:sla (iy+#12),a:assert $==getsize('sla (iy+#12),a'):bank:sra (iy+#12),b:assert $==getsize('sra (iy+#12),b')" \
+":bank:sra (iy+#12),c:assert $==getsize('sra (iy+#12),c'):bank:sra (iy+#12),d:assert $==getsize('sra (iy+#12),d'):bank:sra (iy+#12),e:assert $==getsize('sra (iy+#12),e')" \
+":bank:sra (iy+#12),h:assert $==getsize('sra (iy+#12),h'):bank:sra (iy+#12),l:assert $==getsize('sra (iy+#12),l'):bank:sra (iy+#12):assert $==getsize('sra (iy+#12)')" \
+":bank:sra (iy+#12),a:assert $==getsize('sra (iy+#12),a'):bank:sll (iy+#12),b:assert $==getsize('sll (iy+#12),b'):bank:sll (iy+#12),c:assert $==getsize('sll (iy+#12),c')" \
+":bank:sll (iy+#12),d:assert $==getsize('sll (iy+#12),d'):bank:sll (iy+#12),e:assert $==getsize('sll (iy+#12),e'):bank:sll (iy+#12),h:assert $==getsize('sll (iy+#12),h')" \
+":bank:sll (iy+#12),l:assert $==getsize('sll (iy+#12),l'):bank:sll (iy+#12):assert $==getsize('sll (iy+#12)'):bank:sll (iy+#12),a:assert $==getsize('sll (iy+#12),a')" \
+":bank:srl (iy+#12),b:assert $==getsize('srl (iy+#12),b'):bank:srl (iy+#12),c:assert $==getsize('srl (iy+#12),c'):bank:srl (iy+#12),d:assert $==getsize('srl (iy+#12),d')" \
+":bank:srl (iy+#12),e:assert $==getsize('srl (iy+#12),e'):bank:srl (iy+#12),h:assert $==getsize('srl (iy+#12),h'):bank:srl (iy+#12),l:assert $==getsize('srl (iy+#12),l')" \
+":bank:srl (iy+#12):assert $==getsize('srl (iy+#12)'):bank:srl (iy+#12),a:assert $==getsize('srl (iy+#12),a'):bank:bit 0,(iy+#12):assert $==getsize('bit 0,(iy+#12)')" \
+":bank:bit 1,(iy+#12):assert $==getsize('bit 1,(iy+#12)'):bank:bit 2,(iy+#12):assert $==getsize('bit 2,(iy+#12)'):bank:bit 3,(iy+#12):assert $==getsize('bit 3,(iy+#12)')" \
+":bank:bit 4,(iy+#12):assert $==getsize('bit 4,(iy+#12)'):bank:bit 5,(iy+#12):assert $==getsize('bit 5,(iy+#12)'):bank:bit 6,(iy+#12):assert $==getsize('bit 6,(iy+#12)')" \
+":bank:bit 7,(iy+#12):assert $==getsize('bit 7,(iy+#12)'):bank:res 0,(iy+#12),b:assert $==getsize('res 0,(iy+#12),b'):bank:res 0,(iy+#12),c:assert $==getsize('res 0,(iy+#12),c')" \
+":bank:res 0,(iy+#12),d:assert $==getsize('res 0,(iy+#12),d'):bank:res 0,(iy+#12),e:assert $==getsize('res 0,(iy+#12),e'):bank:res 0,(iy+#12),h:assert $==getsize('res 0,(iy+#12),h')" \
+":bank:res 0,(iy+#12),l:assert $==getsize('res 0,(iy+#12),l'):bank:res 0,(iy+#12):assert $==getsize('res 0,(iy+#12)'):bank:res 0,(iy+#12),a:assert $==getsize('res 0,(iy+#12),a')" \
+":bank:res 1,(iy+#12),b:assert $==getsize('res 1,(iy+#12),b'):bank:res 1,(iy+#12),c:assert $==getsize('res 1,(iy+#12),c'):bank:res 1,(iy+#12),d:assert $==getsize('res 1,(iy+#12),d')" \
+":bank:res 1,(iy+#12),e:assert $==getsize('res 1,(iy+#12),e'):bank:res 1,(iy+#12),h:assert $==getsize('res 1,(iy+#12),h'):bank:res 1,(iy+#12),l:assert $==getsize('res 1,(iy+#12),l')" \
+":bank:res 1,(iy+#12):assert $==getsize('res 1,(iy+#12)'):bank:res 1,(iy+#12),a:assert $==getsize('res 1,(iy+#12),a'):bank:res 2,(iy+#12),b:assert $==getsize('res 2,(iy+#12),b')" \
+":bank:res 2,(iy+#12),c:assert $==getsize('res 2,(iy+#12),c'):bank:res 2,(iy+#12),d:assert $==getsize('res 2,(iy+#12),d'):bank:res 2,(iy+#12),e:assert $==getsize('res 2,(iy+#12),e')" \
+":bank:res 2,(iy+#12),h:assert $==getsize('res 2,(iy+#12),h'):bank:res 2,(iy+#12),l:assert $==getsize('res 2,(iy+#12),l'):bank:res 2,(iy+#12):assert $==getsize('res 2,(iy+#12)')" \
+":bank:res 2,(iy+#12),a:assert $==getsize('res 2,(iy+#12),a'):bank:res 3,(iy+#12),b:assert $==getsize('res 3,(iy+#12),b'):bank:res 3,(iy+#12),c:assert $==getsize('res 3,(iy+#12),c')" \
+":bank:res 3,(iy+#12),d:assert $==getsize('res 3,(iy+#12),d'):bank:res 3,(iy+#12),e:assert $==getsize('res 3,(iy+#12),e'):bank:res 3,(iy+#12),h:assert $==getsize('res 3,(iy+#12),h')" \
+":bank:res 3,(iy+#12),l:assert $==getsize('res 3,(iy+#12),l'):bank:res 3,(iy+#12):assert $==getsize('res 3,(iy+#12)'):bank:res 3,(iy+#12),a:assert $==getsize('res 3,(iy+#12),a')" \
+":bank:res 4,(iy+#12),b:assert $==getsize('res 4,(iy+#12),b'):bank:res 4,(iy+#12),c:assert $==getsize('res 4,(iy+#12),c'):bank:res 4,(iy+#12),d:assert $==getsize('res 4,(iy+#12),d')" \
+":bank:res 4,(iy+#12),e:assert $==getsize('res 4,(iy+#12),e'):bank:res 4,(iy+#12),h:assert $==getsize('res 4,(iy+#12),h'):bank:res 4,(iy+#12),l:assert $==getsize('res 4,(iy+#12),l')" \
+":bank:res 4,(iy+#12):assert $==getsize('res 4,(iy+#12)'):bank:res 4,(iy+#12),a:assert $==getsize('res 4,(iy+#12),a'):bank:res 5,(iy+#12),b:assert $==getsize('res 5,(iy+#12),b')" \
+":bank:res 5,(iy+#12),c:assert $==getsize('res 5,(iy+#12),c'):bank:res 5,(iy+#12),d:assert $==getsize('res 5,(iy+#12),d'):bank:res 5,(iy+#12),e:assert $==getsize('res 5,(iy+#12),e')" \
+":bank:res 5,(iy+#12),h:assert $==getsize('res 5,(iy+#12),h'):bank:res 5,(iy+#12),l:assert $==getsize('res 5,(iy+#12),l'):bank:res 5,(iy+#12):assert $==getsize('res 5,(iy+#12)')" \
+":bank:res 5,(iy+#12),a:assert $==getsize('res 5,(iy+#12),a'):bank:res 6,(iy+#12),b:assert $==getsize('res 6,(iy+#12),b'):bank:res 6,(iy+#12),c:assert $==getsize('res 6,(iy+#12),c')" \
+":bank:res 6,(iy+#12),d:assert $==getsize('res 6,(iy+#12),d'):bank:res 6,(iy+#12),e:assert $==getsize('res 6,(iy+#12),e'):bank:res 6,(iy+#12),h:assert $==getsize('res 6,(iy+#12),h')" \
+":bank:res 6,(iy+#12),l:assert $==getsize('res 6,(iy+#12),l'):bank:res 6,(iy+#12):assert $==getsize('res 6,(iy+#12)'):bank:res 6,(iy+#12),a:assert $==getsize('res 6,(iy+#12),a')" \
+":bank:res 7,(iy+#12),b:assert $==getsize('res 7,(iy+#12),b'):bank:res 7,(iy+#12),c:assert $==getsize('res 7,(iy+#12),c'):bank:res 7,(iy+#12),d:assert $==getsize('res 7,(iy+#12),d')" \
+":bank:res 7,(iy+#12),e:assert $==getsize('res 7,(iy+#12),e'):bank:res 7,(iy+#12),h:assert $==getsize('res 7,(iy+#12),h'):bank:res 7,(iy+#12),l:assert $==getsize('res 7,(iy+#12),l')" \
+":bank:res 7,(iy+#12):assert $==getsize('res 7,(iy+#12)'):bank:res 7,(iy+#12),a:assert $==getsize('res 7,(iy+#12),a'):bank:set 0,(iy+#12),b:assert $==getsize('set 0,(iy+#12),b')" \
+":bank:set 0,(iy+#12),c:assert $==getsize('set 0,(iy+#12),c'):bank:set 0,(iy+#12),d:assert $==getsize('set 0,(iy+#12),d'):bank:set 0,(iy+#12),e:assert $==getsize('set 0,(iy+#12),e')" \
+":bank:set 0,(iy+#12),h:assert $==getsize('set 0,(iy+#12),h'):bank:set 0,(iy+#12),l:assert $==getsize('set 0,(iy+#12),l'):bank:set 0,(iy+#12):assert $==getsize('set 0,(iy+#12)')" \
+":bank:set 1,(iy+#12),d:assert $==getsize('set 1,(iy+#12),d'):bank:set 1,(iy+#12),e:assert $==getsize('set 1,(iy+#12),e'):bank:set 1,(iy+#12),h:assert $==getsize('set 1,(iy+#12),h')" \
+":bank:set 1,(iy+#12),l:assert $==getsize('set 1,(iy+#12),l'):bank:set 1,(iy+#12):assert $==getsize('set 1,(iy+#12)'):bank:set 1,(iy+#12),a:assert $==getsize('set 1,(iy+#12),a')" \
+":bank:set 2,(iy+#12),b:assert $==getsize('set 2,(iy+#12),b'):bank:set 2,(iy+#12),c:assert $==getsize('set 2,(iy+#12),c'):bank:set 2,(iy+#12),d:assert $==getsize('set 2,(iy+#12),d')" \
+":bank:set 2,(iy+#12),e:assert $==getsize('set 2,(iy+#12),e'):bank:set 2,(iy+#12),h:assert $==getsize('set 2,(iy+#12),h'):bank:set 2,(iy+#12),l:assert $==getsize('set 2,(iy+#12),l')" \
+":bank:set 2,(iy+#12):assert $==getsize('set 2,(iy+#12)'):bank:set 2,(iy+#12),a:assert $==getsize('set 2,(iy+#12),a'):bank:set 3,(iy+#12),b:assert $==getsize('set 3,(iy+#12),b')" \
+":bank:set 3,(iy+#12),c:assert $==getsize('set 3,(iy+#12),c'):bank:set 3,(iy+#12),d:assert $==getsize('set 3,(iy+#12),d'):bank:set 3,(iy+#12),e:assert $==getsize('set 3,(iy+#12),e')" \
+":bank:set 3,(iy+#12),h:assert $==getsize('set 3,(iy+#12),h'):bank:set 3,(iy+#12),l:assert $==getsize('set 3,(iy+#12),l'):bank:set 3,(iy+#12):assert $==getsize('set 3,(iy+#12)')" \
+":bank:set 3,(iy+#12),a:assert $==getsize('set 3,(iy+#12),a'):bank:set 4,(iy+#12),b:assert $==getsize('set 4,(iy+#12),b'):bank:set 4,(iy+#12),c:assert $==getsize('set 4,(iy+#12),c')" \
+":bank:set 4,(iy+#12),d:assert $==getsize('set 4,(iy+#12),d'):bank:set 4,(iy+#12),e:assert $==getsize('set 4,(iy+#12),e'):bank:set 4,(iy+#12),h:assert $==getsize('set 4,(iy+#12),h')" \
+":bank:set 4,(iy+#12),l:assert $==getsize('set 4,(iy+#12),l'):bank:set 4,(iy+#12):assert $==getsize('set 4,(iy+#12)'):bank:set 4,(iy+#12),a:assert $==getsize('set 4,(iy+#12),a')" \
+":bank:set 5,(iy+#12),b:assert $==getsize('set 5,(iy+#12),b'):bank:set 5,(iy+#12),c:assert $==getsize('set 5,(iy+#12),c'):bank:set 5,(iy+#12),d:assert $==getsize('set 5,(iy+#12),d')" \
+":bank:set 5,(iy+#12),e:assert $==getsize('set 5,(iy+#12),e'):bank:set 5,(iy+#12),h:assert $==getsize('set 5,(iy+#12),h'):bank:set 5,(iy+#12),l:assert $==getsize('set 5,(iy+#12),l')" \
+":bank:set 5,(iy+#12):assert $==getsize('set 5,(iy+#12)'):bank:set 5,(iy+#12),a:assert $==getsize('set 5,(iy+#12),a'):bank:set 6,(ix+#12),c:assert $==getsize('set 6,(ix+#12),c')" \
+":bank:set 6,(ix+#12),d:assert $==getsize('set 6,(ix+#12),d'):bank:set 6,(ix+#12),e:assert $==getsize('set 6,(ix+#12),e'):bank:set 6,(ix+#12),h:assert $==getsize('set 6,(ix+#12),h')" \
+":bank:set 6,(ix+#12),l:assert $==getsize('set 6,(ix+#12),l'):bank:set 6,(ix+#12):assert $==getsize('set 6,(ix+#12)'):bank:set 6,(ix+#12),a:assert $==getsize('set 6,(ix+#12),a')" \
+":bank:set 7,(ix+#12),b:assert $==getsize('set 7,(ix+#12),b'):bank:set 7,(ix+#12),c:assert $==getsize('set 7,(ix+#12),c'):bank:set 7,(ix+#12),d:assert $==getsize('set 7,(ix+#12),d')" \
+":bank:set 7,(ix+#12),e:assert $==getsize('set 7,(ix+#12),e'):bank:set 7,(ix+#12),h:assert $==getsize('set 7,(ix+#12),h'):bank:set 7,(ix+#12),l:assert $==getsize('set 7,(ix+#12),l')" \
+":bank:set 7,(ix+#12):assert $==getsize('set 7,(ix+#12)'):bank:set 7,(ix+#12),a:assert $==getsize('set 7,(ix+#12),a'):bank:add iy,bc:assert $==getsize('add iy,bc')" \
+":bank:add iy,de:assert $==getsize('add iy,de'):bank:ld iy,#1234:assert $==getsize('ld iy,#1234'):bank:ld (#1234),iy:assert $==getsize('ld (#1234),iy')" \
+":bank:inc iy:assert $==getsize('inc iy'):bank:inc yh:assert $==getsize('inc yh'):bank:dec yh:assert $==getsize('dec yh')" \
+":bank:ld yh,#12:assert $==getsize('ld yh,#12'):bank:add iy,iy:assert $==getsize('add iy,iy'):bank:ld iy,(#1234):assert $==getsize('ld iy,(#1234)')" \
+":bank:dec iy:assert $==getsize('dec iy'):bank:inc yl:assert $==getsize('inc yl'):bank:dec yl:assert $==getsize('dec yl')" \
+":bank:ld yl,#12:assert $==getsize('ld yl,#12'):bank:inc (iy+#12):assert $==getsize('inc (iy+#12)'):bank:dec (iy+#12):assert $==getsize('dec (iy+#12)')" \
+":bank:ld (iy+#12),#34:assert $==getsize('ld (iy+#12),#34'):bank:add iy,sp:assert $==getsize('add iy,sp'):bank:ld b,yh:assert $==getsize('ld b,yh')" \
+":bank:ld b,yl:assert $==getsize('ld b,yl'):bank:ld b,(iy+#12):assert $==getsize('ld b,(iy+#12)'):bank:ld c,yh:assert $==getsize('ld c,yh')" \
+":bank:ld c,yl:assert $==getsize('ld c,yl'):bank:ld c,(iy+#12):assert $==getsize('ld c,(iy+#12)'):bank:ld d,yh:assert $==getsize('ld d,yh')" \
+":bank:ld d,yl:assert $==getsize('ld d,yl'):bank:ld d,(iy+#12):assert $==getsize('ld d,(iy+#12)'):bank:ld e,yh:assert $==getsize('ld e,yh')" \
+":bank:ld e,yl:assert $==getsize('ld e,yl'):bank:ld e,(iy+#12):assert $==getsize('ld e,(iy+#12)'):bank:ld yh,b:assert $==getsize('ld yh,b')" \
+":bank:ld yh,c:assert $==getsize('ld yh,c'):bank:ld yh,d:assert $==getsize('ld yh,d'):bank:ld yh,e:assert $==getsize('ld yh,e')" \
+":bank:ld yh,yh:assert $==getsize('ld yh,yh'):bank:ld yh,yl:assert $==getsize('ld yh,yl'):bank:ld h,(iy+#12):assert $==getsize('ld h,(iy+#12)')" \
+":bank:ld yh,a:assert $==getsize('ld yh,a'):bank:ld yl,b:assert $==getsize('ld yl,b'):bank:ld yl,c:assert $==getsize('ld yl,c')" \
+":bank:ld yl,d:assert $==getsize('ld yl,d'):bank:ld yl,e:assert $==getsize('ld yl,e'):bank:ld yl,yh:assert $==getsize('ld yl,yh')" \
+":bank:ld yl,yl:assert $==getsize('ld yl,yl'):bank:ld l,(iy+#12):assert $==getsize('ld l,(iy+#12)'):bank:ld yl,a:assert $==getsize('ld yl,a')" \
+":bank:ld (iy+#12),b:assert $==getsize('ld (iy+#12),b'):bank:ld (iy+#12),c:assert $==getsize('ld (iy+#12),c'):bank:ld (iy+#12),d:assert $==getsize('ld (iy+#12),d')" \
+":bank:ld (iy+#12),e:assert $==getsize('ld (iy+#12),e'):bank:ld (iy+#12),h:assert $==getsize('ld (iy+#12),h'):bank:ld (iy+#12),l:assert $==getsize('ld (iy+#12),l')" \
+":bank:ld (iy+#12),a:assert $==getsize('ld (iy+#12),a'):bank:ld a,yh:assert $==getsize('ld a,yh'):bank:ld a,yl:assert $==getsize('ld a,yl')" \
+":bank:ld a,(iy+#12):assert $==getsize('ld a,(iy+#12)'):bank:add yh:assert $==getsize('add yh'):bank:add yl:assert $==getsize('add yl')" \
+":bank:add (iy+#12):assert $==getsize('add (iy+#12)'):bank:adc yh:assert $==getsize('adc yh'):bank:adc yl:assert $==getsize('adc yl')" \
+":bank:adc (iy+#12):assert $==getsize('adc (iy+#12)'):bank:sub yh:assert $==getsize('sub yh'):bank:sub yl:assert $==getsize('sub yl')" \
+":bank:sub (iy+#12):assert $==getsize('sub (iy+#12)'):bank:sbc yh:assert $==getsize('sbc yh'):bank:sbc yl:assert $==getsize('sbc yl')" \
+":bank:sbc (iy+#12):assert $==getsize('sbc (iy+#12)'):bank:and yh:assert $==getsize('and yh'):bank:and yl:assert $==getsize('and yl')" \
+":bank:and (iy+#12):assert $==getsize('and (iy+#12)'):bank:xor yh:assert $==getsize('xor yh'):bank:xor yl:assert $==getsize('xor yl')" \
+":bank:xor (iy+#12):assert $==getsize('xor (iy+#12)'):bank:or yh:assert $==getsize('or yh'):bank:or yl:assert $==getsize('or yl')" \
+":bank:or (iy+#12):assert $==getsize('or (iy+#12)'):bank:cp yh:assert $==getsize('cp yh'):bank:cp yl:assert $==getsize('cp yl')" \
+":bank:cp (iy+#12):assert $==getsize('cp (iy+#12)'):bank:pop iy:assert $==getsize('pop iy'):bank:ex (sp),iy:assert $==getsize('ex (sp),iy')" \
+":bank:push iy:assert $==getsize('push iy'):bank:jp (iy):assert $==getsize('jp (iy)'):bank:ld sp,iy:assert $==getsize('ld sp,iy')" \
+":bank:rlc (iy+#12),b:assert $==getsize('rlc (iy+#12),b'):bank:rlc (iy+#12),c:assert $==getsize('rlc (iy+#12),c'):bank:rlc (iy+#12),d:assert $==getsize('rlc (iy+#12),d')" \
+":bank:rlc (iy+#12),e:assert $==getsize('rlc (iy+#12),e'):bank:rlc (iy+#12),h:assert $==getsize('rlc (iy+#12),h'):bank:rlc (iy+#12),l:assert $==getsize('rlc (iy+#12),l')" \
+":bank:rlc (iy+#12):assert $==getsize('rlc (iy+#12)'):bank:rlc (iy+#12),a:assert $==getsize('rlc (iy+#12),a'):bank:rrc (iy+#12),b:assert $==getsize('rrc (iy+#12),b')" \
+":bank:rrc (iy+#12),c:assert $==getsize('rrc (iy+#12),c'):bank:rrc (iy+#12),d:assert $==getsize('rrc (iy+#12),d'):bank:rrc (iy+#12),e:assert $==getsize('rrc (iy+#12),e')" \
+":bank:rrc (iy+#12),h:assert $==getsize('rrc (iy+#12),h'):bank:rrc (iy+#12),l:assert $==getsize('rrc (iy+#12),l'):bank:rrc (iy+#12):assert $==getsize('rrc (iy+#12)')" \
+":bank:rrc (iy+#12),a:assert $==getsize('rrc (iy+#12),a'):bank:rl (iy+#12),b:assert $==getsize('rl (iy+#12),b'):bank:rl (iy+#12),c:assert $==getsize('rl (iy+#12),c')" \
+":bank:rl (iy+#12),d:assert $==getsize('rl (iy+#12),d'):bank:rl (iy+#12),e:assert $==getsize('rl (iy+#12),e'):bank:rl (iy+#12),h:assert $==getsize('rl (iy+#12),h')" \
+":bank:rl (iy+#12),l:assert $==getsize('rl (iy+#12),l'):bank:rl (iy+#12):assert $==getsize('rl (iy+#12)'):bank:rl (iy+#12),a:assert $==getsize('rl (iy+#12),a')" \
+":bank:rr (iy+#12),b:assert $==getsize('rr (iy+#12),b'):bank:rr (iy+#12),c:assert $==getsize('rr (iy+#12),c'):bank:rr (iy+#12),d:assert $==getsize('rr (iy+#12),d')" \
+":bank:rr (iy+#12),e:assert $==getsize('rr (iy+#12),e'):bank:rr (iy+#12),h:assert $==getsize('rr (iy+#12),h'):bank:rr (iy+#12),l:assert $==getsize('rr (iy+#12),l')" \
+":bank:rr (iy+#12):assert $==getsize('rr (iy+#12)'):bank:rr (iy+#12),a:assert $==getsize('rr (iy+#12),a'):bank:sla (iy+#12),b:assert $==getsize('sla (iy+#12),b')" \
+":bank:sla (iy+#12),c:assert $==getsize('sla (iy+#12),c'):bank:sla (iy+#12),d:assert $==getsize('sla (iy+#12),d'):bank:sla (iy+#12),e:assert $==getsize('sla (iy+#12),e')" \
+":bank:sla (iy+#12),h:assert $==getsize('sla (iy+#12),h'):bank:sla (iy+#12),l:assert $==getsize('sla (iy+#12),l'):bank:sla (iy+#12):assert $==getsize('sla (iy+#12)')" \
+":bank:sla (iy+#12),a:assert $==getsize('sla (iy+#12),a'):bank:sra (iy+#12),b:assert $==getsize('sra (iy+#12),b'):bank:sra (iy+#12),c:assert $==getsize('sra (iy+#12),c')" \
+":bank:sra (iy+#12),d:assert $==getsize('sra (iy+#12),d'):bank:sra (iy+#12),e:assert $==getsize('sra (iy+#12),e'):bank:sra (iy+#12),h:assert $==getsize('sra (iy+#12),h')" \
+":bank:sra (iy+#12),l:assert $==getsize('sra (iy+#12),l'):bank:sra (iy+#12):assert $==getsize('sra (iy+#12)'):bank:sra (iy+#12),a:assert $==getsize('sra (iy+#12),a')" \
+":bank:sll (iy+#12),b:assert $==getsize('sll (iy+#12),b'):bank:sll (iy+#12),c:assert $==getsize('sll (iy+#12),c'):bank:sll (iy+#12),d:assert $==getsize('sll (iy+#12),d')" \
+":bank:sll (iy+#12),e:assert $==getsize('sll (iy+#12),e'):bank:sll (iy+#12),h:assert $==getsize('sll (iy+#12),h'):bank:sll (iy+#12),l:assert $==getsize('sll (iy+#12),l')" \
+":bank:sll (iy+#12):assert $==getsize('sll (iy+#12)'):bank:sll (iy+#12),a:assert $==getsize('sll (iy+#12),a'):bank:srl (iy+#12),b:assert $==getsize('srl (iy+#12),b')" \
+":bank:srl (iy+#12),c:assert $==getsize('srl (iy+#12),c'):bank:srl (iy+#12),d:assert $==getsize('srl (iy+#12),d'):bank:srl (iy+#12),e:assert $==getsize('srl (iy+#12),e')" \
+":bank:srl (iy+#12),h:assert $==getsize('srl (iy+#12),h'):bank:srl (iy+#12),l:assert $==getsize('srl (iy+#12),l'):bank:srl (iy+#12):assert $==getsize('srl (iy+#12)')" \
+":bank:srl (iy+#12),a:assert $==getsize('srl (iy+#12),a'):bank:bit 0,(iy+#12):assert $==getsize('bit 0,(iy+#12)'):bank:bit 1,(iy+#12):assert $==getsize('bit 1,(iy+#12)')" \
+":bank:bit 2,(iy+#12):assert $==getsize('bit 2,(iy+#12)'):bank:bit 3,(iy+#12):assert $==getsize('bit 3,(iy+#12)'):bank:bit 4,(iy+#12):assert $==getsize('bit 4,(iy+#12)')" \
+":bank:bit 5,(iy+#12):assert $==getsize('bit 5,(iy+#12)'):bank:bit 6,(iy+#12):assert $==getsize('bit 6,(iy+#12)'):bank:bit 7,(iy+#12):assert $==getsize('bit 7,(iy+#12)')" \
+":bank:res 0,(iy+#12),b:assert $==getsize('res 0,(iy+#12),b'):bank:res 0,(iy+#12),c:assert $==getsize('res 0,(iy+#12),c'):bank:res 0,(iy+#12),d:assert $==getsize('res 0,(iy+#12),d')" \
+":bank:res 0,(iy+#12),e:assert $==getsize('res 0,(iy+#12),e'):bank:res 0,(iy+#12),h:assert $==getsize('res 0,(iy+#12),h'):bank:res 0,(iy+#12),l:assert $==getsize('res 0,(iy+#12),l')" \
+":bank:res 0,(iy+#12):assert $==getsize('res 0,(iy+#12)'):bank:res 0,(iy+#12),a:assert $==getsize('res 0,(iy+#12),a'):bank:res 1,(iy+#12),b:assert $==getsize('res 1,(iy+#12),b')" \
+":bank:res 1,(iy+#12),c:assert $==getsize('res 1,(iy+#12),c'):bank:res 1,(iy+#12),d:assert $==getsize('res 1,(iy+#12),d'):bank:res 1,(iy+#12),e:assert $==getsize('res 1,(iy+#12),e')" \
+":bank:res 1,(iy+#12),h:assert $==getsize('res 1,(iy+#12),h'):bank:res 1,(iy+#12),l:assert $==getsize('res 1,(iy+#12),l'):bank:res 1,(iy+#12):assert $==getsize('res 1,(iy+#12)')" \
+":bank:res 1,(iy+#12),a:assert $==getsize('res 1,(iy+#12),a'):bank:res 2,(iy+#12),b:assert $==getsize('res 2,(iy+#12),b'):bank:res 2,(iy+#12),c:assert $==getsize('res 2,(iy+#12),c')" \
+":bank:res 2,(iy+#12),d:assert $==getsize('res 2,(iy+#12),d'):bank:res 2,(iy+#12),e:assert $==getsize('res 2,(iy+#12),e'):bank:res 2,(iy+#12),h:assert $==getsize('res 2,(iy+#12),h')" \
+":bank:res 2,(iy+#12),l:assert $==getsize('res 2,(iy+#12),l'):bank:res 2,(iy+#12):assert $==getsize('res 2,(iy+#12)'):bank:res 2,(iy+#12),a:assert $==getsize('res 2,(iy+#12),a')" \
+":bank:res 3,(iy+#12),b:assert $==getsize('res 3,(iy+#12),b'):bank:res 3,(iy+#12),c:assert $==getsize('res 3,(iy+#12),c'):bank:res 3,(iy+#12),d:assert $==getsize('res 3,(iy+#12),d')" \
+":bank:res 3,(iy+#12),e:assert $==getsize('res 3,(iy+#12),e'):bank:res 3,(iy+#12),h:assert $==getsize('res 3,(iy+#12),h'):bank:res 3,(iy+#12),l:assert $==getsize('res 3,(iy+#12),l')" \
+":bank:res 3,(iy+#12):assert $==getsize('res 3,(iy+#12)'):bank:res 3,(iy+#12),a:assert $==getsize('res 3,(iy+#12),a'):bank:res 4,(iy+#12),b:assert $==getsize('res 4,(iy+#12),b')" \
+":bank:res 4,(iy+#12),c:assert $==getsize('res 4,(iy+#12),c'):bank:res 4,(iy+#12),d:assert $==getsize('res 4,(iy+#12),d'):bank:res 4,(iy+#12),e:assert $==getsize('res 4,(iy+#12),e')" \
+":bank:res 4,(iy+#12),h:assert $==getsize('res 4,(iy+#12),h'):bank:res 4,(iy+#12),l:assert $==getsize('res 4,(iy+#12),l'):bank:res 4,(iy+#12):assert $==getsize('res 4,(iy+#12)')" \
+":bank:res 4,(iy+#12),a:assert $==getsize('res 4,(iy+#12),a'):bank:res 5,(iy+#12),b:assert $==getsize('res 5,(iy+#12),b'):bank:res 5,(iy+#12),c:assert $==getsize('res 5,(iy+#12),c')" \
+":bank:res 5,(iy+#12),d:assert $==getsize('res 5,(iy+#12),d'):bank:res 5,(iy+#12),e:assert $==getsize('res 5,(iy+#12),e'):bank:res 5,(iy+#12),h:assert $==getsize('res 5,(iy+#12),h')" \
+":bank:res 5,(iy+#12),l:assert $==getsize('res 5,(iy+#12),l'):bank:res 5,(iy+#12):assert $==getsize('res 5,(iy+#12)'):bank:res 5,(iy+#12),a:assert $==getsize('res 5,(iy+#12),a')" \
+":bank:res 6,(iy+#12),b:assert $==getsize('res 6,(iy+#12),b'):bank:res 6,(iy+#12),c:assert $==getsize('res 6,(iy+#12),c'):bank:res 6,(iy+#12),d:assert $==getsize('res 6,(iy+#12),d')" \
+":bank:res 6,(iy+#12),e:assert $==getsize('res 6,(iy+#12),e'):bank:res 6,(iy+#12),h:assert $==getsize('res 6,(iy+#12),h'):bank:res 6,(iy+#12),l:assert $==getsize('res 6,(iy+#12),l')" \
+":bank:res 6,(iy+#12):assert $==getsize('res 6,(iy+#12)'):bank:res 6,(iy+#12),a:assert $==getsize('res 6,(iy+#12),a'):bank:res 7,(iy+#12),b:assert $==getsize('res 7,(iy+#12),b')" \
+":bank:res 7,(iy+#12),c:assert $==getsize('res 7,(iy+#12),c'):bank:res 7,(iy+#12),d:assert $==getsize('res 7,(iy+#12),d'):bank:res 7,(iy+#12),e:assert $==getsize('res 7,(iy+#12),e')" \
+":bank:res 7,(iy+#12),h:assert $==getsize('res 7,(iy+#12),h'):bank:res 7,(iy+#12),l:assert $==getsize('res 7,(iy+#12),l'):bank:res 7,(iy+#12):assert $==getsize('res 7,(iy+#12)')" \
+":bank:res 7,(iy+#12),a:assert $==getsize('res 7,(iy+#12),a'):bank:set 0,(iy+#12),b:assert $==getsize('set 0,(iy+#12),b'):bank:set 0,(iy+#12),c:assert $==getsize('set 0,(iy+#12),c')" \
+":bank:set 0,(iy+#12),d:assert $==getsize('set 0,(iy+#12),d'):bank:set 0,(iy+#12),e:assert $==getsize('set 0,(iy+#12),e'):bank:set 0,(iy+#12),h:assert $==getsize('set 0,(iy+#12),h')" \
+":bank:set 0,(iy+#12),l:assert $==getsize('set 0,(iy+#12),l'):bank:set 0,(iy+#12):assert $==getsize('set 0,(iy+#12)'):bank:set 0,(iy+#12),a:assert $==getsize('set 0,(iy+#12),a')" \
+":bank:set 1,(iy+#12),b:assert $==getsize('set 1,(iy+#12),b'):bank:set 1,(iy+#12),c:assert $==getsize('set 1,(iy+#12),c'):bank:set 1,(iy+#12),d:assert $==getsize('set 1,(iy+#12),d')" \
+":bank:set 1,(iy+#12),e:assert $==getsize('set 1,(iy+#12),e'):bank:set 1,(iy+#12),h:assert $==getsize('set 1,(iy+#12),h'):bank:set 1,(iy+#12),l:assert $==getsize('set 1,(iy+#12),l')" \
+":bank:set 1,(iy+#12):assert $==getsize('set 1,(iy+#12)'):bank:set 1,(iy+#12),a:assert $==getsize('set 1,(iy+#12),a'):bank:set 2,(iy+#12),b:assert $==getsize('set 2,(iy+#12),b')" \
+":bank:set 2,(iy+#12),c:assert $==getsize('set 2,(iy+#12),c'):bank:set 2,(iy+#12),d:assert $==getsize('set 2,(iy+#12),d'):bank:set 2,(iy+#12),e:assert $==getsize('set 2,(iy+#12),e')" \
+":bank:set 2,(iy+#12),h:assert $==getsize('set 2,(iy+#12),h'):bank:set 2,(iy+#12),l:assert $==getsize('set 2,(iy+#12),l'):bank:set 2,(iy+#12):assert $==getsize('set 2,(iy+#12)')" \
+":bank:set 2,(iy+#12),a:assert $==getsize('set 2,(iy+#12),a'):bank:set 3,(iy+#12),b:assert $==getsize('set 3,(iy+#12),b'):bank:set 3,(iy+#12),c:assert $==getsize('set 3,(iy+#12),c')" \
+":bank:set 3,(iy+#12),d:assert $==getsize('set 3,(iy+#12),d'):bank:set 3,(iy+#12),e:assert $==getsize('set 3,(iy+#12),e'):bank:set 3,(iy+#12),h:assert $==getsize('set 3,(iy+#12),h')" \
+":bank:set 3,(iy+#12),l:assert $==getsize('set 3,(iy+#12),l'):bank:set 3,(iy+#12):assert $==getsize('set 3,(iy+#12)'):bank:set 3,(iy+#12),a:assert $==getsize('set 3,(iy+#12),a')" \
+":bank:set 4,(iy+#12),b:assert $==getsize('set 4,(iy+#12),b'):bank:set 4,(iy+#12),c:assert $==getsize('set 4,(iy+#12),c'):bank:set 4,(iy+#12),d:assert $==getsize('set 4,(iy+#12),d')" \
+":bank:set 4,(iy+#12),e:assert $==getsize('set 4,(iy+#12),e'):bank:set 4,(iy+#12),h:assert $==getsize('set 4,(iy+#12),h'):bank:set 4,(iy+#12),l:assert $==getsize('set 4,(iy+#12),l')" \
+":bank:set 4,(iy+#12):assert $==getsize('set 4,(iy+#12)'):bank:set 4,(iy+#12),a:assert $==getsize('set 4,(iy+#12),a'):bank:set 5,(iy+#12),b:assert $==getsize('set 5,(iy+#12),b')" \
+":bank:set 5,(iy+#12),c:assert $==getsize('set 5,(iy+#12),c'):bank:set 5,(iy+#12),d:assert $==getsize('set 5,(iy+#12),d'):bank:set 5,(iy+#12),e:assert $==getsize('set 5,(iy+#12),e')" \
+":bank:set 5,(iy+#12),h:assert $==getsize('set 5,(iy+#12),h'):bank:set 5,(iy+#12),l:assert $==getsize('set 5,(iy+#12),l'):bank:set 5,(iy+#12):assert $==getsize('set 5,(iy+#12)')" \
+":bank:set 5,(iy+#12),a:assert $==getsize('set 5,(iy+#12),a'):bank:set 6,(iy+#12),b:assert $==getsize('set 6,(iy+#12),b'):bank:set 6,(iy+#12),c:assert $==getsize('set 6,(iy+#12),c')" \
+":bank:set 6,(iy+#12),d:assert $==getsize('set 6,(iy+#12),d'):bank:set 6,(iy+#12),e:assert $==getsize('set 6,(iy+#12),e'):bank:set 6,(iy+#12),h:assert $==getsize('set 6,(iy+#12),h')" \
+":bank:set 6,(iy+#12),l:assert $==getsize('set 6,(iy+#12),l'):bank:set 6,(iy+#12):assert $==getsize('set 6,(iy+#12)'):bank:set 6,(iy+#12),a:assert $==getsize('set 6,(iy+#12),a')" \
+":bank:set 7,(iy+#12),b:assert $==getsize('set 7,(iy+#12),b'):bank:set 7,(iy+#12),c:assert $==getsize('set 7,(iy+#12),c'):bank:set 7,(iy+#12),d:assert $==getsize('set 7,(iy+#12),d')" \
+":bank:set 7,(iy+#12),e:assert $==getsize('set 7,(iy+#12),e'):bank:set 7,(iy+#12),h:assert $==getsize('set 7,(iy+#12),h'):bank:set 7,(iy+#12),l:assert $==getsize('set 7,(iy+#12),l')" \
+":bank:set 7,(iy+#12):assert $==getsize('set 7,(iy+#12)'):bank:set 7,(iy+#12),a:assert $==getsize('set 7,(iy+#12),a'):bank:set 7,(iy+#12),a:assert $==getsize('set 7,(iy+#12),a')"
+
+#define AUTOTEST_REPEAT3 "y=0: repeat 0: y+=1: rend: assert y==0: y=0: repeat 1: y+=1: rend: assert y==1:"\
+ "y=0: repeat 5: y+=1: rend: assert y==5: y=1: repeat 5,x: assert y==x: y+=1: rend: y=2: repeat 5,x,2,2: assert x==y:"\
+ "y+=2: rend: startingindex 5: y=5: repeat 2,x: assert x==y: y+=1: rend: startingindex 5,5: y=10: repeat 3,x,10: assert x==y: "\
+ "y+=5: rend: startingindex: y=1: repeat 2,x: assert x==y: y+=1: rend: nop "
+
+#define AUTOTEST_SNASET "buildsna:bank 0:nop:"\
+ ":snaset Z80_AF,0x1234 :snaset Z80_A,0x11 :snaset Z80_F,0x11 :snaset Z80_BC,0x11 :snaset Z80_B,0x11 :snaset Z80_C,0x11 :snaset Z80_DE,0x11 :snaset Z80_D,0x11"\
+ ":snaset Z80_E,0x11 :snaset Z80_HL,0x11 :snaset Z80_H,0x11 :snaset Z80_L,0x11 :snaset Z80_R,0x11 :snaset Z80_I,0x11 :snaset Z80_IFF0,0x11 :snaset Z80_IFF1,0x11"\
+ ":snaset Z80_IX,0x11 :snaset Z80_IY,0x11 :snaset Z80_IXL,0x11 :snaset Z80_IXH,0x11 :snaset Z80_IYL,0x11 :snaset Z80_IYH,0x11 :snaset Z80_SP,0x11 :snaset Z80_PC,0x11"\
+ ":snaset Z80_IM,0x11 :snaset Z80_AFX,0x11 :snaset Z80_AX,0x11 :snaset Z80_FX,0x11 :snaset Z80_BCX,0x11 :snaset Z80_BX,0x11 :snaset Z80_CX,0x11 :snaset Z80_DEX,0x11"\
+ ":snaset Z80_DX,0x11 :snaset Z80_EX,0x11 :snaset Z80_HLX,0x11 :snaset Z80_HX,0x11 :snaset Z80_LX,0x11 :snaset FDD_MOTOR,0x11 :snaset FDD_TRACK,0x11 :snaset PRNT_DATA,0x11"\
+ ":snaset PPI_A,0x1 :snaset PPI_B,0x1 :snaset PPI_C,0x1 :snaset PPI_CTL,0x1 :snaset INT_NUM,0x1 :snaset INT_REQ,0x11 :snaset PSG_SEL,0x1 :snaset CRTC_SEL,0x1"\
+ ":snaset CRTC_TYPE,0x1 :snaset CRTC_HCC,0x11 :snaset CRTC_CLC,0x11 :snaset CRTC_RLC,0x11 :snaset CRTC_VAC,0x11 :snaset CRTC_VSWC,0x11 :snaset CRTC_HSWC,0x11"\
+ ":snaset CRTC_STATE,0x11 :snaset GA_VSC,0x11 :snaset GA_ISC,0x11 :snaset GA_PEN,0x11 :snaset GA_ROMCFG,0x11 :snaset GA_RAMCFG,0x11 :snaset ROM_UP,0x11"\
+ ":snaset CRTC_REG,0,0x11 :snaset CRTC_REG,1,0x11 :snaset CRTC_REG,16,0x11 :snaset PSG_REG,0,0x11 :snaset PSG_REG,5,0x11 :snaset PSG_REG,15,0x11: bank : nop"
+
+#define AUTOTEST_INKCONV "assert s2h_ink(0)==0x54 :assert s2h_ink(1)==0x44 :assert s2h_ink(2)==0x55 :assert s2h_ink(3)==0x5C :assert s2h_ink(4)==0x58 :assert s2h_ink(5)==0x5D "\
+":assert s2h_ink(6)==0x4C :assert s2h_ink(7)==0x45 :assert s2h_ink(8)==0x4D :assert s2h_ink(9)==0x56 :assert s2h_ink(10)==0x46 :assert s2h_ink(11)==0x57 "\
+":assert s2h_ink(12)==0x5E :assert s2h_ink(13)==0x40 :assert soft2hard_ink(14)==0x5F :assert soft2hard_ink(15)==0x4E :assert soft2hard_ink(16)==0x47 "\
+":assert soft2hard_ink(17)==0x4F :assert soft2hard_ink(18)==0x52 :assert soft2hard_ink(19)==0x42 :assert soft2hard_ink(20)==0x53 :assert soft2hard_ink(21)==0x5A "\
+":assert soft2hard_ink(22)==0x59 :assert soft2hard_ink(23)==0x5B :assert soft2hard_ink(24)==0x4A :assert soft2hard_ink(25)==0x43 :assert soft2hard_ink(26)==0x4B "\
+":nop :assert h2s_ink(0)==13 :assert h2s_ink(0x40)==13 :assert h2s_ink(1)==13 :assert h2s_ink(2)==19 :assert h2s_ink(3)==25 :assert h2s_ink(4)==1 "\
+":assert h2s_ink(5)==7 :assert h2s_ink(6)==10 :assert h2s_ink(7)==16 :assert h2s_ink(8)==7 :assert h2s_ink(9)==25 :assert h2s_ink(10)==24 "\
+":assert h2s_ink(11)==26 :assert h2s_ink(12)==6 :assert h2s_ink(13)==8 :assert h2s_ink(14)==15 :assert hard2soft_ink(15)==17 :assert hard2soft_ink(16)==1 "\
+":assert hard2soft_ink(17)==19 :assert hard2soft_ink(18)==18 :assert hard2soft_ink(19)==20 :assert hard2soft_ink(20)==0 :assert hard2soft_ink(21)==2 "\
+":assert hard2soft_ink(22)==9 :assert hard2soft_ink(23)==11 :assert hard2soft_ink(24)==4 :assert hard2soft_ink(25)==22 :assert hard2soft_ink(26)==21 "\
+":assert hard2soft_ink(27)==23 :assert hard2soft_ink(28)==3 :assert hard2soft_ink(29)==5 :assert h2s_ink(30)==12 :assert h2s_ink(31)==14 :nop "
+
+#define AUTOTEST_ECPR1 "buildcpr extended : bank 32 : label1 : assert {bank}label1==32 : nop"
+
+#define AUTOTEST_BANKPROX " buildcpr: bank 0: grouik: .tape1: nop: ld hl,{bank}.tape2: bank 1: ld hl,{bank}.tape2: defw {bank}.tape2: .tape2: nop: "
+
+#define AUTOTEST_INTORAM1 " buildsna : bankset 0 : org #3FF8 : defb 'roudoudou in da house' "
+
+#define AUTOTEST_DEFMOD "nbt=0: module preums: label1 nop: label3: label4: ifdef label1:nbt+=1:endif: ifdef label3:nbt+=1:endif:"\
+"ifdef label4:nbt+=1:endif: ifndef label5:nbt+=1:endif: module deuze: label1 nop: label3: label5: ifdef label1:nbt+=1:endif:"\
+"ifdef label3:nbt+=1:endif: ifndef label4:nbt+=1:endif: ifdef label5:nbt+=1:endif: assert nbt==8:"\
+"module grouik: plop: ifused plop : glop=1 : endif:assert glop==1"
+
+#define AUTOTEST_GTILES "incbin 'autotest_include.raw',GTILES,4"
+#define AUTOTEST_ITILES "incbin 'autotest_include.raw',ITILES,4"
+#define AUTOTEST_GTILES_KO "incbin 'autotest_include.raw',GTILES,5"
+#define AUTOTEST_ITILES_KO "incbin 'autotest_include.raw',ITILES,5"
struct s_autotest_keyword {
@@ -16062,6 +22013,12 @@ struct s_autotest_keyword autotest_keyword[]={
{"jr z,$",0},{"jr 0",0},{"jr jr",1},{"jr (hl)",1},{"jr a",1},
{"jr nz,$",0},{"jr 0",0},{"jr jr",1},{"jr (hl)",1},{"jr a",1},
{"jp $",0},{"jp 0",0},{"jp jp",1},{"jp (hl)",0},{"jp (ix)",0},{"jp (iy)",0},{"jp (de)",1},{"jp a",1},
+ {"jp (ix+5)",1}, {"jp (ix-5)",1}, {"jp (iy-5)",1}, {"jp (iy+5)",1},
+
+ // new unsupported test cases
+ {"jp (ix+1)",1},{"ld iy,(ix+1)",1},{"ld ix,(iy+1)",1},{"ld ix,(ix+2)",1},{"ld ixh,(ix+1)",1},{"ld sp,(ix+0)",1},
+ {"ld (hl),(ix+0)",1},{"ld (iy+0),(iy+1)",1},{"ld (iy+0),(ix+1)",1},{"ld (ix+0),(iy+1)",1},{"ld (ix+0),(ix+1)",1},
+
{"jp c,$",0},{"jp c,0",0},{"jp c,jp",1}, {"jp c,(hl)",1}, {"jp c,(ix)",1}, {"jp c,(iy)",1},{"jp c,(de)",1},{"jp c,a",1},
{"jp nc,$",0},{"jp nc,0",0},{"jp nc,jp",1},{"jp nc,(hl)",1},{"jp nc,(ix)",1},{"jp nc,(iy)",1},{"jp nc,(de)",1},{"jp nc,a",1},
{"jp z,$",0},{"jp z,0",0},{"jp z,jp",1}, {"jp z,(hl)",1}, {"jp z,(ix)",1}, {"jp z,(iy)",1},{"jp z,(de)",1},{"jp z,a",1},
@@ -16071,9 +22028,9 @@ struct s_autotest_keyword autotest_keyword[]={
{"jp p,$",0},{"jp p,0",0},{"jp p,jp",1}, {"jp p,(hl)",1}, {"jp p,(ix)",1}, {"jp p,(iy)",1},{"jp p,(de)",1},{"jp p,a",1},
{"jp m,$",0},{"jp m,0",0},{"jp m,jp",1}, {"jp m,(hl)",1}, {"jp m,(ix)",1}, {"jp m,(iy)",1},{"jp m,(de)",1},{"jp m,a",1},
{"ret",0},{"ret c",0},{"ret nc",0},{"ret pe",0},{"ret po",0},{"ret m",0},{"ret p",0},{"reti",0},{"ret ret",1},{"ret 5",1},{"ret (hl)",1},{"ret a",1},
- {"xor a",0},{"xor a,b",1},{"xor",1},{"xor (de)",1},{"xor (hl)",0},{"xor (bc)",1},{"xor (ix+0)",0},{"xor (iy+0)",},{"xor xor",1},
- {"and a",0},{"and a,b",1},{"xor",1},{"and (de)",1},{"and (hl)",0},{"and (bc)",1},{"and (ix+0)",0},{"and (iy+0)",},{"and xor",1},
- {"or a",0},{"or a,b",1},{"xor",1},{"or (de)",1},{"or (hl)",0},{"or (bc)",1},{"or (ix+0)",0},{"or (iy+0)",},{"or xor",1},
+ {"xor a",0},{"xor a,b",1},{"xor",1},{"xor (de)",1},{"xor (hl)",0},{"xor (bc)",1},{"xor (ix+0)",0},{"xor (iy+0)",0},{"xor xor",1},
+ {"and a",0},{"and a,b",1},{"xor",1},{"and (de)",1},{"and (hl)",0},{"and (bc)",1},{"and (ix+0)",0},{"and (iy+0)",0},{"and xor",1},
+ {"or a",0},{"or a,b",1},{"xor",1},{"or (de)",1},{"or (hl)",0},{"or (bc)",1},{"or (ix+0)",0},{"or (iy+0)",0},{"or xor",1},
{"add",1},{"add a",0},{"add a,a",0},{"add add",1},{"add (hl)",0},{"add (de)",1},{"add xh",0},{"add grouik",1},
{"add hl,ix",1},{"add hl,iy",1},{"add ix,iy",1},{"add iy,ix",1},{"add hl,0",1},{"add hl,grouik",1},{"add ix,hl",1},{"add iy,hl",1},
{"adc",1},{"adc a",0},{"adc a,a",0},{"adc adc",1},{"adc (hl)",0},{"adc (de)",1},{"adc xh",0},{"adc grouik",1},
@@ -16084,7 +22041,7 @@ struct s_autotest_keyword autotest_keyword[]={
{"sbc hl,ix",1},{"sbc hl,iy",1},{"sbc ix,iy",1},{"sbc iy,ix",1},{"sbc hl,0",1},{"sbc hl,grouik",1},{"sbc ix,hl",1},{"sbc iy,hl",1},
{"exx",0},{"exx hl",1},{"exx hl,de",1},{"exx af,af'",1},{"exx exx",1},{"exx 5",1},
{"ex",1},{"ex af,af'",0},{"ex hl,de",0},{"ex hl,bc",1},{"ex hl,hl",1},{"ex hl,ix",1},
- {"cp",1},{"cp cp ",1},{"cp 5",0},{"cp c",0},{"cp a,5",0},{"cp a,c",0},{"cp hl",1},{"cp (hl)",0},{"cp a,(hl)",0},{"cp (de)",1},{"cp de",1},
+ {"cp",1},{"cp cp ",1},{"cp $",0},{"cp '$'",0},{"cp 'c'",0},{"cp 5",0},{"cp c",0},{"cp a,5",0},{"cp a,c",0},{"cp hl",1},{"cp (hl)",0},{"cp a,(hl)",0},{"cp (de)",1},{"cp de",1},
{"cpi",0},{"cpi (hl)",1},{"cpi a",1},{"cpi 5",1},
{"cpd",0},{"cpd (hl)",1},{"cpd a",1},{"cpd 5",1},
{"cpir",0},{"cpir (hl)",1},{"cpir a",1},{"cpir 5",1},
@@ -16107,6 +22064,7 @@ struct s_autotest_keyword autotest_keyword[]={
{"ccf ccf",1},{"ccf 0",1},{"ccf (hl)",1},
{"out",1},{"out out",1},{"out (c)",1},{"out (c),xh",1},{"out 0",1},
{"out (c),hl",1},{"out (hl),c",1},{"out (c),(ix+0)",1},{"out (c),a,b",1},
+ {"v nop:v0 nop:x=1:v{x} nop",0},
{"outi 0",1},{"outi (hl)",1},
{"otir 0",1},{"otir (hl)",1},
{"otdr 0",1},{"otdr (hl)",1},
@@ -16125,7 +22083,147 @@ struct s_autotest_keyword autotest_keyword[]={
{"repeat 5:nop:rend",0},{"repeat 100000:a=5:rend",1},{"repeat -5:nop:rend",1},{"repeat repeat:nop:rend",1},
{"macro bidule:nop:mend:bidule",0},{"macro bidule:nop:macro glop:nop:mend:mend:bidule",1},
{"macro bidule:nop",1},{"macro bidule:nop:mend:macro glop:nop:bidule",1},
+
+
+ {"defb getnop(1)",1},{"defb getnop(-1)",1},{"defb getnop(10)",1},{"defb getnop(\"rien\")",1},{"defb getnop()",1},{"defb getnop(\"djNz\")",0},
+ {"assert getnop('nop')==1 : nop",0},
+ {"assert getnop('ldi')==5 : nop",0}, {"assert getnop('ldd')==5 : nop",0},
+ {"assert getnop('dec a')==1 : nop",0}, {"assert getnop('dec b')==1 : nop",0}, {"assert getnop('dec c')==1 : nop",0},
+ {"assert getnop('dec d')==1 : nop",0}, {"assert getnop('dec e')==1 : nop",0}, {"assert getnop('dec h')==1 : nop",0},
+ {"assert getnop('dec l')==1 : nop",0}, {"assert getnop('dec xl')==2 : nop",0}, {"assert getnop('dec yl')==2 : nop",0},
+ {"assert getnop('dec xh')==2 : nop",0}, {"assert getnop('dec yh')==2 : nop",0}, {"assert getnop('dec bc')==2 : nop",0},
+ {"assert getnop('dec de')==2 : nop",0}, {"assert getnop('dec hl')==2 : nop",0}, {"assert getnop('dec sp')==2 : nop",0},
+ {"assert getnop('dec ix')==3 : nop",0}, {"assert getnop('dec iy')==3 : nop",0}, {"assert getnop('dec (hl)')==3 : nop",0},
+ {"assert getnop('dec (ix-50)')==6 : nop",0}, {"assert getnop('dec (iy+1)')==6 : nop",0},
+ {"assert getnop('set 0,a')==2 : nop",0}, {"assert getnop('set 2,a')==2 : nop",0}, {"assert getnop('set 5,a')==2 : nop",0},
+ {"assert getnop('set 0,b')==2 : nop",0}, {"assert getnop('set 0,c')==2 : nop",0}, {"assert getnop('set 0,d')==2 : nop",0},
+ {"assert getnop('set 0,e')==2 : nop",0}, {"assert getnop('set 0,h')==2 : nop",0}, {"assert getnop('set 0,l')==2 : nop",0},
+ {"assert getnop('set 0,(hl)')==4 : nop",0}, {"assert getnop('set 1,(ix+12),d')==7 : nop",0}, {"assert getnop('set 3,(iy-34),h')==7 : nop",0},
+ {"assert getnop('res 0,a')==2 : nop",0}, {"assert getnop('res 2,a')==2 : nop",0}, {"assert getnop('res 5,a')==2 : nop",0},
+ {"assert getnop('res 0,b')==2 : nop",0}, {"assert getnop('res 0,c')==2 : nop",0}, {"assert getnop('res 0,d')==2 : nop",0},
+ {"assert getnop('res 0,e')==2 : nop",0}, {"assert getnop('res 0,h')==2 : nop",0}, {"assert getnop('res 0,l')==2 : nop",0},
+ {"assert getnop('res 0,(hl)')==4 : nop",0}, {"assert getnop('res 1,(ix+12),d')==7 : nop",0}, {"assert getnop('res 3,(iy-34),h')==7 : nop",0},
+ {"assert getnop('bit 0,a')==2 : nop",0}, {"assert getnop('bit 2,a')==2 : nop",0}, {"assert getnop('bit 5,a')==2 : nop",0},
+ {"assert getnop('bit 0,b')==2 : nop",0}, {"assert getnop('bit 0,c')==2 : nop",0}, {"assert getnop('bit 0,d')==2 : nop",0},
+ {"assert getnop('bit 0,e')==2 : nop",0}, {"assert getnop('bit 0,h')==2 : nop",0}, {"assert getnop('bit 0,l')==2 : nop",0},
+ {"assert getnop('bit 0,(hl)')==3 : nop",0}, {"assert getnop('bit 1,(ix+12),d')==6 : nop",0}, {"assert getnop('bit 3,(iy-34),h')==6 : nop",0},
+ {"assert getnop(\"ex af,af' \")==1 : nop",0}, {"assert getnop('ex hl,de ')==1 : nop",0}, {"assert getnop('ex de,hl ')==1 : nop",0},
+ {"assert getnop('ex (sp),hl')==6 : nop",0}, {"assert getnop('ex (sp),ix ')==7 : nop",0}, {"assert getnop('ex (sp),iy ')==7 : nop",0},
+
+ {"assert getnop('exx ')==1 : nop",0}, {"assert getnop('rla ')==1 : nop",0}, {"assert getnop('rlca')==1 : nop",0}, {"assert getnop('rrca')==1 : nop",0},
+ {"assert getnop('rra')==1 : nop",0}, {"assert getnop('ccf')==1 : nop",0}, {"assert getnop('daa')==1 : nop",0}, {"assert getnop('scf')==1 : nop",0},
+ {"assert getnop('cpl')==1 : nop",0}, {"assert getnop('ei')==1 : nop",0}, {"assert getnop('di')==1 : nop",0}, {"assert getnop('im')==2 : nop",0},
+ {"assert getnop('neg')==2 : nop",0}, {"assert getnop('rst')==4 : nop",0}, {"assert getnop('retn')==4 : nop",0}, {"assert getnop('reti')==4 : nop",0},
+ {"assert getnop('rld')==5 : nop",0}, {"assert getnop('rrd')==5 : nop",0}, {"assert getnop('outi')==5 : nop",0}, {"assert getnop('outd')==5 : nop",0},
+ {"assert getnop('ind')==5 : nop",0}, {"assert getnop('ini')==5 : nop",0}, {"assert getnop(\"ret\")==3 : nop",0}, {"assert getnop(\"ret nz\")==2 : nop",0},
+ {"assert getnop(\"djNz\")==3 : nop",0}, {"assert getnop(\"jr\")==3 : nop",0}, {"assert getnop(\"jr nz\")==3 : nop",0}, {"assert getnop(\"jp (ix)\")==2 : nop",0},
+ {"assert getnop(\"jp (iy)\")==2 : nop",0}, {"assert getnop(\"jp (hl)\")==1 : nop",0},
+
+ {"assert getnop(' pop af ' )==3 : nop",0}, {"assert getnop(' pop bc ' )==3 : nop",0}, {"assert getnop(' pop de ' )==3 : nop",0},
+ {"assert getnop(' pop hl ' )==3 : nop",0}, {"assert getnop(' pop ix ' )==4 : nop",0}, {"assert getnop(' pop iy ' )==4 : nop",0},
+ {"assert getnop(' push af ' )==4 : nop",0}, {"assert getnop(' push bc ' )==4 : nop",0}, {"assert getnop(' push de ' )==4 : nop",0},
+ {"assert getnop(' push hl ' )==4 : nop",0}, {"assert getnop(' push ix ' )==5 : nop",0}, {"assert getnop(' push iy ' )==5 : nop",0},
+
+ {"assert getnop('add a,a')==1 : nop",0}, {"assert getnop('add a,b')==1 : nop",0}, {"assert getnop('add a,c')==1 : nop",0},
+ {"assert getnop('add a,d')==1 : nop",0}, {"assert getnop('add a,e')==1 : nop",0}, {"assert getnop('add a,h')==1 : nop",0}, {"assert getnop('add a,l')==1 : nop",0},
+ {"assert getnop('add a')==1 : nop",0}, {"assert getnop('add b')==1 : nop",0}, {"assert getnop('add c')==1 : nop",0},
+ {"assert getnop('add d')==1 : nop",0}, {"assert getnop('add e')==1 : nop",0}, {"assert getnop('add h')==1 : nop",0}, {"assert getnop('add l')==1 : nop",0},
+ {"assert getnop('add a,#12')==2 : nop",0}, {"assert getnop('add #12')==2 : nop",0}, {"assert getnop('add a,(hl)')==2 : nop",0},
+ {"assert getnop('add (hl)')==2 : nop",0}, {"assert getnop('add a,xl')==2 : nop",0}, {"assert getnop('add xl')==2 : nop",0},
+ {"assert getnop('add hl,bc')==3 : nop",0}, {"assert getnop('add hl,de')==3 : nop",0}, {"assert getnop('add hl,hl')==3 : nop",0}, {"assert getnop('add hl,sp')==3 : nop",0},
+ {"assert getnop('add ix,bc')==4 : nop",0}, {"assert getnop('add ix,de')==4 : nop",0}, {"assert getnop('add ix,ix')==4 : nop",0}, {"assert getnop('add ix,sp')==4 : nop",0},
+ {"assert getnop('add a,(ix+12)' )==5 : nop",0}, {"assert getnop('add (iy-102)' )==5 : nop",0},
+
+ {"assert getnop('adc a,a')==1 : nop",0}, {"assert getnop('adc a,b')==1 : nop",0}, {"assert getnop('adc a,c')==1 : nop",0},
+ {"assert getnop('adc a,d')==1 : nop",0}, {"assert getnop('adc a,e')==1 : nop",0}, {"assert getnop('adc a,h')==1 : nop",0}, {"assert getnop('adc a,l')==1 : nop",0},
+ {"assert getnop('adc a')==1 : nop",0}, {"assert getnop('adc b')==1 : nop",0}, {"assert getnop('adc c')==1 : nop",0},
+ {"assert getnop('adc d')==1 : nop",0}, {"assert getnop('adc e')==1 : nop",0}, {"assert getnop('adc h')==1 : nop",0}, {"assert getnop('adc l')==1 : nop",0},
+ {"assert getnop('adc a,#12')==2 : nop",0}, {"assert getnop('adc #12')==2 : nop",0}, {"assert getnop('adc a,(hl)')==2 : nop",0},
+ {"assert getnop('adc (hl)')==2 : nop",0}, {"assert getnop('adc a,xl')==2 : nop",0}, {"assert getnop('adc xl')==2 : nop",0},
+ {"assert getnop('adc hl,bc')==4 : nop",0}, {"assert getnop('adc hl,de')==4 : nop",0}, {"assert getnop('adc hl,hl')==4 : nop",0}, {"assert getnop('adc hl,sp')==4 : nop",0},
+ {"assert getnop('adc a,(ix+12)' )==5 : nop",0}, {"assert getnop('adc (iy-102)' )==5 : nop",0},
+
+ {"assert getnop('sbc a,a')==1 : nop",0}, {"assert getnop('sbc a,b')==1 : nop",0}, {"assert getnop('sbc a,c')==1 : nop",0},
+ {"assert getnop('sbc a,d')==1 : nop",0}, {"assert getnop('sbc a,e')==1 : nop",0}, {"assert getnop('sbc a,h')==1 : nop",0}, {"assert getnop('sbc a,l')==1 : nop",0},
+ {"assert getnop('sbc a')==1 : nop",0}, {"assert getnop('sbc b')==1 : nop",0}, {"assert getnop('sbc c')==1 : nop",0},
+ {"assert getnop('sbc d')==1 : nop",0}, {"assert getnop('sbc e')==1 : nop",0}, {"assert getnop('sbc h')==1 : nop",0}, {"assert getnop('sbc l')==1 : nop",0},
+ {"assert getnop('sbc a,#12')==2 : nop",0}, {"assert getnop('sbc #12')==2 : nop",0}, {"assert getnop('sbc a,(hl)')==2 : nop",0},
+ {"assert getnop('sbc (hl)')==2 : nop",0}, {"assert getnop('sbc a,xl')==2 : nop",0}, {"assert getnop('sbc xl')==2 : nop",0},
+ {"assert getnop('sbc hl,bc')==4 : nop",0}, {"assert getnop('sbc hl,de')==4 : nop",0}, {"assert getnop('sbc hl,hl')==4 : nop",0}, {"assert getnop('sbc hl,sp')==4 : nop",0},
+ {"assert getnop('sbc a,(ix+12)' )==5 : nop",0}, {"assert getnop('sbc (iy-102)' )==5 : nop",0},
+
+ {"assert getnop('sub a,a')==1 : nop",0}, {"assert getnop('sub a,b')==1 : nop",0}, {"assert getnop('sub a,c')==1 : nop",0},
+ {"assert getnop('sub a,d')==1 : nop",0}, {"assert getnop('sub a,e')==1 : nop",0}, {"assert getnop('sub a,h')==1 : nop",0}, {"assert getnop('sub a,l')==1 : nop",0},
+ {"assert getnop('sub a')==1 : nop",0}, {"assert getnop('sub b')==1 : nop",0}, {"assert getnop('sub c')==1 : nop",0},
+ {"assert getnop('sub d')==1 : nop",0}, {"assert getnop('sub e')==1 : nop",0}, {"assert getnop('sub h')==1 : nop",0}, {"assert getnop('sub l')==1 : nop",0},
+ {"assert getnop('sub a,#12')==2 : nop",0}, {"assert getnop('sub #12')==2 : nop",0}, {"assert getnop('sub a,(hl)')==2 : nop",0},
+ {"assert getnop('sub (hl)')==2 : nop",0}, {"assert getnop('sub a,xl')==2 : nop",0}, {"assert getnop('sub xl')==2 : nop",0},
+ {"assert getnop('sub a,(ix+12)' )==5 : nop",0}, {"assert getnop('sub (iy-102)' )==5 : nop",0},
+
+ {"assert getnop('out (c),a' )==4 : nop",0}, {"assert getnop('out (c),b' )==4 : nop",0}, {"assert getnop('out (c),c' )==4 : nop",0},
+ {"assert getnop('out (c),d' )==4 : nop",0}, {"assert getnop('out (c),e' )==4 : nop",0}, {"assert getnop('out (c),h' )==4 : nop",0},
+ {"assert getnop('out (c),l' )==4 : nop",0}, {"assert getnop('out (c),0' )==4 : nop",0}, {"assert getnop('out (12),a')==3 : nop",0},
+ {"assert getnop('out (c),l : out (c),0 : out (12),a')==11 : nop",0},
+ {"assert getnop('in a,(c)' )==4 : nop",0}, {"assert getnop('in b,(c)' )==4 : nop",0}, {"assert getnop('in a,(0)' )==3 : nop",0},
+ {"assert getnop('in a,(0) : in a,(c)' )==7 : nop",0},
+
+ {"assert getnop('or a')==1 : nop",0}, {"assert getnop('or b')==1 : nop",0}, {"assert getnop('or c')==1 : nop",0},
+ {"assert getnop('or d')==1 : nop",0}, {"assert getnop('or e')==1 : nop",0}, {"assert getnop('or h')==1 : nop",0},
+ {"assert getnop('or l')==1 : nop",0}, {"assert getnop('or (hl)')==2 : nop",0}, {"assert getnop('or ixl')==2 : nop",0},
+ {"assert getnop('or ixh')==2 : nop",0}, {"assert getnop('or xl')==2 : nop",0}, {"assert getnop('or xh')==2 : nop",0},
+ {"assert getnop('or lx')==2 : nop",0}, {"assert getnop('or hx')==2 : nop",0}, {"assert getnop('or (ix+d)')==5 : nop",0},
+ {"assert getnop('or (iy-d)')==5 : nop",0}, {"assert getnop('or a,(iy-d)')==5 : nop",0},
+ {"assert getnop('xor a')==1 : nop",0}, {"assert getnop('xor b')==1 : nop",0}, {"assert getnop('xor c')==1 : nop",0},
+ {"assert getnop('xor d')==1 : nop",0}, {"assert getnop('xor e')==1 : nop",0}, {"assert getnop('xor h')==1 : nop",0},
+ {"assert getnop('xor l')==1 : nop",0}, {"assert getnop('xor (hl)')==2 : nop",0}, {"assert getnop('xor ixl')==2 : nop",0},
+ {"assert getnop('xor ixh')==2 : nop",0}, {"assert getnop('xor xl')==2 : nop",0}, {"assert getnop('xor xh')==2 : nop",0},
+ {"assert getnop('xor lx')==2 : nop",0}, {"assert getnop('xor hx')==2 : nop",0}, {"assert getnop('xor (ix+d)')==5 : nop",0},
+ {"assert getnop('xor (iy-d)')==5 : nop",0}, {"assert getnop('xor a,(iy-d)')==5 : nop",0},
+ {"assert getnop('and a')==1 : nop",0}, {"assert getnop('and b')==1 : nop",0}, {"assert getnop('and c')==1 : nop",0},
+ {"assert getnop('and d')==1 : nop",0}, {"assert getnop('and e')==1 : nop",0}, {"assert getnop('and h')==1 : nop",0},
+ {"assert getnop('and l')==1 : nop",0}, {"assert getnop('and (hl)')==2 : nop",0}, {"assert getnop('and ixl')==2 : nop",0},
+ {"assert getnop('and ixh')==2 : nop",0}, {"assert getnop('and xl')==2 : nop",0}, {"assert getnop('and xh')==2 : nop",0},
+ {"assert getnop('and lx')==2 : nop",0}, {"assert getnop('and hx')==2 : nop",0}, {"assert getnop('and (ix+d)')==5 : nop",0},
+ {"assert getnop('and (iy-d)')==5 : nop",0}, {"assert getnop('and a,(iy-d)')==5 : nop",0},
+
+ {"assert getnop('rr a')==2 : nop",0}, {"assert getnop('rr b')==2 : nop",0}, {"assert getnop('rr (hl)')==4 : nop",0},
+ {"assert getnop('rr (ix+5)')==7 : nop",0}, {"assert getnop('rr (iy-111)')==7 : nop",0}, {"assert getnop('rr (ix+2),b')==7 : nop",0},
+ {"assert getnop('rl a')==2 : nop",0}, {"assert getnop('rl b')==2 : nop",0}, {"assert getnop('rl (hl)')==4 : nop",0},
+ {"assert getnop('rl (ix+5)')==7 : nop",0}, {"assert getnop('rl (iy-111)')==7 : nop",0}, {"assert getnop('rl (ix+2),b')==7 : nop",0},
+ {"assert getnop('rrc a')==2 : nop",0}, {"assert getnop('rrc b')==2 : nop",0}, {"assert getnop('rrc (hl)')==4 : nop",0},
+ {"assert getnop('rrc (ix+5)')==7 : nop",0}, {"assert getnop('rrc (iy-111)')==7 : nop",0}, {"assert getnop('rrc (ix+2),b')==7 : nop",0},
+ {"assert getnop('rlc a')==2 : nop",0}, {"assert getnop('rlc b')==2 : nop",0}, {"assert getnop('rlc (hl)')==4 : nop",0},
+ {"assert getnop('rlc (ix+5)')==7 : nop",0}, {"assert getnop('rlc (iy-111)')==7 : nop",0}, {"assert getnop('rlc (ix+2),b')==7 : nop",0},
+ {"assert getnop('sla a')==2 : nop",0}, {"assert getnop('sla b')==2 : nop",0}, {"assert getnop('sla (hl)')==4 : nop",0},
+ {"assert getnop('sla (ix+5)')==7 : nop",0}, {"assert getnop('sla (iy-111)')==7 : nop",0}, {"assert getnop('sla (ix+2),b')==7 : nop",0},
+ {"assert getnop('sra a')==2 : nop",0}, {"assert getnop('sra b')==2 : nop",0}, {"assert getnop('sra (hl)')==4 : nop",0},
+ {"assert getnop('sra (ix+5)')==7 : nop",0}, {"assert getnop('sra (iy-111)')==7 : nop",0}, {"assert getnop('sra (ix+2),b')==7 : nop",0},
+ {"assert getnop('sll a')==2 : nop",0}, {"assert getnop('sll b')==2 : nop",0}, {"assert getnop('sll (hl)')==4 : nop",0},
+ {"assert getnop('sll (ix+5)')==7 : nop",0}, {"assert getnop('sll (iy-111)')==7 : nop",0}, {"assert getnop('sll (ix+2),b')==7 : nop",0},
+ {"assert getnop('srl a')==2 : nop",0}, {"assert getnop('srl b')==2 : nop",0}, {"assert getnop('srl (hl)')==4 : nop",0},
+ {"assert getnop('srl (ix+5)')==7 : nop",0}, {"assert getnop('srl (iy-111)')==7 : nop",0}, {"assert getnop('srl (ix+2),b')==7 : nop",0},
+
+ /* wrong snapshot settings */
+ {"buildsna:bank 0:nop:snaset crtc_type",1},
+ {"buildsna:bank 0:nop:snaset crtc_type,3,2",1},
+ {"buildsna:bank 0:nop:snaset crtc_reg,3",1},
+ {"buildsna:bank 0:nop:snaset crtc_reg,20,0",1},
+ {"buildsna:bank 0:nop:snaset crtc_reg,-1,0",1},
+ {"buildsna:bank 0:nop:snaset psg_reg,3",1},
+ {"buildsna:bank 0:nop:snaset psg_reg,20,0",1},
+ {"buildsna:bank 0:nop:snaset psg_reg,-1,0",1},
+ {"buildsna:bank 0:nop:snaset ga_pal,3",1},
+ {"buildsna:bank 0:nop:snaset ga_pal,20,0",1},
+ {"buildsna:bank 0:nop:snaset ga_pal,-1,0",1},
+ {"glop=rnd(5):nop",0},{"glop=rnd(0):nop",1},{"glop=rnd():nop",1},{"glop=rnd(-1):nop",1},{"pifou=8:glop=rnd(pifou):defb glop",0},
+ /* wrong include usage */
+ {"incbin",1},{"include",1},{"incbin'",1},{"include'",1},{"'include",1}, {"'incbin",1},
+ {"incexo",1},{"inczx7",1},{"incaaa",0}, {"inc",1}, {"incl48",1},{"incl49",1},{"incapu",1},{"inclz4",1},
+ {"incexo'",1},{"inczx7'",1},{"incaaa'",1}, {"inc'",1}, {"incl48'",1},{"incl49'",1},{"incapu'",1},{"inclz4'",1},
+ {"incexb",0}, {"includee",0}, {"incexb'",1}, {"includee'",1},
/*
+ {"",},{"",},{"",},{"",},{"",},
+ {"",},{"",},{"",},{"",},{"",},{"",},
{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},
{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},
{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},{"",},
@@ -16140,7 +22238,7 @@ void MiniDump(unsigned char *opcode, int opcodelen) {
int i;
printf("%d byte%s to dump\n",opcodelen,opcodelen>1?"s":"");
for (i=0;i<opcodelen;i++) {
- printf("%02X \n",opcode[i]);
+ printf("%02X ",opcode[i]);
}
printf("\n");
}
@@ -16150,71 +22248,20 @@ void RasmAutotest(void)
#undef FUNC
#define FUNC "RasmAutotest"
+ struct s_parameter param;
struct s_rasm_info *debug;
unsigned char *opcode=NULL;
- int opcodelen,ret,filelen;
- int cpt=0,chk,i,idx;
- char tmpstr1[256],tmpstr2[256],*tmpstr3,**tmpsplit;
+ int opcodelen,ret;
+ int cpt=0,chk,i,j,k,idx,sko=0;
+ char *tmpstr3,**tmpsplit;
+ unsigned char RealDump[65]={00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x80,
+ 0x2d,0x86,0x9e,0xda,0x0f,0x49,0x82,0x00,0x00,0x00,0x80,0x7f,0x20,0x84,0xdb,0x7f,0x80,0xcd,0x85,0xdb,0x7f,
+ 0x80,0x20,0x84,0xdb,0xff,0x80,0xcd,0x85,0xdb,0xff,0x80,0xc8,0xdd,0xd6,0x7c,0x7d,0x53,0x51,0x06,0x1e,0x81,
+ 0xBE,0xF6,0xCC,0x12,0x73};
#ifdef RDD
printf("\n%d bytes\n",_static_library_memory_used);
#endif
-#if 0
- /* Autotest CORE */
- #ifdef OS_WIN
- printf(".");fflush(stdout);
- strcpy(tmpstr1,".\\archives\\job.asm");
- strcpy(tmpstr2,".\\archives\\job.asm");
- SimplifyPath(tmpstr1);if (strcmp(tmpstr1,tmpstr2)) {printf("Autotest %03d ERROR (Core:SimplifyPath0) %s!=%s\n",cpt,tmpstr1,tmpstr2);exit(-1);}
- strcpy(tmpstr1,".\\archives\\..\\job.asm");
- strcpy(tmpstr2,".\\job.asm");
- SimplifyPath(tmpstr1);if (strcmp(tmpstr1,tmpstr2)) {printf("Autotest %03d ERROR (Core:SimplifyPath1) %s!=%s\n",cpt,tmpstr1,tmpstr2);exit(-1);}
- strcpy(tmpstr1,".\\archives\\gruik\\..\\..\\job.asm");
- strcpy(tmpstr2,".\\job.asm");
- SimplifyPath(tmpstr1);if (strcmp(tmpstr1,tmpstr2)) {printf("Autotest %03d ERROR (Core:SimplifyPath2) %s!=%s\n",cpt,tmpstr1,tmpstr2);exit(-1);}
- strcpy(tmpstr1,".\\archives\\..\\gruik\\..\\job.asm");
- strcpy(tmpstr2,".\\job.asm");
- SimplifyPath(tmpstr1);if (strcmp(tmpstr1,tmpstr2)) {printf("Autotest %03d ERROR (Core:SimplifyPath3) %s!=%s\n",cpt,tmpstr1,tmpstr2);exit(-1);}
- strcpy(tmpstr1,"..\\archives\\job.asm");
- strcpy(tmpstr2,"..\\archives\\job.asm");
- SimplifyPath(tmpstr1);if (strcmp(tmpstr1,tmpstr2)) {printf("Autotest %03d ERROR (Core:SimplifyPath4) %s!=%s\n",cpt,tmpstr1,tmpstr2);exit(-1);}
- strcpy(tmpstr1,".\\src\\..\\..\\src\\job.asm");
- strcpy(tmpstr2,"..\\src\\job.asm");
- SimplifyPath(tmpstr1);if (strcmp(tmpstr1,tmpstr2)) {printf("Autotest %03d ERROR (Core:SimplifyPath5) %s!=%s\n",cpt,tmpstr1,tmpstr2);exit(-1);}
- strcpy(tmpstr1,"src\\..\\..\\src\\job.asm");
- strcpy(tmpstr2,"..\\src\\job.asm");
- SimplifyPath(tmpstr1);if (strcmp(tmpstr1,tmpstr2)) {printf("Autotest %03d ERROR (Core:SimplifyPath6) %s!=%s\n",cpt,tmpstr1,tmpstr2);exit(-1);}
- cpt++;
- #else
- printf(".");fflush(stdout);
- strcpy(tmpstr1,"./archives/job.asm");
- strcpy(tmpstr2,"./archives/job.asm");
- SimplifyPath(tmpstr1);if (strcmp(tmpstr1,tmpstr2)) {printf("Autotest %03d ERROR (Core:SimplifyPath0) %s!=%s\n",cpt,tmpstr1,tmpstr2);exit(-1);}
- strcpy(tmpstr1,"./archives/../job.asm");
- strcpy(tmpstr2,"./job.asm");
- SimplifyPath(tmpstr1);if (strcmp(tmpstr1,tmpstr2)) {printf("Autotest %03d ERROR (Core:SimplifyPath1) %s!=%s\n",cpt,tmpstr1,tmpstr2);exit(-1);}
- strcpy(tmpstr1,"./archives/gruik/../../job.asm");
- strcpy(tmpstr2,"./job.asm");
- SimplifyPath(tmpstr1);if (strcmp(tmpstr1,tmpstr2)) {printf("Autotest %03d ERROR (Core:SimplifyPath2) %s!=%s\n",cpt,tmpstr1,tmpstr2);exit(-1);}
- strcpy(tmpstr1,"./archives/../gruik/../job.asm");
- strcpy(tmpstr2,"./job.asm");
- SimplifyPath(tmpstr1);if (strcmp(tmpstr1,tmpstr2)) {printf("Autotest %03d ERROR (Core:SimplifyPath3) %s!=%s\n",cpt,tmpstr1,tmpstr2);exit(-1);}
- strcpy(tmpstr1,"../archives/job.asm");
- strcpy(tmpstr2,"../archives/job.asm");
- SimplifyPath(tmpstr1);if (strcmp(tmpstr1,tmpstr2)) {printf("Autotest %03d ERROR (Core:SimplifyPath4) %s!=%s\n",cpt,tmpstr1,tmpstr2);exit(-1);}
- strcpy(tmpstr1,"./src/../../src/job.asm");
- strcpy(tmpstr2,"../src/job.asm");
- SimplifyPath(tmpstr1);if (strcmp(tmpstr1,tmpstr2)) {printf("Autotest %03d ERROR (Core:SimplifyPath5) %s!=%s\n",cpt,tmpstr1,tmpstr2);exit(-1);}
- strcpy(tmpstr1,"src/../../../src/job.asm");
- strcpy(tmpstr2,"../../src/job.asm");
- SimplifyPath(tmpstr1);if (strcmp(tmpstr1,tmpstr2)) {printf("Autotest %03d ERROR (Core:SimplifyPath6) %s!=%s\n",cpt,tmpstr1,tmpstr2);exit(-1);}
- cpt++;
- printf(".");fflush(stdout);
- if (strcmp(GetPath("/home/roudoudou/"),"/home/roudoudou/")) {printf("Autotest %03d ERROR (Core:GetPath0) [%s]\n",cpt,GetPath("/home/roudoudou/"));exit(-1);}
- if (strcmp(GetPath("/home/roudoudou"),"/home/")) {printf("Autotest %03d ERROR (Core:GetPath1) [%s]\n",cpt,GetPath("/home/roudoudou"));exit(-1);}
- cpt++;
- #endif
-#endif
/* Autotest preprocessing */
ret=RasmAssemble(AUTOTEST_VIRGULE,strlen(AUTOTEST_VIRGULE),&opcode,&opcodelen);
@@ -16264,9 +22311,24 @@ printf("testing Maxam operator conversion OK\n");
printf("testing modulo operator conversion OK\n");
ret=RasmAssemble(AUTOTEST_NOINCLUDE,strlen(AUTOTEST_NOINCLUDE),&opcode,&opcodelen);
- if (!ret) {} else {printf("Autotest %03d ERROR (include missing file)\n",cpt);exit(-1);}
+ if (!ret) {} else {printf("Autotest %03d ERROR (include missing file)\n",cpt);exit(-1);} // file not found MUST trigger an error! => NOT ANYMORE
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing include on a missing file OK\n");
+
+ ret=RasmAssemble(AUTOTEST_BADINCLUDE,strlen(AUTOTEST_BADINCLUDE),&opcode,&opcodelen);
+ if (ret) {} else {printf("Autotest %03d ERROR (bad include test)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing include filename on multiple lines OK\n");
+
+ ret=RasmAssemble(AUTOTEST_BADINCLUDE02,strlen(AUTOTEST_BADINCLUDE02),&opcode,&opcodelen);
+ if (ret) {} else {printf("Autotest %03d ERROR (bad include test 2)\n",cpt);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
-printf("include on a missing file OK\n");
+printf("testing wrong READ usage OK\n");
+
+ ret=RasmAssemble(AUTOTEST_BADINCBIN,strlen(AUTOTEST_BADINCBIN),&opcode,&opcodelen);
+ if (ret) {} else {printf("Autotest %03d ERROR (bad incbin test)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing incbin filename on multiple lines OK\n");
ret=RasmAssemble(AUTOTEST_FORMAT,strlen(AUTOTEST_FORMAT),&opcode,&opcodelen);
if (!ret) {} else {printf("Autotest %03d ERROR (digit formats)\n",cpt);exit(-1);}
@@ -16279,6 +22341,95 @@ printf("testing digit formats OK\n");
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
printf("testing all opcodes OK\n");
+ /********************************************
+ Autotest assembly options
+ *********************************************/
+
+ #define AUTOTEST_PARAM_AMPER "ld a,&10 : assert &10==#10"
+ memset(&param,0,sizeof(struct s_parameter));
+ param.noampersand=1;
+ ret=RasmAssembleInfoParam(AUTOTEST_PARAM_AMPER,strlen(AUTOTEST_PARAM_AMPER),&opcode,&opcodelen,&debug,&param);
+ if (!ret) {} else {printf("Autotest %03d ERROR (testing compilation option -amper)\n",cpt);MiniDump(opcode,opcodelen);for (i=0;i<debug->nberror;i++) printf("%d -> %s\n",i,debug->error[i].msg);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing command line parameter -amper OK\n");
+
+ #define AUTOTEST_PARAM_MAXAM "aaa=10+5*3 : assert aaa==45 : nop"
+ memset(&param,0,sizeof(struct s_parameter));
+ param.rough=0.0; // 0.5 as default
+ ret=RasmAssembleInfoParam(AUTOTEST_PARAM_MAXAM,strlen(AUTOTEST_PARAM_MAXAM),&opcode,&opcodelen,&debug,&param);
+ if (!ret) {} else {printf("Autotest %03d ERROR (testing compilation option -m)\n",cpt);MiniDump(opcode,opcodelen);for (i=0;i<debug->nberror;i++) printf("%d -> %s\n",i,debug->error[i].msg);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing command line parameter -m OK\n");
+
+ #define AUTOTEST_PARAM_DAMS ".grouik : djnz grouik"
+ memset(&param,0,sizeof(struct s_parameter));
+ param.dams=1;
+ ret=RasmAssembleInfoParam(AUTOTEST_PARAM_DAMS,strlen(AUTOTEST_PARAM_DAMS),&opcode,&opcodelen,&debug,&param);
+ if (!ret) {} else {printf("Autotest %03d ERROR (testing compilation option -dams)\n",cpt);MiniDump(opcode,opcodelen);for (i=0;i<debug->nberror;i++) printf("%d -> %s\n",i,debug->error[i].msg);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing command line parameter -dams OK\n");
+
+ #define AUTOTEST_PARAM_PASMO "org #1234 : defw $,$"
+ memset(&param,0,sizeof(struct s_parameter));
+ param.pasmo=1;
+ ret=RasmAssembleInfoParam(AUTOTEST_PARAM_PASMO,strlen(AUTOTEST_PARAM_PASMO),&opcode,&opcodelen,&debug,&param);
+ if (!ret && opcodelen==4 && opcode[0]==opcode[2] && opcode[1]==opcode[3]) {} else {printf("Autotest %03d ERROR (testing compilation option -pasmo)\n",cpt);MiniDump(opcode,opcodelen);for (i=0;i<debug->nberror;i++) printf("%d -> %s\n",i,debug->error[i].msg);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing command line parameter -pasmo OK\n");
+
+ #define AUTOTEST_PARAM_VOID "macro grouik : nop : mend : grouik"
+ memset(&param,0,sizeof(struct s_parameter));
+ param.macrovoid=1;
+ ret=RasmAssembleInfoParam(AUTOTEST_PARAM_VOID,strlen(AUTOTEST_PARAM_VOID),&opcode,&opcodelen,&debug,&param);
+ if (ret) {} else {printf("Autotest %03d ERROR (testing compilation option -void)\n",cpt);MiniDump(opcode,opcodelen);for (i=0;i<debug->nberror;i++) printf("%d -> %s\n",i,debug->error[i].msg);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing command line parameter -void OK\n");
+
+ #define AUTOTEST_PARAM_VOID2 "macro grouik : nop : mend : grouik (void)"
+ memset(&param,0,sizeof(struct s_parameter));
+ param.macrovoid=1;
+ ret=RasmAssembleInfoParam(AUTOTEST_PARAM_VOID2,strlen(AUTOTEST_PARAM_VOID2),&opcode,&opcodelen,&debug,&param);
+ if (!ret) {} else {printf("Autotest %03d ERROR (testing compilation option (bis) -void)\n",cpt);MiniDump(opcode,opcodelen);for (i=0;i<debug->nberror;i++) printf("%d -> %s\n",i,debug->error[i].msg);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing command line parameter (bis) -void OK\n");
+
+ #define AUTOTEST_PARAM_TWE "ld a,300"
+ memset(&param,0,sizeof(struct s_parameter));
+ param.erronwarn=1;
+ ret=RasmAssembleInfoParam(AUTOTEST_PARAM_TWE,strlen(AUTOTEST_PARAM_TWE),&opcode,&opcodelen,&debug,&param);
+ if (ret) {} else {printf("Autotest %03d ERROR (testing compilation option -twe)\n",cpt);MiniDump(opcode,opcodelen);for (i=0;i<debug->nberror;i++) printf("%d -> %s\n",i,debug->error[i].msg);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing command line parameter -twe OK\n");
+
+/*
+ #define AUTOTEST_PARAM_ ""
+ memset(&param,0,sizeof(struct s_parameter));
+ param.dams=1;
+ ret=RasmAssembleInfoParam(AUTOTEST_PARAM_,strlen(AUTOTEST_PARAM_),&opcode,&opcodelen,&debug,&param);
+ if (!ret) {} else {printf("Autotest %03d ERROR (testing compilation option -)\n",cpt);MiniDump(opcode,opcodelen);for (i=0;i<debug->nberror;i++) printf("%d -> %s\n",i,debug->error[i].msg);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing command line parameter - OK\n");
+
+ #define AUTOTEST_PARAM_ ""
+ memset(&param,0,sizeof(struct s_parameter));
+ param.dams=1;
+ ret=RasmAssembleInfoParam(AUTOTEST_PARAM_,strlen(AUTOTEST_PARAM_),&opcode,&opcodelen,&debug,&param);
+ if (!ret) {} else {printf("Autotest %03d ERROR (testing compilation option -)\n",cpt);MiniDump(opcode,opcodelen);for (i=0;i<debug->nberror;i++) printf("%d -> %s\n",i,debug->error[i].msg);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing command line parameter - OK\n");
+*/
+
+
+
/* Autotest single instruction writes that must failed */
tmpstr3=TxtStrDup(AUTOTEST_INSTRMUSTFAILED);
tmpsplit=TxtSplitWithChar(tmpstr3,':');
@@ -16299,14 +22450,30 @@ printf("testing various opcode tests OK\n");
if (!ret && !autotest_keyword[idx].result) {
} else if (ret && autotest_keyword[idx].result) {
} else {
- printf("Autotest %03d ERROR ([%s] test) is %s instead of %s\n",cpt,autotest_keyword[idx].keywordtest,!ret?"ok":"ko",ret?"ok":"ko");
+ printf("Autotest %03d ERROR ([%s] test) has %d error%s instead of %serror expected\n",cpt,autotest_keyword[idx].keywordtest,ret,ret>1?"s":"",autotest_keyword[idx].result?"":"no ");
+ sko++;
}
if (opcode) MemFree(opcode);opcode=NULL;
idx++;
}
cpt++;
printf("testing moar various opcode tests OK\n");
-
+
+ {
+ unsigned char RAMEMU[65536*2];
+
+ for (i=0;i<65536*2;i++) RAMEMU[i]=0xDD;
+ ret=RasmAssembleInfoIntoRAM(AUTOTEST_INTORAM1,strlen(AUTOTEST_INTORAM1),&debug, RAMEMU,65536*2);
+ if (ret || RAMEMU[0]!=0xDD || RAMEMU[0x8000]!=0xDD || RAMEMU[0xC000]!=0xDD || memcmp(&RAMEMU[0x3FF8],"roudoudou",9)) {printf("Autotest %03d ERROR (Assemble into emulator RAM)\n",cpt);
+ RAMEMU[0x4020]=0;
+ printf("ret=%d R[0]=%02X R[0xC000]=%02X str=[%s]\n ",ret,RAMEMU[0],RAMEMU[0xC000],&RAMEMU[0x3FF8]);
+
+ exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing assembling into external RAM OK\n");
+ }
+
ret=RasmAssemble(AUTOTEST_ORG,strlen(AUTOTEST_ORG),&opcode,&opcodelen);
if (!ret && opcodelen==4 && opcode[1]==0x80 && opcode[2]==2 && opcode[3]==0x10) {} else {printf("Autotest %03d ERROR (ORG relocation)\n",cpt);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
@@ -16357,6 +22524,16 @@ printf("testing opcode overriding LIMIT OK\n");
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
printf("testing opcode with variable overriding LIMIT OK\n");
+ ret=RasmAssemble(AUTOTEST_ALIGN,strlen(AUTOTEST_ALIGN),&opcode,&opcodelen);
+ if (!ret && opcodelen==257 && opcode[64]==64 && opcode[128]==128 && opcode[256]==255) {} else {printf("Autotest %03d ERROR (ALIGN directive)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing ALIGN OK\n");
+
+ ret=RasmAssemble(AUTOTEST_CONFINE,strlen(AUTOTEST_CONFINE),&opcode,&opcodelen);
+ if (!ret && opcodelen==501 && opcode[256]==0xAA && opcode[500]==0xBB) {} else {printf("Autotest %03d ERROR (HICONFINE directive)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing CONFINE OK\n");
+
ret=RasmAssemble(AUTOTEST_DELAYED_RUN,strlen(AUTOTEST_DELAYED_RUN),&opcode,&opcodelen);
if (!ret) {} else {printf("Autotest %03d ERROR (delayed RUN set)\n",cpt);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
@@ -16366,12 +22543,37 @@ printf("testing delayed RUN OK\n");
if (!ret && opcodelen==23 && opcode[1]==21 && opcode[9]==23) {} else {printf("Autotest %03d ERROR (LZ segment relocation)\n",cpt);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
printf("testing LZ segment relocation OK\n");
+
+#ifndef NOAPULTRA
+#ifndef NO_3RD_PARTIES
+ ret=RasmAssemble(AUTOTEST_MULTILZ,strlen(AUTOTEST_MULTILZ),&opcode,&opcodelen);
+ if (!ret && opcodelen==43 && opcode[3]==6 && opcode[11]==0x1F) {} else {printf("Autotest %03d ERROR (multi-LZ segment relocation with multiple BANK)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing multi-LZ segment relocation with multiple banks OK\n");
+#else
+printf("*** multi-LZ segment test disabled as there is no APUltra support for this version ***\n");
+#endif
+#else
+printf("*** multi-LZ segment test disabled as there is no APUltra support for this version ***\n");
+#endif
+ ret=RasmAssemble(AUTOTEST_MULTILZORG,strlen(AUTOTEST_MULTILZORG),&opcode,&opcodelen);
+ if (!ret && opcodelen==38 && opcode[0]==6 && opcode[2]==0x10
+ && opcode[4]==0x1A && opcode[0x23]==0xFF && opcode[0x24]==0xFB) {} else {printf("Autotest %03d ERROR (LZ segments mixed with ORG)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZ segment + ORG relocation OK\n");
+
+
+ ret=RasmAssemble(AUTOTEST_LZDEFERED,strlen(AUTOTEST_LZDEFERED),&opcode,&opcodelen);
+ if (!ret && opcodelen==7 && opcode[6]==6) {} else {printf("Autotest %03d ERROR (LZ segment + defered $)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZ segment + defered $ OK\n");
+#ifndef NO_3RD_PARTIES
ret=RasmAssemble(AUTOTEST_LZ4,strlen(AUTOTEST_LZ4),&opcode,&opcodelen);
if (!ret && opcodelen==49 && opcode[0]==0x15 && opcode[4]==0x44 && opcode[0xB]==0xF0) {} else {printf("Autotest %03d ERROR (LZ4 segment)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
printf("testing LZ4 segment OK\n");
-
+#endif
ret=RasmAssemble(AUTOTEST_DEFS,strlen(AUTOTEST_DEFS),&opcode,&opcodelen);
if (!ret && opcodelen==256 && opcode[0]==0) {} else {printf("Autotest %03d ERROR (defs)\n",cpt);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
@@ -16482,6 +22684,26 @@ printf("testing NOT operator OK\n");
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
printf("testing macro usage OK\n");
+ ret=RasmAssemble(AUTOTEST_MACRO_CONF01,strlen(AUTOTEST_MACRO_CONF01),&opcode,&opcodelen);
+ if (ret) {} else {printf("Autotest %03d ERROR (macro name conflict with another macro)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing macro usage 2 OK\n");
+
+ ret=RasmAssemble(AUTOTEST_MACRO_CONF02,strlen(AUTOTEST_MACRO_CONF02),&opcode,&opcodelen);
+ if (ret) {} else {printf("Autotest %03d ERROR (macro name conflict with a variable)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing macro usage 3 OK\n");
+
+ ret=RasmAssemble(AUTOTEST_MACRO_CONF03,strlen(AUTOTEST_MACRO_CONF03),&opcode,&opcodelen);
+ if (ret) {} else {printf("Autotest %03d ERROR (macro name conflict with an alias)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing macro usage 4 OK\n");
+
+ ret=RasmAssemble(AUTOTEST_MACRO_CONF04,strlen(AUTOTEST_MACRO_CONF04),&opcode,&opcodelen);
+ if (ret) {} else {printf("Autotest %03d ERROR (macro name conflict with a label)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing macro usage 5 OK\n");
+
ret=RasmAssemble(AUTOTEST_ASSERT,strlen(AUTOTEST_ASSERT),&opcode,&opcodelen);
if (!ret) {} else {printf("Autotest %03d ERROR (assert usage)\n",cpt);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
@@ -16517,16 +22739,47 @@ printf("testing variables in labels OK\n");
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
printf("testing variables in aliases OK\n");
+ ret=RasmAssemble(AUTOTEST_EQUDOLLAR,strlen(AUTOTEST_EQUDOLLAR),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (delayed EQU + $) r=%d l=%d\n",cpt,ret,opcodelen);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing delayed EQU + $ OK\n");
+
ret=RasmAssemble(AUTOTEST_DELAYNUM,strlen(AUTOTEST_DELAYNUM),&opcode,&opcodelen);
if (!ret && opcodelen==9 && opcode[0]==6 && opcode[2]==7 && opcode[4]==8) {} else {printf("Autotest %03d ERROR (delayed expr labels) r=%d l=%d\n",cpt,ret,opcodelen);MiniDump(opcode,opcodelen);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
printf("testing delayed expression labels OK\n");
+ ret=RasmAssemble(AUTOTEST_MODULE01,strlen(AUTOTEST_MODULE01),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (modules)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing modules + proximity OK\n");
+
+ ret=RasmAssemble(AUTOTEST_MODULE02,strlen(AUTOTEST_MODULE02),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (modules 2)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing modules + proximity (bis) OK\n");
+
+ ret=RasmAssemble(AUTOTEST_MODULE03,strlen(AUTOTEST_MODULE03),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (modules 3)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing modules + endmodule OK\n");
+
+ ret=RasmAssemble(AUTOTEST_DEFMOD,strlen(AUTOTEST_DEFMOD),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (modules & IFDEF)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing modules + IFDEF OK\n");
+
ret=RasmAssemble(AUTOTEST_PROXIM,strlen(AUTOTEST_PROXIM),&opcode,&opcodelen);
if (!ret && opcode[1]==3) {} else {printf("Autotest %03d ERROR (proximity labels)\n",cpt);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
printf("testing proximity labels OK\n");
+ ret=RasmAssembleInfo(AUTOTEST_BANKPROX,strlen(AUTOTEST_BANKPROX),&opcode,&opcodelen,&debug);
+ if (!ret) {} else {printf("Autotest %03d ERROR (BANK tag + proximity labels)\n",cpt);for (i=0;i<debug->nberror;i++) printf("%d -> %s\n",i,debug->error[i].msg);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing BANK tag + proximity labels OK\n");
+
ret=RasmAssemble(AUTOTEST_STRUCT,strlen(AUTOTEST_STRUCT),&opcode,&opcodelen);
if (!ret) {} else {printf("Autotest %03d ERROR (structs)\n",cpt);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
@@ -16542,6 +22795,11 @@ printf("testing SIZEOF struct fields OK\n");
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
printf("testing REPEAT cases OK\n");
+ ret=RasmAssemble(AUTOTEST_REPEAT3,strlen(AUTOTEST_REPEAT3),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (repeat options + startingindex)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing REPEAT+STARTINGINDEX cases OK\n");
+
ret=RasmAssemble(AUTOTEST_REPEATKO,strlen(AUTOTEST_REPEATKO),&opcode,&opcodelen);
if (ret) {} else {printf("Autotest %03d ERROR (repeat without end must return error)\n",cpt);exit(-1);}
printf("testing REPEAT without REND OK\n");
@@ -16560,6 +22818,11 @@ printf("testing ticker OK\n");
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
printf("testing IFDEF / IFUSED OK\n");
+ ret=RasmAssemble(AUTOTEST_SAVEINVALID0,strlen(AUTOTEST_SAVEINVALID0),&opcode,&opcodelen);
+ if (!ret && FileGetSize("rasmoutput.bin")==256) { } else {printf("Autotest %03d ERROR (invalid file size on DISK with SAVE => mostly a pure windows compilation error)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing correct file size on DISK with SAVE OK\n");
+
ret=RasmAssemble(AUTOTEST_SAVEINVALID1,strlen(AUTOTEST_SAVEINVALID1),&opcode,&opcodelen);
if (ret) {} else {printf("Autotest %03d ERROR (invalid size for SAVE)\n",cpt);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
@@ -16600,6 +22863,11 @@ printf("testing global label back as reference when leaving macro and loops OK\n
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
printf("testing far access of a proximity label refering to local OK\n");
+ ret=RasmAssemble(AUTOTEST_PUSHPOPGLOBAL,strlen(AUTOTEST_PUSHPOPGLOBAL),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (get back global for proximity inside macro+loops)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing push/pop global label for proximity inside macro+loops OK\n");
+
ret=RasmAssemble(AUTOTEST_NEGATIVE,strlen(AUTOTEST_NEGATIVE),&opcode,&opcodelen);
if (!ret) {} else {printf("Autotest %03d ERROR (formula case 0)\n",cpt);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
@@ -16613,8 +22881,18 @@ printf("testing operator assignment OK\n");
ret=RasmAssemble(AUTOTEST_OPERATORASSIGN2,strlen(AUTOTEST_OPERATORASSIGN2),&opcode,&opcodelen);
if (!ret && opcodelen==1) {} else {printf("Autotest %03d ERROR (operator assignment + repeat)\n",cpt);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
-printf("testing operator assignment OK\n");
+printf("testing operator assignment + repeat OK\n");
+ ret=RasmAssemble(AUTOTEST_OPERATORASSIGN3,strlen(AUTOTEST_OPERATORASSIGN3),&opcode,&opcodelen);
+ if (!ret && opcodelen==1) {} else {printf("Autotest %03d ERROR (operator assignment + repeat)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing operator assignment + repeat + spacing OK\n");
+
+ ret=RasmAssemble(AUTOTEST_REAL,strlen(AUTOTEST_REAL),&opcode,&opcodelen);
+ if (!ret && opcodelen==sizeof(RealDump) && memcmp(RealDump,opcode,sizeof(RealDump))==0) {} else {printf("Autotest %03d ERROR (DEFR conversion to REAL)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing Amstrad REAL OK\n");
+
ret=RasmAssemble(AUTOTEST_FORMULA1,strlen(AUTOTEST_FORMULA1),&opcode,&opcodelen);
if (!ret) {} else {printf("Autotest %03d ERROR (formula case 1)\n",cpt);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
@@ -16635,6 +22913,27 @@ printf("testing code skip OK\n");
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
printf("testing formula functions + multiple parenthesis OK\n");
+ ret=RasmAssembleInfo(AUTOTEST_GETSIZE,strlen(AUTOTEST_GETSIZE),&opcode,&opcodelen,&debug);
+ if (!ret) {} else {printf("Autotest %03d ERROR (math function GETSIZE)\n",cpt);for (i=0;i<debug->nberror;i++) printf("%d -> %s\n",i,debug->error[i].msg);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing GETSIZE integrity on ALL opcodes OK\n");
+
+ ret=RasmAssemble(AUTOTEST_GETNOP_LD,strlen(AUTOTEST_GETNOP_LD),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (math function GETNOP with multiple LD syncronised with TICKER)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing synchronisation between TICKER and GETNOP on multiple LD OK\n");
+
+ ret=RasmAssemble(AUTOTEST_TICKERNOP_FULL,strlen(AUTOTEST_TICKERNOP_FULL),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (math function GETNOP with almost full instruction set)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing synchronisation between TICKER and GETNOP on almost full instruction set OK\n");
+
+ ret=RasmAssemble(AUTOTEST_TICKER_FULL,strlen(AUTOTEST_TICKER_FULL),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (math function GETTICK with almost full instruction set)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing synchronisation between TICKER and GETTICK on almost full instruction set OK\n");
+
ret=RasmAssemble(AUTOTEST_SHIFTMAX,strlen(AUTOTEST_SHIFTMAX),&opcode,&opcodelen);
if (!ret) {} else {printf("Autotest %03d ERROR (shifting more than 31 must give zero result)\n",cpt);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
@@ -16650,6 +22949,11 @@ printf("testing formula function for Plus color management OK\n");
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
printf("testing formula FRAC function OK\n");
+ ret=RasmAssemble(AUTOTEST_RND,strlen(AUTOTEST_RND),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (formula func RND)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing formula RND function OK\n");
+
ret=RasmAssemble(AUTOTEST_UNDERVAR,strlen(AUTOTEST_UNDERVAR),&opcode,&opcodelen);
if (!ret && opcodelen==4) {} else {printf("Autotest %03d ERROR (var starting with _)\n",cpt);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
@@ -16670,11 +22974,82 @@ printf("testing enhanced LD OK\n");
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
printf("testing enhanced LD variante OK\n");
+ ret=RasmAssemble(AUTOTEST_ENHANCED_LD3,strlen(AUTOTEST_ENHANCED_LD3),&opcode,&opcodelen);
+ if (!ret && memcmp(opcode,opcode+opcodelen/2,opcodelen/2)==0) {} else {printf("Autotest %03d ERROR (enhanced LD 3)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing enhanced LD variante OK\n");
+
ret=RasmAssemble(AUTOTEST_ENHANCED_PUSHPOP,strlen(AUTOTEST_ENHANCED_PUSHPOP),&opcode,&opcodelen);
if (!ret && memcmp(opcode,opcode+opcodelen/2,opcodelen/2)==0) {} else {printf("Autotest %03d ERROR (enhanced PUSH/POP/NOP)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
printf("testing enhanced PUSH/POP OK\n");
+ ret=RasmAssembleInfo(AUTOTEST_INKCONV,strlen(AUTOTEST_INKCONV),&opcode,&opcodelen,&debug);
+ if (!ret && opcodelen==2) {} else {printf("Autotest %03d ERROR (gate array color conversion)\n",cpt);MiniDump(opcode,opcodelen);for (i=0;i<debug->nberror;i++) printf("%d -> %s\n",i,debug->error[i].msg);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing gate array color conversion OK\n");
+
+ FileRemoveIfExists("autotest_include.raw");
+ opcode=MemMalloc(256);
+ for (i=0;i<256;i++) opcode[i]=i;
+ FileWriteBinary("autotest_include.raw",(char *)opcode,256);
+ FileWriteBinaryClose("autotest_include.raw");
+ MemFree(opcode);opcode=NULL;
+
+ ret=RasmAssembleInfo(AUTOTEST_GTILES,strlen(AUTOTEST_GTILES),&opcode,&opcodelen,&debug);
+ if (!ret && opcodelen==256 && opcode[0]==0 && opcode[3]==3 && opcode[4]==4 && opcode[8]==12 && opcode[12]==8 && opcode[16]==24 && opcode[20]==28 && opcode[24]==20 && opcode[28]==16) {} // minimal check
+ else {printf("Autotest %03d ERROR (INCBIN GTILES import)\n",cpt);MiniDump(opcode,opcodelen);for (i=0;i<debug->nberror;i++) printf("%d -> %s\n",i,debug->error[i].msg);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing gray coding tile import OK\n");
+
+ ret=RasmAssembleInfo(AUTOTEST_ITILES,strlen(AUTOTEST_ITILES),&opcode,&opcodelen,&debug);
+ if (!ret && opcodelen==256 && opcode[0]==0 && opcode[3]==3 && opcode[4]==7 && opcode[8]==12 && opcode[12]==11 && opcode[16]==24 && opcode[20]==31 && opcode[24]==20 && opcode[28]==19) {} // minimal check
+ else {printf("Autotest %03d ERROR (INCBIN ITILES import)\n",cpt);MiniDump(opcode,opcodelen);for (i=0;i<debug->nberror;i++) printf("%d -> %s\n",i,debug->error[i].msg);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing zigzag gray coding tile import OK\n");
+
+ ret=RasmAssembleInfo(AUTOTEST_GTILES_KO,strlen(AUTOTEST_GTILES_KO),&opcode,&opcodelen,&debug);
+ if (ret) {} // must be error
+ else {printf("Autotest %03d ERROR (INCBIN GTILES import check)\n",cpt);MiniDump(opcode,opcodelen);for (i=0;i<debug->nberror;i++) printf("%d -> %s\n",i,debug->error[i].msg);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing gray coding tile size check error OK\n");
+
+ ret=RasmAssembleInfo(AUTOTEST_ITILES_KO,strlen(AUTOTEST_ITILES_KO),&opcode,&opcodelen,&debug);
+ if (ret) {} // must be error
+ else {printf("Autotest %03d ERROR (INCBIN ITILES import check)\n",cpt);MiniDump(opcode,opcodelen);for (i=0;i<debug->nberror;i++) printf("%d -> %s\n",i,debug->error[i].msg);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing zigzag gray coding tile size check error OK\n");
+
+
+/************************** segfault test **********************/
+ ret=RasmAssembleInfo(AUTOTEST_ACCENT,strlen(AUTOTEST_ACCENT),&opcode,&opcodelen,&debug);
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing segfault bugfix for accent in quote OK\n");
+ ret=RasmAssembleInfo(AUTOTEST_QUOTELAST,strlen(AUTOTEST_QUOTELAST),&opcode,&opcodelen,&debug);
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing segfault bugfix for opened quote with SAVE as last directive used OK\n");
+ ret=RasmAssembleInfo(AUTOTEST_DELAYED_EQU,strlen(AUTOTEST_DELAYED_EQU),&opcode,&opcodelen,&debug);
+ if (!ret && opcodelen>2 && opcode[2]==1) {} else {printf("Autotest %03d ERROR (DELAYED EQU regression test)\n",cpt);MiniDump(opcode,opcodelen);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing delayed alias regression bugfix OK\n");
+
+/*************************************************************/
+
+
+ ret=RasmAssembleInfo(AUTOTEST_SNASET,strlen(AUTOTEST_SNASET),&opcode,&opcodelen,&debug);
+ if (!ret) {} else {printf("Autotest %03d ERROR (snapshot settings)\n",cpt);MiniDump(opcode,opcodelen);for (i=0;i<debug->nberror;i++) printf("%d -> %s\n",i,debug->error[i].msg);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ RasmFreeInfoStruct(debug);
+printf("testing snapshot settings OK\n");
+
ret=RasmAssemble(AUTOTEST_PAGELABELGEN,strlen(AUTOTEST_PAGELABELGEN),&opcode,&opcodelen);
if (!ret) {} else {printf("Autotest %03d ERROR (pagelabelgen)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
@@ -16690,8 +23065,8 @@ printf("testing page tag with generated label name OK\n");
for (i=0;i<debug->nbsymbol;i++) {
printf("%d -> %s=%d\n",i,debug->symbol[i].name,debug->symbol[i].v);
}
- RasmFreeInfoStruct(debug);
*/
+ RasmFreeInfoStruct(debug);
} else {printf("Autotest %03d ERROR (embedded error struct) err=%d nberr=%d (2) nbsymb=%d (3)\n",cpt,ret,debug->nberror,debug->nbsymbol);MiniDump(opcode,opcodelen);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
printf("testing internal error struct OK\n");
@@ -16710,20 +23085,390 @@ printf("testing internal label struct OK\n");
#ifdef RDD
printf("\n%d bytes\n",_static_library_memory_used);
-
+ {
+ int filelen;
tmpstr3=FileReadContent("./test/PlayerAky.asm",&filelen);
printf(".");fflush(stdout);ret=RasmAssembleInfo(tmpstr3,filelen,&opcode,&opcodelen,&debug);
if (!ret) {} else {printf("Autotest %03d ERROR (PlayerAky)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
if (opcode) MemFree(opcode);opcode=NULL;cpt++;
RasmFreeInfoStruct(debug);
MemFree(tmpstr3);
+ }
printf("\n%d bytes\n",_static_library_memory_used);
#endif
-
+
+ /************************** include testing + crunch ****************/
+ idx=0;
+ opcode=MemMalloc(8000);
+ for (k=40;k>1;k--) {
+ for (i='A';i<'F';i++) {
+ for (j=0;j<k;j++) opcode[idx++]=i;
+ }
+ }
+ for (k=1;k<40;k++) {
+ for (i='A';i<'F';i++) {
+ for (j=0;j<k;j++) opcode[idx++]=i;
+ }
+ }
+ FileRemoveIfExists("autotest_include.raw");
+ FileWriteBinary("autotest_include.raw",(char *)opcode,idx);
+ FileWriteBinaryClose("autotest_include.raw");
+ MemFree(opcode);opcode=NULL;
+
+ ret=RasmAssemble(AUTOTEST_INCBIN1,strlen(AUTOTEST_INCBIN1),&opcode,&opcodelen);
+ if (!ret && opcodelen==7995) {} else {printf("Autotest %03d ERROR (INCBIN)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCBIN OK\n");
+
+ ret=RasmAssemble(AUTOTEST_INCBIN2,strlen(AUTOTEST_INCBIN2),&opcode,&opcodelen);
+ if (!ret && opcodelen==6995) {} else {printf("Autotest %03d ERROR (INCBIN+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCBIN+offset OK\n");
+
+ ret=RasmAssemble(AUTOTEST_INCBIN3,strlen(AUTOTEST_INCBIN3),&opcode,&opcodelen);
+ if (!ret && opcodelen==1000) {} else {printf("Autotest %03d ERROR (INCBIN+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCBIN+size OK\n");
+
+#ifndef NO_3RD_PARTIES
+ ret=RasmAssemble(AUTOTEST_LZ4_A,strlen(AUTOTEST_LZ4_A),&opcode,&opcodelen);
+ if (!ret && opcodelen==544) {} else {printf("Autotest %03d ERROR (INCBIN + LZ4 segment)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCBIN + LZ4 segment OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZ4_B,strlen(AUTOTEST_LZ4_B),&opcode,&opcodelen);
+ if (!ret && opcodelen==544) {} else {printf("Autotest %03d ERROR (INCLZ4)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCLZ4 OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZ4_C,strlen(AUTOTEST_LZ4_C),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCLZ4+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZ4_D,strlen(AUTOTEST_LZ4_D),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZ4+INCBIN+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZ4 variant+offset OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZ4_E,strlen(AUTOTEST_LZ4_E),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCLZ4+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZ4_F,strlen(AUTOTEST_LZ4_F),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZ4+INCBIN+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZ4 variant+size OK\n");
+#else
+printf("*** LZ4/LZEXO/LZX0/LZX7tests disabled as there is no 3rd parties support for this version ***\n");
+#endif
+
+ ret=RasmAssemble(AUTOTEST_LZ48_A,strlen(AUTOTEST_LZ48_A),&opcode,&opcodelen);
+ if (!ret && opcodelen==738) {} else {printf("Autotest %03d ERROR (INCBIN + LZ48 segment)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCBIN + LZ48 segment OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZ48_B,strlen(AUTOTEST_LZ48_B),&opcode,&opcodelen);
+ if (!ret && opcodelen==738) {} else {printf("Autotest %03d ERROR (INCL48)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCL48 OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZ48_C,strlen(AUTOTEST_LZ48_C),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCL48+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZ48_D,strlen(AUTOTEST_LZ48_D),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZ48+INCBIN+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZ48 variant+offset OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZ48_E,strlen(AUTOTEST_LZ48_E),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCLZ48+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZ48_F,strlen(AUTOTEST_LZ48_F),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZ48+INCBIN+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZ48 variant+size OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZ49_A,strlen(AUTOTEST_LZ49_A),&opcode,&opcodelen);
+ if (!ret && opcodelen==717) {} else {printf("Autotest %03d ERROR (INCBIN + LZ49 segment)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCBIN + LZ49 segment OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZ49_B,strlen(AUTOTEST_LZ49_B),&opcode,&opcodelen);
+ if (!ret && opcodelen==717) {} else {printf("Autotest %03d ERROR (INCL49)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCL49 OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZ49_C,strlen(AUTOTEST_LZ49_C),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCL49+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZ49_D,strlen(AUTOTEST_LZ49_D),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZ49+INCBIN+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZ49 variant+offset OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZ49_E,strlen(AUTOTEST_LZ49_E),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCL49+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZ49_F,strlen(AUTOTEST_LZ49_F),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZ49+INCBIN+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZ49 variant+size OK\n");
+
+#ifndef NO_3RD_PARTIES
+ ret=RasmAssemble(AUTOTEST_LZEXO_A,strlen(AUTOTEST_LZEXO_A),&opcode,&opcodelen);
+ if (!ret && opcodelen==335) {} else {printf("Autotest %03d ERROR (INCBIN + LZEXO segment)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCBIN + LZEXO segment OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZEXO_B,strlen(AUTOTEST_LZEXO_B),&opcode,&opcodelen);
+ if (!ret && opcodelen==335) {} else {printf("Autotest %03d ERROR (INCEXO)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCEXO OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZEXO_C,strlen(AUTOTEST_LZEXO_C),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCEXO+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZEXO_D,strlen(AUTOTEST_LZEXO_D),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZEXO+INCBIN+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZEXO variant+offset OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZEXO_E,strlen(AUTOTEST_LZEXO_E),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCEXO+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZEXO_F,strlen(AUTOTEST_LZEXO_F),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZEXO+INCBIN+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZEXO variant+size OK\n");
+
+
+ ret=RasmAssemble(AUTOTEST_LZX0_A,strlen(AUTOTEST_LZX0_A),&opcode,&opcodelen);
+ if (!ret && opcodelen==384) {} else {printf("Autotest %03d ERROR (INCBIN + LZX0 segment)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ i=opcodelen;
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCBIN + LZX0 segment OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZX0_B,strlen(AUTOTEST_LZX0_B),&opcode,&opcodelen);
+ if (!ret && opcodelen==i) {} else {printf("Autotest %03d ERROR (INCZX0 must crunch like LZX0 segment)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCZX0 OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZX0_C,strlen(AUTOTEST_LZX0_C),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCZX0+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZX0_D,strlen(AUTOTEST_LZX0_D),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZX0+INCBIN+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZX0 variant+offset OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZX0_E,strlen(AUTOTEST_LZX0_E),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCZX0+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZX0_F,strlen(AUTOTEST_LZX0_F),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZX0+INCBIN+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZX0 variant+size OK\n");
+
+
+
+ ret=RasmAssemble(AUTOTEST_LZX0B_A,strlen(AUTOTEST_LZX0B_A),&opcode,&opcodelen);
+ if (!ret && opcodelen==386) {} else {printf("Autotest %03d ERROR (INCBIN + LZX0B segment)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ i=opcodelen;
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCBIN + LZX0B segment OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZX0B_B,strlen(AUTOTEST_LZX0B_B),&opcode,&opcodelen);
+ if (!ret && opcodelen==i) {} else {printf("Autotest %03d ERROR (INCZX0B must crunch like LZX0B segment)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCZX0B OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZX0B_C,strlen(AUTOTEST_LZX0B_C),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCZX0B+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZX0B_D,strlen(AUTOTEST_LZX0B_D),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZX0B+INCBIN+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZX0B variant+offset OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZX0B_E,strlen(AUTOTEST_LZX0B_E),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCZX0B+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZX0B_F,strlen(AUTOTEST_LZX0B_F),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZX0B+INCBIN+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZX0B variant+size OK\n");
+
+
+
+ ret=RasmAssemble(AUTOTEST_LZX7_A,strlen(AUTOTEST_LZX7_A),&opcode,&opcodelen);
+ if (!ret && opcodelen==535) {} else {printf("Autotest %03d ERROR (INCBIN + LZX7 segment)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCBIN + LZX7 segment OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZX7_B,strlen(AUTOTEST_LZX7_B),&opcode,&opcodelen);
+ if (!ret && opcodelen==535) {} else {printf("Autotest %03d ERROR (INCZX7)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCZX7 OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZX7_C,strlen(AUTOTEST_LZX7_C),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCZX7+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZX7_D,strlen(AUTOTEST_LZX7_D),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZX7+INCBIN+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZX7 variant+offset OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZX7_E,strlen(AUTOTEST_LZX7_E),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCZX7+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZX7_F,strlen(AUTOTEST_LZX7_F),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZX7+INCBIN+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZX7 variant+size OK\n");
+
+
+#ifndef NOAPULTRA
+ ret=RasmAssemble(AUTOTEST_LZAPU_A,strlen(AUTOTEST_LZAPU_A),&opcode,&opcodelen);
+ if (!ret && opcodelen==396) {} else {printf("Autotest %03d ERROR (INCBIN + LZAPU segment)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCBIN + LZAPU segment OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZAPU_B,strlen(AUTOTEST_LZAPU_B),&opcode,&opcodelen);
+ if (!ret && opcodelen==396) {} else {printf("Autotest %03d ERROR (INCAPU)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCAPU OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZAPU_C,strlen(AUTOTEST_LZAPU_C),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCAPU+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZAPU_D,strlen(AUTOTEST_LZAPU_D),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZAPU+INCBIN+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZAPU variant+offset OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZAPU_E,strlen(AUTOTEST_LZAPU_E),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCAPU+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZAPU_F,strlen(AUTOTEST_LZAPU_F),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZAPU+INCBIN+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZAPU variant+size OK\n");
+
+
+
+ ret=RasmAssemble(AUTOTEST_LZSA1_A,strlen(AUTOTEST_LZSA1_A),&opcode,&opcodelen);
+ if (!ret && opcodelen<=442) {} else {printf("Autotest %03d ERROR (INCBIN + LZSA1 segment)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCBIN + LZSA1 segment OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZSA1_Abis,strlen(AUTOTEST_LZSA1_Abis),&opcode,&opcodelen);
+ if (!ret && opcodelen<=437) {} else {printf("Autotest %03d ERROR (INCBIN + LZSA1 segment)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCBIN + LZSA1 segment OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZSA1_B,strlen(AUTOTEST_LZSA1_B),&opcode,&opcodelen);
+ if (!ret && opcodelen<=442) {} else {printf("Autotest %03d ERROR (INCLZSA1)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCLZSA1 OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZSA1_C,strlen(AUTOTEST_LZSA1_C),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCLZSA1+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZSA1_D,strlen(AUTOTEST_LZSA1_D),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZSA1+INCBIN+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZSA1 variant+offset OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZSA1_E,strlen(AUTOTEST_LZSA1_E),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCLZSA1+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZSA1_F,strlen(AUTOTEST_LZSA1_F),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZSA1+INCBIN+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZSA1 variant+size OK\n");
+
+
+
+
+ ret=RasmAssemble(AUTOTEST_LZSA2_A,strlen(AUTOTEST_LZSA2_A),&opcode,&opcodelen);
+ if (!ret && opcodelen<=463) {} else {printf("Autotest %03d ERROR (INCBIN + LZSA2 segment)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCBIN + LZSA2 segment OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZSA2_Abis,strlen(AUTOTEST_LZSA2_Abis),&opcode,&opcodelen);
+ if (!ret && opcodelen<=462) {} else {printf("Autotest %03d ERROR (INCBIN + LZSA2 segment)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCBIN + LZSA2 segment OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZSA2_B,strlen(AUTOTEST_LZSA2_B),&opcode,&opcodelen);
+ if (!ret && opcodelen<=463) {} else {printf("Autotest %03d ERROR (INCLZSA2)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing INCLZSA2 OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZSA2_C,strlen(AUTOTEST_LZSA2_C),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCLZSA2+offset)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZSA2_D,strlen(AUTOTEST_LZSA2_D),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZSA2+INCBIN+offset) %d!=%d\n",cpt,i,opcodelen);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZSA2 variant+offset OK\n");
+
+ ret=RasmAssemble(AUTOTEST_LZSA2_E,strlen(AUTOTEST_LZSA2_E),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (INCLZSA2+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+ i=opcodelen;
+ ret=RasmAssemble(AUTOTEST_LZSA2_F,strlen(AUTOTEST_LZSA2_F),&opcode,&opcodelen);
+ if (!ret && i==opcodelen) {} else {printf("Autotest %03d ERROR (LZSA2+INCBIN+size)\n",cpt);MiniDump(opcode,opcodelen);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing LZSA2 variant+size OK\n");
+#endif
+#else
+printf("*** LZAPU and INCAPU tests disabled as there is no APUltra support for this version ***\n");
+printf("*** LZSA1 and INCLZSA1 tests disabled as there is no LZSA v1 support for this version ***\n");
+printf("*** LZSA2 and INCLZSA2 tests disabled as there is no LZSA v2 support for this version ***\n");
+#endif
+
+
+ ret=RasmAssemble(AUTOTEST_ECPR1,strlen(AUTOTEST_ECPR1),&opcode,&opcodelen);
+ if (!ret) {} else {printf("Autotest %03d ERROR (extended CPR test 1)\n",cpt);exit(-1);}
+ if (opcode) MemFree(opcode);opcode=NULL;cpt++;
+printf("testing simple extended CPR behaviour OK\n");
+
+
+
+ FileRemoveIfExists("autotest_include.raw");
+ FileRemoveIfExists("rasmoutput.xpr");
FileRemoveIfExists("rasmoutput.cpr");
+ FileRemoveIfExists("rasmoutput.sna");
- printf("All internal tests OK\n");
+ ret=RasmAssemble(NULL,0,&opcode,&opcodelen)+RasmAssembleInfo(NULL,0,&opcode,&opcodelen,&debug)+RasmAssembleInfoParam(NULL,0,&opcode,&opcodelen,&debug,&param);
+
+ if (sko) {
+ printf("ERROR => various opcode tests did not pass! (check backlog)\n");
+ printf("All other tests OK => %d tests done\n",ret);
+ } else {
+ printf("All internal tests OK => %d tests done\n",ret);
+ }
+
+
#ifdef RDD
/* private dev lib tools */
printf("checking memory\n");
@@ -16970,9 +23715,9 @@ void Usage(int help)
#undef FUNC
#define FUNC "Usage"
- printf("%s (c) 2017 Edouard BERGE (use -n option to display all licenses)\n",RASM_VERSION);
+ printf("%s (c) 2017 Edouard BERGE (use -n option to display all licenses / -autotest for self-testing)\n",RASM_VERSION);
#ifndef NO_3RD_PARTIES
- printf("LZ4 (c) Yann Collet / ZX7 (c) Einar Saukas / Exomizer 2 (c) Magnus Lind\n");
+ printf("LZ4 (c) Yann Collet / ZX0 & ZX7 (c) Einar Saukas / Exomizer 2 (c) Magnus Lind / LZSA & AP-Ultra (c) Emmanuel Marty\n");
#endif
printf("\n");
printf("SYNTAX: rasm <inputfile> [options]\n");
@@ -16982,8 +23727,10 @@ void Usage(int help)
printf("FILENAMES:\n");
printf("-oa automatic radix from input filename\n");
printf("-o <outputfile radix> choose a common radix for all files\n");
+ printf("-or <ROM filename(s)> choose a radix filename for ROM output\n");
printf("-ob <binary filename> choose a full filename for binary output\n");
printf("-oc <cartridge filename> choose a full filename for cartridge output\n");
+ printf("-ol <ROM label filename> choose a full filename for ROM label output\n");
printf("-oi <snapshot filename> choose a full filename for snapshot output\n");
printf("-os <symbol filename> choose a full filename for symbol output\n");
printf("-ot <tape filename> choose a full filename for tape output\n");
@@ -17002,6 +23749,8 @@ void Usage(int help)
printf("-ss export symbols in the snapshot (SYMB chunk for ACE)\n");
printf("-sc <format> export symbols with source code convention\n");
printf("-sm export symbol in multiple files (one per bank)\n");
+ printf("-ec export labels with original case\n");
+ printf("-er export ROM labels\n");
printf("-l <labelfile> import symbol file (winape,pasmo,rasm)\n");
printf("-eb export breakpoints\n");
printf("-wu warn for unused symbols (alias, var or label)\n");
@@ -17012,11 +23761,18 @@ void Usage(int help)
printf("-sa export all symbols (like -sl -sv -sq option)\n");
printf("-Dvariable=value import value for variable\n");
printf("COMPATIBILITY:\n");
- printf("-m Maxam style calculations\n");
- printf("-dams Dams 'dot' label convention\n");
- printf("-ass AS80 behaviour mimic\n");
- printf("-uz UZ80 behaviour mimic\n");
-
+ printf("-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("-pasmo PASMO behaviour mimic\n");
+ printf("-amper use ampersand for hex values\n");
+ printf("-msep <separator> set separator for modules\n");
+ printf("-utf8 convert symbols from french or spanish keyboard inside quotes\n");
+ printf("-fq do not bother with special chars inside quotes\n");
+ printf("MISCELLANEOUS:\n");
+ printf("-quick enable fast mode for ZX0 crunching\n");
+ printf("-cprquiet do not display ROM detailed informations\n");
printf("EDSK generation/update:\n");
printf("-eo overwrite files on disk if it already exists\n");
printf("SNAPSHOT:\n");
@@ -17025,6 +23781,7 @@ void Usage(int help)
printf("-v2 export snapshot version 2 instead of version 3\n");
printf("PARSING:\n");
printf("-me <value> set maximum number of error (0 means no limit)\n");
+ printf("-twe treat warnings as errors\n");
printf("-xr extended error display\n");
printf("-w disable warnings\n");
printf("-void force void usage with macro without parameter\n");
@@ -17079,7 +23836,7 @@ printf("Software. \"\n");
#ifndef NO_3RD_PARTIES
printf("\n\n\n\n");
-printf("******* license of LZ4 cruncher / sources were modified ***********\n\n\n\n");
+printf("******* license for LZ4 cruncher / sources were modified ***********\n\n\n\n");
printf("BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n");
@@ -17112,10 +23869,9 @@ printf(" - LZ4 source repository : https://github.com/lz4/lz4\n");
printf("\n\n\n\n");
-printf("******* license of ZX7 cruncher / sources were modified ***********\n\n\n\n");
-
-
-printf(" * (c) Copyright 2012 by Einar Saukas. All rights reserved.\n");
+printf("******* license for ZX0 / ZX7 cruncher / sources were modified ***********\n\n\n\n");
+printf("BSD 3-Clause License\n");
+printf(" * (c) Copyright 2012/2021 by Einar Saukas. All rights reserved.\n");
printf(" *\n");
printf(" * Redistribution and use in source and binary forms, with or without\n");
printf(" * modification, are permitted provided that the following conditions are met:\n");
@@ -17139,9 +23895,9 @@ printf(" * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
printf(" * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n");
-printf("\n\n\n\n");
-printf("******* license of exomizer cruncher / sources were modified ***********\n\n\n\n");
+printf("\n\n\n\n");
+printf("******* license for exomizer cruncher / sources were modified ***********\n\n\n\n");
printf(" * Copyright (c) 2005 Magnus Lind.\n");
printf(" *\n");
@@ -17166,6 +23922,45 @@ printf(" *\n");
printf(" * 4. The names of this software and/or it's copyright holders may not be\n");
printf(" * used to endorse or promote products derived from this software without\n");
printf(" * specific prior written permission.\n");
+
+
+printf("\n\n\n\n");
+printf("******* license for AP-Ultra & LZSA crunchers ****************************\n\n\n\n");
+printf(" * apultra.c - command line compression utility for the apultra library\n");
+printf(" * Copyright (C) 2019 Emmanuel Marty\n");
+printf(" * https://github.com/emmanuel-marty\n");
+printf(" *\n");
+printf(" LZSA code use Zlib license\n");
+printf(" Match finder use CC0 license due to using portions of code from Eric Bigger's\n");
+printf(" Wimlib in the suffix array-based matchfinder\n");
+printf(" *\n");
+printf(" * This software is provided 'as-is', without any express or implied\n");
+printf(" * warranty. In no event will the authors be held liable for any damages\n");
+printf(" * arising from the use of this software.\n");
+printf(" *\n");
+printf(" * Permission is granted to anyone to use this software for any purpose,\n");
+printf(" * including commercial applications, and to alter it and redistribute it\n");
+printf(" * freely, subject to the following restrictions:\n");
+printf(" *\n");
+printf(" * 1. The origin of this software must not be misrepresented; you must not\n");
+printf(" * claim that you wrote the original software. If you use this software\n");
+printf(" * in a product, an acknowledgment in the product documentation would be\n");
+printf(" * appreciated but is not required.\n");
+printf(" * 2. Altered source versions must be plainly marked as such, and must not be\n");
+printf(" * misrepresented as being the original software.\n");
+printf(" * 3. This notice may not be removed or altered from any source distribution.\n");
+printf(" *\n");
+printf(" * Uses the libdivsufsort library Copyright (c) 2003-2008 Yuta Mori\n");
+printf(" *\n");
+printf(" * Inspired by cap by Sven-Ake Dahl. https://github.com/svendahl/cap\n");
+printf(" * Also inspired by Charles Bloom's compression blog. http://cbloomrants.blogspot.com/\n");
+printf(" * With ideas from LZ4 by Yann Collet. https://github.com/lz4/lz4\n");
+printf(" * With help and support from spke <zxintrospec@gmail.com>\n");
+printf("\n\n\n\n");
+printf("*** license for CDT export (record11() function and some other code extracts) ***\n\n\n\n");
+printf("Author: CNGSoft http://cngsoft.no-ip.org , the tool is in GPL2 licence,\nCopyright (C) 2007 Free Software Foundation, Inc. https://fsf.org\n");
+printf("\n");
+printf("\n");
#endif
printf("\n\n");
@@ -17217,15 +24012,39 @@ int ParseOptions(char **argv,int argc, struct s_parameter *param)
RasmAutotest();
} else if (strcmp(argv[i],"-uz")==0) {
param->as80=2;
+ } else if (strcmp(argv[i],"-quick")==0) {
+ MAX_OFFSET_ZX0=2176;
+ } else if (strcmp(argv[i],"-msep")==0) {
+ if (i+1<argc) {
+ param->module_separator=argv[++i][0];
+ } else Usage(1);
+ } else if (strcmp(argv[i],"-fq")==0) {
+ param->freequote=1;
+ } else if (strcmp(argv[i],"-utf8")==0) {
+ param->utf8enable=1;
+ } else if (strcmp(argv[i],"-twe")==0) {
+ param->erronwarn=1;
+ } else if (strcmp(argv[i],"-pasmo")==0) {
+ param->pasmo=1;
+ } else if (strcmp(argv[i],"-cprquiet")==0) {
+ param->cprinfo=0;
} else if (strcmp(argv[i],"-ass")==0) {
param->as80=1;
+ } else if (strcmp(argv[i],"-amper")==0 || strcmp(argv[i],"--noampersand")==0) {
+ param->noampersand=1;
} else if (strcmp(argv[i],"-eb")==0) {
param->export_brk=1;
} else if (strcmp(argv[i],"-wu")==0) {
param->warn_unused=1;
+ } else if (strcmp(argv[i],"-xpr")==0) {
+ param->xpr=1;
} else if (strcmp(argv[i],"-dams")==0) {
} else if (strcmp(argv[i],"-void")==0) {
param->macrovoid=1;
+ } else if (strcmp(argv[i],"-ec")==0) {
+ param->enforce_symbol_case=1;
+ } else if (strcmp(argv[i],"-er")==0) {
+ param->cprinfoexport=1;
} else if (strcmp(argv[i],"-xr")==0) {
param->extended_error=1;
} else if (strcmp(argv[i],"-eo")==0) {
@@ -17250,11 +24069,15 @@ int ParseOptions(char **argv,int argc, struct s_parameter *param)
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
+
+printf("curpath=[%s]\n",curpath);
+
FieldArrayAddDynamicValueConcat(&param->pathdef,&param->npath,&param->mpath,curpath);
MemFree(curpath);
} else {
@@ -17283,12 +24106,15 @@ int ParseOptions(char **argv,int argc, struct s_parameter *param)
param->maxerr=atoi(argv[++i]);
return i;
}
- default:Usage(1);
+ Usage(1);
+ break;
+ default:Usage(1);break;
}
Usage(1);
break;
case 's':
if (argv[i][2] && argv[i][3]) Usage(1);
+
switch (argv[i][2]) {
case 0:param->export_sym=1;return 0;
case 'z':
@@ -17311,6 +24137,7 @@ int ParseOptions(char **argv,int argc, struct s_parameter *param)
if (_internal_check_flexible(param->flexible_export)) return i; else Usage(1);
}
Usage(1);
+ break;
case 'l':
param->export_local=1;return 0;
case 'v':
@@ -17327,9 +24154,11 @@ int ParseOptions(char **argv,int argc, struct s_parameter *param)
param->export_sym=1;
param->export_sna=1;return 0;
default:
- break;
+ Usage(1);
+ break;
}
Usage(1);
+ break;
case 'l':
if (argv[i][2]) Usage(1);
if (i+1<argc) {
@@ -17337,9 +24166,7 @@ int ParseOptions(char **argv,int argc, struct s_parameter *param)
break;
}
Usage(1);
- case 'i':
-printf("@@@\n@@@ --> deprecated option, there is no need to use -i option to set input file <--\n@@@\n");
- Usage(0);
+ break;
case 'o':
if (argv[i][2] && argv[i][3]) Usage(1);
switch (argv[i][2]) {
@@ -17349,6 +24176,7 @@ printf("@@@\n@@@ --> deprecated option, there is no need to use -i option to set
break;
}
Usage(1);
+ break;
case 'a':
param->automatic_radix=1;
break;
@@ -17358,38 +24186,59 @@ printf("@@@\n@@@ --> deprecated option, there is no need to use -i option to set
break;
}
Usage(1);
+ break;
+ case 'r':
+ if (i+1<argc && param->rom_name==NULL) {
+ param->rom_name=argv[++i];
+ break;
+ }
+ Usage(1);
+ break;
case 'i':
if (i+1<argc && param->snapshot_name==NULL) {
param->snapshot_name=argv[++i];
break;
}
Usage(1);
+ break;
+ case 'l':
+ if (i+1<argc && param->cprinfo_name==NULL) {
+ param->cprinfo_name=argv[++i];
+ break;
+ }
+ Usage(1);
+ break;
case 'b':
if (i+1<argc && param->binary_name==NULL) {
param->binary_name=argv[++i];
break;
}
Usage(1);
+ break;
case 'c':
if (i+1<argc && param->cartridge_name==NULL) {
param->cartridge_name=argv[++i];
break;
}
Usage(1);
+ break;
case 'k':
if (i+1<argc && param->breakpoint_name==NULL) {
param->breakpoint_name=argv[++i];
break;
}
Usage(1);
+ break;
case 's':
if (i+1<argc && param->symbol_name==NULL) {
param->symbol_name=argv[++i];
break;
}
Usage(1);
+ break;
default:
Usage(1);
+ break;
}
break;
case 'd':if (!argv[i][2]) printf("deprecated option -d\n"); else Usage(1);
@@ -17400,15 +24249,15 @@ printf("@@@\n@@@ --> deprecated option, there is no need to use -i option to set
break;
case 'v':
if (!argv[i][2]) {
- printf("deprecated option -v\n");
+ param->display_stats=1;
} else if (argv[i][2]=='2') {
param->v2=1;
}
break;
case 'n':if (!argv[i][2]) Licenses(); else Usage(1);
- case 'h':Usage(1);
+ case 'h':Usage(1);break;
default:
- Usage(1);
+ Usage(1);break;
}
} else {
if (param->filename==NULL) {
@@ -17453,8 +24302,10 @@ int main(int argc, char **argv)
struct s_parameter param={0};
int ret;
+ param.cprinfo=1;
param.maxerr=20;
param.rough=0.5;
+ param.module_separator='_';
GetParametersFromCommandLine(argc,argv,&param);
ret=Rasm(&param);
@@ -17468,5 +24319,3 @@ printf("checking memory\n");
}
#endif
-
-
diff --git a/tools/rasm/rasm.h b/tools/rasm/rasm.h
index 211cf9e..4899446 100644
--- a/tools/rasm/rasm.h
+++ b/tools/rasm/rasm.h
@@ -14,13 +14,20 @@ struct s_rasm_info {
int nberror,maxerror;
struct s_debug_symbol *symbol;
int nbsymbol,maxsymbol;
+ int run,start;
+ unsigned char *emuram;
+ int lenram;
};
+#ifndef INSIDE_RASM
//extern "C" {
int RasmAssemble(const char *datain, int lenin, unsigned char **dataout, int *lenout);
int RasmAssembleInfo(const char *datain, int lenin, unsigned char **dataout, int *lenout, struct s_rasm_info **debug);
+int RasmAssembleInfoIntoRAM(const char *datain, int lenin, struct s_rasm_info **debug, unsigned char *emuram, int ramsize);
void RasmFreeInfoStruct(struct s_rasm_info *debug);
//};
+#endif
+
diff --git a/tools/rasm/resources/opcodes_first_byte.asm b/tools/rasm/resources/opcodes_first_byte.asm
new file mode 100644
index 0000000..6a6e21b
--- /dev/null
+++ b/tools/rasm/resources/opcodes_first_byte.asm
@@ -0,0 +1,542 @@
+;; This file was generated with the help of a bash script.
+;; The use case was mentioned by user https://github.com/rgiot on
+;; https://github.com/EdouardBERGE/rasm/issues/2
+
+;; When you need the value of a Z80 instruction, e.g. for any purpose
+;; handling instructions, like analyzing or generating code, your code
+;; might look like this:
+;;
+;; ld a, 0xe1 ; POP HL but this comment might be out of date
+;; ld (somelabel), a
+;;
+;; This file allows you something more readable and maintainable:
+;;
+;; include "opcodes_first_byte.asm"
+;; ...your code...
+;; ld a, opcode_pop_hl
+;; ld (somelabel), a
+;;
+;; which is better because you are certain about what the code does.
+;;
+;; Still better, if your editor allows auto-completion, you may
+;; autocomplete it to the explicit value:
+;;
+;; ld a, opcode_pop_hl_0xe1
+;; ld (somelabel), a
+;;
+;; This way, both the code meaning and the numeric opcode value are
+;; visible in your source code, and they will always be in sync.
+
+;; The script is in
+;; cpc-dev-tool-chain/documentation-for-maintainers/z80_data_transform/generate_names_for_first_byte_of_ops.sh
+;; The script uses data published at https://borilla.co.uk/z80.html . Thanks John
+;; Adams a.k.a. https://github.com/borilla !
+
+;; The list below is in alphabetical order of macro.
+;; If you have a GNU environment, you can sort it by op code with:
+
+opcode_adc_a_a_0x8f EQU 0x8f
+opcode_adc_a_a EQU 0x8f
+opcode_adc_a_b_0x88 EQU 0x88
+opcode_adc_a_b EQU 0x88
+opcode_adc_a_c_0x89 EQU 0x89
+opcode_adc_a_c EQU 0x89
+opcode_adc_a_d_0x8a EQU 0x8a
+opcode_adc_a_d EQU 0x8a
+opcode_adc_a_e_0x8b EQU 0x8b
+opcode_adc_a_e EQU 0x8b
+opcode_adc_a_h_0x8c EQU 0x8c
+opcode_adc_a_h EQU 0x8c
+opcode_adc_a_hl_0x8e EQU 0x8e
+opcode_adc_a_hl EQU 0x8e
+opcode_adc_a_l_0x8d EQU 0x8d
+opcode_adc_a_l EQU 0x8d
+opcode_adc_a_nn_0xce EQU 0xce
+opcode_adc_a_nn EQU 0xce
+opcode_add_a_a_0x87 EQU 0x87
+opcode_add_a_a EQU 0x87
+opcode_add_a_b_0x80 EQU 0x80
+opcode_add_a_b EQU 0x80
+opcode_add_a_c_0x81 EQU 0x81
+opcode_add_a_c EQU 0x81
+opcode_add_a_d_0x82 EQU 0x82
+opcode_add_a_d EQU 0x82
+opcode_add_a_e_0x83 EQU 0x83
+opcode_add_a_e EQU 0x83
+opcode_add_a_h_0x84 EQU 0x84
+opcode_add_a_h EQU 0x84
+opcode_add_a_hl_0x86 EQU 0x86
+opcode_add_a_hl EQU 0x86
+opcode_add_a_l_0x85 EQU 0x85
+opcode_add_a_l EQU 0x85
+opcode_add_a_nn_0xc6 EQU 0xc6
+opcode_add_a_nn EQU 0xc6
+opcode_add_hl_bc_0x09 EQU 0x09
+opcode_add_hl_bc EQU 0x09
+opcode_add_hl_de_0x19 EQU 0x19
+opcode_add_hl_de EQU 0x19
+opcode_add_hl_hl_0x29 EQU 0x29
+opcode_add_hl_hl EQU 0x29
+opcode_add_hl_sp_0x39 EQU 0x39
+opcode_add_hl_sp EQU 0x39
+opcode_and_a_0xa7 EQU 0xa7
+opcode_and_a EQU 0xa7
+opcode_and_b_0xa0 EQU 0xa0
+opcode_and_b EQU 0xa0
+opcode_and_c_0xa1 EQU 0xa1
+opcode_and_c EQU 0xa1
+opcode_and_d_0xa2 EQU 0xa2
+opcode_and_d EQU 0xa2
+opcode_and_e_0xa3 EQU 0xa3
+opcode_and_e EQU 0xa3
+opcode_and_h_0xa4 EQU 0xa4
+opcode_and_h EQU 0xa4
+opcode_and_hl_0xa6 EQU 0xa6
+opcode_and_hl EQU 0xa6
+opcode_and_l_0xa5 EQU 0xa5
+opcode_and_l EQU 0xa5
+opcode_and_nn_0xe6 EQU 0xe6
+opcode_and_nn EQU 0xe6
+opcode_call_c_nnnn_0xdc EQU 0xdc
+opcode_call_c_nnnn EQU 0xdc
+opcode_call_m_nnnn_0xfc EQU 0xfc
+opcode_call_m_nnnn EQU 0xfc
+opcode_call_nc_nnnn_0xd4 EQU 0xd4
+opcode_call_nc_nnnn EQU 0xd4
+opcode_call_nnnn_0xcd EQU 0xcd
+opcode_call_nnnn EQU 0xcd
+opcode_call_nz_nnnn_0xc4 EQU 0xc4
+opcode_call_nz_nnnn EQU 0xc4
+opcode_call_pe_nnnn_0xec EQU 0xec
+opcode_call_pe_nnnn EQU 0xec
+opcode_call_p_nnnn_0xf4 EQU 0xf4
+opcode_call_p_nnnn EQU 0xf4
+opcode_call_po_nnnn_0xe4 EQU 0xe4
+opcode_call_po_nnnn EQU 0xe4
+opcode_call_z_nnnn_0xcc EQU 0xcc
+opcode_call_z_nnnn EQU 0xcc
+opcode_ccf_0x3f EQU 0x3f
+opcode_ccf EQU 0x3f
+opcode_cp_a_0xbf EQU 0xbf
+opcode_cp_a EQU 0xbf
+opcode_cp_b_0xb8 EQU 0xb8
+opcode_cp_b EQU 0xb8
+opcode_cp_c_0xb9 EQU 0xb9
+opcode_cp_c EQU 0xb9
+opcode_cp_d_0xba EQU 0xba
+opcode_cp_d EQU 0xba
+opcode_cp_e_0xbb EQU 0xbb
+opcode_cp_e EQU 0xbb
+opcode_cp_h_0xbc EQU 0xbc
+opcode_cp_h EQU 0xbc
+opcode_cp_hl_0xbe EQU 0xbe
+opcode_cp_hl EQU 0xbe
+opcode_cpl_0x2f EQU 0x2f
+opcode_cp_l_0xbd EQU 0xbd
+opcode_cpl EQU 0x2f
+opcode_cp_l EQU 0xbd
+opcode_cp_nn_0xfe EQU 0xfe
+opcode_cp_nn EQU 0xfe
+opcode_daa_0x27 EQU 0x27
+opcode_daa EQU 0x27
+opcode_dec_a_0x3d EQU 0x3d
+opcode_dec_a EQU 0x3d
+opcode_dec_b_0x05 EQU 0x05
+opcode_dec_bc_0x0b EQU 0x0b
+opcode_dec_bc EQU 0x0b
+opcode_dec_b EQU 0x05
+opcode_dec_c_0x0d EQU 0x0d
+opcode_dec_c EQU 0x0d
+opcode_dec_d_0x15 EQU 0x15
+opcode_dec_de_0x1b EQU 0x1b
+opcode_dec_de EQU 0x1b
+opcode_dec_d EQU 0x15
+opcode_dec_e_0x1d EQU 0x1d
+opcode_dec_e EQU 0x1d
+opcode_dec_h_0x25 EQU 0x25
+opcode_dec_h EQU 0x25
+opcode_dec_hl_0x2b EQU 0x2b
+opcode_dec_hl_0x35 EQU 0x35
+opcode_dec_hl EQU 0x2b
+opcode_dec_hl EQU 0x35
+opcode_dec_l_0x2d EQU 0x2d
+opcode_dec_l EQU 0x2d
+opcode_dec_sp_0x3b EQU 0x3b
+opcode_dec_sp EQU 0x3b
+opcode_di_0xf3 EQU 0xf3
+opcode_di EQU 0xf3
+opcode_djnz_nn_0x10 EQU 0x10
+opcode_djnz_nn EQU 0x10
+opcode_ei_0xfb EQU 0xfb
+opcode_ei EQU 0xfb
+opcode_ex_af_af_0x08 EQU 0x08
+opcode_ex_af_af EQU 0x08
+opcode_ex_de_hl_0xeb EQU 0xeb
+opcode_ex_de_hl EQU 0xeb
+opcode_ex_sp_hl_0xe3 EQU 0xe3
+opcode_ex_sp_hl EQU 0xe3
+opcode_exx_0xd9 EQU 0xd9
+opcode_exx EQU 0xd9
+opcode_halt_0x76 EQU 0x76
+opcode_halt EQU 0x76
+opcode_in_a_nn_0xdb EQU 0xdb
+opcode_in_a_nn EQU 0xdb
+opcode_inc_a_0x3c EQU 0x3c
+opcode_inc_a EQU 0x3c
+opcode_inc_b_0x04 EQU 0x04
+opcode_inc_bc_0x03 EQU 0x03
+opcode_inc_bc EQU 0x03
+opcode_inc_b EQU 0x04
+opcode_inc_c_0x0c EQU 0x0c
+opcode_inc_c EQU 0x0c
+opcode_inc_d_0x14 EQU 0x14
+opcode_inc_de_0x13 EQU 0x13
+opcode_inc_de EQU 0x13
+opcode_inc_d EQU 0x14
+opcode_inc_e_0x1c EQU 0x1c
+opcode_inc_e EQU 0x1c
+opcode_inc_h_0x24 EQU 0x24
+opcode_inc_h EQU 0x24
+opcode_inc_hl_0x23 EQU 0x23
+opcode_inc_hl_0x34 EQU 0x34
+opcode_inc_hl EQU 0x23
+opcode_inc_hl EQU 0x34
+opcode_inc_l_0x2c EQU 0x2c
+opcode_inc_l EQU 0x2c
+opcode_inc_sp_0x33 EQU 0x33
+opcode_inc_sp EQU 0x33
+opcode_jp_c_nnnn_0xda EQU 0xda
+opcode_jp_c_nnnn EQU 0xda
+opcode_jp_hl_0xe9 EQU 0xe9
+opcode_jp_hl EQU 0xe9
+opcode_jp_m_nnnn_0xfa EQU 0xfa
+opcode_jp_m_nnnn EQU 0xfa
+opcode_jp_nc_nnnn_0xd2 EQU 0xd2
+opcode_jp_nc_nnnn EQU 0xd2
+opcode_jp_nnnn_0xc3 EQU 0xc3
+opcode_jp_nnnn EQU 0xc3
+opcode_jp_nz_nnnn_0xc2 EQU 0xc2
+opcode_jp_nz_nnnn EQU 0xc2
+opcode_jp_pe_nnnn_0xea EQU 0xea
+opcode_jp_pe_nnnn EQU 0xea
+opcode_jp_p_nnnn_0xf2 EQU 0xf2
+opcode_jp_p_nnnn EQU 0xf2
+opcode_jp_po_nnnn_0xe2 EQU 0xe2
+opcode_jp_po_nnnn EQU 0xe2
+opcode_jp_z_nnnn_0xca EQU 0xca
+opcode_jp_z_nnnn EQU 0xca
+opcode_jr_c_nn_0x38 EQU 0x38
+opcode_jr_c_nn EQU 0x38
+opcode_jr_nc_nn_0x30 EQU 0x30
+opcode_jr_nc_nn EQU 0x30
+opcode_jr_nn_0x18 EQU 0x18
+opcode_jr_nn EQU 0x18
+opcode_jr_nz_nn_0x20 EQU 0x20
+opcode_jr_nz_nn EQU 0x20
+opcode_jr_z_nn_0x28 EQU 0x28
+opcode_jr_z_nn EQU 0x28
+opcode_ld_a_a_0x7f EQU 0x7f
+opcode_ld_a_a EQU 0x7f
+opcode_ld_a_b_0x78 EQU 0x78
+opcode_ld_a_bc_0x0a EQU 0x0a
+opcode_ld_a_bc EQU 0x0a
+opcode_ld_a_b EQU 0x78
+opcode_ld_a_c_0x79 EQU 0x79
+opcode_ld_a_c EQU 0x79
+opcode_ld_a_d_0x7a EQU 0x7a
+opcode_ld_a_de_0x1a EQU 0x1a
+opcode_ld_a_de EQU 0x1a
+opcode_ld_a_d EQU 0x7a
+opcode_ld_a_e_0x7b EQU 0x7b
+opcode_ld_a_e EQU 0x7b
+opcode_ld_a_h_0x7c EQU 0x7c
+opcode_ld_a_h EQU 0x7c
+opcode_ld_a_hl_0x7e EQU 0x7e
+opcode_ld_a_hl EQU 0x7e
+opcode_ld_a_l_0x7d EQU 0x7d
+opcode_ld_a_l EQU 0x7d
+opcode_ld_a_nn_0x3e EQU 0x3e
+opcode_ld_a_nn EQU 0x3e
+opcode_ld_a_nnnn_0x3a EQU 0x3a
+opcode_ld_a_nnnn EQU 0x3a
+opcode_ld_b_a_0x47 EQU 0x47
+opcode_ld_b_a EQU 0x47
+opcode_ld_b_b_0x40 EQU 0x40
+opcode_ld_b_b EQU 0x40
+opcode_ld_b_c_0x41 EQU 0x41
+opcode_ld_bc_a_0x02 EQU 0x02
+opcode_ld_bc_a EQU 0x02
+opcode_ld_b_c EQU 0x41
+opcode_ld_bc_nnnn_0x01 EQU 0x01
+opcode_ld_bc_nnnn EQU 0x01
+opcode_ld_b_d_0x42 EQU 0x42
+opcode_ld_b_d EQU 0x42
+opcode_ld_b_e_0x43 EQU 0x43
+opcode_ld_b_e EQU 0x43
+opcode_ld_b_h_0x44 EQU 0x44
+opcode_ld_b_h EQU 0x44
+opcode_ld_b_hl_0x46 EQU 0x46
+opcode_ld_b_hl EQU 0x46
+opcode_ld_b_l_0x45 EQU 0x45
+opcode_ld_b_l EQU 0x45
+opcode_ld_b_nn_0x06 EQU 0x06
+opcode_ld_b_nn EQU 0x06
+opcode_ld_c_a_0x4f EQU 0x4f
+opcode_ld_c_a EQU 0x4f
+opcode_ld_c_b_0x48 EQU 0x48
+opcode_ld_c_b EQU 0x48
+opcode_ld_c_c_0x49 EQU 0x49
+opcode_ld_c_c EQU 0x49
+opcode_ld_c_d_0x4a EQU 0x4a
+opcode_ld_c_d EQU 0x4a
+opcode_ld_c_e_0x4b EQU 0x4b
+opcode_ld_c_e EQU 0x4b
+opcode_ld_c_h_0x4c EQU 0x4c
+opcode_ld_c_h EQU 0x4c
+opcode_ld_c_hl_0x4e EQU 0x4e
+opcode_ld_c_hl EQU 0x4e
+opcode_ld_c_l_0x4d EQU 0x4d
+opcode_ld_c_l EQU 0x4d
+opcode_ld_c_nn_0x0e EQU 0x0e
+opcode_ld_c_nn EQU 0x0e
+opcode_ld_d_a_0x57 EQU 0x57
+opcode_ld_d_a EQU 0x57
+opcode_ld_d_b_0x50 EQU 0x50
+opcode_ld_d_b EQU 0x50
+opcode_ld_d_c_0x51 EQU 0x51
+opcode_ld_d_c EQU 0x51
+opcode_ld_d_d_0x52 EQU 0x52
+opcode_ld_d_d EQU 0x52
+opcode_ld_d_e_0x53 EQU 0x53
+opcode_ld_de_a_0x12 EQU 0x12
+opcode_ld_de_a EQU 0x12
+opcode_ld_d_e EQU 0x53
+opcode_ld_de_nnnn_0x11 EQU 0x11
+opcode_ld_de_nnnn EQU 0x11
+opcode_ld_d_h_0x54 EQU 0x54
+opcode_ld_d_h EQU 0x54
+opcode_ld_d_hl_0x56 EQU 0x56
+opcode_ld_d_hl EQU 0x56
+opcode_ld_d_l_0x55 EQU 0x55
+opcode_ld_d_l EQU 0x55
+opcode_ld_d_nn_0x16 EQU 0x16
+opcode_ld_d_nn EQU 0x16
+opcode_ld_e_a_0x5f EQU 0x5f
+opcode_ld_e_a EQU 0x5f
+opcode_ld_e_b_0x58 EQU 0x58
+opcode_ld_e_b EQU 0x58
+opcode_ld_e_c_0x59 EQU 0x59
+opcode_ld_e_c EQU 0x59
+opcode_ld_e_d_0x5a EQU 0x5a
+opcode_ld_e_d EQU 0x5a
+opcode_ld_e_e_0x5b EQU 0x5b
+opcode_ld_e_e EQU 0x5b
+opcode_ld_e_h_0x5c EQU 0x5c
+opcode_ld_e_h EQU 0x5c
+opcode_ld_e_hl_0x5e EQU 0x5e
+opcode_ld_e_hl EQU 0x5e
+opcode_ld_e_l_0x5d EQU 0x5d
+opcode_ld_e_l EQU 0x5d
+opcode_ld_e_nn_0x1e EQU 0x1e
+opcode_ld_e_nn EQU 0x1e
+opcode_ld_h_a_0x67 EQU 0x67
+opcode_ld_h_a EQU 0x67
+opcode_ld_h_b_0x60 EQU 0x60
+opcode_ld_h_b EQU 0x60
+opcode_ld_h_c_0x61 EQU 0x61
+opcode_ld_h_c EQU 0x61
+opcode_ld_h_d_0x62 EQU 0x62
+opcode_ld_h_d EQU 0x62
+opcode_ld_h_e_0x63 EQU 0x63
+opcode_ld_h_e EQU 0x63
+opcode_ld_h_h_0x64 EQU 0x64
+opcode_ld_h_h EQU 0x64
+opcode_ld_h_hl_0x66 EQU 0x66
+opcode_ld_h_hl EQU 0x66
+opcode_ld_h_l_0x65 EQU 0x65
+opcode_ld_hl_a_0x77 EQU 0x77
+opcode_ld_hl_a EQU 0x77
+opcode_ld_hl_b_0x70 EQU 0x70
+opcode_ld_hl_b EQU 0x70
+opcode_ld_hl_c_0x71 EQU 0x71
+opcode_ld_hl_c EQU 0x71
+opcode_ld_hl_d_0x72 EQU 0x72
+opcode_ld_hl_d EQU 0x72
+opcode_ld_hl_e_0x73 EQU 0x73
+opcode_ld_hl_e EQU 0x73
+opcode_ld_h_l EQU 0x65
+opcode_ld_hl_h_0x74 EQU 0x74
+opcode_ld_hl_h EQU 0x74
+opcode_ld_hl_l_0x75 EQU 0x75
+opcode_ld_hl_l EQU 0x75
+opcode_ld_hl_nn_0x36 EQU 0x36
+opcode_ld_hl_nn EQU 0x36
+opcode_ld_hl_nnnn_0x21 EQU 0x21
+opcode_ld_hl_nnnn_0x2a EQU 0x2a
+opcode_ld_hl_nnnn EQU 0x21
+opcode_ld_hl_nnnn EQU 0x2a
+opcode_ld_h_nn_0x26 EQU 0x26
+opcode_ld_h_nn EQU 0x26
+opcode_ld_l_a_0x6f EQU 0x6f
+opcode_ld_l_a EQU 0x6f
+opcode_ld_l_b_0x68 EQU 0x68
+opcode_ld_l_b EQU 0x68
+opcode_ld_l_c_0x69 EQU 0x69
+opcode_ld_l_c EQU 0x69
+opcode_ld_l_d_0x6a EQU 0x6a
+opcode_ld_l_d EQU 0x6a
+opcode_ld_l_e_0x6b EQU 0x6b
+opcode_ld_l_e EQU 0x6b
+opcode_ld_l_h_0x6c EQU 0x6c
+opcode_ld_l_h EQU 0x6c
+opcode_ld_l_hl_0x6e EQU 0x6e
+opcode_ld_l_hl EQU 0x6e
+opcode_ld_l_l_0x6d EQU 0x6d
+opcode_ld_l_l EQU 0x6d
+opcode_ld_l_nn_0x2e EQU 0x2e
+opcode_ld_l_nn EQU 0x2e
+opcode_ld_nnnn_a_0x32 EQU 0x32
+opcode_ld_nnnn_a EQU 0x32
+opcode_ld_nnnn_hl_0x22 EQU 0x22
+opcode_ld_nnnn_hl EQU 0x22
+opcode_ld_sp_hl_0xf9 EQU 0xf9
+opcode_ld_sp_hl EQU 0xf9
+opcode_ld_sp_nnnn_0x31 EQU 0x31
+opcode_ld_sp_nnnn EQU 0x31
+opcode_nop_0x00 EQU 0x00
+opcode_nop EQU 0x00
+opcode_or_a_0xb7 EQU 0xb7
+opcode_or_a EQU 0xb7
+opcode_or_b_0xb0 EQU 0xb0
+opcode_or_b EQU 0xb0
+opcode_or_c_0xb1 EQU 0xb1
+opcode_or_c EQU 0xb1
+opcode_or_d_0xb2 EQU 0xb2
+opcode_or_d EQU 0xb2
+opcode_or_e_0xb3 EQU 0xb3
+opcode_or_e EQU 0xb3
+opcode_or_h_0xb4 EQU 0xb4
+opcode_or_h EQU 0xb4
+opcode_or_hl_0xb6 EQU 0xb6
+opcode_or_hl EQU 0xb6
+opcode_or_l_0xb5 EQU 0xb5
+opcode_or_l EQU 0xb5
+opcode_or_nn_0xf6 EQU 0xf6
+opcode_or_nn EQU 0xf6
+opcode_out_nn_a_0xd3 EQU 0xd3
+opcode_out_nn_a EQU 0xd3
+opcode_pop_af_0xf1 EQU 0xf1
+opcode_pop_af EQU 0xf1
+opcode_pop_bc_0xc1 EQU 0xc1
+opcode_pop_bc EQU 0xc1
+opcode_pop_de_0xd1 EQU 0xd1
+opcode_pop_de EQU 0xd1
+opcode_pop_hl_0xe1 EQU 0xe1
+opcode_pop_hl EQU 0xe1
+opcode_push_af_0xf5 EQU 0xf5
+opcode_push_af EQU 0xf5
+opcode_push_bc_0xc5 EQU 0xc5
+opcode_push_bc EQU 0xc5
+opcode_push_de_0xd5 EQU 0xd5
+opcode_push_de EQU 0xd5
+opcode_push_hl_0xe5 EQU 0xe5
+opcode_push_hl EQU 0xe5
+opcode_ret_0xc9 EQU 0xc9
+opcode_ret_c_0xd8 EQU 0xd8
+opcode_ret_c EQU 0xd8
+opcode_ret EQU 0xc9
+opcode_ret_m_0xf8 EQU 0xf8
+opcode_ret_m EQU 0xf8
+opcode_ret_nc_0xd0 EQU 0xd0
+opcode_ret_nc EQU 0xd0
+opcode_ret_nz_0xc0 EQU 0xc0
+opcode_ret_nz EQU 0xc0
+opcode_ret_p_0xf0 EQU 0xf0
+opcode_ret_pe_0xe8 EQU 0xe8
+opcode_ret_pe EQU 0xe8
+opcode_ret_p EQU 0xf0
+opcode_ret_po_0xe0 EQU 0xe0
+opcode_ret_po EQU 0xe0
+opcode_ret_z_0xc8 EQU 0xc8
+opcode_ret_z EQU 0xc8
+opcode_rla_0x17 EQU 0x17
+opcode_rla EQU 0x17
+opcode_rlca_0x07 EQU 0x07
+opcode_rlca EQU 0x07
+opcode_rra_0x1f EQU 0x1f
+opcode_rra EQU 0x1f
+opcode_rrca_0x0f EQU 0x0f
+opcode_rrca EQU 0x0f
+opcode_rst_0_0xc7 EQU 0xc7
+opcode_rst_0 EQU 0xc7
+opcode_rst_10h_0xd7 EQU 0xd7
+opcode_rst_10h EQU 0xd7
+opcode_rst_18h_0xdf EQU 0xdf
+opcode_rst_18h EQU 0xdf
+opcode_rst_20h_0xe7 EQU 0xe7
+opcode_rst_20h EQU 0xe7
+opcode_rst_28h_0xef EQU 0xef
+opcode_rst_28h EQU 0xef
+opcode_rst_30h_0xf7 EQU 0xf7
+opcode_rst_30h EQU 0xf7
+opcode_rst_38h_0xff EQU 0xff
+opcode_rst_38h EQU 0xff
+opcode_rst_8h_0xcf EQU 0xcf
+opcode_rst_8h EQU 0xcf
+opcode_sbc_a_a_0x9f EQU 0x9f
+opcode_sbc_a_a EQU 0x9f
+opcode_sbc_a_b_0x98 EQU 0x98
+opcode_sbc_a_b EQU 0x98
+opcode_sbc_a_c_0x99 EQU 0x99
+opcode_sbc_a_c EQU 0x99
+opcode_sbc_a_d_0x9a EQU 0x9a
+opcode_sbc_a_d EQU 0x9a
+opcode_sbc_a_e_0x9b EQU 0x9b
+opcode_sbc_a_e EQU 0x9b
+opcode_sbc_a_h_0x9c EQU 0x9c
+opcode_sbc_a_h EQU 0x9c
+opcode_sbc_a_hl_0x9e EQU 0x9e
+opcode_sbc_a_hl EQU 0x9e
+opcode_sbc_a_l_0x9d EQU 0x9d
+opcode_sbc_a_l EQU 0x9d
+opcode_sbc_a_nn_0xde EQU 0xde
+opcode_sbc_a_nn EQU 0xde
+opcode_scf_0x37 EQU 0x37
+opcode_scf EQU 0x37
+opcode_sub_a_0x97 EQU 0x97
+opcode_sub_a EQU 0x97
+opcode_sub_b_0x90 EQU 0x90
+opcode_sub_b EQU 0x90
+opcode_sub_c_0x91 EQU 0x91
+opcode_sub_c EQU 0x91
+opcode_sub_d_0x92 EQU 0x92
+opcode_sub_d EQU 0x92
+opcode_sub_e_0x93 EQU 0x93
+opcode_sub_e EQU 0x93
+opcode_sub_h_0x94 EQU 0x94
+opcode_sub_h EQU 0x94
+opcode_sub_hl_0x96 EQU 0x96
+opcode_sub_hl EQU 0x96
+opcode_sub_l_0x95 EQU 0x95
+opcode_sub_l EQU 0x95
+opcode_sub_nn_0xd6 EQU 0xd6
+opcode_sub_nn EQU 0xd6
+opcode_xor_a_0xaf EQU 0xaf
+opcode_xor_a EQU 0xaf
+opcode_xor_b_0xa8 EQU 0xa8
+opcode_xor_b EQU 0xa8
+opcode_xor_c_0xa9 EQU 0xa9
+opcode_xor_c EQU 0xa9
+opcode_xor_d_0xaa EQU 0xaa
+opcode_xor_d EQU 0xaa
+opcode_xor_e_0xab EQU 0xab
+opcode_xor_e EQU 0xab
+opcode_xor_h_0xac EQU 0xac
+opcode_xor_h EQU 0xac
+opcode_xor_hl_0xae EQU 0xae
+opcode_xor_hl EQU 0xae
+opcode_xor_l_0xad EQU 0xad
+opcode_xor_l EQU 0xad
+opcode_xor_nn_0xee EQU 0xee
+opcode_xor_nn EQU 0xee
+
diff --git a/tools/rasm/win32.bat b/tools/rasm/win32.bat
new file mode 100755
index 0000000..f73cca4
--- /dev/null
+++ b/tools/rasm/win32.bat
@@ -0,0 +1,7 @@
+cl ZX0-main\src\compress.c /Ox /c -I ZX0-main\src
+cl ZX0-main\src\optimize.c /Ox /c -I ZX0-main\src
+cl ZX0-main\src\memory.c /Ox /c -I ZX0-main\src
+
+cl rasm.c /Ox /DNOAPULTRA=1 /DDOS_WIN=1 optimize.obj compress.obj memory.obj
+
+
diff --git a/tools/rasm/zx7.h b/tools/rasm/zx7.h
index f03659d..f371e58 100644
--- a/tools/rasm/zx7.h
+++ b/tools/rasm/zx7.h
@@ -46,9 +46,9 @@ typedef struct optimal_t {
int len;
} Optimal;
-Optimal *optimize(unsigned char *input_data, size_t input_size);
+Optimal *zx7_optimize(unsigned char *input_data, int input_size);
-unsigned char *ZX7_compress(Optimal *optimal, unsigned char *input_data, size_t input_size, size_t *output_size);
+unsigned char *ZX7_compress(Optimal *optimal, unsigned char *input_data, int input_size, int *output_size);
/*
* (c) Copyright 2012 by Einar Saukas. All rights reserved.
@@ -75,7 +75,7 @@ unsigned char *ZX7_compress(Optimal *optimal, unsigned char *input_data, size_t
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-int elias_gamma_bits(int value) {
+int zx7_elias_gamma_bits(int value) {
int bits;
bits = 1;
@@ -87,10 +87,10 @@ int elias_gamma_bits(int value) {
}
int count_bits(int offset, int len) {
- return 1 + (offset > 128 ? 12 : 8) + elias_gamma_bits(len-1);
+ return 1 + (offset > 128 ? 12 : 8) + zx7_elias_gamma_bits(len-1);
}
-Optimal* optimize(unsigned char *input_data, size_t input_size) {
+Optimal* zx7_optimize(unsigned char *input_data, int input_size) {
size_t *min;
size_t *max;
Match *matches;
@@ -190,20 +190,20 @@ Optimal* optimize(unsigned char *input_data, size_t input_size) {
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-unsigned char* output_data;
-size_t output_index;
-size_t bit_index;
-int bit_mask;
+extern unsigned char* output_data;
+extern int output_index;
+extern int bit_index;
+extern int bit_mask;
-void write_byte(int value) {
+void zx7_write_byte(int value) {
output_data[output_index++] = value;
}
-void write_bit(int value) {
+void zx7_write_bit(int value) {
if (bit_mask == 0) {
bit_mask = 128;
bit_index = output_index;
- write_byte(0);
+ zx7_write_byte(0);
}
if (value > 0) {
output_data[bit_index] |= bit_mask;
@@ -211,18 +211,18 @@ void write_bit(int value) {
bit_mask >>= 1;
}
-void write_elias_gamma(int value) {
+void zx7_write_elias_gamma(int value) {
int i;
for (i = 2; i <= value; i <<= 1) {
- write_bit(0);
+ zx7_write_bit(0);
}
while ((i >>= 1) > 0) {
- write_bit(value & i);
+ zx7_write_bit(value & i);
}
}
-unsigned char *ZX7_compress(Optimal *optimal, unsigned char *input_data, size_t input_size, size_t *output_size) {
+unsigned char *ZX7_compress(Optimal *optimal, unsigned char *input_data, int input_size, int *output_size) {
size_t input_index;
size_t input_prev;
int offset1;
@@ -246,48 +246,48 @@ unsigned char *ZX7_compress(Optimal *optimal, unsigned char *input_data, size_t
bit_mask = 0;
/* first byte is always literal */
- write_byte(input_data[0]);
+ zx7_write_byte(input_data[0]);
/* process remaining bytes */
while ((input_index = optimal[input_index].bits) > 0) {
if (optimal[input_index].len == 0) {
/* literal indicator */
- write_bit(0);
+ zx7_write_bit(0);
/* literal value */
- write_byte(input_data[input_index]);
+ zx7_write_byte(input_data[input_index]);
} else {
/* sequence indicator */
- write_bit(1);
+ zx7_write_bit(1);
/* sequence length */
- write_elias_gamma(optimal[input_index].len-1);
+ zx7_write_elias_gamma(optimal[input_index].len-1);
/* sequence offset */
offset1 = optimal[input_index].offset-1;
if (offset1 < 128) {
- write_byte(offset1);
+ zx7_write_byte(offset1);
} else {
offset1 -= 128;
- write_byte((offset1 & 127) | 128);
+ zx7_write_byte((offset1 & 127) | 128);
for (mask = 1024; mask > 127; mask >>= 1) {
- write_bit(offset1 & mask);
+ zx7_write_bit(offset1 & mask);
}
}
}
}
/* sequence indicator */
- write_bit(1);
+ zx7_write_bit(1);
/* end marker > MAX_LEN */
for (i = 0; i < 16; i++) {
- write_bit(0);
+ zx7_write_bit(0);
}
- write_bit(1);
+ zx7_write_bit(1);
return output_data;
}