diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index a31d101fb..0508172d9 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -8,8 +8,6 @@ on: branches: - main pull_request: - branches: - - main branches-ignore: - docs diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 714dde1fa..000000000 --- a/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: python -python: - # - "2.7" <- Unsupported, uses 2.7.9 ? - - "3.8" - # PyPy versions - # - "pypy" # PyPy2 2.5.0 - # - "pypy3" # Pypy3 2.4.0 - # - "pypy-5.3.1" - - -cache: pip - -install: - - pip install tox-travis - -# command to run tests -script: tox -- --no-cov diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml deleted file mode 100644 index 04eb35a70..000000000 --- a/bitbucket-pipelines.yml +++ /dev/null @@ -1,18 +0,0 @@ -# This is a sample build configuration for Python. -# Check our guides at https://confluence.atlassian.com/x/x4UWN for more examples. -# Only use spaces to indent your .yml configuration. -# ----- -# You can specify a custom docker image from Docker Hub as your build environment. -image: python:3.5.3 - -pipelines: - default: - - step: - caches: - - pip - script: # Modify the commands below to build your repository. - - pip install tox - - mkdir -p tests/functional/tmp - - tox -e py27,py35,flake8 - - diff --git a/docs/architectures/uzebox.md b/docs/architectures/uzebox.md index 66989e350..395c7ab80 100644 --- a/docs/architectures/uzebox.md +++ b/docs/architectures/uzebox.md @@ -6,9 +6,9 @@ * RAM Memory: 4kb * Colours: 256 (same palette as from msx2-screen8, or zxspectrum-ulaplus) * Video "Memory": 1 byte (!) - The video display is just a 8bit port, used defaultly from the interrupt video-mode kernels. -* Tile Display Memory Area: is (defaultly) inside the 4kb RAM memory, size depending on how is it used from the video-mode kernel choosed. Most of the ready video modes can have 256 different tiles available. -* Pattern Display Memory Area (tiles and sprites): is (defaultly) inside the 64kb Flash memory, size depending on how is it used from the video-mode kernel choosed -* Sprite Attribute Memory Area: is (defaultly) inside the 4kb RAM memory, size depending on how is it used from the video-mode kernel choosed +* Tile Display Memory Area: is (defaultly) inside the 4kb RAM memory, size depending on how is it used from the video-mode kernel chosen. Most of the ready video modes can have 256 different tiles available. +* Pattern Display Memory Area (tiles and sprites): is (defaultly) inside the 64kb Flash memory, size depending on how is it used from the video-mode kernel chosen +* Sprite Attribute Memory Area: is (defaultly) inside the 4kb RAM memory, size depending on how is it used from the video-mode kernel chosen * Video Modes: 9 (up to now) - Since display modes are from interrupt, anyone is welcome on creating new video-modes when needed (and skilled for helping). Theoretically, from 1 cycle from ATmega644 processor, a display resolution like 1440x240 could be obtained. But since at least 4 cycles are needed to display a pixel, the width resolutions available from video modes are 360 (4 cycles), 288 (5), 240 (6), 180 (8), 144 (10) and 120 (12). ## more information diff --git a/docs/code.md b/docs/code.md index 52508aad9..65b14ddf8 100644 --- a/docs/code.md +++ b/docs/code.md @@ -19,7 +19,7 @@ Returned value type is [UByte](types.md#UByte). REM ASCII CODE of "A" PRINT "ASCII CODE of A is "; CODE("A") LET a$ = "" -PRINT "ASCII CODE of emtpy string is "; CODE(a$) +PRINT "ASCII CODE of empty string is "; CODE(a$) ``` ## Remarks diff --git a/docs/if.md b/docs/if.md index 8072b1891..222f35bd3 100644 --- a/docs/if.md +++ b/docs/if.md @@ -37,7 +37,7 @@ End If ``` -Since **IF** is a _sentence_, it can be nested; however, remember that _every_ **IF** _must be closed with_ **END IF** when the line is splitted after **THEN** (mutiline **IF**): +Since **IF** is a _sentence_, it can be nested; however, remember that _every_ **IF** _must be closed with_ **END IF** when the line is split after **THEN** (mutiline **IF**): ``` If a < 5 Then Print "A is less than five" diff --git a/docs/library/keys/getkey.md b/docs/library/keys/getkey.md index 08687c254..d5a3819ae 100644 --- a/docs/library/keys/getkey.md +++ b/docs/library/keys/getkey.md @@ -22,7 +22,7 @@ x = GetKey PRINT "You pressed the "; CHR x; " key" ``` Will print the key pressed. Unlike [INKEY$](../../inkey.md) it returns an Ubyte (ASCII code) -which is more efficent that working with strings. +which is more efficient that working with strings. ### See also @@ -30,4 +30,4 @@ which is more efficent that working with strings. * [MultiKeys](multikeys.md) -Back to parent page: [Keys ibrary](../keys.bas.md) +Back to parent page: [Keys library](../keys.bas.md) diff --git a/docs/library/print64.bas.md b/docs/library/print64.bas.md index af4863de6..5425c27b5 100644 --- a/docs/library/print64.bas.md +++ b/docs/library/print64.bas.md @@ -211,7 +211,7 @@ BLp64_END_LOOP: sra a ; sra a ; sra a ; Multiply by 8 60155 203 47 - add a, 88 ; Add to attrbute base address + add a, 88 ; Add to attribute base address ld h, a ; Put high byte value for attribute into H. ld a, d ; get y value again and 7 ; set within third diff --git a/docs/library/putchars.bas.md b/docs/library/putchars.bas.md index 6a702f480..38480509a 100644 --- a/docs/library/putchars.bas.md +++ b/docs/library/putchars.bas.md @@ -95,7 +95,7 @@ Asm INC DE INC H ld a,(DE) - LD (HL),a ; Eigth Row + LD (HL),a ; Eighth Row INC DE ; Move to next data item. diff --git a/docs/library/puttile.md b/docs/library/puttile.md index 58998036e..f718e87e9 100644 --- a/docs/library/puttile.md +++ b/docs/library/puttile.md @@ -20,7 +20,7 @@ It uses 36 bytes of data, starting at the address given. ``` -' Routine to place a 16 pixel by 16 pixel "Tile" onto the screen at character position x,y from adddress given. +' Routine to place a 16 pixel by 16 pixel "Tile" onto the screen at character position x,y from address given. ' Data must be in the format of 16 bit rows, followed by attribute data. ' (c) 2010 Britlion, donated to the ZX BASIC project. ' Thanks to Boriel, LCD and Na_than for inspiration behind this. diff --git a/docs/pause.md b/docs/pause.md index fa9c7e8b3..daa589a6f 100644 --- a/docs/pause.md +++ b/docs/pause.md @@ -7,7 +7,7 @@ PAUSE Just as in Sinclair basic, this command pauses the execution for the given number of frames (1 frame equals to 1/50th of second in Europe, 1/60th of second in the US: this is usually in -sync with the electricity AC frecuency) or until a key is pressed. +sync with the electricity AC frequency) or until a key is pressed. Bear in mind the number 0 is actually taken as 65536. Currently this sentence uses the Sinclair BASIC ROM, so **it needs interruptions enabled**. diff --git a/docs/zxb.md b/docs/zxb.md index cd80d8c7c..27db3c27d 100644 --- a/docs/zxb.md +++ b/docs/zxb.md @@ -76,7 +76,7 @@ ZXB provides several (and useful) command line options. To see them, just type * -T, --tzx Sets output format to tzx (default is .bin) -t, --tap Sets output format to tap (default is .bin) -B, --BASIC Creates a BASIC loader which loads the rest of the - CODE. Requires -T ot -t + CODE. Requires -T or -t -a, --autorun Sets the program to be run once loaded -A, --asm Sets output format to asm -S ORG, --org ORG Start of machine code. By default 32768 @@ -184,7 +184,7 @@ and it size is fixed (won't change during program execution). * **--debug-memory**
During your program execution, using strings might fail due to lack of memory, but your program won't report it and will continue executing (except the strings not fitting into the heap will be converted to `NULL` string or `""`). -The same aplies to other dynamic objects. So enabling this flag, will make your program to stop reporting a +The same applies to other dynamic objects. So enabling this flag, will make your program to stop reporting a ROM _Out of memory_ error. This will add a little overhead to your program execution, but it's useful to detect _Out of Memory_ errors. diff --git a/pyproject.toml b/pyproject.toml index dfe05b939..2d8e72a44 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -107,6 +107,7 @@ target-version = "py310" select = [ "C4", "E", + "EXE", "F", "I", "PLR", @@ -120,6 +121,7 @@ ignore = [ "E722", "E731", "E741", + "EXE002", "PLR0124", "PLR0911", "PLR0912", @@ -135,7 +137,6 @@ ignore = [ "RET501", "RET503", "RET504", - "RET506", "RET507", "RUF005", "RUF012", diff --git a/src/__init__.py b/src/__init__.py index b31320ab4..b259a367a 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python3 - import sys PYTHON_VERSION = 3, 10 # Minimum python version required diff --git a/src/api/check.py b/src/api/check.py index 7c817a6f4..7d252c49a 100644 --- a/src/api/check.py +++ b/src/api/check.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim:ts=4:sw=4:et: # ---------------------------------------------------------------------- @@ -407,7 +406,7 @@ def is_temporary_value(node) -> bool: return node.token not in ("STRING", "VAR") and node.t[0] not in ("_", "#") -def common_type(a, b): +def common_type(a: symbols.TYPE | Type | None, b: symbols.TYPE | Type | None) -> symbols.TYPE | Type | None: """Returns a type which is common for both a and b types. Returns None if no common types allowed. """ @@ -436,7 +435,7 @@ def common_type(a, b): assert a.is_basic assert b.is_basic - types = (a, b) + types = a, b if Type.float_ in types: return Type.float_ diff --git a/src/api/config.py b/src/api/config.py index 90e68d515..66361b27d 100644 --- a/src/api/config.py +++ b/src/api/config.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim:ts=4:et:sw=4: # ---------------------------------------------------------------------- @@ -13,7 +12,7 @@ import os import sys from collections.abc import Callable -from enum import Enum +from enum import StrEnum from src.api import errmsg, global_, options, python_version_check from src.api.options import ANYTYPE, Action @@ -25,14 +24,21 @@ # Common setup and configuration for all tools # ------------------------------------------------------ @enum.unique -class ConfigSections(str, Enum): +class ConfigSections(StrEnum): ZXBC = "zxbc" ZXBASM = "zxbasm" ZXBPP = "zxbpp" @enum.unique -class OPTION(str, Enum): +class OptimizationStrategy(StrEnum): + Size = "size" + Speed = "speed" + Auto = "auto" + + +@enum.unique +class OPTION(StrEnum): OUTPUT_FILENAME = "output_filename" INPUT_FILENAME = "input_filename" STDERR_FILENAME = "stderr_filename" @@ -77,6 +83,9 @@ class OPTION(str, Enum): ASM_ZXNEXT = "zxnext" FORCE_ASM_BRACKET = "force_asm_brackets" + # Optimization Preferences + OPT_STRATEGY = "opt_strategy" + OPTIONS = options.Options() OPTIONS_NOT_SAVED = { @@ -227,6 +236,15 @@ def init() -> None: # Whether to show WXXX warning codes or not OPTIONS(Action.ADD, name=OPTION.HIDE_WARNING_CODES, type=bool, default=False, ignore_none=True) + # Optimization preferences + OPTIONS( + Action.ADD, + name=OPTION.OPT_STRATEGY, + type=OptimizationStrategy, + default=OptimizationStrategy.Auto, + ignore_none=True, + ) + OPTIONS( Action.ADD, name=OPTION.PROJECT_FILENAME, diff --git a/src/api/constants.py b/src/api/constants.py index 3e2e74218..489b496ac 100644 --- a/src/api/constants.py +++ b/src/api/constants.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- @@ -10,7 +9,8 @@ import enum import os -from typing import Optional, Union +from enum import StrEnum +from typing import Final, Optional, Union from .decorator import classproperty @@ -30,7 +30,7 @@ @enum.unique -class CLASS(str, enum.Enum): +class CLASS(StrEnum): """Enums class constants""" unknown = "unknown" # 0 @@ -81,10 +81,12 @@ class TYPE(enum.IntEnum): fixed = 7 float = 8 string = 9 + boolean = 10 @classmethod - def type_size(cls, type_: "TYPE"): + def type_size(cls, type_: "TYPE") -> int: type_sizes = { + cls.boolean: 1, cls.byte: 1, cls.ubyte: 1, cls.integer: 2, @@ -99,59 +101,66 @@ def type_size(cls, type_: "TYPE"): return type_sizes[type_] @classproperty - def types(cls): + def types(cls) -> set["TYPE"]: return set(TYPE) @classmethod - def size(cls, type_: "TYPE"): + def size(cls, type_: "TYPE") -> int: return cls.type_size(type_) @classproperty - def integral(cls): - return {cls.byte, cls.ubyte, cls.integer, cls.uinteger, cls.long, cls.ulong} + def integral(cls) -> set["TYPE"]: + return {cls.boolean, cls.byte, cls.ubyte, cls.integer, cls.uinteger, cls.long, cls.ulong} @classproperty - def signed(cls): + def signed(cls) -> set["TYPE"]: return {cls.byte, cls.integer, cls.long, cls.fixed, cls.float} @classproperty - def unsigned(cls): - return {cls.ubyte, cls.uinteger, cls.ulong} + def unsigned(cls) -> set["TYPE"]: + return {cls.boolean, cls.ubyte, cls.uinteger, cls.ulong} @classproperty - def decimals(cls): + def decimals(cls) -> set["TYPE"]: return {cls.fixed, cls.float} @classproperty - def numbers(cls): - return set(cls.integral) | set(cls.decimals) + def numbers(cls) -> set["TYPE"]: + return cls.integral | cls.decimals @classmethod - def is_valid(cls, type_: "TYPE"): + def is_valid(cls, type_: "TYPE") -> bool: """Whether the given type is valid or not. """ return type_ in cls.types @classmethod - def is_signed(cls, type_: "TYPE"): + def is_signed(cls, type_: "TYPE") -> bool: return type_ in cls.signed @classmethod - def is_unsigned(cls, type_: "TYPE"): + def is_unsigned(cls, type_: "TYPE") -> bool: return type_ in cls.unsigned @classmethod - def to_signed(cls, type_: "TYPE"): + def to_signed(cls, type_: "TYPE") -> "TYPE": """Return signed type or equivalent""" if type_ in cls.unsigned: - return {TYPE.ubyte: TYPE.byte, TYPE.uinteger: TYPE.integer, TYPE.ulong: TYPE.long}[type_] + return { + TYPE.boolean: TYPE.boolean, + TYPE.ubyte: TYPE.byte, + TYPE.uinteger: TYPE.integer, + TYPE.ulong: TYPE.long, + }[type_] + if type_ in cls.decimals or type_ in cls.signed: return type_ + return cls.unknown @staticmethod - def to_string(type_: "TYPE"): + def to_string(type_: "TYPE") -> str: """Return ID representation (string) of a type""" return type_.name @@ -174,11 +183,11 @@ class SCOPE(str, enum.Enum): parameter = "parameter" @staticmethod - def is_valid(scope: Union[str, "SCOPE"]): + def is_valid(scope: Union[str, "SCOPE"]) -> bool: return scope in set(SCOPE) @staticmethod - def to_string(scope: "SCOPE"): + def to_string(scope: "SCOPE") -> str: assert SCOPE.is_valid(scope) return scope.value @@ -209,7 +218,7 @@ class LoopType(str, enum.Enum): # ---------------------------------------------------------------------- # Deprecated suffixes for variable names, such as "a$" # ---------------------------------------------------------------------- -DEPRECATED_SUFFIXES = ("$", "%", "&") +DEPRECATED_SUFFIXES: Final[frozenset[str]] = frozenset(("$", "%", "&")) # ---------------------------------------------------------------------- # Identifier type diff --git a/src/api/debug.py b/src/api/debug.py index ed5a1a5e2..24ace48d4 100644 --- a/src/api/debug.py +++ b/src/api/debug.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim:ts=4:sw=4:et: # Simple debugging module diff --git a/src/api/decorator.py b/src/api/decorator.py index e1e6b5155..a9bc6bb83 100644 --- a/src/api/decorator.py +++ b/src/api/decorator.py @@ -1,9 +1,7 @@ -#!/usr/bin/env python - from collections.abc import Callable -class classproperty: +class ClassProperty: """Decorator for class properties. Use @classproperty instead of @property to add properties to the class object. @@ -14,3 +12,8 @@ def __init__(self, fget: Callable[[type], Callable]) -> None: def __get__(self, owner_self, owner_cls: type): return self.fget(owner_cls) + + +def classproperty(fget: Callable[[type], Callable]) -> ClassProperty: + """Use this function as the decorator in lowercase to follow Python conventions.""" + return ClassProperty(fget) diff --git a/src/api/errmsg.py b/src/api/errmsg.py index da6906a90..17c88afd4 100644 --- a/src/api/errmsg.py +++ b/src/api/errmsg.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- @@ -107,7 +106,7 @@ def warning_command_line_flag_deprecation(flag: str) -> None: """Warning signaling command line flag is deprecated. This is a special warning that can't be silenced, and needs no line number nor filename. """ - # msg_output(f"WARNING: deprecated flag {flag}") # TODO: To be enabled upon 1.18+ + msg_output(f"WARNING: deprecated flag {flag}") # TODO: To be enabled upon 1.18+ # region [Warnings] diff --git a/src/api/exception.py b/src/api/exception.py index 435f9d6c3..01bfb9efb 100644 --- a/src/api/exception.py +++ b/src/api/exception.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim:ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/api/fp.py b/src/api/fp.py old mode 100755 new mode 100644 index 403b1d14e..478271000 --- a/src/api/fp.py +++ b/src/api/fp.py @@ -1,5 +1,3 @@ -#!/usr/bin/python - # Floating point converter diff --git a/src/api/global_.py b/src/api/global_.py index a15eeb1d0..03dd03f22 100644 --- a/src/api/global_.py +++ b/src/api/global_.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim:ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/api/opcodestemps.py b/src/api/opcodestemps.py index cd315ba29..a17aa27b3 100644 --- a/src/api/opcodestemps.py +++ b/src/api/opcodestemps.py @@ -1,5 +1,3 @@ -#!/usr/bin/python - # ---------------------------------------------------------------------- # Copyleft (K), Jose M. Rodriguez-Rosa (a.k.a. Boriel) # diff --git a/src/api/optimize.py b/src/api/optimize.py index e72a99ae4..87d2e7312 100644 --- a/src/api/optimize.py +++ b/src/api/optimize.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python import symtable from collections.abc import Generator from typing import Any, NamedTuple diff --git a/src/api/options.py b/src/api/options.py index e65fb4839..9b2b207d1 100644 --- a/src/api/options.py +++ b/src/api/options.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:sw=4:et: # ---------------------------------------------------------------------- @@ -10,11 +9,12 @@ import enum import json -from typing import Any +from enum import StrEnum +from typing import Any, Final from src.api.exception import Error -__all__ = ["Option", "Options", "ANYTYPE", "Action"] +__all__: Final[tuple[str, ...]] = "Option", "Options", "ANYTYPE", "Action" class ANYTYPE: @@ -52,7 +52,7 @@ def __str__(self): return "Cannot pop option '%s'. Option stack is empty" % self.option -class InvalidValueError(Error): +class InvalidValueError(ValueError, Error): def __init__(self, option_name, _type, value): self.option = option_name self.value = value @@ -160,7 +160,7 @@ def pop(self) -> Any: # Options commands # ---------------------------------------------------------------------- @enum.unique -class Action(str, enum.Enum): +class Action(StrEnum): ADD = "add" ADD_IF_NOT_DEFINED = "add_if_not_defined" CLEAR = "clear" diff --git a/src/api/string_labels.py b/src/api/string_labels.py index d33f70861..35a87841c 100644 --- a/src/api/string_labels.py +++ b/src/api/string_labels.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - # ---------------------------------------------------------------------- # Copyleft (K), Jose M. Rodriguez-Rosa (a.k.a. Boriel) # diff --git a/src/api/symboltable/scope.py b/src/api/symboltable/scope.py index 9ae1931d7..2ef7deefc 100644 --- a/src/api/symboltable/scope.py +++ b/src/api/symboltable/scope.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/api/symboltable/symboltable.py b/src/api/symboltable/symboltable.py index 6054d3ad9..5fb0c9043 100644 --- a/src/api/symboltable/symboltable.py +++ b/src/api/symboltable/symboltable.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- @@ -361,6 +360,9 @@ def access_id( # The entry was already declared. If it's type is auto and the default type is not None, # update its type. if default_type is not None and result.type_ == self.basic_types[TYPE.unknown]: + if default_type == self.basic_types[TYPE.boolean]: + default_type = self.basic_types[TYPE.ubyte] + result.type_ = default_type warning_implicit_type(lineno, id_, default_type.name) diff --git a/src/api/utils.py b/src/api/utils.py index f23c5ea62..78a7f5684 100644 --- a/src/api/utils.py +++ b/src/api/utils.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import errno import os import shelve diff --git a/src/arch/z80/__init__.py b/src/arch/z80/__init__.py old mode 100755 new mode 100644 index e7e45417e..cf8aa5da1 --- a/src/arch/z80/__init__.py +++ b/src/arch/z80/__init__.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim:ts=4:et:sw=4: import src.api.global_ diff --git a/src/arch/z80/backend/_16bit.py b/src/arch/z80/backend/_16bit.py index 5ed052a7e..77b1278c4 100644 --- a/src/arch/z80/backend/_16bit.py +++ b/src/arch/z80/backend/_16bit.py @@ -1,5 +1,3 @@ -#!/usr/bin/python - # -------------------------------------------------------------- # Copyleft (k) 2008, by Jose M. Rodriguez-Rosa # (a.k.a. Boriel, http://www.boriel.com) diff --git a/src/arch/z80/backend/_32bit.py b/src/arch/z80/backend/_32bit.py index 3e6133995..0ac274e2a 100644 --- a/src/arch/z80/backend/_32bit.py +++ b/src/arch/z80/backend/_32bit.py @@ -1,5 +1,3 @@ -#!/usr/bin/python - # -------------------------------------------------------------- # Copyleft (k) 2008, by Jose M. Rodriguez-Rosa # (a.k.a. Boriel, http://www.boriel.com) diff --git a/src/arch/z80/backend/_8bit.py b/src/arch/z80/backend/_8bit.py index e3df938a5..f0b1a7d41 100644 --- a/src/arch/z80/backend/_8bit.py +++ b/src/arch/z80/backend/_8bit.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim: ts=4:sw=4:et # -------------------------------------------------------------- @@ -746,14 +745,13 @@ def and8(cls, ins: Quad) -> list[str]: return output output = cls.get_oper(op1, op2) - # output.append('call __AND8') + lbl = tmp_label() output.append("or a") output.append("jr z, %s" % lbl) output.append("ld a, h") output.append("%s:" % lbl) output.append("push af") - # REQUIRES.add('and8.asm') return output diff --git a/src/arch/z80/backend/__init__.py b/src/arch/z80/backend/__init__.py index 0a4750bed..2cf942857 100644 --- a/src/arch/z80/backend/__init__.py +++ b/src/arch/z80/backend/__init__.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - from src.arch.z80.optimizer.helpers import HI16, LO16 from src.arch.z80.peephole import engine diff --git a/src/arch/z80/backend/_array.py b/src/arch/z80/backend/_array.py index 4f3a37143..c25c6429f 100644 --- a/src/arch/z80/backend/_array.py +++ b/src/arch/z80/backend/_array.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim:ts=4:et:sw=4: # -------------------------------------------------------------- diff --git a/src/arch/z80/backend/_f16.py b/src/arch/z80/backend/_f16.py index 91df46c5b..771214cb6 100644 --- a/src/arch/z80/backend/_f16.py +++ b/src/arch/z80/backend/_f16.py @@ -1,5 +1,3 @@ -#!/usr/bin/python - # -------------------------------------------------------------- # Copyleft (k) 2008, by Jose M. Rodriguez-Rosa # (a.k.a. Boriel, http://www.boriel.com) diff --git a/src/arch/z80/backend/_float.py b/src/arch/z80/backend/_float.py index 7df7b0871..f1fc0324d 100644 --- a/src/arch/z80/backend/_float.py +++ b/src/arch/z80/backend/_float.py @@ -1,5 +1,3 @@ -#!/usr/bin/python - # -------------------------------------------------------------- # Copyleft (k) 2008, by Jose M. Rodriguez-Rosa # (a.k.a. Boriel, http://www.boriel.com) diff --git a/src/arch/z80/backend/_parray.py b/src/arch/z80/backend/_parray.py index a7938a168..4dd28b105 100644 --- a/src/arch/z80/backend/_parray.py +++ b/src/arch/z80/backend/_parray.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim:ts=4:et:sw=4: # -------------------------------------------------------------- diff --git a/src/arch/z80/backend/_pload.py b/src/arch/z80/backend/_pload.py index c4ee5ae80..99cc9062b 100644 --- a/src/arch/z80/backend/_pload.py +++ b/src/arch/z80/backend/_pload.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim: et:ts=4:sw=4 # -------------------------------------------------------------- diff --git a/src/arch/z80/backend/_str.py b/src/arch/z80/backend/_str.py index 0e238b892..4492b636c 100644 --- a/src/arch/z80/backend/_str.py +++ b/src/arch/z80/backend/_str.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim:ts=4:et:sw=4: # -------------------------------------------------------------- diff --git a/src/arch/z80/backend/common.py b/src/arch/z80/backend/common.py index ad959a0af..933b12b08 100644 --- a/src/arch/z80/backend/common.py +++ b/src/arch/z80/backend/common.py @@ -1,11 +1,11 @@ -#!/usr/bin/python -# vim ts=4:et:sw=4:ai - import math import re -from typing import Any, Final +from enum import StrEnum +from types import MappingProxyType +from typing import Final from src.api import global_, tmp_labels +from src.api.config import OPTIONS, OptimizationStrategy from src.api.exception import TempAlreadyFreedError from .runtime import LABEL_REQUIRED_MODULES, NAMESPACE, RUNTIME_LABELS @@ -23,18 +23,46 @@ "strslice.asm", } + +class DataType(StrEnum): + bool = "bool" + u8 = "u8" + u16 = "u16" + u32 = "u32" + i8 = "i8" + i16 = "i16" + i32 = "i32" + f16 = "f16" + f = "f" + + +# Handy constants, to not having to type long names :-) +BOOL_t: Final[DataType] = DataType.bool +U8_t: Final[DataType] = DataType.u8 +U16_t: Final[DataType] = DataType.u16 +U32_t: Final[DataType] = DataType.u32 +I8_t: Final[DataType] = DataType.i8 +I16_t: Final[DataType] = DataType.i16 +I32_t: Final[DataType] = DataType.i32 +F16_t: Final[DataType] = DataType.f16 +F_t: Final[DataType] = DataType.f + + # Internal data types definition, with its size in bytes, or -1 if it is variable (string) # Compound types are only arrays, and have the t -YY_TYPES = { - "u8": 1, # 8 bit unsigned integer - "u16": 2, # 16 bit unsigned integer - "u32": 4, # 32 bit unsigned integer - "i8": 1, # 8 bit SIGNED integer - "i16": 2, # 16 bit SIGNED integer - "i32": 4, # 32 bit SIGNED integer - "f16": 4, # -32768.9999 to 32767.9999 -aprox.- fixed point decimal (step = 1/2^16) - "f": 5, # Floating point -} +YY_TYPES: Final[MappingProxyType[DataType, int]] = MappingProxyType( + { + BOOL_t: 1, + U8_t: 1, # 8 bit unsigned integer + U16_t: 2, # 16 bit unsigned integer + U32_t: 4, # 32 bit unsigned integer + I8_t: 1, # 8 bit SIGNED integer + I16_t: 2, # 16 bit SIGNED integer + I32_t: 4, # 32 bit SIGNED integer + F16_t: 4, # -32768.9999 to 32767.9999 -aprox.- fixed point decimal (step = 1/2^16) + F_t: 5, # Floating point + } +) # Matches a boolean instruction like 'equ16' or 'andi32' RE_BOOL: Final[re.Pattern] = re.compile(r"^(eq|ne|lt|le|gt|ge|and|or|xor|not)(([ui](8|16|32))|(f16|f|str))$") @@ -110,14 +138,14 @@ def is_2n(x: float) -> bool: return n == int(n) -def tmp_remove(label: str): +def tmp_remove(label: str) -> None: if label not in TMP_STORAGES: raise TempAlreadyFreedError(label) TMP_STORAGES.pop(TMP_STORAGES.index(label)) -def runtime_call(label: str): +def runtime_call(label: str) -> str: assert label in RUNTIME_LABELS, f"Invalid runtime label '{label}'" if label in LABEL_REQUIRED_MODULES: REQUIRES.add(LABEL_REQUIRED_MODULES[label]) @@ -130,7 +158,7 @@ def runtime_call(label: str): # ------------------------------------------------------------------ -def is_int(op: Any) -> bool: +def is_int(op: str) -> bool: """Returns True if the given operand (string) contains an integer number """ @@ -144,7 +172,7 @@ def is_int(op: Any) -> bool: return False -def is_float(op: Any) -> bool: +def is_float(op: str) -> bool: """Returns True if the given operand (string) contains a floating point number """ @@ -162,7 +190,7 @@ def _int_ops(op1: str, op2: str) -> tuple[str, str | int] | None: """Receives a list with two strings (operands). If none of them contains integers, returns None. Otherwise, returns a t-uple with (op[0], op[1]), - where op[1] (2nd operan) is always the integer one (the list is swapped) + where op[1] (2nd operand) is always the integer one (the list is swapped) This cannot be used by non-commutative operations like sub and div used this because they're not commutative). @@ -199,7 +227,7 @@ def _f_ops(op1: str, op2: str, *, swap: bool = True) -> tuple[str | float, str | return None -def is_int_type(stype: str) -> bool: +def is_int_type(stype: DataType) -> bool: """Returns whether a given type is integer""" return stype[0] in ("u", "i") @@ -269,120 +297,196 @@ def get_bytes_size(elements: list[str]) -> int: return len(get_bytes(elements)) -def to_byte(stype: str) -> list[str]: +def to_bool(stype: DataType) -> list[str]: + """Returns the instruction sequence for converting the number given number (in the stack) + to boolean (just 0 (False) or non-zero (True)).""" + + if stype in (U8_t, I8_t): + return [] + + if stype in (U16_t, I16_t): + return [ + "ld a, h" "or l", + ] + + if stype in (U32_t, I32_t, F16_t): + return ["ld a, h" "or l" "or d", "or e,"] + + if stype == F_t: + return [ + "or b", + "or c", + "or d", + "or e", + ] + + raise NotImplementedError(f"type conversion from {stype} to bool is undefined") + + +def normalize_boolean() -> list[str]: + if OPTIONS.opt_strategy == OptimizationStrategy.Size: + return [runtime_call(RuntimeLabel.NORMALIZE_BOOLEAN)] + + return [ + "sub 1", # Carry if A = 0 + "sbc a, a", # 0xFF if A was 0, 0 otherwise + "inc a", # 0 if A was 0, 1 otherwise + ] + + +def to_byte(stype: DataType) -> list[str]: """Returns the instruction sequence for converting from the given type to byte. """ output = [] - if stype in ("i8", "u8"): + if stype == BOOL_t: + return normalize_boolean() + + if stype in (I8_t, U8_t): return [] if is_int_type(stype): output.append("ld a, l") - elif stype == "f16": + elif stype == F16_t: output.append("ld a, e") - elif stype == "f": # Converts C ED LH to byte + elif stype == F_t: # Converts C ED LH to byte output.append(runtime_call(RuntimeLabel.FTOU32REG)) output.append("ld a, l") return output -def to_word(stype: str) -> list[str]: +def to_word(stype: DataType) -> list[str]: """Returns the instruction sequence for converting the given type stored in DE,HL to word (unsigned) HL. """ output = [] # List of instructions - if stype == "u8": # Byte to word + if stype == BOOL_t: + output.extend(normalize_boolean()) + + if stype in (BOOL_t, U8_t): # Byte to word output.append("ld l, a") output.append("ld h, 0") - elif stype == "i8": # Signed byte to word + elif stype == I8_t: # Signed byte to word output.append("ld l, a") output.append("add a, a") output.append("sbc a, a") output.append("ld h, a") - elif stype == "f16": # Must MOVE HL into DE + elif stype == F16_t: # Must MOVE HL into DE output.append("ex de, hl") - elif stype == "f": + elif stype == F_t: output.append(runtime_call(RuntimeLabel.FTOU32REG)) return output -def to_long(stype: str) -> list[str]: +def to_long(stype: DataType) -> list[str]: """Returns the instruction sequence for converting the given type stored in DE,HL to long (DE, HL). """ output = [] # List of instructions - if stype in ("i8", "u8", "f16"): # Byte to word + if stype == BOOL_t: + output = normalize_boolean() + output.extend( + [ + "ld l, a", + "ld h, 0", + "ld e, h", + "ld d, h", + ] + ) + return output + + if stype in {I8_t, U8_t, F16_t}: # Byte to word output = to_word(stype) - if stype != "f16": # If its a byte, just copy H to D,E + if stype != F16_t: # If it's a byte, just copy H to D,E output.append("ld e, h") output.append("ld d, h") - if stype in ("i16", "f16"): # Signed byte or fixed to word + elif stype in (I16_t, F16_t): # Signed byte or fixed to word output.append("ld a, h") output.append("add a, a") output.append("sbc a, a") output.append("ld e, a") output.append("ld d, a") - elif stype == "u16": + elif stype == U16_t: output.append("ld de, 0") - elif stype == "f": + elif stype == F_t: output.append(runtime_call(RuntimeLabel.FTOU32REG)) + else: + raise NotImplementedError(f"type conversion from {stype} to long is undefined") return output -def to_fixed(stype: str) -> list[str]: +def to_fixed(stype: DataType) -> list[str]: """Returns the instruction sequence for converting the given type stored in DE,HL to fixed DE,HL. """ - output = [] # List of instructions + if stype == BOOL_t: + output = to_word(stype) + output.extend( + [ + "ex de, hl", + "ld hl, 0", # 'Truncate' the fixed point + ] + ) + return output if is_int_type(stype): output = to_word(stype) - output.append("ex de, hl") - output.append("ld hl, 0") # 'Truncate' the fixed point - elif stype == "f": - output.append(runtime_call(RuntimeLabel.FTOF16REG)) + output.extend( + [ + "ex de, hl", + "ld hl, 0", # 'Truncate' the fixed point + ] + ) + return output - return output + if stype == F_t: + return [runtime_call(RuntimeLabel.FTOF16REG)] + raise NotImplementedError(f"type conversion from {stype} to fixed") -def to_float(stype: str) -> list[str]: + +def to_float(stype: DataType) -> list[str]: """Returns the instruction sequence for converting the given type stored in DE,HL to fixed DE,HL. """ output: list[str] = [] # List of instructions - if stype == "f": + if stype == F_t: return output # Nothing to do - if stype == "f16": + if stype == F16_t: output.append(runtime_call(RuntimeLabel.F16TOFREG)) return output + if stype == BOOL_t: + output.extend(normalize_boolean()) + # If we reach this point, it's an integer type - if stype == "u8": + if stype in (BOOL_t, U8_t): # The ZX Spectrum ROM FP-Calc already returns 0 or 1 for Booleans output.append(runtime_call(RuntimeLabel.U8TOFREG)) - elif stype == "i8": + elif stype == I8_t: output.append(runtime_call(RuntimeLabel.I8TOFREG)) - else: + elif stype in {I16_t, I32_t, U16_t, U32_t}: output = to_long(stype) - if stype in ("i16", "i32"): + if stype in (I16_t, I32_t): output.append(runtime_call(RuntimeLabel.I32TOFREG)) else: output.append(runtime_call(RuntimeLabel.U32TOFREG)) + else: + raise NotImplementedError(f"type conversion from {stype} to float is undefined") return output diff --git a/src/arch/z80/backend/exception.py b/src/arch/z80/backend/exception.py index d018b8606..47845e5a9 100644 --- a/src/arch/z80/backend/exception.py +++ b/src/arch/z80/backend/exception.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim:ts=4:et:sw=4: from src.api.exception import Error diff --git a/src/arch/z80/backend/generic.py b/src/arch/z80/backend/generic.py index d0f5a91d2..882e49739 100644 --- a/src/arch/z80/backend/generic.py +++ b/src/arch/z80/backend/generic.py @@ -24,6 +24,7 @@ get_bytes_size, new_ASMID, runtime_call, + to_bool, to_byte, to_fixed, to_float, @@ -341,7 +342,7 @@ def _cast(ins: Quad): xsB = sB = YY_TYPES[tB] # Type sizes output = [] - if tA in ("u8", "i8"): + if tA in ("u8", "i8", "bool"): output.extend(Bits8.get_oper(ins[4])) elif tA in ("u16", "i16"): output.extend(Bits16.get_oper(ins[4])) @@ -364,6 +365,10 @@ def _cast(ins: Quad): output.extend(to_fixed(tA)) elif tB == "f": output.extend(to_float(tA)) + elif tB == "bool": + output.extend(to_bool(tA)) + else: + raise exception.GenericError("Internal error: invalid typecast from %s to %s" % (tA, tB)) xsB += sB % 2 # make it even (round up) diff --git a/src/arch/z80/backend/main.py b/src/arch/z80/backend/main.py index 79d8d487f..6b10983b0 100644 --- a/src/arch/z80/backend/main.py +++ b/src/arch/z80/backend/main.py @@ -100,7 +100,6 @@ # String comparison functions # String arithmetic functions from ._str import String -from .common import runtime_call from .generic import ( _call, _cast, @@ -130,7 +129,6 @@ from .icinstruction import ICInstruction from .quad import Quad from .runtime import NAMESPACE -from .runtime import Labels as RuntimeLabel __all__ = ("Backend",) @@ -677,16 +675,6 @@ def emit_prologue() -> list[str]: return output - @staticmethod - def emit_cast_to_bool(): - """Convert a byte value to boolean (0 or 1) if - the global flag strictBool is True - """ - if not OPTIONS.strict_bool: - return [] - - return ["pop af", runtime_call(RuntimeLabel.NORMALIZE_BOOLEAN), "push af"] - @staticmethod def emit_epilogue() -> list[str]: """This special ending autoinitializes required inits @@ -780,9 +768,6 @@ def emit(self, *, optimize: bool = True) -> list[str]: output: list[str] = [] for quad in self.MEMORY: self._output_join(output, self._QUAD_TABLE[quad.instr].func(quad), optimize=optimize) - # If it is a boolean operation convert it to 0/1 if the STRICT_BOOL flag is True - if common.RE_BOOL.match(quad.instr): - self._output_join(output, self.emit_cast_to_bool(), optimize=optimize) if optimize and OPTIONS.optimization_level > 1: self.remove_unused_labels(output) diff --git a/src/arch/z80/peephole/engine.py b/src/arch/z80/peephole/engine.py index 3c50cc6e2..abb56d743 100644 --- a/src/arch/z80/peephole/engine.py +++ b/src/arch/z80/peephole/engine.py @@ -1,7 +1,4 @@ -#!/usr/bin/env python3 - import os -import sys from collections.abc import Iterable from typing import NamedTuple @@ -161,7 +158,3 @@ def main(list_of_directories: list[str] | None = None, force: bool = False): for directory in list_of_directories or [OPTS_PATH]: read_opts(directory, PATTERNS) - - -if __name__ == "__main__": - main(sys.argv[1:]) diff --git a/src/arch/z80/peephole/evaluator.py b/src/arch/z80/peephole/evaluator.py index dae65ee11..82c57632f 100644 --- a/src/arch/z80/peephole/evaluator.py +++ b/src/arch/z80/peephole/evaluator.py @@ -2,7 +2,7 @@ import re from collections.abc import Callable -from enum import Enum, unique +from enum import StrEnum, unique from typing import Any from src.api import utils @@ -13,7 +13,7 @@ @unique -class FN(str, Enum): +class FN(StrEnum): OP_NOT = "!" OP_PLUS = "+" OP_EQ = "==" @@ -75,8 +75,8 @@ class FN(str, Enum): FN.CTEST: lambda x: memcell.MemCell(x, 1).condition_flag, # condition test, if any. E.g. retz returns 'z' FN.NEEDS: lambda x: memcell.MemCell(x[0], 1).needs(x[1]), FN.FLAGVAL: lambda x: helpers.new_tmp_val(), - FN.OP1: lambda x: (x.strip().replace(",", " ", 1).split() + [""])[1], - FN.OP2: lambda x: (x.strip().replace(",", " ", 1).split() + ["", ""])[2], + FN.OP1: lambda x: (x.strip().replace(",", " ", 1).split() + [""])[1], # 1st Operand of an instruction or "" + FN.OP2: lambda x: (x.strip().replace(",", " ", 1).split() + ["", ""])[2], # 2nd Operand of an instruction or "" } # Binary operators @@ -195,7 +195,7 @@ def __init__(self, expression): expression[2] = Evaluator(expression[2]) else: # It's a list assert len(expression) % 2 # Must be odd length - assert all(x == FN.OP_COMMA for i, x in enumerate(expression) if i % 2) + assert all(x == FN.OP_COMMA for i, x in enumerate(expression) if i % 2), f"Invalid expression {expression}" self.expression = [Evaluator(x) if not i % 2 else x for i, x in enumerate(expression)] @staticmethod @@ -215,28 +215,39 @@ def eval(self, vars_: dict[str, Any] | None = None) -> str | Evaluator | list[An val = self.expression[0] if not isinstance(val, str): return val + if val == "$": return val + if not RE_SVAR.match(val): return val + if val not in vars_: raise UnboundVarError(f"Unbound variable '{val}'") + return vars_[val] if len(self.expression) == 2: - oper = self.expression[0] - assert oper in UNARY + try: + oper = FN(self.expression[0]) + assert oper in UNARY + except (AssertionError, ValueError): + raise ValueError(f"Invalid unary operator '{self.expression[0]}'") + operand = self.expression[1].eval(vars_) - # FIXME - return self.normalize(UNARY[oper](operand)) # type: ignore[index] + return self.normalize(UNARY[oper](operand)) if len(self.expression) == 3 and self.expression[1] != FN.OP_COMMA: - assert self.expression[1] in BINARY + try: + oper = FN(self.expression[1]) + assert oper in BINARY + except (AssertionError, ValueError): + raise ValueError(f"Invalid binary operator '{self.expression[1]}'") + # Do lazy evaluation left_ = lambda: self.expression[0].eval(vars_) right_ = lambda: self.expression[2].eval(vars_) - # FIXME - return self.normalize(BINARY[self.expression[1]](left_, right_)) # type: ignore[index] + return self.normalize(BINARY[oper](left_, right_)) # It's a list return [x.eval(vars_) for i, x in enumerate(self.expression) if not i % 2] diff --git a/src/arch/z80/peephole/opts/020_o1_bool_norm_empty.opt b/src/arch/z80/peephole/opts/020_o1_bool_norm_empty.opt new file mode 100644 index 000000000..07acaf1ae --- /dev/null +++ b/src/arch/z80/peephole/opts/020_o1_bool_norm_empty.opt @@ -0,0 +1,32 @@ +;; Remove the boolean normalization if it's done after calling +;; certain routines that return the bool result already normalized. + +;; The sequence +;; sub 1 +;; sbc a, a +;; inc a +;; can be removed + +OLEVEL: 1 +OFLAG: 20 + +REPLACE {{ + $1 + sub 1 + sbc a, a + inc a +}} + +WITH {{ + $1 +}} + +IF {{ + $1 IN ("xor a", "ld a, 0", + "call .core.__GEF", "call .core.__LEI16", "call .core.__LEI8", "call .core.__LTI8", + "call .core.__ANDF", "call .core.__EQF", "call .core.__GTF", "call .core.__LTI16", + "call .core.__LEF", "call .core.__LEI32", "call .core.__LTF", "call .core.__LTI32", + "call .core.__NEF", "call .core.__NOTF", "call .core.__ORF", "call .core.__XORF", + "call .core.__STREQ", "call .core.__STRNE", "call .core.__STRLT", "call .core.__STRLE", + "call .core.__STRGT", "call .core.__STRGE") +}} diff --git a/src/arch/z80/peephole/opts/021_o1_bool_norm_neg.opt b/src/arch/z80/peephole/opts/021_o1_bool_norm_neg.opt new file mode 100644 index 000000000..dc7f71d37 --- /dev/null +++ b/src/arch/z80/peephole/opts/021_o1_bool_norm_neg.opt @@ -0,0 +1,26 @@ +;; The sequence: +;; sbc a, a ; A is either 0 or -1 +;; sub 1 +;; sbc a, a +;; inc a +;; can be replaced by +;; neg ; A is either 0 or 1 + +OLEVEL: 1 +OFLAG: 21 + +REPLACE {{ + $1 + sub 1 + sbc a, a + inc a +}} + +WITH {{ + $1 + neg +}} + +IF {{ + $1 IN ("sbc a, a", "call .core.__NOT32", "call .core.__XOR8", "call .core.__XOR16", "call .core.__XOR32") +}} diff --git a/src/arch/z80/peephole/parser.py b/src/arch/z80/peephole/parser.py index 2f49b5654..99d2958e8 100644 --- a/src/arch/z80/peephole/parser.py +++ b/src/arch/z80/peephole/parser.py @@ -1,6 +1,4 @@ -#!/usr/bin/env python3 import re -import sys from collections import defaultdict from types import MappingProxyType from typing import Any, Final, NamedTuple @@ -13,7 +11,7 @@ TreeType = list[str | list["TreeType"]] COMMENT: Final[str] = ";;" -RE_REGION = re.compile(r"([_a-zA-Z][a-zA-Z0-9]*)[ \t]*{{") +RE_REGION = re.compile(r"([_a-zA-Z][a-zA-Z0-9]*)[ \t]*\{\{$") RE_DEF = re.compile(r"([_a-zA-Z][a-zA-Z0-9]*)[ \t]*:[ \t]*(.*)") RE_IFPARSE = re.compile(r'"(""|[^"])*"|[(),]|\b[_a-zA-Z]+\b|[^," \t()]+') RE_ID = re.compile(r"\b[_a-zA-Z]+\b") @@ -27,7 +25,7 @@ O_LEVEL = "OLEVEL" O_FLAG = "OFLAG" -# Operators : priority (lower number -> highest priority) +# Operators : precedence (lower number -> highest priority) IF_OPERATORS: Final[MappingProxyType[FN, int]] = MappingProxyType( { FN.OP_NMUL: 3, @@ -56,6 +54,10 @@ REQUIRED = (REG_REPLACE, REG_WITH, O_LEVEL, O_FLAG) +class PeepholeParserSyntaxError(SyntaxError): + pass + + def simplify_expr(expr: list[Any]) -> list[Any]: """Simplifies ("unnest") a list, removing redundant brackets. i.e. [[x, [[y]]] becomes [x, [y]] @@ -81,23 +83,35 @@ class DefineLine(NamedTuple): expr: Evaluator -def parse_ifline(if_line: str, lineno: int) -> TreeType | None: - """Given a line from within a IF region (i.e. $1 == "af'") - returns it as a list of tokens ['$1', '==', "af'"] - """ - stack: list[TreeType] = [] - expr: TreeType = [] - paren = 0 - error_ = False +class Tokenizer: + def __init__(self, source: str, lineno: int) -> None: + self.source = source + self.lineno = lineno - while not error_ and if_line: - if_line = if_line.strip() - if not if_line: - break - qq = RE_IFPARSE.match(if_line) + def get_token(self) -> str: + """Returns next token, or "" as EOL""" + tok = self.lookahead() + self.source = self.source[len(tok) :] + return tok + + def get_next_token(self) -> str: + if self.has_finished(): + raise PeepholeParserSyntaxError("Unexpected EOL") + + return self.get_token() + + def has_finished(self) -> bool: + return self.source == "" + + def lookahead(self) -> str: + """Returns next token, or "" as EOL""" + self.source = self.source.strip() + if self.has_finished(): + return "" + + qq = RE_IFPARSE.match(self.source) if not qq: - error_ = True - break + raise PeepholeParserSyntaxError(f"Syntax error in line {self.lineno}: {self.source}") tok = qq.group() if not RE_ID.match(tok): @@ -106,7 +120,25 @@ def parse_ifline(if_line: str, lineno: int) -> TreeType | None: tok = tok[: len(oper)] break - if_line = if_line[len(tok) :] + return tok + + +def parse_ifline(if_line: str, lineno: int) -> TreeType | None: + """Given a line from within a IF region (i.e. $1 == "af'") + returns it as a list of tokens ['$1', '==', "af'"] + """ + stack: list[TreeType] = [] + expr: TreeType = [] + paren = 0 + error_ = False + tokenizer = Tokenizer(if_line, lineno) + + while not tokenizer.has_finished(): + try: + tok = tokenizer.get_token() + except PeepholeParserSyntaxError as e: + errmsg.warning(lineno, str(e)) + return None if tok == "(": paren += 1 @@ -129,6 +161,10 @@ def parse_ifline(if_line: str, lineno: int) -> TreeType | None: errmsg.warning(lineno, "missing element in list") return None + if any(x != FN.OP_COMMA for i, x in enumerate(expr) if i % 2): + errmsg.warning(lineno, f"Invalid list {expr}") + return None + stack[-1].append(expr) expr = stack.pop() else: @@ -141,8 +177,8 @@ def parse_ifline(if_line: str, lineno: int) -> TreeType | None: errmsg.warning(lineno, f"Unexpected {tok} in list") return None - while len(expr) == 2 and isinstance(expr[-2], str): - op: str | TreeType = expr[-2] + while len(expr) == 2 and isinstance(expr[0], str): + op: str = expr[0] if op in UNARY: stack[-1].append(expr) expr = stack.pop() @@ -154,13 +190,21 @@ def parse_ifline(if_line: str, lineno: int) -> TreeType | None: if not isinstance(op, str) or op not in IF_OPERATORS: errmsg.warning(lineno, f"Unexpected binary operator '{op}'") return None - # FIXME - if isinstance(left_, list) and len(left_) == 3 and IF_OPERATORS[left_[-2]] > IF_OPERATORS[op]: # type: ignore[index] - expr = [[left_[:-2], left_[-2], [left_[-1], op, right_]]] # Rebalance tree - else: - expr = [expr] - if not error_ and paren: + oper = FN(op) + if isinstance(left_, list) and len(left_) == 3: + oper2 = FN(left_[-2]) + if IF_OPERATORS[oper2] > IF_OPERATORS[oper]: + expr = [[left_[:-2], left_[-2], [left_[-1], op, right_]]] # Rebalance tree + continue + + expr = [expr] + + if error_: + errmsg.warning(lineno, "syntax error in IF section") + return None + + if paren: errmsg.warning(lineno, "unclosed parenthesis in IF section") return None @@ -179,11 +223,20 @@ def parse_ifline(if_line: str, lineno: int) -> TreeType | None: errmsg.warning(lineno, f"unexpected binary operator '{op}'") return None - if error_: - errmsg.warning(lineno, "syntax error in IF section") + expr = simplify_expr(expr) + if len(expr) == 2 and isinstance(expr[-1], str) and expr[-1] in BINARY: + errmsg.warning(lineno, f"Unexpected binary operator '{expr[-1]}'") return None - return simplify_expr(expr) + if len(expr) == 3 and (expr[1] not in BINARY or expr[1] == FN.OP_COMMA): + errmsg.warning(lineno, f"Unexpected binary operator '{expr[1]}'") + return None + + if len(expr) > 3: + errmsg.warning(lineno, "Lists not allowed in IF section condition. Missing operator") + return None + + return expr def parse_define_line(sourceline: SourceLine) -> tuple[str | None, TreeType | None]: @@ -327,17 +380,13 @@ def check_entry(key: str) -> bool: return result -def parse_file(fname: str): +def parse_file(fname: str) -> dict[str, str | int | list[str | list]] | None: """Opens and parse a file given by filename""" tmp = global_.FILENAME global_.FILENAME = fname # set filename so it shows up in error/warning msgs - with open(fname, "rt") as f: + with open(fname, "rt", encoding="utf-8") as f: result = parse_str(f.read()) global_.FILENAME = tmp # restores original filename return result - - -if __name__ == "__main__": - print(parse_file(sys.argv[1])) diff --git a/src/arch/z80/visitor/translator.py b/src/arch/z80/visitor/translator.py index 64d511066..86f735e72 100644 --- a/src/arch/z80/visitor/translator.py +++ b/src/arch/z80/visitor/translator.py @@ -1,6 +1,6 @@ -#!/usr/bin/env python - from collections import namedtuple +from collections.abc import Callable +from typing import Any import src.api.errmsg import src.api.global_ as gl @@ -147,8 +147,29 @@ def visit_BINARY(self, node): yield node.right ins = {"PLUS": "add", "MINUS": "sub"}.get(node.operator, node.operator.lower()) - s = self.TSUFFIX(node.left.type_) # Operands type - self.emit(ins + s, node.t, str(node.left.t), str(node.right.t)) + ins_t: dict[str, Callable[[TYPE | symbols.BASICTYPE, Any, Any, Any], None]] = { + "add": self.ic_add, + "sub": self.ic_sub, + "mul": self.ic_mul, + "div": self.ic_div, + "or": self.ic_or, + "xor": self.ic_xor, + "and": self.ic_and, + "eq": self.ic_eq, + "ne": self.ic_ne, + "gt": self.ic_gt, + "lt": self.ic_lt, + "le": self.ic_le, + "ge": self.ic_ge, + "band": self.ic_band, + "bor": self.ic_bor, + "bxor": self.ic_bxor, + "shl": self.ic_shl, + "shr": self.ic_shr, + "pow": self.ic_pow, + "mod": self.ic_mod, + } + ins_t[ins](node.left.type_, node.t, str(node.left.t), str(node.right.t)) def visit_TYPECAST(self, node): yield node.operand @@ -440,6 +461,10 @@ def visit_RESTORE(self, node): self.runtime_call(RuntimeLabel.RESTORE, 0) def visit_READ(self, node): + if not gl.DATAS: + src.api.errmsg.syntax_error_no_data_defined(node.lineno) + return + self.ic_fparam(TYPE.ubyte, "#" + str(self.DATA_TYPES[self.TSUFFIX(node.args[0].type_)])) self.runtime_call(RuntimeLabel.READ, node.args[0].type_.size) diff --git a/src/arch/z80/visitor/translator_inst_visitor.py b/src/arch/z80/visitor/translator_inst_visitor.py index d731de347..a16a89640 100644 --- a/src/arch/z80/visitor/translator_inst_visitor.py +++ b/src/arch/z80/visitor/translator_inst_visitor.py @@ -2,6 +2,7 @@ from src.api.debug import __DEBUG__ from src.arch.interface.quad import Quad from src.arch.z80.backend import Backend +from src.arch.z80.backend.common import BOOL_t, F16_t, F_t, I8_t, I16_t, I32_t, U8_t, U16_t, U32_t from src.ast import NodeVisitor from src.symbols import sym as symbols @@ -10,26 +11,27 @@ class TranslatorInstVisitor(NodeVisitor): def __init__(self, backend: Backend): self.backend = backend - def emit(self, *args): + def emit(self, *args: str) -> None: """Convert the given args to a Quad (3 address code) instruction""" quad = Quad(*args) - __DEBUG__("EMIT " + str(quad)) + __DEBUG__(f"EMIT {quad!s}") self.backend.MEMORY.append(quad) @staticmethod - def TSUFFIX(type_): + def TSUFFIX(type_: TYPE | symbols.TYPEREF | symbols.BASICTYPE) -> str: assert isinstance(type_, symbols.TYPE) or TYPE.is_valid(type_) _TSUFFIX = { - TYPE.byte: "i8", - TYPE.ubyte: "u8", - TYPE.integer: "i16", - TYPE.uinteger: "u16", - TYPE.long: "i32", - TYPE.ulong: "u32", - TYPE.fixed: "f16", - TYPE.float: "f", + TYPE.byte: I8_t, + TYPE.ubyte: U8_t, + TYPE.integer: I16_t, + TYPE.uinteger: U16_t, + TYPE.long: I32_t, + TYPE.ulong: U32_t, + TYPE.fixed: F16_t, + TYPE.float: F_t, TYPE.string: "str", + TYPE.boolean: BOOL_t, } if isinstance(type_, symbols.TYPEREF): @@ -41,200 +43,205 @@ def TSUFFIX(type_): return _TSUFFIX[type_] - def ic_aaddr(self, t1, t2): - return self.emit("aaddr", t1, t2) + @classmethod + def _no_bool(cls, type_: TYPE | symbols.TYPEREF | symbols.BASICTYPE) -> str: + """Returns the corresponding type suffix except for bool which maps to U8_t""" + return cls.TSUFFIX(type_) if cls.TSUFFIX(type_) != BOOL_t else U8_t - def ic_abs(self, type_, t1, t2): - return self.emit("abs" + self.TSUFFIX(type_), t1, t2) + def ic_aaddr(self, t1, t2) -> None: + self.emit("aaddr", t1, t2) - def ic_add(self, type_, t1, t2, t3): - return self.emit("add" + self.TSUFFIX(type_), t1, t2, t3) + def ic_abs(self, type_: TYPE | symbols.BASICTYPE, t1, t2) -> None: + self.emit("abs" + self.TSUFFIX(type_), t1, t2) - def ic_aload(self, type_, t1, mangle: str): - return self.emit("aload" + self.TSUFFIX(type_), t1, mangle) + def ic_add(self, type_: TYPE | symbols.BASICTYPE, t1, t2, t3) -> None: + self.emit("add" + self.TSUFFIX(type_), t1, t2, t3) - def ic_and(self, type_): - return self.emit("and" + self.TSUFFIX(type_)) + def ic_aload(self, type_: TYPE | symbols.BASICTYPE, t1, mangle: str) -> None: + self.emit("aload" + self.TSUFFIX(type_), t1, mangle) - def ic_astore(self, type_, addr: str, t): - return self.emit("astore" + self.TSUFFIX(type_), addr, t) + def ic_and(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit(f"and{self._no_bool(type_)}", t, t1, t2) - def ic_band(self, type_): - return self.emit("band" + self.TSUFFIX(type_)) + def ic_astore(self, type_: TYPE | symbols.BASICTYPE, addr: str, t) -> None: + self.emit("astore" + self.TSUFFIX(type_), addr, t) - def ic_bnot(self, type_, t1, t2): - return self.emit("bnot" + self.TSUFFIX(type_), t1, t2) + def ic_band(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit("band" + self.TSUFFIX(type_), t, t1, t2) - def ic_bor(self, type_): - return self.emit("bor" + self.TSUFFIX(type_)) + def ic_bnot(self, type_: TYPE | symbols.BASICTYPE, t1, t2) -> None: + self.emit("bnot" + self.TSUFFIX(type_), t1, t2) - def ic_bxor(self, type_): - return self.emit("bxor" + self.TSUFFIX(type_)) + def ic_bor(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit("bor" + self.TSUFFIX(type_), t, t1, t2) - def ic_call(self, label: str, num: int): - return self.emit("call", label, num) + def ic_bxor(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit("bxor" + self.TSUFFIX(type_), t, t1, t2) - def ic_cast(self, t1, type1, type2, t2): + def ic_call(self, label: str, num: int) -> None: + self.emit("call", label, num) + + def ic_cast(self, t1, type1, type2, t2) -> None: self.emit("cast", t1, self.TSUFFIX(type1), self.TSUFFIX(type2), t2) - def ic_data(self, type_, data: list): - return self.emit("data", self.TSUFFIX(type_), data) + def ic_data(self, type_: TYPE | symbols.BASICTYPE, data: list) -> None: + self.emit("data", self.TSUFFIX(type_), data) - def ic_deflabel(self, label: str, t): - return self.emit("deflabel", label, t) + def ic_deflabel(self, label: str, t) -> None: + self.emit("deflabel", label, t) - def ic_div(self, type_): - return self.emit("div" + self.TSUFFIX(type_)) + def ic_div(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit("div" + self.TSUFFIX(type_), t, t1, t2) - def ic_end(self, t): - return self.emit("end", t) + def ic_end(self, t) -> None: + self.emit("end", t) - def ic_enter(self, arg): - return self.emit("enter", arg) + def ic_enter(self, arg) -> None: + self.emit("enter", arg) - def ic_eq(self, type_, t, t1, t2): - return self.emit("eq" + self.TSUFFIX(type_), t, t1, t2) + def ic_eq(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit("eq" + self.TSUFFIX(type_), t, t1, t2) - def ic_exchg(self): - return self.emit("exchg") + def ic_exchg(self) -> None: + self.emit("exchg") - def ic_fparam(self, type_, t): - return self.emit("fparam" + self.TSUFFIX(type_), t) + def ic_fparam(self, type_: TYPE | symbols.BASICTYPE, t) -> None: + self.emit("fparam" + self.TSUFFIX(type_), t) - def ic_fpload(self, type_, t, offset): - return self.emit("fpload" + self.TSUFFIX(type_), t, offset) + def ic_fpload(self, type_: TYPE | symbols.BASICTYPE, t, offset) -> None: + self.emit("fpload" + self.TSUFFIX(type_), t, offset) - def ic_ge(self, type_, t, t1, t2): - return self.emit("ge" + self.TSUFFIX(type_), t, t1, t2) + def ic_ge(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit("ge" + self.TSUFFIX(type_), t, t1, t2) - def ic_gt(self, type_, t, t1, t2): - return self.emit("gt" + self.TSUFFIX(type_), t, t1, t2) + def ic_gt(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit("gt" + self.TSUFFIX(type_), t, t1, t2) - def ic_in(self, t): - return self.emit("in", t) + def ic_in(self, t) -> None: + self.emit("in", t) - def ic_inline(self, asm_code: str): - return self.emit("inline", asm_code) + def ic_inline(self, asm_code: str) -> None: + self.emit("inline", asm_code) - def ic_jgezero(self, type_, t, label: str): - return self.emit("jgezero" + self.TSUFFIX(type_), t, label) + def ic_jgezero(self, type_: TYPE | symbols.BASICTYPE, t, label: str) -> None: + self.emit(f"jgezero{self._no_bool(type_)}", t, label) - def ic_jnzero(self, type_, t, label: str): - return self.emit("jnzero" + self.TSUFFIX(type_), t, label) + def ic_jnzero(self, type_: TYPE | symbols.BASICTYPE, t, label: str) -> None: + self.emit(f"jnzero{self._no_bool(type_)}", t, label) - def ic_jump(self, label: str): - return self.emit("jump", label) + def ic_jump(self, label: str) -> None: + self.emit("jump", label) - def ic_jzero(self, type_, t, label: str): - return self.emit("jzero" + self.TSUFFIX(type_), t, label) + def ic_jzero(self, type_: TYPE | symbols.BASICTYPE, t, label: str) -> None: + self.emit(f"jzero{self._no_bool(type_)}", t, label) - def ic_label(self, label: str): - return self.emit("label", label) + def ic_label(self, label: str) -> None: + self.emit("label", label) - def ic_larrd(self, offset, arg1, size, arg2, bound_ptrs): - return self.emit("larrd", offset, arg1, size, arg2, bound_ptrs) + def ic_larrd(self, offset, arg1, size, arg2, bound_ptrs) -> None: + self.emit("larrd", offset, arg1, size, arg2, bound_ptrs) - def ic_le(self, type_, t, t1, t2): - return self.emit("le" + self.TSUFFIX(type_), t, t1, t2) + def ic_le(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit("le" + self.TSUFFIX(type_), t, t1, t2) - def ic_leave(self, convention: str): - return self.emit("leave", convention) + def ic_leave(self, convention: str) -> None: + self.emit("leave", convention) - def ic_lenstr(self, t1, t2): - return self.emit("lenstr", t1, t2) + def ic_lenstr(self, t1, t2) -> None: + self.emit("lenstr", t1, t2) - def ic_load(self, type_, t1, t2): - return self.emit("load" + self.TSUFFIX(type_), t1, t2) + def ic_load(self, type_: TYPE | symbols.BASICTYPE, t1, t2) -> None: + self.emit("load" + self.TSUFFIX(type_), t1, t2) - def ic_lt(self, type_, t, t1, t2): - return self.emit("lt" + self.TSUFFIX(type_), t, t1, t2) + def ic_lt(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit("lt" + self.TSUFFIX(type_), t, t1, t2) - def ic_lvard(self, offset, default_value: list): - return self.emit("lvard", offset, default_value) + def ic_lvard(self, offset, default_value: list) -> None: + self.emit("lvard", offset, default_value) - def ic_lvarx(self, type_, offset, default_value: list): + def ic_lvarx(self, type_: TYPE | symbols.BASICTYPE, offset, default_value: list) -> None: self.emit("lvarx", offset, self.TSUFFIX(type_), default_value) - def ic_memcopy(self, t1, t2, t3): - return self.emit("memcopy", t1, t2, t3) + def ic_memcopy(self, t1, t2, t3) -> None: + self.emit("memcopy", t1, t2, t3) - def ic_mod(self, type_): - return self.emit("mod" + self.TSUFFIX(type_)) + def ic_mod(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit("mod" + self.TSUFFIX(type_), t, t1, t2) - def ic_mul(self, type_): - return self.emit("mul" + self.TSUFFIX(type_)) + def ic_mul(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit("mul" + self.TSUFFIX(type_), t, t1, t2) - def ic_ne(self, type_, t, t1, t2): - return self.emit("ne" + self.TSUFFIX(type_), t, t1, t2) + def ic_ne(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit("ne" + self.TSUFFIX(type_), t, t1, t2) - def ic_neg(self, type_, t1, t2): - return self.emit("neg" + self.TSUFFIX(type_), t1, t2) + def ic_neg(self, type_: TYPE | symbols.BASICTYPE, t1, t2) -> None: + self.emit("neg" + self.TSUFFIX(type_), t1, t2) - def ic_nop(self): - return self.emit("nop") + def ic_nop(self) -> None: + self.emit("nop") - def ic_not(self, type_, t1, t2): - return self.emit("not" + self.TSUFFIX(type_), t1, t2) + def ic_not(self, type_: TYPE | symbols.BASICTYPE, t1, t2) -> None: + self.emit("not" + self.TSUFFIX(type_), t1, t2) - def ic_or(self, type_): - return self.emit("or" + self.TSUFFIX(type_)) + def ic_or(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit(f"or{self._no_bool(type_)}", t, t1, t2) - def ic_org(self, type_): - return self.emit("org" + self.TSUFFIX(type_)) + def ic_org(self, type_: TYPE | symbols.BASICTYPE) -> None: + self.emit("org" + self.TSUFFIX(type_)) - def ic_out(self, t1, t2): - return self.emit("out", t1, t2) + def ic_out(self, t1, t2) -> None: + self.emit("out", t1, t2) - def ic_paaddr(self, t1, t2): - return self.emit("paaddr", t1, t2) + def ic_paaddr(self, t1, t2) -> None: + self.emit("paaddr", t1, t2) - def ic_paddr(self, t1, t2): - return self.emit("paddr", t1, t2) + def ic_paddr(self, t1, t2) -> None: + self.emit("paddr", t1, t2) - def ic_paload(self, type_, t, offset: int): - return self.emit("paload" + self.TSUFFIX(type_), t, offset) + def ic_paload(self, type_: TYPE | symbols.BASICTYPE, t, offset: int) -> None: + self.emit("paload" + self.TSUFFIX(type_), t, offset) - def ic_param(self, type_, t): - return self.emit("param" + self.TSUFFIX(type_), t) + def ic_param(self, type_: TYPE | symbols.BASICTYPE, t) -> None: + self.emit("param" + self.TSUFFIX(type_), t) - def ic_pastore(self, type_, offset, t): - return self.emit("pastore" + self.TSUFFIX(type_), offset, t) + def ic_pastore(self, type_: TYPE | symbols.BASICTYPE, offset, t) -> None: + self.emit("pastore" + self.TSUFFIX(type_), offset, t) - def ic_pload(self, type_, t1, offset): - return self.emit("pload" + self.TSUFFIX(type_), t1, offset) + def ic_pload(self, type_: TYPE | symbols.BASICTYPE, t1, offset) -> None: + self.emit("pload" + self.TSUFFIX(type_), t1, offset) - def ic_pow(self, type_): - return self.emit("pow" + self.TSUFFIX(type_)) + def ic_pow(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit("pow" + self.TSUFFIX(type_), t, t1, t2) - def ic_pstore(self, type_, offset, t): - return self.emit("pstore" + self.TSUFFIX(type_), offset, t) + def ic_pstore(self, type_: TYPE | symbols.BASICTYPE, offset, t) -> None: + self.emit("pstore" + self.TSUFFIX(type_), offset, t) - def ic_ret(self, type_, t, addr): - return self.emit("ret" + self.TSUFFIX(type_), t, addr) + def ic_ret(self, type_: TYPE | symbols.BASICTYPE, t, addr) -> None: + self.emit("ret" + self.TSUFFIX(type_), t, addr) - def ic_return(self, addr): - return self.emit("ret", addr) + def ic_return(self, addr) -> None: + self.emit("ret", addr) - def ic_shl(self, type_): - return self.emit("shl" + self.TSUFFIX(type_)) + def ic_shl(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit("shl" + self.TSUFFIX(type_), t, t1, t2) - def ic_shr(self, type_): - return self.emit("shr" + self.TSUFFIX(type_)) + def ic_shr(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit("shr" + self.TSUFFIX(type_), t, t1, t2) - def ic_store(self, type_, t1, t2): - return self.emit("store" + self.TSUFFIX(type_), t1, t2) + def ic_store(self, type_: TYPE | symbols.BASICTYPE, t1, t2) -> None: + self.emit("store" + self.TSUFFIX(type_), t1, t2) - def ic_sub(self, type_): - return self.emit("sub" + self.TSUFFIX(type_)) + def ic_sub(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit("sub" + self.TSUFFIX(type_), t, t1, t2) - def ic_var(self, name: str, size_): - return self.emit("var", name, size_) + def ic_var(self, name: str, size_) -> None: + self.emit("var", name, size_) - def ic_vard(self, name: str, data: list): - return self.emit("vard", name, data) + def ic_vard(self, name: str, data: list) -> None: + self.emit("vard", name, data) - def ic_varx(self, name: str, type_, default_value: list): - return self.emit("varx", name, self.TSUFFIX(type_), default_value) + def ic_varx(self, name: str, type_: TYPE | symbols.BASICTYPE, default_value: list) -> None: + self.emit("varx", name, self.TSUFFIX(type_), default_value) - def ic_xor(self, type_): - return self.emit("xor" + self.TSUFFIX(type_)) + def ic_xor(self, type_: TYPE | symbols.BASICTYPE, t, t1, t2) -> None: + self.emit("xor" + self.TSUFFIX(type_), t, t1, t2) diff --git a/src/arch/z80/visitor/translator_visitor.py b/src/arch/z80/visitor/translator_visitor.py index 88cdcee06..389e95762 100644 --- a/src/arch/z80/visitor/translator_visitor.py +++ b/src/arch/z80/visitor/translator_visitor.py @@ -117,7 +117,7 @@ def runtime_call(self, label: str, num: int): # This function must be called before emit_strings def emit_data_blocks(self): - if not gl.DATA_IS_USED: + if not gl.DATA_IS_USED or not gl.DATAS: return # nothing to do for label_, datas in gl.DATAS: @@ -139,12 +139,9 @@ def emit_data_blocks(self): else: self.ic_data(d.value.type_, [self.traverse_const(d.value)]) - if not gl.DATAS: # The above loop was not executed, because there's no data - self.ic_label("__DATA__0") - else: - missing_data_labels = set(gl.DATA_LABELS_REQUIRED).difference([x.label.name for x in gl.DATAS]) - for data_label in missing_data_labels: - self.ic_label(data_label) # A label reference by a RESTORE beyond the last DATA line + missing_data_labels = set(gl.DATA_LABELS_REQUIRED).difference([x.label.name for x in gl.DATAS]) + for data_label in missing_data_labels: + self.ic_label(data_label) # A label reference by a RESTORE beyond the last DATA line self.ic_vard("__DATA__END", ["00"]) diff --git a/src/arch/zx48k/__init__.py b/src/arch/zx48k/__init__.py old mode 100755 new mode 100644 index 2a4f6b27d..86bacdde5 --- a/src/arch/zx48k/__init__.py +++ b/src/arch/zx48k/__init__.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim:ts=4:et:sw=4: import src.api.global_ diff --git a/src/arch/zxnext/__init__.py b/src/arch/zxnext/__init__.py old mode 100755 new mode 100644 index 884f53a11..130ba4bc7 --- a/src/arch/zxnext/__init__.py +++ b/src/arch/zxnext/__init__.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim:ts=4:et:sw=4: import src.api.global_ diff --git a/src/ast/__init__.py b/src/ast/__init__.py index 95798a877..cf01e415a 100644 --- a/src/ast/__init__.py +++ b/src/ast/__init__.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - from .ast import Ast, NodeVisitor, types from .tree import Tree diff --git a/src/ast/ast.py b/src/ast/ast.py index aac88c7d4..0ad86e4b3 100644 --- a/src/ast/ast.py +++ b/src/ast/ast.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/ast/tree.py b/src/ast/tree.py index c14570611..aa5e1ee2a 100644 --- a/src/ast/tree.py +++ b/src/ast/tree.py @@ -1,4 +1,3 @@ -#!/usr/bin/python from __future__ import annotations import collections.abc diff --git a/src/lib/arch/zx48k/runtime/bool/and8.asm b/src/lib/arch/zx48k/runtime/bool/and8.asm deleted file mode 100644 index 1e6795eff..000000000 --- a/src/lib/arch/zx48k/runtime/bool/and8.asm +++ /dev/null @@ -1,14 +0,0 @@ -; FASTCALL boolean and 8 version. -; result in Accumulator (0 False, not 0 True) -; __FASTCALL__ version (operands: A, H) -; Performs 8bit and 8bit and returns the boolean - - push namespace core - -__AND8: - or a - ret z - ld a, h - ret - - pop namespace diff --git a/src/lib/arch/zx48k/runtime/read_restore.asm b/src/lib/arch/zx48k/runtime/read_restore.asm index da788f40f..2876a97a6 100644 --- a/src/lib/arch/zx48k/runtime/read_restore.asm +++ b/src/lib/arch/zx48k/runtime/read_restore.asm @@ -212,6 +212,13 @@ _from_u16: dynamic_cast4: ;; The user type is "shorter" than the read one + ld a, b ;; read type + cp _i16 ;; if user type < read type < _i16 => From Ubyte to Byte. Return af' + jr nc, 1f + ex af, af' + ret +1: + ld a, c ;; recover user required type cp _f16 ;; required type jr c, before_to_int ;; required < fixed (f16) ex af, af' diff --git a/src/lib/arch/zx48k/runtime/strictbool.asm b/src/lib/arch/zx48k/runtime/strictbool.asm index 0461b1a55..80a7460a4 100644 --- a/src/lib/arch/zx48k/runtime/strictbool.asm +++ b/src/lib/arch/zx48k/runtime/strictbool.asm @@ -4,10 +4,9 @@ push namespace core __NORMALIZE_BOOLEAN: - or a - ret z - ld a, 1 + sub 1 + sbc a, a + inc a ret pop namespace - diff --git a/src/lib/arch/zx48k/runtime/string.asm b/src/lib/arch/zx48k/runtime/string.asm index 0631c2a85..31321ea7b 100644 --- a/src/lib/arch/zx48k/runtime/string.asm +++ b/src/lib/arch/zx48k/runtime/string.asm @@ -126,11 +126,11 @@ __STREQ: ; Compares a$ == b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 pop de pop hl sub 1 - sbc a, a + sbc a, a ; 0 if A register was 0, 0xFF if A was 1 or -1 jp __FREE_STR -__STRNE: ; Compares a$ != b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRNE: ; Compares a$ != b$ (HL = ptr a$, DE = ptr b$). Returns 1 (True) or 0 (False) push hl push de call __STRCMP @@ -139,7 +139,7 @@ __STRNE: ; Compares a$ != b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 jp __FREE_STR -__STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FE (True) or 0 (False) push hl push de call __STRCMP @@ -152,7 +152,7 @@ __STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 ( jp __FREE_STR -__STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF or FE (True) or 0 (False) push hl push de call __STRCMP @@ -163,7 +163,7 @@ __STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 jp __FREE_STR -__STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns 2 (True) or 0 (False) push hl push de call __STRCMP @@ -176,7 +176,7 @@ __STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 ( jp __FREE_STR -__STRGE: ; Compares a$ >= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRGE: ; Compares a$ >= b$ (HL = ptr a$, DE = ptr b$). Returns 1 or 2 (True) or 0 (False) push hl push de call __STRCMP @@ -193,6 +193,10 @@ __FREE_STR: ; This exit point will test A' for bits 0 and 1 LOCAL __FREE_STR2 LOCAL __FREE_END + ;; normalize boolean + sub 1 + sbc a, a + inc a ex af, af' bit 0, a diff --git a/src/lib/arch/zxnext/runtime/bool/and8.asm b/src/lib/arch/zxnext/runtime/bool/and8.asm deleted file mode 100644 index 1e6795eff..000000000 --- a/src/lib/arch/zxnext/runtime/bool/and8.asm +++ /dev/null @@ -1,14 +0,0 @@ -; FASTCALL boolean and 8 version. -; result in Accumulator (0 False, not 0 True) -; __FASTCALL__ version (operands: A, H) -; Performs 8bit and 8bit and returns the boolean - - push namespace core - -__AND8: - or a - ret z - ld a, h - ret - - pop namespace diff --git a/src/lib/arch/zxnext/runtime/read_restore.asm b/src/lib/arch/zxnext/runtime/read_restore.asm index da788f40f..2876a97a6 100644 --- a/src/lib/arch/zxnext/runtime/read_restore.asm +++ b/src/lib/arch/zxnext/runtime/read_restore.asm @@ -212,6 +212,13 @@ _from_u16: dynamic_cast4: ;; The user type is "shorter" than the read one + ld a, b ;; read type + cp _i16 ;; if user type < read type < _i16 => From Ubyte to Byte. Return af' + jr nc, 1f + ex af, af' + ret +1: + ld a, c ;; recover user required type cp _f16 ;; required type jr c, before_to_int ;; required < fixed (f16) ex af, af' diff --git a/src/lib/arch/zxnext/runtime/strictbool.asm b/src/lib/arch/zxnext/runtime/strictbool.asm index 0461b1a55..80a7460a4 100644 --- a/src/lib/arch/zxnext/runtime/strictbool.asm +++ b/src/lib/arch/zxnext/runtime/strictbool.asm @@ -4,10 +4,9 @@ push namespace core __NORMALIZE_BOOLEAN: - or a - ret z - ld a, 1 + sub 1 + sbc a, a + inc a ret pop namespace - diff --git a/src/outfmt/__init__.py b/src/outfmt/__init__.py index f35c15ddd..1609a4dd5 100644 --- a/src/outfmt/__init__.py +++ b/src/outfmt/__init__.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - from .binary import BinaryEmitter from .codeemitter import CodeEmitter from .sna import SnaEmitter diff --git a/src/outfmt/binary.py b/src/outfmt/binary.py index 26999f504..463521ded 100644 --- a/src/outfmt/binary.py +++ b/src/outfmt/binary.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python3 - # -------------------------------------------- # KopyLeft (K) 2008 # by Jose M. Rodriguez de la Rosa diff --git a/src/outfmt/codeemitter.py b/src/outfmt/codeemitter.py index d672708a0..aa19ec687 100644 --- a/src/outfmt/codeemitter.py +++ b/src/outfmt/codeemitter.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python3 - # -------------------------------------------- # KopyLeft (K) 2008 # by Jose M. Rodriguez de la Rosa diff --git a/src/outfmt/gensnapshot.py b/src/outfmt/gensnapshot.py index 918e4a238..ba1e5b605 100644 --- a/src/outfmt/gensnapshot.py +++ b/src/outfmt/gensnapshot.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python3 - # 48K Snapshot generation module # # © Copyright 2008-2024 José Manuel Rodríguez de la Rosa and contributors. diff --git a/src/outfmt/sna.py b/src/outfmt/sna.py index 58fd55e2c..b934b79d0 100644 --- a/src/outfmt/sna.py +++ b/src/outfmt/sna.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python3 - # 48K .SNA format output module # # © Copyright 2008-2024 José Manuel Rodríguez de la Rosa and contributors. diff --git a/src/outfmt/z80.py b/src/outfmt/z80.py index 7298dc40a..2cb44ae46 100644 --- a/src/outfmt/z80.py +++ b/src/outfmt/z80.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python3 - # 48K .Z80 format output module # # © Copyright 2008-2024 José Manuel Rodríguez de la Rosa and contributors. diff --git a/src/parsetab/__init__.py b/src/parsetab/__init__.py index 4265cc3e6..e69de29bb 100644 --- a/src/parsetab/__init__.py +++ b/src/parsetab/__init__.py @@ -1 +0,0 @@ -#!/usr/bin/env python diff --git a/src/ply/yacc.py b/src/ply/yacc.py index b9acb955b..ece139b59 100644 --- a/src/ply/yacc.py +++ b/src/ply/yacc.py @@ -893,8 +893,7 @@ def add_production(self, prodname, syms, func=None, file="", line=0): prodprec = self.Precedence.get(precname) if not prodprec: raise GrammarError("%s:%d: Nothing known about the precedence of %r" % (file, line, precname)) - else: - self.UsedPrecedence.add(precname) + self.UsedPrecedence.add(precname) del syms[-2:] # Drop %prec from the rule else: # If no %prec, precedence is determined by the rightmost terminal symbol diff --git a/src/symbols/arglist.py b/src/symbols/arglist.py index fa586afc9..a7195e165 100644 --- a/src/symbols/arglist.py +++ b/src/symbols/arglist.py @@ -1,5 +1,3 @@ -#!/usr/bin/python - # ---------------------------------------------------------------------- # Copyleft (K), Jose M. Rodriguez-Rosa (a.k.a. Boriel) # diff --git a/src/symbols/argument.py b/src/symbols/argument.py index 61e497f87..87fbd014c 100644 --- a/src/symbols/argument.py +++ b/src/symbols/argument.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/arrayaccess.py b/src/symbols/arrayaccess.py index 378b0ef8f..bf40ea01b 100644 --- a/src/symbols/arrayaccess.py +++ b/src/symbols/arrayaccess.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4: from functools import cached_property from typing import Optional diff --git a/src/symbols/arraydecl.py b/src/symbols/arraydecl.py index 1e62ad898..3aff49d26 100644 --- a/src/symbols/arraydecl.py +++ b/src/symbols/arraydecl.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/arrayload.py b/src/symbols/arrayload.py index 22ea71e83..171e34d93 100644 --- a/src/symbols/arrayload.py +++ b/src/symbols/arrayload.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/asm.py b/src/symbols/asm.py index 88c3d753b..130fc9eb5 100644 --- a/src/symbols/asm.py +++ b/src/symbols/asm.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/binary.py b/src/symbols/binary.py index 919790b54..34f1c1b44 100644 --- a/src/symbols/binary.py +++ b/src/symbols/binary.py @@ -1,11 +1,8 @@ -#!/usr/bin/env python -# vim: ts=4:et:sw=4: - # ---------------------------------------------------------------------- -# Copyleft (K), Jose M. Rodriguez-Rosa (a.k.a. Boriel) +# Copyleft, Jose M. Rodriguez-Rosa (a.k.a. Boriel) # # This program is Free Software and is released under the terms of -# the GNU General License +# the Affero GNU General License v3 # ---------------------------------------------------------------------- from src.api import check, errmsg @@ -22,7 +19,7 @@ class SymbolBINARY(Symbol): Only the operator (e.g. 'PLUS') is stored. """ - def __init__(self, operator, left, right, lineno, type_=None, func=None): + def __init__(self, operator: str, left: Symbol, right: Symbol, lineno: int, type_=None, func=None): super().__init__(left, right) self.lineno = lineno self.operator = operator @@ -133,7 +130,7 @@ def make_node(cls, operator, left, right, lineno, func=None, type_=None): if type_ is None: if operator in ("LT", "GT", "EQ", "LE", "GE", "NE", "AND", "OR", "XOR", "NOT"): - type_ = TYPE.ubyte # Boolean type + type_ = TYPE.boolean else: type_ = c_type diff --git a/src/symbols/block.py b/src/symbols/block.py index e80a581f2..e573ba1f1 100644 --- a/src/symbols/block.py +++ b/src/symbols/block.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/bound.py b/src/symbols/bound.py index 111d0d722..e313e9bd4 100644 --- a/src/symbols/bound.py +++ b/src/symbols/bound.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/boundlist.py b/src/symbols/boundlist.py index 29b06d6ab..38ea04d4b 100644 --- a/src/symbols/boundlist.py +++ b/src/symbols/boundlist.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/builtin.py b/src/symbols/builtin.py index 986173b0e..54565d6cc 100644 --- a/src/symbols/builtin.py +++ b/src/symbols/builtin.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - # ---------------------------------------------------------------------- # Copyleft (K), Jose M. Rodriguez-Rosa (a.k.a. Boriel) # diff --git a/src/symbols/call.py b/src/symbols/call.py index 920dbfddd..aebc1d4b1 100644 --- a/src/symbols/call.py +++ b/src/symbols/call.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/constexpr.py b/src/symbols/constexpr.py index bf8fd4ff7..123abdbe6 100644 --- a/src/symbols/constexpr.py +++ b/src/symbols/constexpr.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/funccall.py b/src/symbols/funccall.py index c47030be6..fc973fb42 100644 --- a/src/symbols/funccall.py +++ b/src/symbols/funccall.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/funcdecl.py b/src/symbols/funcdecl.py index 537528ecf..7517fca16 100644 --- a/src/symbols/funcdecl.py +++ b/src/symbols/funcdecl.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/id_/_id.py b/src/symbols/id_/_id.py index b78c5f4e3..93679fad7 100644 --- a/src/symbols/id_/_id.py +++ b/src/symbols/id_/_id.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/nop.py b/src/symbols/nop.py index 1fc13ab2e..0b1e02225 100644 --- a/src/symbols/nop.py +++ b/src/symbols/nop.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/number.py b/src/symbols/number.py index 59067c00e..e4b766ba9 100644 --- a/src/symbols/number.py +++ b/src/symbols/number.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/paramlist.py b/src/symbols/paramlist.py index 403735704..b3e2b285e 100644 --- a/src/symbols/paramlist.py +++ b/src/symbols/paramlist.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/sentence.py b/src/symbols/sentence.py index 7263a8853..5b90fd443 100644 --- a/src/symbols/sentence.py +++ b/src/symbols/sentence.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/string_.py b/src/symbols/string_.py index 13047e770..83b8e9839 100644 --- a/src/symbols/string_.py +++ b/src/symbols/string_.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/strslice.py b/src/symbols/strslice.py index 4903da3cd..8435852bc 100644 --- a/src/symbols/strslice.py +++ b/src/symbols/strslice.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/sym.py b/src/symbols/sym.py index 3e131f74e..4188bed34 100644 --- a/src/symbols/sym.py +++ b/src/symbols/sym.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/symbol_.py b/src/symbols/symbol_.py index f18235296..7f63a3aae 100644 --- a/src/symbols/symbol_.py +++ b/src/symbols/symbol_.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/symbols/type_.py b/src/symbols/type_.py index be6ccaaa1..02fbb49fc 100644 --- a/src/symbols/type_.py +++ b/src/symbols/type_.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- @@ -27,7 +26,7 @@ def __init__(self, name: str, lineno: int, *children): self.name = name # typename self.lineno = lineno # The line the type was defined. Line 0 = basic type self.final = self # self.final always return the original aliased type (if this type is an alias) - self.caseins = OPTIONS.case_insensitive # Whether this ID is case insensitive or not + self.caseins = OPTIONS.case_insensitive # Whether this ID is case-insensitive or not self.class_ = CLASS.type self.accessed = False # Whether this type has been used or not @@ -109,12 +108,12 @@ def __bool__(self): class SymbolBASICTYPE(SymbolTYPE): - """Defines a basic type (Ubyte, Byte, etc..) - Basic (default) types are defined upon start and are case insensitive. + """Defines a basic type (Ubyte, Byte, etc.) + Basic (default) types are defined upon start and are case-insensitive. If name is None or '', default typename from TYPES.to_string will be used. """ - def __init__(self, type_, name: str = None): + def __init__(self, type_: TYPE, name: str = None): """type_ = Internal representation (e.g. TYPE.ubyte)""" assert TYPE.is_valid(type_) if not name: @@ -147,7 +146,7 @@ def is_dynamic(self): return self.type_ == TYPE.string def __hash__(self): - return self.type_ + return hash(self.type_) def __eq__(self, other): if self is not self.final: @@ -238,73 +237,74 @@ class Type: fixed = SymbolBASICTYPE(TYPE.fixed) float_ = SymbolBASICTYPE(TYPE.float) string = SymbolBASICTYPE(TYPE.string) + boolean = SymbolBASICTYPE(TYPE.boolean) - types = [unknown, ubyte, byte_, uinteger, integer, ulong, long_, fixed, float_, string] + types = unknown, ubyte, byte_, uinteger, integer, ulong, long_, fixed, float_, string, boolean _by_name = {x.name: x for x in types} @staticmethod - def size(t: SymbolTYPE): + def size(t: SymbolTYPE) -> int: assert isinstance(t, SymbolTYPE) return t.size @staticmethod - def to_string(t: SymbolTYPE): + def to_string(t: SymbolTYPE) -> str: assert isinstance(t, SymbolTYPE) return t.name @classmethod - def by_name(cls, typename): + def by_name(cls, typename) -> SymbolBASICTYPE | None: """Converts a given typename to Type""" return cls._by_name.get(typename, None) @classproperty - def integrals(cls): - return (cls.byte_, cls.ubyte, cls.integer, cls.uinteger, cls.long_, cls.ulong) + def integrals(cls) -> set[SymbolBASICTYPE]: + return {cls.boolean, cls.byte_, cls.ubyte, cls.integer, cls.uinteger, cls.long_, cls.ulong} @classproperty - def signed(cls): - return cls.byte_, cls.integer, cls.long_, cls.fixed, cls.float_ + def signed(cls) -> set[SymbolBASICTYPE]: + return {cls.byte_, cls.integer, cls.long_, cls.fixed, cls.float_} @classproperty - def unsigned(cls): - return cls.ubyte, cls.uinteger, cls.ulong + def unsigned(cls) -> set[SymbolBASICTYPE]: + return {cls.boolean, cls.ubyte, cls.uinteger, cls.ulong} @classproperty - def decimals(cls): - return cls.fixed, cls.float_ + def decimals(cls) -> set[SymbolBASICTYPE]: + return {cls.fixed, cls.float_} @classproperty - def numbers(cls): - return tuple(list(cls.integrals) + list(cls.decimals)) + def numbers(cls) -> set[SymbolBASICTYPE]: + return cls.integrals | cls.decimals @classmethod - def is_numeric(cls, t: SymbolTYPE): + def is_numeric(cls, t: SymbolTYPE) -> bool: assert isinstance(t, SymbolTYPE) return t.final in cls.numbers @classmethod - def is_signed(cls, t: SymbolTYPE): + def is_signed(cls, t: SymbolTYPE) -> bool: assert isinstance(t, SymbolTYPE) return t.final in cls.signed @classmethod - def is_unsigned(cls, t: SymbolTYPE): + def is_unsigned(cls, t: SymbolTYPE) -> bool: assert isinstance(t, SymbolTYPE) return t.final in cls.unsigned @classmethod - def is_integral(cls, t: SymbolTYPE): + def is_integral(cls, t: SymbolTYPE) -> bool: assert isinstance(t, SymbolTYPE) return t.final in cls.integrals @classmethod - def is_decimal(cls, t: SymbolTYPE): + def is_decimal(cls, t: SymbolTYPE) -> bool: assert isinstance(t, SymbolTYPE) return t.final in cls.decimals @classmethod - def is_string(cls, t: SymbolTYPE): + def is_string(cls, t: SymbolTYPE) -> bool: assert isinstance(t, SymbolTYPE) return t.final == cls.string @@ -316,7 +316,7 @@ def to_signed(cls, t: SymbolTYPE): assert t.is_basic if cls.is_unsigned(t): # FIXME - return {cls.ubyte: cls.byte_, cls.uinteger: cls.integer, cls.ulong: cls.long_}[t] # type:ignore[index] + return {cls.boolean: cls.byte_, cls.ubyte: cls.byte_, cls.uinteger: cls.integer, cls.ulong: cls.long_}[t] # type:ignore[index] if cls.is_signed(t) or cls.is_decimal(t): return t return cls.unknown diff --git a/src/symbols/typecast.py b/src/symbols/typecast.py index 5a6e0508e..db0a98a46 100644 --- a/src/symbols/typecast.py +++ b/src/symbols/typecast.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- @@ -88,7 +87,10 @@ def make_node(cls, new_type: SymbolTYPE, node: Symbol, lineno: int): if check.is_const(node): node = SymbolNUMBER(node.value, node.lineno, node.type_) - if new_type.is_basic and not TYPE.is_integral(new_type): # not an integer + if new_type == TYPE.boolean: + node.value = int(bool(node.value)) + new_type = TYPE.ubyte # For the moment we'll use UByte externally + elif new_type.is_basic and not TYPE.is_integral(new_type): # not an integer node.value = float(node.value) else: # It's an integer new_val = int(node.value) & ((1 << (8 * new_type.size)) - 1) # Mask it diff --git a/src/symbols/unary.py b/src/symbols/unary.py index c1af89af1..5021c9d43 100644 --- a/src/symbols/unary.py +++ b/src/symbols/unary.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- @@ -81,6 +80,6 @@ def make_node(cls, lineno, operator, operand, func=None, type_=None): type_ = type_.to_signed() operand = SymbolTYPECAST.make_node(type_, operand, lineno) elif operator == "NOT": - type_ = TYPE.ubyte + type_ = TYPE.boolean return cls(operator, operand, lineno, type_) diff --git a/src/symbols/vardecl.py b/src/symbols/vardecl.py index b74128596..d0bb32f6b 100644 --- a/src/symbols/vardecl.py +++ b/src/symbols/vardecl.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/zxbasm/asm_instruction.py b/src/zxbasm/asm_instruction.py index 0e1ed856a..563f4cd4a 100644 --- a/src/zxbasm/asm_instruction.py +++ b/src/zxbasm/asm_instruction.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4 import re diff --git a/src/zxbasm/z80.py b/src/zxbasm/z80.py index 431177ca6..67704d5a8 100644 --- a/src/zxbasm/z80.py +++ b/src/zxbasm/z80.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim:ts=4:et: from typing import Final, NamedTuple diff --git a/src/zxbc/__init__.py b/src/zxbc/__init__.py index 335b1b66b..375ff7c6c 100644 --- a/src/zxbc/__init__.py +++ b/src/zxbc/__init__.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim: ts=4:et:sw=4: # ---------------------------------------------------------------------- diff --git a/src/zxbc/args_config.py b/src/zxbc/args_config.py index c3ae2e59c..1b607f746 100644 --- a/src/zxbc/args_config.py +++ b/src/zxbc/args_config.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python3 from __future__ import annotations import os @@ -51,6 +50,7 @@ def parse_options(args: list[str] | None = None) -> Namespace: OPTIONS.zxnext = options.zxnext OPTIONS.expected_warnings = gl.EXPECTED_WARNINGS = options.expect_warnings OPTIONS.hide_warning_codes = options.hide_warning_codes + OPTIONS.opt_strategy = options.opt_strategy if options.arch not in arch.AVAILABLE_ARCHITECTURES: parser.error(f"Invalid architecture '{options.arch}'") @@ -91,7 +91,6 @@ def parse_options(args: list[str] | None = None) -> Namespace: if OPTIONS.sinclair: OPTIONS.array_base = 1 OPTIONS.string_base = 1 - OPTIONS.strict_bool = True OPTIONS.case_insensitive = True OPTIONS.case_insensitive = options.ignore_case @@ -102,16 +101,28 @@ def parse_options(args: list[str] | None = None) -> Namespace: OPTIONS.output_file_type = options.output_format elif options.tzx: OPTIONS.output_file_type = FileType.TZX - warning_command_line_flag_deprecation(f"--tzx (use --output-format={FileType.TZX} instead)") + warning_command_line_flag_deprecation( + f"--tzx (use -f {FileType.TZX} or --output-format={FileType.TZX} instead)" + ) elif options.tap: OPTIONS.output_file_type = FileType.TAP - warning_command_line_flag_deprecation(f"--tap (use --output-format={FileType.TAP} instead)") + warning_command_line_flag_deprecation( + f"--tap (use -f {FileType.TAP} or --output-format={FileType.TAP} instead)" + ) elif options.asm: OPTIONS.output_file_type = FileType.ASM - warning_command_line_flag_deprecation(f"--asm (use --output-format={FileType.ASM} instead)") + warning_command_line_flag_deprecation( + f"--asm (use -f {FileType.ASM} or --output-format={FileType.ASM} instead)" + ) elif options.emit_backend: OPTIONS.output_file_type = FileType.IR - warning_command_line_flag_deprecation(f"--emit-backend (use --output-format={FileType.IR} instead)") + warning_command_line_flag_deprecation( + f"--emit-backend (use -f {FileType.IR} or --output-format={FileType.IR} instead)" + ) + + if OPTIONS.strict_bool: + OPTIONS.strict_bool = False + warning_command_line_flag_deprecation("--strict-bool is deprecated (no longer needed)") if OPTIONS.output_file_type == FileType.IR: OPTIONS.emit_backend = True diff --git a/src/zxbc/args_parser.py b/src/zxbc/args_parser.py index e50047a74..ecbabbb5f 100644 --- a/src/zxbc/args_parser.py +++ b/src/zxbc/args_parser.py @@ -5,7 +5,7 @@ from src import arch from src.api import errmsg -from src.api.config import OPTIONS +from src.api.config import OPTIONS, OptimizationStrategy from .version import VERSION @@ -73,7 +73,7 @@ def parser() -> argparse.ArgumentParser: action="store_true", help="Sets output format to .asm. DEPRECATED. Use -f", ) - parser_.add_argument( + output_file_type_group.add_argument( "-E", "--emit-backend", action="store_true", @@ -86,7 +86,7 @@ def parser() -> argparse.ArgumentParser: "-f", "--output-format", type=str, - choices=FileType, + choices=[str(x) for x in FileType], required=False, help="Output format", ) @@ -125,7 +125,9 @@ def parser() -> argparse.ArgumentParser: parser_.add_argument("--heap-address", type=str, default=None, help="Sets the heap address.") parser_.add_argument("--debug-memory", action="store_true", default=None, help="Enables out-of-memory debug") parser_.add_argument("--debug-array", action="store_true", default=None, help="Enables array boundary checking") - parser_.add_argument("--strict-bool", action="store_true", default=None, help="Enforce boolean values to be 0 or 1") + parser_.add_argument( + "--strict-bool", action="store_true", default=None, help="Enforce boolean values to be 0 or 1 (Deprecated)" + ) parser_.add_argument("--enable-break", action="store_true", help="Enables program execution BREAK detection") parser_.add_argument( @@ -202,5 +204,11 @@ def parser() -> argparse.ArgumentParser: "-F", "--config-file", type=str, default=OPTIONS.project_filename, help="Loads config from config file" ) parser_.add_argument("--save-config", type=str, help="Save options into a config file") + parser_.add_argument( + "--opt-strategy", + choices=[str(x) for x in OptimizationStrategy], + default=OptimizationStrategy.Auto, + help=f"Optimization strategy (optimize for speed or size). Default: {OptimizationStrategy.Auto}", + ) return parser_ diff --git a/src/zxbc/keywords.py b/src/zxbc/keywords.py old mode 100755 new mode 100644 index 14d960d4e..e73bd1490 --- a/src/zxbc/keywords.py +++ b/src/zxbc/keywords.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim:ts=4:et:sw=4 # ---------------------------------------------------------------------- diff --git a/src/zxbc/zxbparser.py b/src/zxbc/zxbparser.py index c89be4963..3abc576a3 100755 --- a/src/zxbc/zxbparser.py +++ b/src/zxbc/zxbparser.py @@ -199,7 +199,7 @@ def make_number(value, lineno: int, type_=None): return sym.NUMBER(value, type_=type_, lineno=lineno) -def make_typecast(type_: sym.TYPE, node: sym.SYMBOL | None, lineno: int): +def make_typecast(type_: sym.TYPE, node: sym.SYMBOL | None, lineno: int) -> sym.TYPECAST | None: """Wrapper: returns a Typecast node""" if node is None or node.type_ is None: return None # syntax / semantic error @@ -208,12 +208,12 @@ def make_typecast(type_: sym.TYPE, node: sym.SYMBOL | None, lineno: int): return sym.TYPECAST.make_node(type_, node, lineno) -def make_binary(lineno, operator, left, right, func=None, type_=None): +def make_binary(lineno: int, operator, left, right, func=None, type_=None): """Wrapper: returns a Binary node""" return sym.BINARY.make_node(operator, left, right, lineno, func, type_) -def make_unary(lineno, operator, operand, func=None, type_=None): +def make_unary(lineno: int, operator, operand, func=None, type_=None): """Wrapper: returns a Unary node""" if operand is None: # syntax / semantic error return None diff --git a/src/zxbpp/base_pplex.py b/src/zxbpp/base_pplex.py old mode 100755 new mode 100644 index 28f390312..274f474a0 --- a/src/zxbpp/base_pplex.py +++ b/src/zxbpp/base_pplex.py @@ -1,5 +1,3 @@ -#!/usr/bin/python3 - # ---------------------------------------------------------------------- # Copyleft (K), Jose M. Rodriguez-Rosa (a.k.a. Boriel) # diff --git a/src/zxbpp/prepro/__init__.py b/src/zxbpp/prepro/__init__.py index cb8e793f3..6f2f6ae77 100644 --- a/src/zxbpp/prepro/__init__.py +++ b/src/zxbpp/prepro/__init__.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim: ts=4:sw=4:et: from .args import Arg, ArgList diff --git a/src/zxbpp/prepro/args.py b/src/zxbpp/prepro/args.py index c68d9c066..6ac2cc33c 100644 --- a/src/zxbpp/prepro/args.py +++ b/src/zxbpp/prepro/args.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim:ts=4:et:sw=4: from .macrocall import MacroCall diff --git a/src/zxbpp/prepro/definestable.py b/src/zxbpp/prepro/definestable.py index 6139cbfac..682327fb2 100644 --- a/src/zxbpp/prepro/definestable.py +++ b/src/zxbpp/prepro/definestable.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim: ts=4:sw=4:et: """Class for a Table of Defines. diff --git a/src/zxbpp/prepro/exceptions.py b/src/zxbpp/prepro/exceptions.py index 5c3cc202d..cbd0f9271 100644 --- a/src/zxbpp/prepro/exceptions.py +++ b/src/zxbpp/prepro/exceptions.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python - - class PreprocError(Exception): """Denotes an exception in the preprocessor""" diff --git a/src/zxbpp/prepro/id_.py b/src/zxbpp/prepro/id_.py index cee343c68..6e50cdc71 100644 --- a/src/zxbpp/prepro/id_.py +++ b/src/zxbpp/prepro/id_.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # vim: ts=4:sw=4:et: __doc__ = """ A class for an identifier parsed by the preprocessor. diff --git a/src/zxbpp/prepro/macrocall.py b/src/zxbpp/prepro/macrocall.py index 96853b8ee..af7d5b981 100644 --- a/src/zxbpp/prepro/macrocall.py +++ b/src/zxbpp/prepro/macrocall.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim:ts=4:et:sw=4: import copy diff --git a/src/zxbpp/prepro/output.py b/src/zxbpp/prepro/output.py index c65db7dd3..05fc10887 100644 --- a/src/zxbpp/prepro/output.py +++ b/src/zxbpp/prepro/output.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # vim:ts=4:et:sw=4: """Common output functions for the preprocessor. diff --git a/tests/__init__.py b/tests/__init__.py index c21325ec5..5ace62cdb 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import os import os.path import sys diff --git a/tests/api/__init__.py b/tests/api/__init__.py index 4265cc3e6..e69de29bb 100644 --- a/tests/api/__init__.py +++ b/tests/api/__init__.py @@ -1 +0,0 @@ -#!/usr/bin/env python diff --git a/tests/api/test_check.py b/tests/api/test_check.py index ac4968c6a..7e5ed55c1 100644 --- a/tests/api/test_check.py +++ b/tests/api/test_check.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import unittest from src.api import check diff --git a/tests/api/test_config.py b/tests/api/test_config.py index 463d25b0c..891eb86bb 100644 --- a/tests/api/test_config.py +++ b/tests/api/test_config.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python import sys import unittest from unittest import mock @@ -39,6 +38,7 @@ def test_init(self): self.assertEqual(config.OPTIONS.emit_backend, False) self.assertIsNone(config.OPTIONS.architecture) self.assertEqual(config.OPTIONS.expected_warnings, 0) + self.assertEqual(config.OPTIONS.opt_strategy, "auto") # private options that cannot be accessed with #pragma self.assertEqual(config.OPTIONS["__DEFINES"].value, {}) @@ -47,44 +47,42 @@ def test_init(self): self.assertEqual(config.OPTIONS.strict, False) def test_initted_values(self): - self.assertEqual( - sorted(config.OPTIONS._options.keys()), - [ - "__DEFINES", - config.OPTION.ARCH, - config.OPTION.ARRAY_BASE, - config.OPTION.CHECK_ARRAYS, - config.OPTION.AUTORUN, - config.OPTION.CASE_INS, - config.OPTION.DEBUG, - config.OPTION.DEFAULT_BYREF, - config.OPTION.EMIT_BACKEND, - config.OPTION.ENABLE_BREAK, - config.OPTION.EXPECTED_WARNINGS, - config.OPTION.EXPLICIT, - config.OPTION.FORCE_ASM_BRACKET, - config.OPTION.HIDE_WARNING_CODES, - config.OPTION.INCLUDE_PATH, - config.OPTION.INPUT_FILENAME, - config.OPTION.MAX_SYN_ERRORS, - config.OPTION.CHECK_MEMORY, - config.OPTION.MEMORY_MAP, - config.OPTION.O_LEVEL, - config.OPTION.OUTPUT_FILE_TYPE, - config.OPTION.OUTPUT_FILENAME, - "project_filename", - "sinclair", - config.OPTION.STDERR, - config.OPTION.STDERR_FILENAME, - config.OPTION.STDIN, - config.OPTION.STDOUT, - config.OPTION.STRICT, - config.OPTION.STRICT_BOOL, - config.OPTION.STR_BASE, - config.OPTION.USE_BASIC_LOADER, - config.OPTION.ASM_ZXNEXT, - ], - ) + assert sorted(config.OPTIONS._options.keys()) == [ + "__DEFINES", + config.OPTION.ARCH, + config.OPTION.ARRAY_BASE, + config.OPTION.CHECK_ARRAYS, + config.OPTION.AUTORUN, + config.OPTION.CASE_INS, + config.OPTION.DEBUG, + config.OPTION.DEFAULT_BYREF, + config.OPTION.EMIT_BACKEND, + config.OPTION.ENABLE_BREAK, + config.OPTION.EXPECTED_WARNINGS, + config.OPTION.EXPLICIT, + config.OPTION.FORCE_ASM_BRACKET, + config.OPTION.HIDE_WARNING_CODES, + config.OPTION.INCLUDE_PATH, + config.OPTION.INPUT_FILENAME, + config.OPTION.MAX_SYN_ERRORS, + config.OPTION.CHECK_MEMORY, + config.OPTION.MEMORY_MAP, + config.OPTION.OPT_STRATEGY, + config.OPTION.O_LEVEL, + config.OPTION.OUTPUT_FILE_TYPE, + config.OPTION.OUTPUT_FILENAME, + "project_filename", + "sinclair", + config.OPTION.STDERR, + config.OPTION.STDERR_FILENAME, + config.OPTION.STDIN, + config.OPTION.STDOUT, + config.OPTION.STRICT, + config.OPTION.STRICT_BOOL, + config.OPTION.STR_BASE, + config.OPTION.USE_BASIC_LOADER, + config.OPTION.ASM_ZXNEXT, + ] def test_loader_ignore_none(self): """Some settings must ignore "None" assignments, since diff --git a/tests/api/test_symbolTable.py b/tests/api/test_symbolTable.py index 7ac28fcfb..c0a7f69f5 100644 --- a/tests/api/test_symbolTable.py +++ b/tests/api/test_symbolTable.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python3 - -import unittest from io import StringIO from unittest import TestCase @@ -182,7 +179,3 @@ def clearOutput(self): @property def OUTPUT(self): return OPTIONS.stderr.getvalue() - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/api/test_utils.py b/tests/api/test_utils.py index f0cf8e939..34bb62fb4 100644 --- a/tests/api/test_utils.py +++ b/tests/api/test_utils.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import unittest from src.api import utils diff --git a/tests/arch/zx48k/optimizer/common.py b/tests/arch/zx48k/optimizer/common.py new file mode 100644 index 000000000..3c604c471 --- /dev/null +++ b/tests/arch/zx48k/optimizer/common.py @@ -0,0 +1,14 @@ +from contextlib import contextmanager + +from src.api.config import OPTIONS + + +@contextmanager +def mock_options_level(level: int): + initial_level = OPTIONS.optimization_level + + try: + OPTIONS.optimization_level = level + yield + finally: + OPTIONS.optimization_level = initial_level diff --git a/tests/arch/zx48k/optimizer/test_o1_optimizer.py b/tests/arch/zx48k/optimizer/test_o1_optimizer.py new file mode 100644 index 000000000..931081681 --- /dev/null +++ b/tests/arch/zx48k/optimizer/test_o1_optimizer.py @@ -0,0 +1,26 @@ +from src.arch.z80.backend import Backend +from tests.arch.zx48k.optimizer.common import mock_options_level + + +class TestO1Optimizer: + @staticmethod + def _asm_code(asm: str) -> list[str]: + return [x.strip() for x in asm.split("\n") if x.strip()] + + def setup_method(self) -> None: + self.backend = Backend() + + def test_call_match(self): + code_src = """ + call .core.__LEI8 + sub 1 + sbc a, a + inc a + """ + code = self._asm_code(code_src) + with mock_options_level(1): + output = [] + self.backend._output_join(output, code, optimize=True) + assert output == [ + "call .core.__LEI8", + ] diff --git a/tests/arch/zx48k/optimizer/test_optimizer.py b/tests/arch/zx48k/optimizer/test_optimizer.py index 3a5225921..3db7f24a7 100644 --- a/tests/arch/zx48k/optimizer/test_optimizer.py +++ b/tests/arch/zx48k/optimizer/test_optimizer.py @@ -1,19 +1,6 @@ -from contextlib import contextmanager - -from src.api.config import OPTIONS from src.arch.z80 import optimizer from src.arch.z80.peephole import engine - - -@contextmanager -def mock_options_level(level: int): - initial_level = OPTIONS.optimization_level - - try: - OPTIONS.optimization_level = level - yield - finally: - OPTIONS.optimization_level = initial_level +from tests.arch.zx48k.optimizer.common import mock_options_level class TestOptimizer: diff --git a/tests/arch/zx48k/peephole/test_parser.py b/tests/arch/zx48k/peephole/test_parser.py index f70062fdb..54762b2e2 100644 --- a/tests/arch/zx48k/peephole/test_parser.py +++ b/tests/arch/zx48k/peephole/test_parser.py @@ -32,25 +32,22 @@ def test_parse_string(self): self.maxDiff = None self.assertIsInstance(result, dict) - self.assertDictEqual( - result, - { - "DEFINE": [], - "IF": [ - [ - [["$1", "==", "af'"], "&&", ["$1", "==", 'Hello ""World""']], - "&&", - [["$1", "==", "(hl)"], "||", ["IS_INDIR", ["$1"]]], - ], - "||", - ["$1", "==", "aa"], + assert result == { + "DEFINE": [], + "IF": [ + [ + [["$1", "==", "af'"], "&&", ["$1", "==", 'Hello ""World""']], + "&&", + [["$1", "==", "(hl)"], "||", ["IS_INDIR", ["$1"]]], ], - "OFLAG": 15, - "OLEVEL": 1, - "REPLACE": ["push $1", "pop $1"], - "WITH": [], - }, - ) + "||", + ["$1", "==", "aa"], + ], + "OFLAG": 15, + "OLEVEL": 1, + "REPLACE": ["push $1", "pop $1"], + "WITH": [], + } def test_parse_call(self): result = parser.parse_str( @@ -355,3 +352,151 @@ def test_in_list(self): "WITH": ["pop $1", "$2"], "DEFINE": [], } + + def test_parse_cond(self): + result = parser.parse_str( + """ + OLEVEL: 1 + OFLAG: 14 + REPLACE {{ + $1 + }} + + WITH {{ + }} + + IF {{ + $1 == "nop" + }} + """ + ) + assert result == { + "OLEVEL": 1, + "OFLAG": 14, + "REPLACE": ["$1"], + "WITH": [], + "DEFINE": [], + "IF": ["$1", "==", "nop"], + } + + def test_parse_if_must_start_in_a_new_line(self): + result = parser.parse_str( + """ + OLEVEL: 1 + OFLAG: 14 + REPLACE {{ + $1 + }} + + WITH {{ + }} + ;; this is not valid + IF {{ $1 == "nop" }} + """ + ) + assert result is None + + def test_parse_with_ending_binary_error(self): + result = parser.parse_str( + """ + ;; Sample Comment + ;; + + OLEVEL: 1 + OFLAG: 20 + + REPLACE {{ + $1 + }} + + WITH {{ + }} + + IF {{ + $1 == "ld a, 0" || + }} + """ + ) + assert result is None + + def test_parse_with_comma_error(self): + result = parser.parse_str( + """ + OLEVEL: 1 + OFLAG: 20 + + REPLACE {{ + $1 + }} + + WITH {{ + }} + + IF {{ + $1 == "ld a, 0" , + $1 == "ld a, 0" + }} + """ + ) + assert result is None + + def test_parse_with_nested_comma_error(self): + result = parser.parse_str( + """ + OLEVEL: 1 + OFLAG: 20 + + REPLACE {{ + $1 + }} + + WITH {{ + }} + + IF {{ + ($1 == "ld a, 0" , + $1 == "ld a, 0") + }} + """ + ) + assert result is None + + def test_parse_with_list_error(self): + result = parser.parse_str( + """ + OLEVEL: 1 + OFLAG: 20 + + REPLACE {{ + $1 + }} + + WITH {{ + }} + + IF {{ + $1 IN ("x", "y" . "pera") + }} + """ + ) + assert result is None + + def test_parse_with_list_error2(self): + result = parser.parse_str( + """ + OLEVEL: 1 + OFLAG: 20 + + REPLACE {{ + $1 + }} + + WITH {{ + }} + + IF {{ + $1 IN ("x", , , "pera") + }} + """ + ) + assert result is None diff --git a/tests/cmdline/__init__.py b/tests/cmdline/__init__.py index 77940f4ec..69b0c613c 100644 --- a/tests/cmdline/__init__.py +++ b/tests/cmdline/__init__.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import os import os.path import sys diff --git a/tests/functional/arch/zx48k/25.asm b/tests/functional/arch/zx48k/25.asm index 3db1b7fe2..2a1d38399 100644 --- a/tests/functional/arch/zx48k/25.asm +++ b/tests/functional/arch/zx48k/25.asm @@ -31,6 +31,7 @@ _c: ld hl, (_a) ld de, (_a + 2) call .core.__NOT32 + neg ld (_c), a ld hl, 0 ld b, h @@ -47,7 +48,7 @@ _c: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/not32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bool/not32.asm" ; ------------------------------------------------------------- ; 32 bit logical NOT ; ------------------------------------------------------------- @@ -61,5 +62,5 @@ __NOT32: ; A = ¬A sbc a, a; Gives 0 if not carry, FF otherwise ret pop namespace -#line 25 "25.bas" +#line 26 "arch/zx48k/25.bas" END diff --git a/tests/functional/arch/zx48k/and16.asm b/tests/functional/arch/zx48k/and16.asm index 255835297..9af2a346c 100644 --- a/tests/functional/arch/zx48k/and16.asm +++ b/tests/functional/arch/zx48k/and16.asm @@ -30,6 +30,9 @@ _b: ld hl, (_a) ld a, h or l + sub 1 + sbc a, a + inc a ld (_b), a ld hl, (_a) xor a @@ -37,10 +40,16 @@ _b: ld hl, (_a) ld a, h or l + sub 1 + sbc a, a + inc a ld (_b), a ld de, (_a) ld hl, (_a) call .core.__AND16 + sub 1 + sbc a, a + inc a ld (_b), a ld hl, 0 ld b, h @@ -57,7 +66,7 @@ _b: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/and16.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bool/and16.asm" ; FASTCALL boolean and 16 version. ; result in Accumulator (0 False, not 0 True) ; __FASTCALL__ version (operands: DE, HL) @@ -71,5 +80,5 @@ __AND16: or e ret pop namespace -#line 35 "and16.bas" +#line 44 "arch/zx48k/and16.bas" END diff --git a/tests/functional/arch/zx48k/and32.asm b/tests/functional/arch/zx48k/and32.asm index bcf511206..9492290cd 100644 --- a/tests/functional/arch/zx48k/and32.asm +++ b/tests/functional/arch/zx48k/and32.asm @@ -33,6 +33,9 @@ _b: ld de, 0 ld hl, 1 call .core.__AND32 + sub 1 + sbc a, a + inc a ld (_b), a xor a ld (_b), a @@ -43,6 +46,9 @@ _b: ld de, 0 ld hl, 1 call .core.__AND32 + sub 1 + sbc a, a + inc a ld (_b), a ld hl, (_a + 2) push hl @@ -51,6 +57,9 @@ _b: ld hl, (_a) ld de, (_a + 2) call .core.__AND32 + sub 1 + sbc a, a + inc a ld (_b), a ld hl, 0 ld b, h @@ -67,7 +76,7 @@ _b: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/and32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bool/and32.asm" ; FASTCALL boolean and 32 version. ; Performs 32bit and 32bit and returns the boolean ; result in Accumulator (0 False, not 0 True) @@ -86,8 +95,8 @@ __AND32: or e or h or l -#line 28 "/zxbasic/src/arch/zx48k/library-asm/and32.asm" +#line 28 "/zxbasic/src/lib/arch/zx48k/runtime/bool/and32.asm" ret pop namespace -#line 45 "and32.bas" +#line 54 "arch/zx48k/and32.bas" END diff --git a/tests/functional/arch/zx48k/and8.asm b/tests/functional/arch/zx48k/and8.asm index f0707296e..5c22c95b6 100644 --- a/tests/functional/arch/zx48k/and8.asm +++ b/tests/functional/arch/zx48k/and8.asm @@ -28,11 +28,17 @@ _b: xor a ld (_b), a ld a, (_a) + sub 1 + sbc a, a + inc a ld (_b), a ld a, (_a) xor a ld (_b), a ld a, (_a) + sub 1 + sbc a, a + inc a ld (_b), a ld hl, (_a - 1) ld a, (_a) @@ -40,6 +46,9 @@ _b: jr z, .LABEL.__LABEL0 ld a, h .LABEL.__LABEL0: + sub 1 + sbc a, a + inc a ld (_b), a ld hl, 0 ld b, h diff --git a/tests/functional/arch/zx48k/arrbase1.asm b/tests/functional/arch/zx48k/arrbase1.asm index c460df294..00b18048a 100644 --- a/tests/functional/arch/zx48k/arrbase1.asm +++ b/tests/functional/arch/zx48k/arrbase1.asm @@ -87,7 +87,9 @@ _c.__LBOUND__: pop ix ei ret -__DATA__0: +.DATA.__DATA__0: + DEFB 3 + DEFB 1 __DATA__END: DEFB 00h ;; --- end of user code --- @@ -107,7 +109,7 @@ __DATA__END: ; O = [a0 + b0 * (a1 + b1 * (a2 + ... bN-2(aN-1)))] ; What I will do here is to calculate the following sequence: ; ((aN-1 * bN-2) + aN-2) * bN-3 + ... -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/mul16.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mul16.asm" push namespace core __MUL16: ; Mutiplies HL with the last value stored into de stack ; Works for both signed and unsigned @@ -247,7 +249,7 @@ __FNMUL2: ret ENDP pop namespace -#line 46 "arch/zx48k/arrbase1.bas" +#line 48 "arch/zx48k/arrbase1.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" ;; This implements READ & RESTORE functions ;; Reads a new element from the DATA Address code @@ -1217,6 +1219,13 @@ _from_u16: jp _from_i32 dynamic_cast4: ;; The user type is "shorter" than the read one + ld a, b ;; read type + cp 4 ;; if user type < read type < _i16 => From Ubyte to Byte. Return af' + jr nc, 1f + ex af, af' + ret +1: + ld a, c ;; recover user required type cp 8 ;; required type jr c, before_to_int ;; required < fixed (f16) ex af, af' @@ -1337,5 +1346,5 @@ __DATA_ADDR: ;; Stores current DATA ptr dw .DATA.__DATA__0 ENDP pop namespace -#line 47 "arch/zx48k/arrbase1.bas" +#line 49 "arch/zx48k/arrbase1.bas" END diff --git a/tests/functional/arch/zx48k/arrbase1.bas b/tests/functional/arch/zx48k/arrbase1.bas index d865713bd..a55a441c6 100644 --- a/tests/functional/arch/zx48k/arrbase1.bas +++ b/tests/functional/arch/zx48k/arrbase1.bas @@ -7,3 +7,5 @@ DIM k as Uinteger FOR k=1 TO 2 READ c(k, 1) NEXT k + +DATA 1 diff --git a/tests/functional/arch/zx48k/data1.asm b/tests/functional/arch/zx48k/data1.asm index bc0d4e370..451fbf26c 100644 --- a/tests/functional/arch/zx48k/data1.asm +++ b/tests/functional/arch/zx48k/data1.asm @@ -57,7 +57,7 @@ _a: __DATA__END: DEFB 00h ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" ;; This implements READ & RESTORE functions ;; Reads a new element from the DATA Address code ;; Updates the DATA_ADDR read ptr for the next read @@ -75,7 +75,7 @@ __DATA__END: ;; 09: Float ;; bit7 is set for a parameter-less function ;; In that case, the next two bytes are the ptr of the function to jump -#line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" ; Simple error control routines ; vim:ts=4:et: push namespace core @@ -109,9 +109,9 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 23 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 23 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa ; (a.k.a. Boriel) @@ -171,7 +171,7 @@ __STOP: ; HL = BLOCK Start & DE = Length. ; An init directive is useful for initialization routines. ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/heapinit.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa ; (a.k.a. Boriel) @@ -278,7 +278,7 @@ __MEM_INIT2: ret ENDP pop namespace -#line 70 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 70 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; --------------------------------------------------------------------- ; MEM_ALLOC ; Allocates a block of memory in the heap. @@ -309,9 +309,9 @@ __MEM_START: __MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE ld a, h ; HL = NULL (No memory available?) or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 113 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 115 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; HL = Pointer to Free block ld e, (hl) inc hl @@ -376,7 +376,7 @@ __MEM_SUBTRACT: ret ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" ; Loads a string (ptr) from HL ; and duplicates it on dynamic memory again ; Finally, it returns result pointer in HL @@ -413,8 +413,8 @@ __LOADSTR: ; __FASTCALL__ entry pop hl ; Recovers destiny in hl as result ret pop namespace -#line 24 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/iload32.asm" +#line 24 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/iload32.asm" ; __FASTCALL__ routine which ; loads a 32 bits integer into DE,HL ; stored at position pointed by POINTER HL @@ -432,8 +432,8 @@ __ILOAD32: ex de, hl ret pop namespace -#line 25 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/iloadf.asm" +#line 25 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/iloadf.asm" ; __FASTCALL__ routine which ; loads a 40 bits floating point into A ED CB ; stored at position pointed by POINTER HL @@ -460,10 +460,10 @@ __LOADF: ; Loads a 40 bits FP number from address pointed by HL ld b, (hl) ret pop namespace -#line 26 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ftof16reg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/neg32.asm" +#line 26 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftof16reg.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg32.asm" push namespace core __ABS32: bit 7, d @@ -488,7 +488,7 @@ __NEG32: ; Negates DEHL (Two's complement) inc de ret pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm" push namespace core __FTOU32REG: ; Converts a Float to (un)signed 32 bit integer (NOTE: It's ALWAYS 32 bit signed) ; Input FP number in A EDCB (A exponent, EDCB mantissa) @@ -560,7 +560,7 @@ __FTOU8: ; Converts float in C ED LH to Unsigned byte in A ld a, l ret pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/ftof16reg.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/ftof16reg.asm" push namespace core __FTOF16REG: ; Converts a Float to 16.16 (32 bit) fixed point decimal ; Input FP number in A EDCB (A exponent, EDCB mantissa) @@ -591,9 +591,9 @@ __FTOF16REG: ; Converts a Float to 16.16 (32 bit) fixed point decimal ld b, a ; Loop counter = exponent - 128 + 16 (we need to shift 16 bit more) jp __FTOU32REG_LOOP ; proceed as an u32 integer pop namespace -#line 27 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/f16tofreg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/u32tofreg.asm" +#line 27 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/f16tofreg.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/u32tofreg.asm" push namespace core __I8TOFREG: ld l, a @@ -663,7 +663,7 @@ __U32TOFREG_END: ret ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/f16tofreg.asm" +#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/f16tofreg.asm" push namespace core __F16TOFREG: ; Converts a 16.16 signed fixed point (stored in DEHL) ; to a Floating Point Number returned in (C ED CB) @@ -698,8 +698,8 @@ __F16TOFREG2: ; Converts an unsigned 32 bit integer (DEHL) jp __U32TOFREG_LOOP ; Proceed as an integer ENDP pop namespace -#line 28 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +#line 28 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa ; (a.k.a. Boriel) @@ -857,16 +857,16 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ret ENDP pop namespace -#line 29 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 31 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 32 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 33 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 34 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 35 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 36 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 37 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 38 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 39 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" +#line 29 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 31 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 32 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 33 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 34 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 35 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 36 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 37 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 38 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 39 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" ;; Updates restore point to the given HL mem. address push namespace core __RESTORE: @@ -1026,6 +1026,13 @@ _from_u16: jp _from_i32 dynamic_cast4: ;; The user type is "shorter" than the read one + ld a, b ;; read type + cp 4 ;; if user type < read type < _i16 => From Ubyte to Byte. Return af' + jr nc, 1f + ex af, af' + ret +1: + ld a, c ;; recover user required type cp 8 ;; required type jr c, before_to_int ;; required < fixed (f16) ex af, af' @@ -1146,8 +1153,8 @@ __DATA_ADDR: ;; Stores current DATA ptr dw .DATA.__DATA__0 ENDP pop namespace -#line 32 "data1.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/storef.asm" +#line 32 "arch/zx48k/data1.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/storef.asm" push namespace core __PISTOREF: ; Indect Stores a float (A, E, D, C, B) at location stored in memory, pointed by (IX + HL) push de @@ -1175,5 +1182,5 @@ __STOREF: ; Stores the given FP number in A EDCB at address HL ld (hl), b ret pop namespace -#line 33 "data1.bas" +#line 33 "arch/zx48k/data1.bas" END diff --git a/tests/functional/arch/zx48k/gef16.asm b/tests/functional/arch/zx48k/gef16.asm index 8940308de..14054c701 100644 --- a/tests/functional/arch/zx48k/gef16.asm +++ b/tests/functional/arch/zx48k/gef16.asm @@ -42,6 +42,7 @@ _l: call .core.__LTI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ex de, hl @@ -57,6 +58,7 @@ _l: call .core.__LTI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ex de, hl @@ -72,6 +74,7 @@ _l: call .core.__LTI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ex de, hl @@ -87,6 +90,7 @@ _l: call .core.__LTI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ex de, hl @@ -108,8 +112,8 @@ _l: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/lti32.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sub32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/lti32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/sub32.asm" ; SUB32 ; Perform TOP of the stack - DEHL ; Pops operand out of the stack (CALLEE) @@ -135,7 +139,7 @@ __SUB32: exx ret pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/lti32.asm" +#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/lti32.asm" push namespace core __LTI32: ; Test 32 bit values in Top of the stack < HLDE PROC @@ -157,8 +161,8 @@ checkParity: ret ENDP pop namespace -#line 78 "gef16.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/swap32.asm" +#line 82 "arch/zx48k/gef16.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/swap32.asm" ; Exchanges current DE HL with the ; ones in the stack push namespace core @@ -175,5 +179,5 @@ __SWAP32: push bc ret pop namespace -#line 79 "gef16.bas" +#line 83 "arch/zx48k/gef16.bas" END diff --git a/tests/functional/arch/zx48k/gei32.asm b/tests/functional/arch/zx48k/gei32.asm index bc71ec1c5..872433a0a 100644 --- a/tests/functional/arch/zx48k/gei32.asm +++ b/tests/functional/arch/zx48k/gei32.asm @@ -42,6 +42,7 @@ _l: call .core.__LTI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -57,6 +58,7 @@ _l: call .core.__LTI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -72,6 +74,7 @@ _l: call .core.__LTI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -87,6 +90,7 @@ _l: call .core.__LTI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -102,6 +106,7 @@ _l: call .core.__LTI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -123,8 +128,8 @@ _l: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/lti32.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sub32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/lti32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/sub32.asm" ; SUB32 ; Perform TOP of the stack - DEHL ; Pops operand out of the stack (CALLEE) @@ -150,7 +155,7 @@ __SUB32: exx ret pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/lti32.asm" +#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/lti32.asm" push namespace core __LTI32: ; Test 32 bit values in Top of the stack < HLDE PROC @@ -172,8 +177,8 @@ checkParity: ret ENDP pop namespace -#line 93 "gei32.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/swap32.asm" +#line 98 "arch/zx48k/gei32.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/swap32.asm" ; Exchanges current DE HL with the ; ones in the stack push namespace core @@ -190,5 +195,5 @@ __SWAP32: push bc ret pop namespace -#line 94 "gei32.bas" +#line 99 "arch/zx48k/gei32.bas" END diff --git a/tests/functional/arch/zx48k/gei8.asm b/tests/functional/arch/zx48k/gei8.asm index ab79fda54..123e5077f 100644 --- a/tests/functional/arch/zx48k/gei8.asm +++ b/tests/functional/arch/zx48k/gei8.asm @@ -18,18 +18,38 @@ .core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA .core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA -_a: +_level: + DEFB 00h +_le: + DEFB 01h +_l: DEFB 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: - ld a, 5 - ld hl, (_a - 1) + ld a, (_level) + ld hl, (_le - 1) call .core.__LEI8 - or a - jp z, .LABEL.__LABEL1 - ld a, 255 - ld (16384), a -.LABEL.__LABEL1: + ld (_l), a + ld a, (_level) + ld hl, (_le - 1) + call .core.__LEI8 + ld (_l), a + ld a, (_le) + push af + ld a, (_level) + pop hl + call .core.__LEI8 + ld (_l), a + ld a, (_le) + push af + ld a, (_level) + pop hl + call .core.__LEI8 + ld (_l), a + ld a, (_level) + ld h, 1 + call .core.__LEI8 + ld (_l), a ld hl, 0 ld b, h ld c, l @@ -45,7 +65,7 @@ _a: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/lei8.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/lei8.asm" push namespace core __LEI8: ; Signed <= comparison for 8bit int ; A <= H (registers) @@ -67,5 +87,5 @@ checkParity: ret ENDP pop namespace -#line 25 "gei8.bas" +#line 41 "arch/zx48k/gei8.bas" END diff --git a/tests/functional/arch/zx48k/gei8.bas b/tests/functional/arch/zx48k/gei8.bas index a71b5632e..d249df894 100644 --- a/tests/functional/arch/zx48k/gei8.bas +++ b/tests/functional/arch/zx48k/gei8.bas @@ -1,5 +1,9 @@ -DIM a as Byte +dim level as Byte = 0 +dim le as Byte = 1 +dim l as Byte -IF a >= 5 THEN - POKE 16384, 255 -END IF +l = le >= (level + 0) +l = le >= level +l = (le + 0) >= level +l = (le + 0) >= (level + 0) +l = 1 >= (level + 0) diff --git a/tests/functional/arch/zx48k/geu16.asm b/tests/functional/arch/zx48k/geu16.asm index 3afc03750..526643996 100644 --- a/tests/functional/arch/zx48k/geu16.asm +++ b/tests/functional/arch/zx48k/geu16.asm @@ -35,6 +35,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -44,6 +45,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -55,6 +57,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -67,6 +70,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -77,6 +81,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld (_l), hl diff --git a/tests/functional/arch/zx48k/geu32.asm b/tests/functional/arch/zx48k/geu32.asm index 67bffa174..72a185b5c 100644 --- a/tests/functional/arch/zx48k/geu32.asm +++ b/tests/functional/arch/zx48k/geu32.asm @@ -42,6 +42,7 @@ _l: call .core.__SUB32 ccf sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -57,6 +58,7 @@ _l: call .core.__SUB32 ccf sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -72,6 +74,7 @@ _l: call .core.__SUB32 ccf sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -87,6 +90,7 @@ _l: call .core.__SUB32 ccf sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -102,6 +106,7 @@ _l: call .core.__SUB32 ccf sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -123,7 +128,7 @@ _l: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sub32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/sub32.asm" ; SUB32 ; Perform TOP of the stack - DEHL ; Pops operand out of the stack (CALLEE) @@ -149,8 +154,8 @@ __SUB32: exx ret pop namespace -#line 93 "geu32.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/swap32.asm" +#line 98 "arch/zx48k/geu32.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/swap32.asm" ; Exchanges current DE HL with the ; ones in the stack push namespace core @@ -167,5 +172,5 @@ __SWAP32: push bc ret pop namespace -#line 94 "geu32.bas" +#line 99 "arch/zx48k/geu32.bas" END diff --git a/tests/functional/arch/zx48k/geu8.asm b/tests/functional/arch/zx48k/geu8.asm index 123596b58..8a7fa2d0f 100644 --- a/tests/functional/arch/zx48k/geu8.asm +++ b/tests/functional/arch/zx48k/geu8.asm @@ -32,12 +32,14 @@ _l: sub h ccf sbc a, a + neg ld (_l), a ld hl, (_level - 1) ld a, (_le) sub h ccf sbc a, a + neg ld (_l), a ld a, (_le) push af @@ -46,12 +48,14 @@ _l: sub h ccf sbc a, a + neg ld (_l), a ld a, (_le) ld hl, (_level - 1) sub h ccf sbc a, a + neg ld (_l), a ld a, (_level) ld h, a @@ -59,6 +63,7 @@ _l: sub h ccf sbc a, a + neg ld (_l), a ld hl, 0 ld b, h diff --git a/tests/functional/arch/zx48k/gtf16.asm b/tests/functional/arch/zx48k/gtf16.asm index 3187481c0..349ada602 100644 --- a/tests/functional/arch/zx48k/gtf16.asm +++ b/tests/functional/arch/zx48k/gtf16.asm @@ -42,6 +42,7 @@ _l: call .core.__LEI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ex de, hl @@ -57,6 +58,7 @@ _l: call .core.__LEI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ex de, hl @@ -72,6 +74,7 @@ _l: call .core.__LEI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ex de, hl @@ -87,6 +90,7 @@ _l: call .core.__LEI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ex de, hl @@ -108,8 +112,8 @@ _l: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/lei32.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sub32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/lei32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/sub32.asm" ; SUB32 ; Perform TOP of the stack - DEHL ; Pops operand out of the stack (CALLEE) @@ -135,7 +139,7 @@ __SUB32: exx ret pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/lei32.asm" +#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/lei32.asm" push namespace core __LEI32: ; Test 32 bit values Top of the stack <= HL,DE PROC @@ -165,8 +169,8 @@ checkParity: ret ENDP pop namespace -#line 78 "gtf16.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/swap32.asm" +#line 82 "arch/zx48k/gtf16.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/swap32.asm" ; Exchanges current DE HL with the ; ones in the stack push namespace core @@ -183,5 +187,5 @@ __SWAP32: push bc ret pop namespace -#line 79 "gtf16.bas" +#line 83 "arch/zx48k/gtf16.bas" END diff --git a/tests/functional/arch/zx48k/gti32.asm b/tests/functional/arch/zx48k/gti32.asm index 634b8a437..c5f1c778c 100644 --- a/tests/functional/arch/zx48k/gti32.asm +++ b/tests/functional/arch/zx48k/gti32.asm @@ -42,6 +42,7 @@ _l: call .core.__LEI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -57,6 +58,7 @@ _l: call .core.__LEI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -72,6 +74,7 @@ _l: call .core.__LEI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -87,6 +90,7 @@ _l: call .core.__LEI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -102,6 +106,7 @@ _l: call .core.__LEI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -123,8 +128,8 @@ _l: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/lei32.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/sub32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/lei32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/sub32.asm" ; SUB32 ; Perform TOP of the stack - DEHL ; Pops operand out of the stack (CALLEE) @@ -150,7 +155,7 @@ __SUB32: exx ret pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/lei32.asm" +#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/lei32.asm" push namespace core __LEI32: ; Test 32 bit values Top of the stack <= HL,DE PROC @@ -180,8 +185,8 @@ checkParity: ret ENDP pop namespace -#line 93 "gti32.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/swap32.asm" +#line 98 "arch/zx48k/gti32.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/swap32.asm" ; Exchanges current DE HL with the ; ones in the stack push namespace core @@ -198,5 +203,5 @@ __SWAP32: push bc ret pop namespace -#line 94 "gti32.bas" +#line 99 "arch/zx48k/gti32.bas" END diff --git a/tests/functional/arch/zx48k/gtu16.asm b/tests/functional/arch/zx48k/gtu16.asm index 51bae3d52..5b5f880a9 100644 --- a/tests/functional/arch/zx48k/gtu16.asm +++ b/tests/functional/arch/zx48k/gtu16.asm @@ -33,6 +33,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -41,6 +42,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -49,6 +51,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -57,6 +60,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -65,6 +69,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl diff --git a/tests/functional/arch/zx48k/gtu32.asm b/tests/functional/arch/zx48k/gtu32.asm index 44ad44503..fc852db7a 100644 --- a/tests/functional/arch/zx48k/gtu32.asm +++ b/tests/functional/arch/zx48k/gtu32.asm @@ -46,6 +46,7 @@ _l: pop de sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -65,6 +66,7 @@ _l: pop de sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -84,6 +86,7 @@ _l: pop de sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -103,6 +106,7 @@ _l: pop de sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -120,6 +124,7 @@ _l: pop de sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -141,7 +146,7 @@ _l: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/swap32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/swap32.asm" ; Exchanges current DE HL with the ; ones in the stack push namespace core @@ -158,5 +163,5 @@ __SWAP32: push bc ret pop namespace -#line 111 "gtu32.bas" +#line 116 "arch/zx48k/gtu32.bas" END diff --git a/tests/functional/arch/zx48k/let_array_local_const0.asm b/tests/functional/arch/zx48k/let_array_local_const0.asm index a91e3f52b..e17ecf1f6 100644 --- a/tests/functional/arch/zx48k/let_array_local_const0.asm +++ b/tests/functional/arch/zx48k/let_array_local_const0.asm @@ -11,7 +11,6 @@ ld (.core.__CALL_BACK__), hl ei call .core.__MEM_INIT - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -68,7 +67,7 @@ _test: push hl push hl ld hl, -4 - ld de, .LABEL.__LABEL6 + ld de, .LABEL.__LABEL5 ld bc, 5 call .core.__ALLOC_LOCAL_ARRAY ld l, (ix-2) @@ -92,7 +91,6 @@ _test: ld (_i), hl jp .LABEL.__LABEL0 .LABEL.__LABEL3: - call .core.COPY_ATTR ld hl, (_i) push hl push ix @@ -101,10 +99,7 @@ _test: add hl, de call .core.__ARRAY ld a, (hl) - call .core.__PRINTI8 - ld hl, .LABEL.__LABEL5 - xor a - call .core.__PRINTSTR + ld (0), a .LABEL.__LABEL4: ld hl, (_i) inc hl @@ -131,9 +126,6 @@ _test__leave: ld sp, ix pop ix ret -.LABEL.__LABEL5: - DEFW 0001h - DEFB 20h ;; --- end of user code --- #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/array.asm" ; vim: ts=4:et:sw=4: @@ -151,7 +143,7 @@ _test__leave: ; O = [a0 + b0 * (a1 + b1 * (a2 + ... bN-2(aN-1)))] ; What I will do here is to calculate the following sequence: ; ((aN-1 * bN-2) + aN-2) * bN-3 + ... -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/mul16.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mul16.asm" push namespace core __MUL16: ; Mutiplies HL with the last value stored into de stack ; Works for both signed and unsigned @@ -291,7 +283,7 @@ __FNMUL2: ret ENDP pop namespace -#line 100 "arch/zx48k/let_array_local_const0.bas" +#line 93 "arch/zx48k/let_array_local_const0.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arrayalloc.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/calloc.asm" ; vim: ts=4:et:sw=4: @@ -704,886 +696,7 @@ __ALLOC_INITIALIZED_LOCAL_ARRAY: ret #line 139 "/zxbasic/src/lib/arch/zx48k/runtime/arrayalloc.asm" pop namespace -#line 101 "arch/zx48k/let_array_local_const0.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 102 "arch/zx48k/let_array_local_const0.bas" +#line 94 "arch/zx48k/let_array_local_const0.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa @@ -1742,172 +855,8 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ret ENDP pop namespace -#line 103 "arch/zx48k/let_array_local_const0.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printnum.asm" - push namespace core -__PRINTU_START: - PROC - LOCAL __PRINTU_CONT - ld a, b - or a - jp nz, __PRINTU_CONT - ld a, '0' - jp __PRINT_DIGIT -__PRINTU_CONT: - pop af - push bc - call __PRINT_DIGIT - pop bc - djnz __PRINTU_CONT - ret - ENDP -__PRINT_MINUS: ; PRINT the MINUS (-) sign. CALLER must preserve registers - ld a, '-' - jp __PRINT_DIGIT - __PRINT_DIGIT EQU __PRINTCHAR ; PRINTS the char in A register, and puts its attrs - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/div8.asm" - ; -------------------------------- - push namespace core -__DIVU8: ; 8 bit unsigned integer division - ; Divides (Top of stack, High Byte) / A - pop hl ; -------------------------------- - ex (sp), hl ; CALLEE -__DIVU8_FAST: ; Does A / H - ld l, h - ld h, a ; At this point do H / L - ld b, 8 - xor a ; A = 0, Carry Flag = 0 -__DIV8LOOP: - sla h - rla - cp l - jr c, __DIV8NOSUB - sub l - inc h -__DIV8NOSUB: - djnz __DIV8LOOP - ld l, a ; save remainder - ld a, h ; - ret ; a = Quotient, - ; -------------------------------- -__DIVI8: ; 8 bit signed integer division Divides (Top of stack) / A - pop hl ; -------------------------------- - ex (sp), hl -__DIVI8_FAST: - ld e, a ; store operands for later - ld c, h - or a ; negative? - jp p, __DIV8A - neg ; Make it positive -__DIV8A: - ex af, af' - ld a, h - or a - jp p, __DIV8B - neg - ld h, a ; make it positive -__DIV8B: - ex af, af' - call __DIVU8_FAST - ld a, c - xor l ; bit 7 of A = 1 if result is negative - ld a, h ; Quotient - ret p ; return if positive - neg - ret -__MODU8: ; 8 bit module. REturns A mod (Top of stack) (unsigned operands) - pop hl - ex (sp), hl ; CALLEE -__MODU8_FAST: ; __FASTCALL__ entry - call __DIVU8_FAST - ld a, l ; Remainder - ret ; a = Modulus -__MODI8: ; 8 bit module. REturns A mod (Top of stack) (For singed operands) - pop hl - ex (sp), hl ; CALLEE -__MODI8_FAST: ; __FASTCALL__ entry - call __DIVI8_FAST - ld a, l ; remainder - ret ; a = Modulus - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" - push namespace core -__PRINTI8: ; Prints an 8 bits number in Accumulator (A) - ; Converts 8 to 32 bits - or a - jp p, __PRINTU8 - push af - call __PRINT_MINUS - pop af - neg -__PRINTU8: - PROC - LOCAL __PRINTU_LOOP - ld b, 0 ; Counter -__PRINTU_LOOP: - or a - jp z, __PRINTU_START - push bc - ld h, 10 - call __DIVU8_FAST ; Divides by 10. D'E'H'L' contains modulo (L' since < 10) - pop bc - ld a, l - or '0' ; Stores ASCII digit (must be print in reversed order) - push af - ld a, h - inc b - jp __PRINTU_LOOP ; Uses JP in loops - ENDP - pop namespace -#line 104 "arch/zx48k/let_array_local_const0.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL - push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later - ld a, h - or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) - ld a, (hl) - call __PRINTCHAR - inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP - pop namespace -#line 105 "arch/zx48k/let_array_local_const0.bas" -.LABEL.__LABEL6: +#line 95 "arch/zx48k/let_array_local_const0.bas" +.LABEL.__LABEL5: DEFB 00h DEFB 00h DEFB 01h diff --git a/tests/functional/arch/zx48k/let_array_local_const0.bas b/tests/functional/arch/zx48k/let_array_local_const0.bas index 6dfc536bf..046536779 100644 --- a/tests/functional/arch/zx48k/let_array_local_const0.bas +++ b/tests/functional/arch/zx48k/let_array_local_const0.bas @@ -13,7 +13,7 @@ sub test dirs(2) = downCellValue dirs(3) = leftCellValue -for i = 1 to 4: print dirs(i); " ";: next i +for i = 1 to 4: Poke 0, dirs(i): next i 'dirs(i) = downCellValue poke 0, dirs(0) end sub diff --git a/tests/functional/arch/zx48k/leu16.asm b/tests/functional/arch/zx48k/leu16.asm index 199187de8..a2f7bad97 100644 --- a/tests/functional/arch/zx48k/leu16.asm +++ b/tests/functional/arch/zx48k/leu16.asm @@ -34,6 +34,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -43,6 +44,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -52,6 +54,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -61,6 +64,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -70,6 +74,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld (_l), hl diff --git a/tests/functional/arch/zx48k/leu32.asm b/tests/functional/arch/zx48k/leu32.asm index 5a6377e0f..eca79b558 100644 --- a/tests/functional/arch/zx48k/leu32.asm +++ b/tests/functional/arch/zx48k/leu32.asm @@ -47,6 +47,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -67,6 +68,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -87,6 +89,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -107,6 +110,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -125,6 +129,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -146,7 +151,7 @@ _l: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/swap32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/swap32.asm" ; Exchanges current DE HL with the ; ones in the stack push namespace core @@ -163,5 +168,5 @@ __SWAP32: push bc ret pop namespace -#line 116 "leu32.bas" +#line 121 "arch/zx48k/leu32.bas" END diff --git a/tests/functional/arch/zx48k/leu8.asm b/tests/functional/arch/zx48k/leu8.asm index ec5714265..317e38b49 100644 --- a/tests/functional/arch/zx48k/leu8.asm +++ b/tests/functional/arch/zx48k/leu8.asm @@ -31,12 +31,14 @@ _l: sub h ccf sbc a, a + neg ld (_l), a ld a, (_level) ld hl, (_le - 1) sub h ccf sbc a, a + neg ld (_l), a ld a, (_le) push af @@ -45,6 +47,7 @@ _l: sub h ccf sbc a, a + neg ld (_l), a ld a, (_le) push af @@ -53,11 +56,13 @@ _l: sub h ccf sbc a, a + neg ld (_l), a ld a, (_level) or a ccf sbc a, a + neg ld (_l), a ld hl, 0 ld b, h diff --git a/tests/functional/arch/zx48k/loadu16ii.asm b/tests/functional/arch/zx48k/loadu16ii.asm index d695577c2..e83bb0ac0 100644 --- a/tests/functional/arch/zx48k/loadu16ii.asm +++ b/tests/functional/arch/zx48k/loadu16ii.asm @@ -10,7 +10,6 @@ add hl, sp ld (.core.__CALL_BACK__), hl ei - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -19,13 +18,12 @@ .core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA .core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA +_a: + DEFB 00, 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: - call .core.COPY_ATTR ld hl, (.LABEL._test) - call .core.__PRINTU16 - call .core.PRINT_EOL - call .core.COPY_ATTR + ld (_a), hl ld a, (.LABEL._test) ld l, a ld h, 0 @@ -38,8 +36,7 @@ ex de, hl pop hl add hl, de - call .core.__PRINTU16 - call .core.PRINT_EOL + ld (_a), hl ld hl, 0 ld b, h ld c, l @@ -55,9 +52,9 @@ ei ret .LABEL._test: -#line 5 "arch/zx48k/loadu16ii.bas" +#line 6 "arch/zx48k/loadu16ii.bas" defw 35600 -#line 8 "arch/zx48k/loadu16ii.bas" +#line 9 "arch/zx48k/loadu16ii.bas" ld hl, 0 ld b, h ld c, l @@ -89,1067 +86,5 @@ __MUL16NOADD: ret ; Result in hl (16 lower bits) ENDP pop namespace -#line 15 "arch/zx48k/loadu16ii.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" - ; Simple error control routines -; vim:ts=4:et: - push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop - ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a - ret - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace #line 16 "arch/zx48k/loadu16ii.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printu16.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi16.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printnum.asm" - push namespace core -__PRINTU_START: - PROC - LOCAL __PRINTU_CONT - ld a, b - or a - jp nz, __PRINTU_CONT - ld a, '0' - jp __PRINT_DIGIT -__PRINTU_CONT: - pop af - push bc - call __PRINT_DIGIT - pop bc - djnz __PRINTU_CONT - ret - ENDP -__PRINT_MINUS: ; PRINT the MINUS (-) sign. CALLER must preserve registers - ld a, '-' - jp __PRINT_DIGIT - __PRINT_DIGIT EQU __PRINTCHAR ; PRINTS the char in A register, and puts its attrs - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printi16.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div16.asm" - ; 16 bit division and modulo functions - ; for both signed and unsigned values -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg16.asm" - ; Negates HL value (16 bit) - push namespace core -__ABS16: - bit 7, h - ret z -__NEGHL: - ld a, l ; HL = -HL - cpl - ld l, a - ld a, h - cpl - ld h, a - inc hl - ret - pop namespace -#line 5 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div16.asm" - push namespace core -__DIVU16: ; 16 bit unsigned division - ; HL = Dividend, Stack Top = Divisor - ; -- OBSOLETE ; Now uses FASTCALL convention - ; ex de, hl - ; pop hl ; Return address - ; ex (sp), hl ; CALLEE Convention -__DIVU16_FAST: - ld a, h - ld c, l - ld hl, 0 - ld b, 16 -__DIV16LOOP: - sll c - rla - adc hl,hl - sbc hl,de - jr nc, __DIV16NOADD - add hl,de - dec c -__DIV16NOADD: - djnz __DIV16LOOP - ex de, hl - ld h, a - ld l, c - ret ; HL = quotient, DE = Mudulus -__MODU16: ; 16 bit modulus - ; HL = Dividend, Stack Top = Divisor - ;ex de, hl - ;pop hl - ;ex (sp), hl ; CALLEE Convention - call __DIVU16_FAST - ex de, hl ; hl = reminder (modulus) - ; de = quotient - ret -__DIVI16: ; 16 bit signed division - ; --- The following is OBSOLETE --- - ; ex de, hl - ; pop hl - ; ex (sp), hl ; CALLEE Convention -__DIVI16_FAST: - ld a, d - xor h - ex af, af' ; BIT 7 of a contains result - bit 7, d ; DE is negative? - jr z, __DIVI16A - ld a, e ; DE = -DE - cpl - ld e, a - ld a, d - cpl - ld d, a - inc de -__DIVI16A: - bit 7, h ; HL is negative? - call nz, __NEGHL -__DIVI16B: - call __DIVU16_FAST - ex af, af' - or a - ret p ; return if positive - jp __NEGHL -__MODI16: ; 16 bit modulus - ; HL = Dividend, Stack Top = Divisor - ;ex de, hl - ;pop hl - ;ex (sp), hl ; CALLEE Convention - call __DIVI16_FAST - ex de, hl ; hl = reminder (modulus) - ; de = quotient - ret - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/printi16.asm" - push namespace core -__PRINTI16: ; Prints a 16bits signed in HL - ; Converts 16 to 32 bits - PROC - LOCAL __PRINTU_LOOP - ld a, h - or a - jp p, __PRINTU16 - call __PRINT_MINUS - call __NEGHL -__PRINTU16: - ld b, 0 -__PRINTU_LOOP: - ld a, h - or l - jp z, __PRINTU_START - push bc - ld de, 10 - call __DIVU16_FAST ; Divides by DE. DE = MODULUS at exit. Since < 256, E = Modulus - pop bc - ld a, e - or '0' ; Stores ASCII digit (must be print in reversed order) - push af - inc b - jp __PRINTU_LOOP ; Uses JP in loops - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printu16.asm" -#line 18 "arch/zx48k/loadu16ii.bas" END diff --git a/tests/functional/arch/zx48k/loadu16ii.bas b/tests/functional/arch/zx48k/loadu16ii.bas index a51a55332..9c5151277 100644 --- a/tests/functional/arch/zx48k/loadu16ii.bas +++ b/tests/functional/arch/zx48k/loadu16ii.bas @@ -1,5 +1,6 @@ -print peek(uinteger,@test) -print peek(@test)+256*peek(@test+1) +dim a as UInteger +let a = peek(uinteger,@test) +let a = peek(@test)+256*peek(@test+1) End test: asm diff --git a/tests/functional/arch/zx48k/ltu16.asm b/tests/functional/arch/zx48k/ltu16.asm index 729952651..f2ab53404 100644 --- a/tests/functional/arch/zx48k/ltu16.asm +++ b/tests/functional/arch/zx48k/ltu16.asm @@ -34,6 +34,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -42,6 +43,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -52,6 +54,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -63,6 +66,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -72,6 +76,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl diff --git a/tests/functional/arch/zx48k/ltu32.asm b/tests/functional/arch/zx48k/ltu32.asm index eddd3364c..88116f19b 100644 --- a/tests/functional/arch/zx48k/ltu32.asm +++ b/tests/functional/arch/zx48k/ltu32.asm @@ -41,6 +41,7 @@ _l: call .core.__SWAP32 call .core.__SUB32 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -55,6 +56,7 @@ _l: ld de, (_level + 2) call .core.__SUB32 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -69,6 +71,7 @@ _l: ld de, (_level + 2) call .core.__SUB32 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -83,6 +86,7 @@ _l: ld de, (_level + 2) call .core.__SUB32 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -97,6 +101,7 @@ _l: push bc call .core.__SUB32 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -144,7 +149,7 @@ __SUB32: exx ret pop namespace -#line 88 "arch/zx48k/ltu32.bas" +#line 93 "arch/zx48k/ltu32.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/swap32.asm" ; Exchanges current DE HL with the ; ones in the stack @@ -162,5 +167,5 @@ __SWAP32: push bc ret pop namespace -#line 89 "arch/zx48k/ltu32.bas" +#line 94 "arch/zx48k/ltu32.bas" END diff --git a/tests/functional/arch/zx48k/ltu8.asm b/tests/functional/arch/zx48k/ltu8.asm index 75e5e65a6..48d1266cf 100644 --- a/tests/functional/arch/zx48k/ltu8.asm +++ b/tests/functional/arch/zx48k/ltu8.asm @@ -31,11 +31,13 @@ _l: ld a, (_le) cp h sbc a, a + neg ld (_l), a ld hl, (_level - 1) ld a, (_le) cp h sbc a, a + neg ld (_l), a ld a, (_le) push af @@ -43,17 +45,20 @@ _l: pop af cp h sbc a, a + neg ld (_l), a ld a, (_le) ld hl, (_level - 1) cp h sbc a, a + neg ld (_l), a ld a, (_level) ld h, a xor a cp h sbc a, a + neg ld (_l), a ld hl, 0 ld b, h diff --git a/tests/functional/arch/zx48k/memcpytest.asm b/tests/functional/arch/zx48k/memcpytest.asm deleted file mode 100644 index 3166a61c1..000000000 --- a/tests/functional/arch/zx48k/memcpytest.asm +++ /dev/null @@ -1,1445 +0,0 @@ - org 32768 -.core.__START_PROGRAM: - di - push ix - push iy - exx - push hl - exx - ld hl, 0 - add hl, sp - ld (.core.__CALL_BACK__), hl - ei - call .core.__MEM_INIT - call .core.__PRINT_INIT - jp .core.__MAIN_PROGRAM__ -.core.__CALL_BACK__: - DEFW 0 -.core.ZXBASIC_USER_DATA: - ; Defines HEAP SIZE -.core.ZXBASIC_HEAP_SIZE EQU 4768 -.core.ZXBASIC_MEM_HEAP: - DEFS 4768 - ; Defines USER DATA Length in bytes -.core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA - .core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN - .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA -_i: - DEFB 00 -.core.ZXBASIC_USER_DATA_END: -.core.__MAIN_PROGRAM__: - call .core.CLS - ld a, 1 - ld (_i), a - jp .LABEL.__LABEL0 -.LABEL.__LABEL3: - call .core.COPY_ATTR - ld hl, .LABEL.__LABEL5 - xor a - call .core.__PRINTSTR -.LABEL.__LABEL4: - ld hl, _i - inc (hl) -.LABEL.__LABEL0: - ld a, 10 - ld hl, (_i - 1) - cp h - jp nc, .LABEL.__LABEL3 -.LABEL.__LABEL2: - ld hl, 6912 - push hl - ld hl, 40000 - push hl - ld hl, 16384 - call _MemCopy - call .core.CLS - ld hl, 0 - call .core.__PAUSE - ld hl, 6912 - push hl - ld hl, 16384 - push hl - ld hl, 40000 - call _MemCopy - ld hl, 0 - ld b, h - ld c, l -.core.__END_PROGRAM: - di - ld hl, (.core.__CALL_BACK__) - ld sp, hl - exx - pop hl - exx - pop iy - pop ix - ei - ret -_MemMove: -#line 31 "/zxbasic/src/lib/arch/zx48k/stdlib/memcopy.bas" - push namespace core - exx - pop hl - exx - pop de - pop bc - exx - push hl - exx - jp __MEMCPY - pop namespace -#line 51 "/zxbasic/src/lib/arch/zx48k/stdlib/memcopy.bas" -_MemMove__leave: - ret -_MemCopy: -#line 67 "/zxbasic/src/lib/arch/zx48k/stdlib/memcopy.bas" - push namespace core - exx - pop hl - exx - pop de - pop bc - exx - push hl - exx - ldir - pop namespace -#line 87 "/zxbasic/src/lib/arch/zx48k/stdlib/memcopy.bas" -_MemCopy__leave: - ret -_MemSet: -#line 100 "/zxbasic/src/lib/arch/zx48k/stdlib/memcopy.bas" - push namespace core - pop de - pop af - pop bc - push de - ld (hl),a - dec bc - ld a, b - or c - ret z - ld d,h - ld e,l - inc de - ldir - pop namespace -#line 122 "/zxbasic/src/lib/arch/zx48k/stdlib/memcopy.bas" -_MemSet__leave: - ret -.LABEL.__LABEL5: - DEFW 0005h - DEFB 54h - DEFB 45h - DEFB 53h - DEFB 54h - DEFB 20h - ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/cls.asm" - ;; Clears the user screen (24 rows) -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/cls.asm" - push namespace core -CLS: - PROC - ld hl, 0 - ld (COORDS), hl - ld hl, SCR_SIZE - ld (S_POSN), hl - ld hl, (SCREEN_ADDR) - ld (DFCC), hl - ld (hl), 0 - ld d, h - ld e, l - inc de - ld bc, 6143 - ldir - ; Now clear attributes - ld hl, (SCREEN_ATTR_ADDR) - ld (DFCCL), hl - ld d, h - ld e, l - inc de - ld a, (ATTR_P) - ld (hl), a - ld bc, 767 - ldir - ret - ENDP - pop namespace -#line 134 "/zxbasic/src/lib/arch/zx48k/stdlib/memcopy.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" - ; Simple error control routines -; vim:ts=4:et: - push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop - ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a - ret - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 135 "/zxbasic/src/lib/arch/zx48k/stdlib/memcopy.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/memcopy.asm" - ; ---------------------------------------------------------------- - ; This file is released under the MIT License - ; - ; Copyleft (k) 2008 -; by Jose Rodriguez-Rosa (a.k.a. Boriel) - ; - ; Use this file as a template to develop your own library file - ; ---------------------------------------------------------------- - ; Emulates both memmove and memcpy C routines - ; Block will be safely copied if they overlap - ; HL => Start of source block - ; DE => Start of destiny block - ; BC => Block length - push namespace core -__MEMCPY: - PROC - LOCAL __MEMCPY2 - push hl - add hl, bc ; addr of last source block byte + 1 - or a - sbc hl, de ; checks if DE > HL + BC - pop hl ; recovers HL. If carry => DE > HL + BC (no overlap) - jr c, __MEMCPY2 - ; Now checks if DE <= HL - sbc hl, de ; Even if overlap, if DE < HL then we can LDIR safely - add hl, de - jr nc, __MEMCPY2 - dec bc - add hl, bc - ex de, hl - add hl, bc - ex de, hl - inc bc ; HL and DE point to the last byte position - lddr ; Copies from end to beginning - ret -__MEMCPY2: - ldir - ret - ENDP - pop namespace -#line 136 "/zxbasic/src/lib/arch/zx48k/stdlib/memcopy.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/pause.asm" - ; The PAUSE statement (Calling the ROM) - push namespace core -__PAUSE: - ld b, h - ld c, l - jp 1F3Dh ; PAUSE_1 - pop namespace -#line 137 "/zxbasic/src/lib/arch/zx48k/stdlib/memcopy.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 5 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL - push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later - ld a, h - or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) - ld a, (hl) - call __PRINTCHAR - inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP - pop namespace -#line 138 "/zxbasic/src/lib/arch/zx48k/stdlib/memcopy.bas" - END diff --git a/tests/functional/arch/zx48k/nef16.asm b/tests/functional/arch/zx48k/nef16.asm index b117170ea..63cc38bcb 100644 --- a/tests/functional/arch/zx48k/nef16.asm +++ b/tests/functional/arch/zx48k/nef16.asm @@ -31,6 +31,7 @@ _t: call .core.__EQ32 sub 1 sbc a, a + neg ld (0), a ld hl, 0 ld b, h @@ -72,5 +73,5 @@ __EQ32: ; Test if 32bit value HLDE equals top of the stack xor a ret pop namespace -#line 27 "arch/zx48k/nef16.bas" +#line 28 "arch/zx48k/nef16.bas" END diff --git a/tests/functional/arch/zx48k/nei16.asm b/tests/functional/arch/zx48k/nei16.asm index 5db465ffe..c421dcd60 100644 --- a/tests/functional/arch/zx48k/nei16.asm +++ b/tests/functional/arch/zx48k/nei16.asm @@ -28,6 +28,9 @@ _t: sbc hl, de ld a, h or l + sub 1 + sbc a, a + inc a ld (0), a ld hl, 0 ld b, h diff --git a/tests/functional/arch/zx48k/nei32.asm b/tests/functional/arch/zx48k/nei32.asm index b410b751b..d216efe91 100644 --- a/tests/functional/arch/zx48k/nei32.asm +++ b/tests/functional/arch/zx48k/nei32.asm @@ -31,6 +31,7 @@ _t: call .core.__EQ32 sub 1 sbc a, a + neg ld (0), a ld hl, 0 ld b, h @@ -72,5 +73,5 @@ __EQ32: ; Test if 32bit value HLDE equals top of the stack xor a ret pop namespace -#line 27 "arch/zx48k/nei32.bas" +#line 28 "arch/zx48k/nei32.bas" END diff --git a/tests/functional/arch/zx48k/nei8.asm b/tests/functional/arch/zx48k/nei8.asm index 273704d71..0cf4df17c 100644 --- a/tests/functional/arch/zx48k/nei8.asm +++ b/tests/functional/arch/zx48k/nei8.asm @@ -23,6 +23,9 @@ _t: .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: ld a, (_t) + sub 1 + sbc a, a + inc a ld (0), a ld hl, 0 ld b, h diff --git a/tests/functional/arch/zx48k/neu16.asm b/tests/functional/arch/zx48k/neu16.asm index 5db465ffe..c421dcd60 100644 --- a/tests/functional/arch/zx48k/neu16.asm +++ b/tests/functional/arch/zx48k/neu16.asm @@ -28,6 +28,9 @@ _t: sbc hl, de ld a, h or l + sub 1 + sbc a, a + inc a ld (0), a ld hl, 0 ld b, h diff --git a/tests/functional/arch/zx48k/neu32.asm b/tests/functional/arch/zx48k/neu32.asm index dcdf70832..e759843d9 100644 --- a/tests/functional/arch/zx48k/neu32.asm +++ b/tests/functional/arch/zx48k/neu32.asm @@ -31,6 +31,7 @@ _t: call .core.__EQ32 sub 1 sbc a, a + neg ld (0), a ld hl, 0 ld b, h @@ -72,5 +73,5 @@ __EQ32: ; Test if 32bit value HLDE equals top of the stack xor a ret pop namespace -#line 27 "arch/zx48k/neu32.bas" +#line 28 "arch/zx48k/neu32.bas" END diff --git a/tests/functional/arch/zx48k/neu8.asm b/tests/functional/arch/zx48k/neu8.asm index 273704d71..0cf4df17c 100644 --- a/tests/functional/arch/zx48k/neu8.asm +++ b/tests/functional/arch/zx48k/neu8.asm @@ -23,6 +23,9 @@ _t: .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: ld a, (_t) + sub 1 + sbc a, a + inc a ld (0), a ld hl, 0 ld b, h diff --git a/tests/functional/arch/zx48k/not16.asm b/tests/functional/arch/zx48k/not16.asm index 53ad82071..a8ce1bb36 100644 --- a/tests/functional/arch/zx48k/not16.asm +++ b/tests/functional/arch/zx48k/not16.asm @@ -33,6 +33,7 @@ _b: or l sub 1 sbc a, a + neg ld (_b), a ld hl, 0 ld b, h diff --git a/tests/functional/arch/zx48k/not32.asm b/tests/functional/arch/zx48k/not32.asm index 829a128b7..3b1c355e5 100644 --- a/tests/functional/arch/zx48k/not32.asm +++ b/tests/functional/arch/zx48k/not32.asm @@ -31,6 +31,7 @@ _b: ld hl, (_a) ld de, (_a + 2) call .core.__NOT32 + neg ld (_b), a ld hl, 0 ld b, h @@ -61,5 +62,5 @@ __NOT32: ; A = ¬A sbc a, a; Gives 0 if not carry, FF otherwise ret pop namespace -#line 25 "arch/zx48k/not32.bas" +#line 26 "arch/zx48k/not32.bas" END diff --git a/tests/functional/arch/zx48k/not8.asm b/tests/functional/arch/zx48k/not8.asm index 57c273ce6..d210a9448 100644 --- a/tests/functional/arch/zx48k/not8.asm +++ b/tests/functional/arch/zx48k/not8.asm @@ -31,6 +31,7 @@ _b: ld a, (_a) sub 1 sbc a, a + neg ld (_b), a ld hl, 0 ld b, h diff --git a/tests/functional/arch/zx48k/ongosub.asm b/tests/functional/arch/zx48k/ongosub.asm index 5834449a7..372ed123f 100644 --- a/tests/functional/arch/zx48k/ongosub.asm +++ b/tests/functional/arch/zx48k/ongosub.asm @@ -10,16 +10,10 @@ add hl, sp ld (.core.__CALL_BACK__), hl ei - call .core.__MEM_INIT - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 .core.ZXBASIC_USER_DATA: - ; Defines HEAP SIZE -.core.ZXBASIC_HEAP_SIZE EQU 4768 -.core.ZXBASIC_MEM_HEAP: - DEFS 4768 ; Defines USER DATA Length in bytes .core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA .core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN @@ -37,11 +31,8 @@ _a: push hl ld a, 1 call .core.__ON_GOSUB - call .core.COPY_ATTR - ld hl, .LABEL.__LABEL2 - xor a - call .core.__PRINTSTR - call .core.PRINT_EOL + ld a, 99 + ld (0), a ld hl, 0 ld b, h ld c, l @@ -57,54 +48,21 @@ _a: ei ret .LABEL._40: - call .core.COPY_ATTR - ld hl, .LABEL.__LABEL3 - xor a - call .core.__PRINTSTR - call .core.PRINT_EOL + ld a, 40 + ld (0), a ret .LABEL._50: - call .core.COPY_ATTR - ld hl, .LABEL.__LABEL4 - xor a - call .core.__PRINTSTR - call .core.PRINT_EOL + ld a, 50 + ld (0), a ret .LABEL._60: - call .core.COPY_ATTR - ld hl, .LABEL.__LABEL5 - xor a - call .core.__PRINTSTR - call .core.PRINT_EOL + ld a, 60 + ld (0), a ret .LABEL._70: - call .core.COPY_ATTR - ld hl, .LABEL.__LABEL6 - xor a - call .core.__PRINTSTR - call .core.PRINT_EOL + ld a, 70 + ld (0), a ret -.LABEL.__LABEL2: - DEFW 0003h - DEFB 45h - DEFB 4Eh - DEFB 44h -.LABEL.__LABEL3: - DEFW 0002h - DEFB 34h - DEFB 30h -.LABEL.__LABEL4: - DEFW 0002h - DEFB 35h - DEFB 30h -.LABEL.__LABEL5: - DEFW 0002h - DEFB 36h - DEFB 30h -.LABEL.__LABEL6: - DEFW 0002h - DEFB 37h - DEFB 30h .LABEL.__LABEL0: DEFB 4 DEFW .LABEL._40 @@ -116,920 +74,6 @@ _a: DEFW .LABEL._50 DEFW .LABEL._60 ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" - ; Simple error control routines -; vim:ts=4:et: - push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop - ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a - ret - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 90 "arch/zx48k/ongosub.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ongoto.asm" ; ------------------------------------------------------ ; Implements ON .. GOTO @@ -1061,316 +105,5 @@ __ON_GOTO_START: ld l, a jp (hl) pop namespace -#line 91 "arch/zx48k/ongosub.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 5 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL - push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later - ld a, h - or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) - ld a, (hl) - call __PRINTCHAR - inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP - pop namespace -#line 93 "arch/zx48k/ongosub.bas" +#line 54 "arch/zx48k/ongosub.bas" END diff --git a/tests/functional/arch/zx48k/ongosub.bas b/tests/functional/arch/zx48k/ongosub.bas index 9815e8a51..cadb72ebd 100644 --- a/tests/functional/arch/zx48k/ongosub.bas +++ b/tests/functional/arch/zx48k/ongosub.bas @@ -3,10 +3,10 @@ DIM a as UBYte = 1 ON a + 2 GOSUB 40, 50, 60, 70 ON 1 GOSUB 50, 60 -PRINT "END" +POKE 0, 99 END -40 PRINT "40": RETURN -50 PRINT "50": RETURN -60 PRINT "60": RETURN -70 PRINT "70": RETURN +40 POKE 0, 40: RETURN +50 POKE 0, 50: RETURN +60 POKE 0, 60: RETURN +70 POKE 0, 70: RETURN diff --git a/tests/functional/arch/zx48k/ongoto.asm b/tests/functional/arch/zx48k/ongoto.asm index 906662e28..32d6f1e66 100644 --- a/tests/functional/arch/zx48k/ongoto.asm +++ b/tests/functional/arch/zx48k/ongoto.asm @@ -10,16 +10,10 @@ add hl, sp ld (.core.__CALL_BACK__), hl ei - call .core.__MEM_INIT - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 .core.ZXBASIC_USER_DATA: - ; Defines HEAP SIZE -.core.ZXBASIC_HEAP_SIZE EQU 4768 -.core.ZXBASIC_MEM_HEAP: - DEFS 4768 ; Defines USER DATA Length in bytes .core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA .core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN @@ -34,28 +28,16 @@ _a: inc a call .core.__ON_GOTO .LABEL._10: - call .core.COPY_ATTR - ld hl, .LABEL.__LABEL1 - xor a - call .core.__PRINTSTR - call .core.PRINT_EOL + ld a, 10 + ld (0), a .LABEL._20: - call .core.COPY_ATTR - ld hl, .LABEL.__LABEL2 - xor a - call .core.__PRINTSTR - call .core.PRINT_EOL + ld a, 20 + ld (0), a .LABEL._30: - call .core.COPY_ATTR - ld hl, .LABEL.__LABEL3 - xor a - call .core.__PRINTSTR - call .core.PRINT_EOL - call .core.COPY_ATTR - ld hl, .LABEL.__LABEL4 - xor a - call .core.__PRINTSTR - call .core.PRINT_EOL + ld a, 30 + ld (0), a + ld a, 99 + ld (0), a ld hl, 0 ld b, h ld c, l @@ -70,943 +52,12 @@ _a: pop ix ei ret -.LABEL.__LABEL1: - DEFW 0002h - DEFB 31h - DEFB 30h -.LABEL.__LABEL2: - DEFW 0002h - DEFB 32h - DEFB 30h -.LABEL.__LABEL3: - DEFW 0002h - DEFB 33h - DEFB 30h -.LABEL.__LABEL4: - DEFW 0003h - DEFB 45h - DEFB 4Eh - DEFB 44h .LABEL.__LABEL0: DEFB 3 DEFW .LABEL._10 DEFW .LABEL._20 DEFW .LABEL._30 ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" - ; Simple error control routines -; vim:ts=4:et: - push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop - ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a - ret - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 67 "arch/zx48k/ongoto.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ongoto.asm" ; ------------------------------------------------------ ; Implements ON .. GOTO @@ -1038,316 +89,5 @@ __ON_GOTO_START: ld l, a jp (hl) pop namespace -#line 68 "arch/zx48k/ongoto.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 5 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL - push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later - ld a, h - or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) - ld a, (hl) - call __PRINTCHAR - inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP - pop namespace -#line 70 "arch/zx48k/ongoto.bas" +#line 38 "arch/zx48k/ongoto.bas" END diff --git a/tests/functional/arch/zx48k/ongoto.bas b/tests/functional/arch/zx48k/ongoto.bas index 210c3bfaa..4c5572a89 100644 --- a/tests/functional/arch/zx48k/ongoto.bas +++ b/tests/functional/arch/zx48k/ongoto.bas @@ -2,8 +2,8 @@ DIM a as UBYte = 1 ON a + 1 GOTO 10, 20, 30 -10 PRINT "10" -20 PRINT "20" -30 PRINT "30" +10 POKE 0, 10 +20 POKE 0, 20 +30 POKE 0, 30 -PRINT "END" +POKE 0, 99 diff --git a/tests/functional/arch/zx48k/opt1_dim_arr_global.asm b/tests/functional/arch/zx48k/opt1_dim_arr_global.asm index e378623c5..7f710b47e 100644 --- a/tests/functional/arch/zx48k/opt1_dim_arr_global.asm +++ b/tests/functional/arch/zx48k/opt1_dim_arr_global.asm @@ -10,7 +10,6 @@ add hl, sp ld (.core.__CALL_BACK__), hl ei - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -41,14 +40,11 @@ _a.__DATA__: .core.__MAIN_PROGRAM__: ld hl, 3 ld (_i), hl - call .core.COPY_ATTR - ld hl, (_i) push hl ld hl, _a call .core.__ARRAY ld a, (hl) - call .core.__PRINTU8 - call .core.PRINT_EOL + ld (0), a ld hl, 0 ld b, h ld c, l @@ -80,7 +76,7 @@ _a.__DATA__: ; O = [a0 + b0 * (a1 + b1 * (a2 + ... bN-2(aN-1)))] ; What I will do here is to calculate the following sequence: ; ((aN-1 * bN-2) + aN-2) * bN-3 + ... -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/mul16.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mul16.asm" push namespace core __MUL16: ; Mutiplies HL with the last value stored into de stack ; Works for both signed and unsigned @@ -220,1041 +216,5 @@ __FNMUL2: ret ENDP pop namespace -#line 27 "arch/zx48k/opt1_dim_arr_global.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" - ; Simple error control routines -; vim:ts=4:et: - push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop - ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a - ret - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 28 "arch/zx48k/opt1_dim_arr_global.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printnum.asm" - push namespace core -__PRINTU_START: - PROC - LOCAL __PRINTU_CONT - ld a, b - or a - jp nz, __PRINTU_CONT - ld a, '0' - jp __PRINT_DIGIT -__PRINTU_CONT: - pop af - push bc - call __PRINT_DIGIT - pop bc - djnz __PRINTU_CONT - ret - ENDP -__PRINT_MINUS: ; PRINT the MINUS (-) sign. CALLER must preserve registers - ld a, '-' - jp __PRINT_DIGIT - __PRINT_DIGIT EQU __PRINTCHAR ; PRINTS the char in A register, and puts its attrs - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/div8.asm" - ; -------------------------------- - push namespace core -__DIVU8: ; 8 bit unsigned integer division - ; Divides (Top of stack, High Byte) / A - pop hl ; -------------------------------- - ex (sp), hl ; CALLEE -__DIVU8_FAST: ; Does A / H - ld l, h - ld h, a ; At this point do H / L - ld b, 8 - xor a ; A = 0, Carry Flag = 0 -__DIV8LOOP: - sla h - rla - cp l - jr c, __DIV8NOSUB - sub l - inc h -__DIV8NOSUB: - djnz __DIV8LOOP - ld l, a ; save remainder - ld a, h ; - ret ; a = Quotient, - ; -------------------------------- -__DIVI8: ; 8 bit signed integer division Divides (Top of stack) / A - pop hl ; -------------------------------- - ex (sp), hl -__DIVI8_FAST: - ld e, a ; store operands for later - ld c, h - or a ; negative? - jp p, __DIV8A - neg ; Make it positive -__DIV8A: - ex af, af' - ld a, h - or a - jp p, __DIV8B - neg - ld h, a ; make it positive -__DIV8B: - ex af, af' - call __DIVU8_FAST - ld a, c - xor l ; bit 7 of A = 1 if result is negative - ld a, h ; Quotient - ret p ; return if positive - neg - ret -__MODU8: ; 8 bit module. REturns A mod (Top of stack) (unsigned operands) - pop hl - ex (sp), hl ; CALLEE -__MODU8_FAST: ; __FASTCALL__ entry - call __DIVU8_FAST - ld a, l ; Remainder - ret ; a = Modulus -__MODI8: ; 8 bit module. REturns A mod (Top of stack) (For singed operands) - pop hl - ex (sp), hl ; CALLEE -__MODI8_FAST: ; __FASTCALL__ entry - call __DIVI8_FAST - ld a, l ; remainder - ret ; a = Modulus - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" - push namespace core -__PRINTI8: ; Prints an 8 bits number in Accumulator (A) - ; Converts 8 to 32 bits - or a - jp p, __PRINTU8 - push af - call __PRINT_MINUS - pop af - neg -__PRINTU8: - PROC - LOCAL __PRINTU_LOOP - ld b, 0 ; Counter -__PRINTU_LOOP: - or a - jp z, __PRINTU_START - push bc - ld h, 10 - call __DIVU8_FAST ; Divides by 10. D'E'H'L' contains modulo (L' since < 10) - pop bc - ld a, l - or '0' ; Stores ASCII digit (must be print in reversed order) - push af - ld a, h - inc b - jp __PRINTU_LOOP ; Uses JP in loops - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" -#line 30 "arch/zx48k/opt1_dim_arr_global.bas" +#line 24 "arch/zx48k/opt1_dim_arr_global.bas" END diff --git a/tests/functional/arch/zx48k/opt1_dim_arr_global.bas b/tests/functional/arch/zx48k/opt1_dim_arr_global.bas index bd6a1ebc7..bd54454c1 100644 --- a/tests/functional/arch/zx48k/opt1_dim_arr_global.bas +++ b/tests/functional/arch/zx48k/opt1_dim_arr_global.bas @@ -3,4 +3,4 @@ DIM a(5) as UByte => {0, 1, 2, 3, 4, 5} DIM i as UInteger i = 3 -PRINT a(i) +POKE 0, a(i) diff --git a/tests/functional/arch/zx48k/opt1_dim_arr_global2.asm b/tests/functional/arch/zx48k/opt1_dim_arr_global2.asm index 578d2bcfd..14d162d0f 100644 --- a/tests/functional/arch/zx48k/opt1_dim_arr_global2.asm +++ b/tests/functional/arch/zx48k/opt1_dim_arr_global2.asm @@ -10,7 +10,6 @@ add hl, sp ld (.core.__CALL_BACK__), hl ei - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -37,10 +36,8 @@ _a.__DATA__: DEFB 01h .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: - call .core.COPY_ATTR ld a, (_a.__DATA__ + 2) - call .core.__PRINTU8 - call .core.PRINT_EOL + ld (0), a ld hl, 0 ld b, h ld c, l @@ -56,1040 +53,4 @@ _a.__DATA__: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" - ; Simple error control routines -; vim:ts=4:et: - push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop - ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a - ret - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 21 "arch/zx48k/opt1_dim_arr_global2.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printnum.asm" - push namespace core -__PRINTU_START: - PROC - LOCAL __PRINTU_CONT - ld a, b - or a - jp nz, __PRINTU_CONT - ld a, '0' - jp __PRINT_DIGIT -__PRINTU_CONT: - pop af - push bc - call __PRINT_DIGIT - pop bc - djnz __PRINTU_CONT - ret - ENDP -__PRINT_MINUS: ; PRINT the MINUS (-) sign. CALLER must preserve registers - ld a, '-' - jp __PRINT_DIGIT - __PRINT_DIGIT EQU __PRINTCHAR ; PRINTS the char in A register, and puts its attrs - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/div8.asm" - ; -------------------------------- - push namespace core -__DIVU8: ; 8 bit unsigned integer division - ; Divides (Top of stack, High Byte) / A - pop hl ; -------------------------------- - ex (sp), hl ; CALLEE -__DIVU8_FAST: ; Does A / H - ld l, h - ld h, a ; At this point do H / L - ld b, 8 - xor a ; A = 0, Carry Flag = 0 -__DIV8LOOP: - sla h - rla - cp l - jr c, __DIV8NOSUB - sub l - inc h -__DIV8NOSUB: - djnz __DIV8LOOP - ld l, a ; save remainder - ld a, h ; - ret ; a = Quotient, - ; -------------------------------- -__DIVI8: ; 8 bit signed integer division Divides (Top of stack) / A - pop hl ; -------------------------------- - ex (sp), hl -__DIVI8_FAST: - ld e, a ; store operands for later - ld c, h - or a ; negative? - jp p, __DIV8A - neg ; Make it positive -__DIV8A: - ex af, af' - ld a, h - or a - jp p, __DIV8B - neg - ld h, a ; make it positive -__DIV8B: - ex af, af' - call __DIVU8_FAST - ld a, c - xor l ; bit 7 of A = 1 if result is negative - ld a, h ; Quotient - ret p ; return if positive - neg - ret -__MODU8: ; 8 bit module. REturns A mod (Top of stack) (unsigned operands) - pop hl - ex (sp), hl ; CALLEE -__MODU8_FAST: ; __FASTCALL__ entry - call __DIVU8_FAST - ld a, l ; Remainder - ret ; a = Modulus -__MODI8: ; 8 bit module. REturns A mod (Top of stack) (For singed operands) - pop hl - ex (sp), hl ; CALLEE -__MODI8_FAST: ; __FASTCALL__ entry - call __DIVI8_FAST - ld a, l ; remainder - ret ; a = Modulus - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" - push namespace core -__PRINTI8: ; Prints an 8 bits number in Accumulator (A) - ; Converts 8 to 32 bits - or a - jp p, __PRINTU8 - push af - call __PRINT_MINUS - pop af - neg -__PRINTU8: - PROC - LOCAL __PRINTU_LOOP - ld b, 0 ; Counter -__PRINTU_LOOP: - or a - jp z, __PRINTU_START - push bc - ld h, 10 - call __DIVU8_FAST ; Divides by 10. D'E'H'L' contains modulo (L' since < 10) - pop bc - ld a, l - or '0' ; Stores ASCII digit (must be print in reversed order) - push af - ld a, h - inc b - jp __PRINTU_LOOP ; Uses JP in loops - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" -#line 23 "arch/zx48k/opt1_dim_arr_global2.bas" END diff --git a/tests/functional/arch/zx48k/opt1_dim_arr_global2.bas b/tests/functional/arch/zx48k/opt1_dim_arr_global2.bas index 448d8be54..bdd21633e 100644 --- a/tests/functional/arch/zx48k/opt1_dim_arr_global2.bas +++ b/tests/functional/arch/zx48k/opt1_dim_arr_global2.bas @@ -1,4 +1,4 @@ DIM a(5) as UByte => {0, 1, 2, 3, 4, 5} -PRINT a(2) +POKE 0, a(2) diff --git a/tests/functional/arch/zx48k/opt1_dim_arr_global3.asm b/tests/functional/arch/zx48k/opt1_dim_arr_global3.asm index 89ee6179e..c4977abae 100644 --- a/tests/functional/arch/zx48k/opt1_dim_arr_global3.asm +++ b/tests/functional/arch/zx48k/opt1_dim_arr_global3.asm @@ -10,7 +10,6 @@ add hl, sp ld (.core.__CALL_BACK__), hl ei - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -39,10 +38,7 @@ _a.__DATA__: .core.__MAIN_PROGRAM__: ld a, 7 ld (_a.__DATA__ + 2), a - call .core.COPY_ATTR - ld a, (_a.__DATA__ + 2) - call .core.__PRINTU8 - call .core.PRINT_EOL + ld (0), a ld hl, 0 ld b, h ld c, l @@ -58,1040 +54,4 @@ _a.__DATA__: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" - ; Simple error control routines -; vim:ts=4:et: - push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop - ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a - ret - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 23 "arch/zx48k/opt1_dim_arr_global3.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printnum.asm" - push namespace core -__PRINTU_START: - PROC - LOCAL __PRINTU_CONT - ld a, b - or a - jp nz, __PRINTU_CONT - ld a, '0' - jp __PRINT_DIGIT -__PRINTU_CONT: - pop af - push bc - call __PRINT_DIGIT - pop bc - djnz __PRINTU_CONT - ret - ENDP -__PRINT_MINUS: ; PRINT the MINUS (-) sign. CALLER must preserve registers - ld a, '-' - jp __PRINT_DIGIT - __PRINT_DIGIT EQU __PRINTCHAR ; PRINTS the char in A register, and puts its attrs - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/div8.asm" - ; -------------------------------- - push namespace core -__DIVU8: ; 8 bit unsigned integer division - ; Divides (Top of stack, High Byte) / A - pop hl ; -------------------------------- - ex (sp), hl ; CALLEE -__DIVU8_FAST: ; Does A / H - ld l, h - ld h, a ; At this point do H / L - ld b, 8 - xor a ; A = 0, Carry Flag = 0 -__DIV8LOOP: - sla h - rla - cp l - jr c, __DIV8NOSUB - sub l - inc h -__DIV8NOSUB: - djnz __DIV8LOOP - ld l, a ; save remainder - ld a, h ; - ret ; a = Quotient, - ; -------------------------------- -__DIVI8: ; 8 bit signed integer division Divides (Top of stack) / A - pop hl ; -------------------------------- - ex (sp), hl -__DIVI8_FAST: - ld e, a ; store operands for later - ld c, h - or a ; negative? - jp p, __DIV8A - neg ; Make it positive -__DIV8A: - ex af, af' - ld a, h - or a - jp p, __DIV8B - neg - ld h, a ; make it positive -__DIV8B: - ex af, af' - call __DIVU8_FAST - ld a, c - xor l ; bit 7 of A = 1 if result is negative - ld a, h ; Quotient - ret p ; return if positive - neg - ret -__MODU8: ; 8 bit module. REturns A mod (Top of stack) (unsigned operands) - pop hl - ex (sp), hl ; CALLEE -__MODU8_FAST: ; __FASTCALL__ entry - call __DIVU8_FAST - ld a, l ; Remainder - ret ; a = Modulus -__MODI8: ; 8 bit module. REturns A mod (Top of stack) (For singed operands) - pop hl - ex (sp), hl ; CALLEE -__MODI8_FAST: ; __FASTCALL__ entry - call __DIVI8_FAST - ld a, l ; remainder - ret ; a = Modulus - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" - push namespace core -__PRINTI8: ; Prints an 8 bits number in Accumulator (A) - ; Converts 8 to 32 bits - or a - jp p, __PRINTU8 - push af - call __PRINT_MINUS - pop af - neg -__PRINTU8: - PROC - LOCAL __PRINTU_LOOP - ld b, 0 ; Counter -__PRINTU_LOOP: - or a - jp z, __PRINTU_START - push bc - ld h, 10 - call __DIVU8_FAST ; Divides by 10. D'E'H'L' contains modulo (L' since < 10) - pop bc - ld a, l - or '0' ; Stores ASCII digit (must be print in reversed order) - push af - ld a, h - inc b - jp __PRINTU_LOOP ; Uses JP in loops - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" -#line 25 "arch/zx48k/opt1_dim_arr_global3.bas" END diff --git a/tests/functional/arch/zx48k/opt1_dim_arr_global3.bas b/tests/functional/arch/zx48k/opt1_dim_arr_global3.bas index b15f879e6..d3459167d 100644 --- a/tests/functional/arch/zx48k/opt1_dim_arr_global3.bas +++ b/tests/functional/arch/zx48k/opt1_dim_arr_global3.bas @@ -2,4 +2,4 @@ DIM a(5) as UByte => {0, 1, 2, 3, 4, 5} LET a(2) = 7 -PRINT a(2) +POKE 0, a(2) diff --git a/tests/functional/arch/zx48k/opt1_dim_arr_global4.asm b/tests/functional/arch/zx48k/opt1_dim_arr_global4.asm index b1dd06e69..4a8eef20f 100644 --- a/tests/functional/arch/zx48k/opt1_dim_arr_global4.asm +++ b/tests/functional/arch/zx48k/opt1_dim_arr_global4.asm @@ -10,7 +10,6 @@ add hl, sp ld (.core.__CALL_BACK__), hl ei - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -45,14 +44,12 @@ _a.__DATA__: ld hl, _a call .core.__ARRAY ld (hl), 7 - call .core.COPY_ATTR ld hl, (_i) push hl ld hl, _a call .core.__ARRAY ld a, (hl) - call .core.__PRINTU8 - call .core.PRINT_EOL + ld (0), a ld hl, 0 ld b, h ld c, l @@ -84,7 +81,7 @@ _a.__DATA__: ; O = [a0 + b0 * (a1 + b1 * (a2 + ... bN-2(aN-1)))] ; What I will do here is to calculate the following sequence: ; ((aN-1 * bN-2) + aN-2) * bN-3 + ... -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/mul16.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mul16.asm" push namespace core __MUL16: ; Mutiplies HL with the last value stored into de stack ; Works for both signed and unsigned @@ -224,1041 +221,5 @@ __FNMUL2: ret ENDP pop namespace -#line 31 "arch/zx48k/opt1_dim_arr_global4.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" - ; Simple error control routines -; vim:ts=4:et: - push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop - ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a - ret - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 32 "arch/zx48k/opt1_dim_arr_global4.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printnum.asm" - push namespace core -__PRINTU_START: - PROC - LOCAL __PRINTU_CONT - ld a, b - or a - jp nz, __PRINTU_CONT - ld a, '0' - jp __PRINT_DIGIT -__PRINTU_CONT: - pop af - push bc - call __PRINT_DIGIT - pop bc - djnz __PRINTU_CONT - ret - ENDP -__PRINT_MINUS: ; PRINT the MINUS (-) sign. CALLER must preserve registers - ld a, '-' - jp __PRINT_DIGIT - __PRINT_DIGIT EQU __PRINTCHAR ; PRINTS the char in A register, and puts its attrs - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/div8.asm" - ; -------------------------------- - push namespace core -__DIVU8: ; 8 bit unsigned integer division - ; Divides (Top of stack, High Byte) / A - pop hl ; -------------------------------- - ex (sp), hl ; CALLEE -__DIVU8_FAST: ; Does A / H - ld l, h - ld h, a ; At this point do H / L - ld b, 8 - xor a ; A = 0, Carry Flag = 0 -__DIV8LOOP: - sla h - rla - cp l - jr c, __DIV8NOSUB - sub l - inc h -__DIV8NOSUB: - djnz __DIV8LOOP - ld l, a ; save remainder - ld a, h ; - ret ; a = Quotient, - ; -------------------------------- -__DIVI8: ; 8 bit signed integer division Divides (Top of stack) / A - pop hl ; -------------------------------- - ex (sp), hl -__DIVI8_FAST: - ld e, a ; store operands for later - ld c, h - or a ; negative? - jp p, __DIV8A - neg ; Make it positive -__DIV8A: - ex af, af' - ld a, h - or a - jp p, __DIV8B - neg - ld h, a ; make it positive -__DIV8B: - ex af, af' - call __DIVU8_FAST - ld a, c - xor l ; bit 7 of A = 1 if result is negative - ld a, h ; Quotient - ret p ; return if positive - neg - ret -__MODU8: ; 8 bit module. REturns A mod (Top of stack) (unsigned operands) - pop hl - ex (sp), hl ; CALLEE -__MODU8_FAST: ; __FASTCALL__ entry - call __DIVU8_FAST - ld a, l ; Remainder - ret ; a = Modulus -__MODI8: ; 8 bit module. REturns A mod (Top of stack) (For singed operands) - pop hl - ex (sp), hl ; CALLEE -__MODI8_FAST: ; __FASTCALL__ entry - call __DIVI8_FAST - ld a, l ; remainder - ret ; a = Modulus - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" - push namespace core -__PRINTI8: ; Prints an 8 bits number in Accumulator (A) - ; Converts 8 to 32 bits - or a - jp p, __PRINTU8 - push af - call __PRINT_MINUS - pop af - neg -__PRINTU8: - PROC - LOCAL __PRINTU_LOOP - ld b, 0 ; Counter -__PRINTU_LOOP: - or a - jp z, __PRINTU_START - push bc - ld h, 10 - call __DIVU8_FAST ; Divides by 10. D'E'H'L' contains modulo (L' since < 10) - pop bc - ld a, l - or '0' ; Stores ASCII digit (must be print in reversed order) - push af - ld a, h - inc b - jp __PRINTU_LOOP ; Uses JP in loops - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" -#line 34 "arch/zx48k/opt1_dim_arr_global4.bas" +#line 29 "arch/zx48k/opt1_dim_arr_global4.bas" END diff --git a/tests/functional/arch/zx48k/opt1_dim_arr_global4.bas b/tests/functional/arch/zx48k/opt1_dim_arr_global4.bas index 8f73c19b6..ddc8025af 100644 --- a/tests/functional/arch/zx48k/opt1_dim_arr_global4.bas +++ b/tests/functional/arch/zx48k/opt1_dim_arr_global4.bas @@ -4,4 +4,4 @@ DIM i as UInteger i = 3 LET a(i) = 7 -PRINT a(i) +POKE 0, a(i) diff --git a/tests/functional/arch/zx48k/opt1_dim_arr_local2.asm b/tests/functional/arch/zx48k/opt1_dim_arr_local2.asm index 159ee2efb..7738c136c 100644 --- a/tests/functional/arch/zx48k/opt1_dim_arr_local2.asm +++ b/tests/functional/arch/zx48k/opt1_dim_arr_local2.asm @@ -11,7 +11,6 @@ ld (.core.__CALL_BACK__), hl ei call .core.__MEM_INIT - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -54,15 +53,13 @@ _test: ld de, .LABEL.__LABEL0 ld bc, 6 call .core.__ALLOC_INITIALIZED_LOCAL_ARRAY - call .core.COPY_ATTR ld l, (ix-2) ld h, (ix-1) inc hl inc hl inc hl ld a, (hl) - call .core.__PRINTU8 - call .core.PRINT_EOL + ld (0), a _test__leave: ex af, af' exx @@ -487,886 +484,7 @@ __ALLOC_INITIALIZED_LOCAL_ARRAY: ret #line 139 "/zxbasic/src/lib/arch/zx48k/runtime/arrayalloc.asm" pop namespace -#line 51 "arch/zx48k/opt1_dim_arr_local2.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 52 "arch/zx48k/opt1_dim_arr_local2.bas" +#line 49 "arch/zx48k/opt1_dim_arr_local2.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa @@ -1525,129 +643,7 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ret ENDP pop namespace -#line 53 "arch/zx48k/opt1_dim_arr_local2.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printnum.asm" - push namespace core -__PRINTU_START: - PROC - LOCAL __PRINTU_CONT - ld a, b - or a - jp nz, __PRINTU_CONT - ld a, '0' - jp __PRINT_DIGIT -__PRINTU_CONT: - pop af - push bc - call __PRINT_DIGIT - pop bc - djnz __PRINTU_CONT - ret - ENDP -__PRINT_MINUS: ; PRINT the MINUS (-) sign. CALLER must preserve registers - ld a, '-' - jp __PRINT_DIGIT - __PRINT_DIGIT EQU __PRINTCHAR ; PRINTS the char in A register, and puts its attrs - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/div8.asm" - ; -------------------------------- - push namespace core -__DIVU8: ; 8 bit unsigned integer division - ; Divides (Top of stack, High Byte) / A - pop hl ; -------------------------------- - ex (sp), hl ; CALLEE -__DIVU8_FAST: ; Does A / H - ld l, h - ld h, a ; At this point do H / L - ld b, 8 - xor a ; A = 0, Carry Flag = 0 -__DIV8LOOP: - sla h - rla - cp l - jr c, __DIV8NOSUB - sub l - inc h -__DIV8NOSUB: - djnz __DIV8LOOP - ld l, a ; save remainder - ld a, h ; - ret ; a = Quotient, - ; -------------------------------- -__DIVI8: ; 8 bit signed integer division Divides (Top of stack) / A - pop hl ; -------------------------------- - ex (sp), hl -__DIVI8_FAST: - ld e, a ; store operands for later - ld c, h - or a ; negative? - jp p, __DIV8A - neg ; Make it positive -__DIV8A: - ex af, af' - ld a, h - or a - jp p, __DIV8B - neg - ld h, a ; make it positive -__DIV8B: - ex af, af' - call __DIVU8_FAST - ld a, c - xor l ; bit 7 of A = 1 if result is negative - ld a, h ; Quotient - ret p ; return if positive - neg - ret -__MODU8: ; 8 bit module. REturns A mod (Top of stack) (unsigned operands) - pop hl - ex (sp), hl ; CALLEE -__MODU8_FAST: ; __FASTCALL__ entry - call __DIVU8_FAST - ld a, l ; Remainder - ret ; a = Modulus -__MODI8: ; 8 bit module. REturns A mod (Top of stack) (For singed operands) - pop hl - ex (sp), hl ; CALLEE -__MODI8_FAST: ; __FASTCALL__ entry - call __DIVI8_FAST - ld a, l ; remainder - ret ; a = Modulus - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" - push namespace core -__PRINTI8: ; Prints an 8 bits number in Accumulator (A) - ; Converts 8 to 32 bits - or a - jp p, __PRINTU8 - push af - call __PRINT_MINUS - pop af - neg -__PRINTU8: - PROC - LOCAL __PRINTU_LOOP - ld b, 0 ; Counter -__PRINTU_LOOP: - or a - jp z, __PRINTU_START - push bc - ld h, 10 - call __DIVU8_FAST ; Divides by 10. D'E'H'L' contains modulo (L' since < 10) - pop bc - ld a, l - or '0' ; Stores ASCII digit (must be print in reversed order) - push af - ld a, h - inc b - jp __PRINTU_LOOP ; Uses JP in loops - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" -#line 55 "arch/zx48k/opt1_dim_arr_local2.bas" +#line 50 "arch/zx48k/opt1_dim_arr_local2.bas" .LABEL.__LABEL0: DEFB 00h DEFB 00h diff --git a/tests/functional/arch/zx48k/opt1_dim_arr_local2.bas b/tests/functional/arch/zx48k/opt1_dim_arr_local2.bas index 24d38c88e..0b3602fc6 100644 --- a/tests/functional/arch/zx48k/opt1_dim_arr_local2.bas +++ b/tests/functional/arch/zx48k/opt1_dim_arr_local2.bas @@ -1,6 +1,6 @@ FUNCTION test as UByte DIM a(5) as UByte => {0, 1, 2, 3, 4, 5} - PRINT a(3) + POKE 0, a(3) END FUNCTION test diff --git a/tests/functional/arch/zx48k/opt2_fastcall_func.asm b/tests/functional/arch/zx48k/opt2_fastcall_func.asm index fc2887e30..50f23a634 100644 --- a/tests/functional/arch/zx48k/opt2_fastcall_func.asm +++ b/tests/functional/arch/zx48k/opt2_fastcall_func.asm @@ -10,7 +10,6 @@ add hl, sp ld (.core.__CALL_BACK__), hl ei - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -43,10 +42,8 @@ _test: push ix ld ix, 0 add ix, sp - call .core.COPY_ATTR ld a, (ix+5) - call .core.__PRINTU8 - call .core.PRINT_EOL + ld (0), a ld a, (ix+5) inc a _test__leave: @@ -84,1040 +81,4 @@ _c2: _c2__leave: ret ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" - ; Simple error control routines -; vim:ts=4:et: - push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop - ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a - ret - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 65 "arch/zx48k/opt2_fastcall_func.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printnum.asm" - push namespace core -__PRINTU_START: - PROC - LOCAL __PRINTU_CONT - ld a, b - or a - jp nz, __PRINTU_CONT - ld a, '0' - jp __PRINT_DIGIT -__PRINTU_CONT: - pop af - push bc - call __PRINT_DIGIT - pop bc - djnz __PRINTU_CONT - ret - ENDP -__PRINT_MINUS: ; PRINT the MINUS (-) sign. CALLER must preserve registers - ld a, '-' - jp __PRINT_DIGIT - __PRINT_DIGIT EQU __PRINTCHAR ; PRINTS the char in A register, and puts its attrs - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/div8.asm" - ; -------------------------------- - push namespace core -__DIVU8: ; 8 bit unsigned integer division - ; Divides (Top of stack, High Byte) / A - pop hl ; -------------------------------- - ex (sp), hl ; CALLEE -__DIVU8_FAST: ; Does A / H - ld l, h - ld h, a ; At this point do H / L - ld b, 8 - xor a ; A = 0, Carry Flag = 0 -__DIV8LOOP: - sla h - rla - cp l - jr c, __DIV8NOSUB - sub l - inc h -__DIV8NOSUB: - djnz __DIV8LOOP - ld l, a ; save remainder - ld a, h ; - ret ; a = Quotient, - ; -------------------------------- -__DIVI8: ; 8 bit signed integer division Divides (Top of stack) / A - pop hl ; -------------------------------- - ex (sp), hl -__DIVI8_FAST: - ld e, a ; store operands for later - ld c, h - or a ; negative? - jp p, __DIV8A - neg ; Make it positive -__DIV8A: - ex af, af' - ld a, h - or a - jp p, __DIV8B - neg - ld h, a ; make it positive -__DIV8B: - ex af, af' - call __DIVU8_FAST - ld a, c - xor l ; bit 7 of A = 1 if result is negative - ld a, h ; Quotient - ret p ; return if positive - neg - ret -__MODU8: ; 8 bit module. REturns A mod (Top of stack) (unsigned operands) - pop hl - ex (sp), hl ; CALLEE -__MODU8_FAST: ; __FASTCALL__ entry - call __DIVU8_FAST - ld a, l ; Remainder - ret ; a = Modulus -__MODI8: ; 8 bit module. REturns A mod (Top of stack) (For singed operands) - pop hl - ex (sp), hl ; CALLEE -__MODI8_FAST: ; __FASTCALL__ entry - call __DIVI8_FAST - ld a, l ; remainder - ret ; a = Modulus - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" - push namespace core -__PRINTI8: ; Prints an 8 bits number in Accumulator (A) - ; Converts 8 to 32 bits - or a - jp p, __PRINTU8 - push af - call __PRINT_MINUS - pop af - neg -__PRINTU8: - PROC - LOCAL __PRINTU_LOOP - ld b, 0 ; Counter -__PRINTU_LOOP: - or a - jp z, __PRINTU_START - push bc - ld h, 10 - call __DIVU8_FAST ; Divides by 10. D'E'H'L' contains modulo (L' since < 10) - pop bc - ld a, l - or '0' ; Stores ASCII digit (must be print in reversed order) - push af - ld a, h - inc b - jp __PRINTU_LOOP ; Uses JP in loops - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" -#line 67 "arch/zx48k/opt2_fastcall_func.bas" END diff --git a/tests/functional/arch/zx48k/opt2_fastcall_func.bas b/tests/functional/arch/zx48k/opt2_fastcall_func.bas index 0c5a20e42..9f43401d3 100644 --- a/tests/functional/arch/zx48k/opt2_fastcall_func.bas +++ b/tests/functional/arch/zx48k/opt2_fastcall_func.bas @@ -1,7 +1,7 @@ function test(a as UByte) as Ubyte DIM x as Uinteger = 1 - print(a) + POKE 0, a return a + 1 end function diff --git a/tests/functional/arch/zx48k/opt2_func_call.asm b/tests/functional/arch/zx48k/opt2_func_call.asm index 6d359152c..e2e7be064 100644 --- a/tests/functional/arch/zx48k/opt2_func_call.asm +++ b/tests/functional/arch/zx48k/opt2_func_call.asm @@ -10,7 +10,6 @@ add hl, sp ld (.core.__CALL_BACK__), hl ei - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -41,10 +40,8 @@ _test: push ix ld ix, 0 add ix, sp - call .core.COPY_ATTR ld a, (ix+5) - call .core.__PRINTU8 - call .core.PRINT_EOL + ld (0), a ld a, (ix+5) inc a _test__leave: @@ -62,1040 +59,4 @@ _c1: _c1__leave: ret ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" - ; Simple error control routines -; vim:ts=4:et: - push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop - ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a - ret - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 43 "arch/zx48k/opt2_func_call.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printnum.asm" - push namespace core -__PRINTU_START: - PROC - LOCAL __PRINTU_CONT - ld a, b - or a - jp nz, __PRINTU_CONT - ld a, '0' - jp __PRINT_DIGIT -__PRINTU_CONT: - pop af - push bc - call __PRINT_DIGIT - pop bc - djnz __PRINTU_CONT - ret - ENDP -__PRINT_MINUS: ; PRINT the MINUS (-) sign. CALLER must preserve registers - ld a, '-' - jp __PRINT_DIGIT - __PRINT_DIGIT EQU __PRINTCHAR ; PRINTS the char in A register, and puts its attrs - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/div8.asm" - ; -------------------------------- - push namespace core -__DIVU8: ; 8 bit unsigned integer division - ; Divides (Top of stack, High Byte) / A - pop hl ; -------------------------------- - ex (sp), hl ; CALLEE -__DIVU8_FAST: ; Does A / H - ld l, h - ld h, a ; At this point do H / L - ld b, 8 - xor a ; A = 0, Carry Flag = 0 -__DIV8LOOP: - sla h - rla - cp l - jr c, __DIV8NOSUB - sub l - inc h -__DIV8NOSUB: - djnz __DIV8LOOP - ld l, a ; save remainder - ld a, h ; - ret ; a = Quotient, - ; -------------------------------- -__DIVI8: ; 8 bit signed integer division Divides (Top of stack) / A - pop hl ; -------------------------------- - ex (sp), hl -__DIVI8_FAST: - ld e, a ; store operands for later - ld c, h - or a ; negative? - jp p, __DIV8A - neg ; Make it positive -__DIV8A: - ex af, af' - ld a, h - or a - jp p, __DIV8B - neg - ld h, a ; make it positive -__DIV8B: - ex af, af' - call __DIVU8_FAST - ld a, c - xor l ; bit 7 of A = 1 if result is negative - ld a, h ; Quotient - ret p ; return if positive - neg - ret -__MODU8: ; 8 bit module. REturns A mod (Top of stack) (unsigned operands) - pop hl - ex (sp), hl ; CALLEE -__MODU8_FAST: ; __FASTCALL__ entry - call __DIVU8_FAST - ld a, l ; Remainder - ret ; a = Modulus -__MODI8: ; 8 bit module. REturns A mod (Top of stack) (For singed operands) - pop hl - ex (sp), hl ; CALLEE -__MODI8_FAST: ; __FASTCALL__ entry - call __DIVI8_FAST - ld a, l ; remainder - ret ; a = Modulus - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" - push namespace core -__PRINTI8: ; Prints an 8 bits number in Accumulator (A) - ; Converts 8 to 32 bits - or a - jp p, __PRINTU8 - push af - call __PRINT_MINUS - pop af - neg -__PRINTU8: - PROC - LOCAL __PRINTU_LOOP - ld b, 0 ; Counter -__PRINTU_LOOP: - or a - jp z, __PRINTU_START - push bc - ld h, 10 - call __DIVU8_FAST ; Divides by 10. D'E'H'L' contains modulo (L' since < 10) - pop bc - ld a, l - or '0' ; Stores ASCII digit (must be print in reversed order) - push af - ld a, h - inc b - jp __PRINTU_LOOP ; Uses JP in loops - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" -#line 45 "arch/zx48k/opt2_func_call.bas" END diff --git a/tests/functional/arch/zx48k/opt2_func_call.bas b/tests/functional/arch/zx48k/opt2_func_call.bas index 134a75c8c..37da401f4 100644 --- a/tests/functional/arch/zx48k/opt2_func_call.bas +++ b/tests/functional/arch/zx48k/opt2_func_call.bas @@ -1,7 +1,7 @@ REM Should ignore c2 and c3, never used function test(a as UByte) as Ubyte DIM x as Uinteger = 1 - print(a) + poke 0, a return a + 1 end function diff --git a/tests/functional/arch/zx48k/opt3_data2.asm b/tests/functional/arch/zx48k/opt3_data2.asm index 52f681f72..1dff2e3a4 100644 --- a/tests/functional/arch/zx48k/opt3_data2.asm +++ b/tests/functional/arch/zx48k/opt3_data2.asm @@ -11,7 +11,6 @@ ld (.core.__CALL_BACK__), hl ei call .core.__MEM_INIT - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -63,7 +62,6 @@ _a.__DATA__: call .core.__ARRAY pop af ld (hl), a - call .core.COPY_ATTR ld a, (_i) ld l, a ld h, 0 @@ -71,8 +69,7 @@ _a.__DATA__: ld hl, _a call .core.__ARRAY ld a, (hl) - call .core.__PRINTU8 - call .core.PRINT_EOL + ld (0), a ld hl, _i inc (hl) .LABEL.__LABEL0: @@ -189,7 +186,7 @@ __MUL8B: ret ; result = HL ENDP pop namespace -#line 97 "arch/zx48k/opt3_data2.bas" +#line 95 "arch/zx48k/opt3_data2.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/array.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa @@ -346,43 +343,25 @@ __FNMUL2: ret ENDP pop namespace -#line 98 "arch/zx48k/opt3_data2.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: +#line 96 "arch/zx48k/opt3_data2.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" + ;; This implements READ & RESTORE functions + ;; Reads a new element from the DATA Address code + ;; Updates the DATA_ADDR read ptr for the next read + ;; Data codification is 1 byte for type followed by data bytes + ;; Byte type is encoded as follows +;; 00: End of data +;; 01: String +;; 02: Byte +;; 03: Ubyte +;; 04: Integer +;; 05: UInteger +;; 06: Long +;; 07: ULong +;; 08: Fixed +;; 09: Float + ;; bit7 is set for a parameter-less function + ;; In that case, the next two bytes are the ptr of the function to jump #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" ; Simple error control routines ; vim:ts=4:et: @@ -417,990 +396,7 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 99 "arch/zx48k/opt3_data2.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printnum.asm" - push namespace core -__PRINTU_START: - PROC - LOCAL __PRINTU_CONT - ld a, b - or a - jp nz, __PRINTU_CONT - ld a, '0' - jp __PRINT_DIGIT -__PRINTU_CONT: - pop af - push bc - call __PRINT_DIGIT - pop bc - djnz __PRINTU_CONT - ret - ENDP -__PRINT_MINUS: ; PRINT the MINUS (-) sign. CALLER must preserve registers - ld a, '-' - jp __PRINT_DIGIT - __PRINT_DIGIT EQU __PRINTCHAR ; PRINTS the char in A register, and puts its attrs - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div8.asm" - ; -------------------------------- - push namespace core -__DIVU8: ; 8 bit unsigned integer division - ; Divides (Top of stack, High Byte) / A - pop hl ; -------------------------------- - ex (sp), hl ; CALLEE -__DIVU8_FAST: ; Does A / H - ld l, h - ld h, a ; At this point do H / L - ld b, 8 - xor a ; A = 0, Carry Flag = 0 -__DIV8LOOP: - sla h - rla - cp l - jr c, __DIV8NOSUB - sub l - inc h -__DIV8NOSUB: - djnz __DIV8LOOP - ld l, a ; save remainder - ld a, h ; - ret ; a = Quotient, - ; -------------------------------- -__DIVI8: ; 8 bit signed integer division Divides (Top of stack) / A - pop hl ; -------------------------------- - ex (sp), hl -__DIVI8_FAST: - ld e, a ; store operands for later - ld c, h - or a ; negative? - jp p, __DIV8A - neg ; Make it positive -__DIV8A: - ex af, af' - ld a, h - or a - jp p, __DIV8B - neg - ld h, a ; make it positive -__DIV8B: - ex af, af' - call __DIVU8_FAST - ld a, c - xor l ; bit 7 of A = 1 if result is negative - ld a, h ; Quotient - ret p ; return if positive - neg - ret -__MODU8: ; 8 bit module. REturns A mod (Top of stack) (unsigned operands) - pop hl - ex (sp), hl ; CALLEE -__MODU8_FAST: ; __FASTCALL__ entry - call __DIVU8_FAST - ld a, l ; Remainder - ret ; a = Modulus -__MODI8: ; 8 bit module. REturns A mod (Top of stack) (For singed operands) - pop hl - ex (sp), hl ; CALLEE -__MODI8_FAST: ; __FASTCALL__ entry - call __DIVI8_FAST - ld a, l ; remainder - ret ; a = Modulus - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" - push namespace core -__PRINTI8: ; Prints an 8 bits number in Accumulator (A) - ; Converts 8 to 32 bits - or a - jp p, __PRINTU8 - push af - call __PRINT_MINUS - pop af - neg -__PRINTU8: - PROC - LOCAL __PRINTU_LOOP - ld b, 0 ; Counter -__PRINTU_LOOP: - or a - jp z, __PRINTU_START - push bc - ld h, 10 - call __DIVU8_FAST ; Divides by 10. D'E'H'L' contains modulo (L' since < 10) - pop bc - ld a, l - or '0' ; Stores ASCII digit (must be print in reversed order) - push af - ld a, h - inc b - jp __PRINTU_LOOP ; Uses JP in loops - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" -#line 101 "arch/zx48k/opt3_data2.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" - ;; This implements READ & RESTORE functions - ;; Reads a new element from the DATA Address code - ;; Updates the DATA_ADDR read ptr for the next read - ;; Data codification is 1 byte for type followed by data bytes - ;; Byte type is encoded as follows -;; 00: End of data -;; 01: String -;; 02: Byte -;; 03: Ubyte -;; 04: Integer -;; 05: UInteger -;; 06: Long -;; 07: ULong -;; 08: Fixed -;; 09: Float - ;; bit7 is set for a parameter-less function - ;; In that case, the next two bytes are the ptr of the function to jump +#line 23 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; vim: ts=4:et:sw=4: @@ -2317,6 +1313,13 @@ _from_u16: jp _from_i32 dynamic_cast4: ;; The user type is "shorter" than the read one + ld a, b ;; read type + cp 4 ;; if user type < read type < _i16 => From Ubyte to Byte. Return af' + jr nc, 1f + ex af, af' + ret +1: + ld a, c ;; recover user required type cp 8 ;; required type jr c, before_to_int ;; required < fixed (f16) ex af, af' @@ -2437,5 +1440,5 @@ __DATA_ADDR: ;; Stores current DATA ptr dw .DATA.__DATA__0 ENDP pop namespace -#line 102 "arch/zx48k/opt3_data2.bas" +#line 97 "arch/zx48k/opt3_data2.bas" END diff --git a/tests/functional/arch/zx48k/opt3_data2.bas b/tests/functional/arch/zx48k/opt3_data2.bas index 0a2a90670..88d5d1697 100644 --- a/tests/functional/arch/zx48k/opt3_data2.bas +++ b/tests/functional/arch/zx48k/opt3_data2.bas @@ -2,7 +2,7 @@ DIM a(9) AS UBYTE FOR i = 0 TO 9: REM 0 TO 9 => 10 elements READ a(i) - PRINT a(i) + POKE 0, a(i) NEXT i REM notice the a * a expression diff --git a/tests/functional/arch/zx48k/opt3_einar.asm b/tests/functional/arch/zx48k/opt3_einar.asm index 2d04a02cf..59d7da62e 100644 --- a/tests/functional/arch/zx48k/opt3_einar.asm +++ b/tests/functional/arch/zx48k/opt3_einar.asm @@ -10,16 +10,10 @@ add hl, sp ld (.core.__CALL_BACK__), hl ei - call .core.__MEM_INIT - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 .core.ZXBASIC_USER_DATA: - ; Defines HEAP SIZE -.core.ZXBASIC_HEAP_SIZE EQU 4768 -.core.ZXBASIC_MEM_HEAP: - DEFS 4768 ; Defines USER DATA Length in bytes .core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA .core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN @@ -51,1255 +45,15 @@ _x2: sub (ix-1) ccf jp nc, .LABEL.__LABEL0 - call .core.COPY_ATTR - ld hl, .LABEL.__LABEL2 - xor a - call .core.__PRINTSTR - call .core.PRINT_EOL + ld a, (ix-1) + ld (0), a jp _x2__leave .LABEL.__LABEL0: - call .core.COPY_ATTR - ld hl, .LABEL.__LABEL3 - xor a - call .core.__PRINTSTR - call .core.PRINT_EOL + ld a, (ix-1) + ld (1), a _x2__leave: ld sp, ix pop ix ret -.LABEL.__LABEL2: - DEFW 0003h - DEFB 4Fh - DEFB 70h - DEFB 73h -.LABEL.__LABEL3: - DEFW 0002h - DEFB 4Fh - DEFB 4Bh ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" - ; Simple error control routines -; vim:ts=4:et: - push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop - ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a - ret - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 53 "arch/zx48k/opt3_einar.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 5 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL - push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later - ld a, h - or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) - ld a, (hl) - call __PRINTCHAR - inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP - pop namespace -#line 55 "arch/zx48k/opt3_einar.bas" END diff --git a/tests/functional/arch/zx48k/opt3_einar.bas b/tests/functional/arch/zx48k/opt3_einar.bas index 270b4886b..3ba9879fa 100644 --- a/tests/functional/arch/zx48k/opt3_einar.bas +++ b/tests/functional/arch/zx48k/opt3_einar.bas @@ -3,9 +3,9 @@ sub x2() LET a = 129 IF (a <= 32) THEN - PRINT "Ops" + POKE 0, a ELSE - PRINT "OK" + POKE 1, a END IF end sub diff --git a/tests/functional/arch/zx48k/optconst.asm b/tests/functional/arch/zx48k/optconst.asm index 1a72540b1..a85fb7a31 100644 --- a/tests/functional/arch/zx48k/optconst.asm +++ b/tests/functional/arch/zx48k/optconst.asm @@ -10,7 +10,6 @@ add hl, sp ld (.core.__CALL_BACK__), hl ei - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -55,11 +54,10 @@ _a: pop ix ei ret - call .core.COPY_ATTR ld hl, (_a) ld de, (_a + 2) - call .core.__PRINTU32 - call .core.PRINT_EOL + ld a, l + ld (0), a .LABEL._label1: .LABEL._label2: ld hl, 0 @@ -67,1119 +65,4 @@ _a: ld c, l jp .core.__END_PROGRAM ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" - ; Simple error control routines -; vim:ts=4:et: - push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop - ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a - ret - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 46 "arch/zx48k/optconst.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printu32.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi32.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printnum.asm" - push namespace core -__PRINTU_START: - PROC - LOCAL __PRINTU_CONT - ld a, b - or a - jp nz, __PRINTU_CONT - ld a, '0' - jp __PRINT_DIGIT -__PRINTU_CONT: - pop af - push bc - call __PRINT_DIGIT - pop bc - djnz __PRINTU_CONT - ret - ENDP -__PRINT_MINUS: ; PRINT the MINUS (-) sign. CALLER must preserve registers - ld a, '-' - jp __PRINT_DIGIT - __PRINT_DIGIT EQU __PRINTCHAR ; PRINTS the char in A register, and puts its attrs - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printi32.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg32.asm" - push namespace core -__ABS32: - bit 7, d - ret z -__NEG32: ; Negates DEHL (Two's complement) - ld a, l - cpl - ld l, a - ld a, h - cpl - ld h, a - ld a, e - cpl - ld e, a - ld a, d - cpl - ld d, a - inc l - ret nz - inc h - ret nz - inc de - ret - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/printi32.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/div32.asm" - ; --------------------------------------------------------- - push namespace core -__DIVU32: ; 32 bit unsigned division - ; DEHL = Dividend, Stack Top = Divisor - ; OPERANDS P = Dividend, Q = Divisor => OPERATION => P / Q - ; - ; Changes A, BC DE HL B'C' D'E' H'L' - ; --------------------------------------------------------- - exx - pop hl ; return address - pop de ; low part - ex (sp), hl ; CALLEE Convention ; H'L'D'E' => Dividend -__DIVU32START: ; Performs D'E'H'L' / HLDE - ; Now switch to DIVIDEND = B'C'BC / DIVISOR = D'E'DE (A / B) - push de ; push Lowpart(Q) - ex de, hl ; DE = HL - ld hl, 0 - exx - ld b, h - ld c, l - pop hl - push de - ex de, hl - ld hl, 0 ; H'L'HL = 0 - exx - pop bc ; Pop HightPart(B) => B = B'C'BC - exx - ld a, 32 ; Loop count -__DIV32LOOP: - sll c ; B'C'BC << 1 ; Output most left bit to carry - rl b - exx - rl c - rl b - exx - adc hl, hl - exx - adc hl, hl - exx - sbc hl,de - exx - sbc hl,de - exx - jp nc, __DIV32NOADD ; use JP inside a loop for being faster - add hl, de - exx - adc hl, de - exx - dec bc -__DIV32NOADD: - dec a - jp nz, __DIV32LOOP ; use JP inside a loop for being faster - ; At this point, quotient is stored in B'C'BC and the reminder in H'L'HL - push hl - exx - pop de - ex de, hl ; D'E'H'L' = 32 bits modulus - push bc - exx - pop de ; DE = B'C' - ld h, b - ld l, c ; DEHL = quotient D'E'H'L' = Modulus - ret ; DEHL = quotient, D'E'H'L' = Modulus -__MODU32: ; 32 bit modulus for 32bit unsigned division - ; DEHL = Dividend, Stack Top = Divisor (DE, HL) - exx - pop hl ; return address - pop de ; low part - ex (sp), hl ; CALLEE Convention ; H'L'D'E' => Dividend - call __DIVU32START ; At return, modulus is at D'E'H'L' -__MODU32START: - exx - push de - push hl - exx - pop hl - pop de - ret -__DIVI32: ; 32 bit signed division - ; DEHL = Dividend, Stack Top = Divisor - ; A = Dividend, B = Divisor => A / B - exx - pop hl ; return address - pop de ; low part - ex (sp), hl ; CALLEE Convention ; H'L'D'E' => Dividend -__DIVI32START: - exx - ld a, d ; Save sign - ex af, af' - bit 7, d ; Negative? - call nz, __NEG32 ; Negates DEHL - exx ; Now works with H'L'D'E' - ex af, af' - xor h - ex af, af' ; Stores sign of the result for later - bit 7, h ; Negative? - ex de, hl ; HLDE = DEHL - call nz, __NEG32 - ex de, hl - call __DIVU32START - ex af, af' ; Recovers sign - and 128 ; positive? - ret z - jp __NEG32 ; Negates DEHL and returns from there -__MODI32: ; 32bits signed division modulus - exx - pop hl ; return address - pop de ; low part - ex (sp), hl ; CALLEE Convention ; H'L'D'E' => Dividend - call __DIVI32START - jp __MODU32START - pop namespace -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/printi32.asm" - push namespace core -__PRINTI32: - ld a, d - or a - jp p, __PRINTU32 - call __PRINT_MINUS - call __NEG32 -__PRINTU32: - PROC - LOCAL __PRINTU_LOOP - ld b, 0 ; Counter -__PRINTU_LOOP: - ld a, h - or l - or d - or e - jp z, __PRINTU_START - push bc - ld bc, 0 - push bc - ld bc, 10 - push bc ; Push 00 0A (10 Dec) into the stack = divisor - call __DIVU32 ; Divides by 32. D'E'H'L' contains modulo (L' since < 10) - pop bc - exx - ld a, l - or '0' ; Stores ASCII digit (must be print in reversed order) - push af - exx - inc b - jp __PRINTU_LOOP ; Uses JP in loops - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printu32.asm" -#line 48 "arch/zx48k/optconst.bas" END diff --git a/tests/functional/arch/zx48k/optconst.bas b/tests/functional/arch/zx48k/optconst.bas index cc31203eb..b0c85c189 100644 --- a/tests/functional/arch/zx48k/optconst.bas +++ b/tests/functional/arch/zx48k/optconst.bas @@ -11,7 +11,7 @@ DIM a as ULONG a = @label1 + @label2 END -PRINT a +POKE 0, a label1: label2: diff --git a/tests/functional/arch/zx48k/or16.asm b/tests/functional/arch/zx48k/or16.asm index 8745f81b0..87d920547 100644 --- a/tests/functional/arch/zx48k/or16.asm +++ b/tests/functional/arch/zx48k/or16.asm @@ -27,16 +27,28 @@ _b: ld hl, (_a) ld a, h or l + sub 1 + sbc a, a + inc a ld (_b), a ld hl, (_a) ld a, 0FFh + sub 1 + sbc a, a + inc a ld (_b), a ld hl, (_a) ld a, h or l + sub 1 + sbc a, a + inc a ld (_b), a ld hl, (_a) ld a, 0FFh + sub 1 + sbc a, a + inc a ld (_b), a ld de, (_a) ld hl, (_a) @@ -44,6 +56,9 @@ _b: or l or d or e + sub 1 + sbc a, a + inc a ld (_b), a ld hl, 0 ld b, h diff --git a/tests/functional/arch/zx48k/or32.asm b/tests/functional/arch/zx48k/or32.asm index ab8527a96..e80338794 100644 --- a/tests/functional/arch/zx48k/or32.asm +++ b/tests/functional/arch/zx48k/or32.asm @@ -31,6 +31,9 @@ _b: ld de, 0 ld hl, 0 call .core.__OR32 + sub 1 + sbc a, a + inc a ld (_b), a ld hl, (_a + 2) push hl @@ -39,6 +42,9 @@ _b: ld de, 0 ld hl, 1 call .core.__OR32 + sub 1 + sbc a, a + inc a ld (_b), a ld hl, (_a) ld de, (_a + 2) @@ -47,6 +53,9 @@ _b: ld bc, 0 push bc call .core.__OR32 + sub 1 + sbc a, a + inc a ld (_b), a ld hl, (_a) ld de, (_a + 2) @@ -55,6 +64,9 @@ _b: ld bc, 1 push bc call .core.__OR32 + sub 1 + sbc a, a + inc a ld (_b), a ld hl, (_a + 2) push hl @@ -63,6 +75,9 @@ _b: ld hl, (_a) ld de, (_a + 2) call .core.__OR32 + sub 1 + sbc a, a + inc a ld (_b), a ld hl, 0 ld b, h @@ -79,7 +94,7 @@ _b: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/or32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bool/or32.asm" push namespace core __OR32: ; Performs logical operation A AND B ; between DEHL and TOP of the stack. @@ -95,8 +110,8 @@ __OR32: ; Performs logical operation A AND B or e or h or l -#line 26 "/zxbasic/src/arch/zx48k/library-asm/or32.asm" +#line 26 "/zxbasic/src/lib/arch/zx48k/runtime/bool/or32.asm" ret pop namespace -#line 57 "or32.bas" +#line 72 "arch/zx48k/or32.bas" END diff --git a/tests/functional/arch/zx48k/or8.asm b/tests/functional/arch/zx48k/or8.asm index 666849d5a..e7c92e3da 100644 --- a/tests/functional/arch/zx48k/or8.asm +++ b/tests/functional/arch/zx48k/or8.asm @@ -25,18 +25,33 @@ _b: .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: ld a, (_a) + sub 1 + sbc a, a + inc a ld (_b), a ld a, (_a) ld a, 1 + sub 1 + sbc a, a + inc a ld (_b), a ld a, (_a) + sub 1 + sbc a, a + inc a ld (_b), a ld a, (_a) ld a, 1 + sub 1 + sbc a, a + inc a ld (_b), a ld hl, (_a - 1) ld a, (_a) or h + sub 1 + sbc a, a + inc a ld (_b), a ld hl, 0 ld b, h diff --git a/tests/functional/arch/zx48k/parambyref1.asm b/tests/functional/arch/zx48k/parambyref1.asm index bdb467a2e..f449705ea 100644 --- a/tests/functional/arch/zx48k/parambyref1.asm +++ b/tests/functional/arch/zx48k/parambyref1.asm @@ -10,7 +10,6 @@ add hl, sp ld (.core.__CALL_BACK__), hl ei - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 @@ -19,6 +18,8 @@ .core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA .core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA +_dummy: + DEFB 00, 00 .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: ld hl, 1234 @@ -42,15 +43,13 @@ _test2: push ix ld ix, 0 add ix, sp - call .core.COPY_ATTR ld h, (ix+5) ld l, (ix+4) ld c, (hl) inc hl ld h, (hl) ld l, c - call .core.__PRINTU16 - call .core.PRINT_EOL + ld (_dummy), hl _test2__leave: ld sp, ix pop ix @@ -78,1066 +77,4 @@ _test__leave: exx ret ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" - ; Simple error control routines -; vim:ts=4:et: - push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop - ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a - ret - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 59 "arch/zx48k/parambyref1.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printu16.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi16.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printnum.asm" - push namespace core -__PRINTU_START: - PROC - LOCAL __PRINTU_CONT - ld a, b - or a - jp nz, __PRINTU_CONT - ld a, '0' - jp __PRINT_DIGIT -__PRINTU_CONT: - pop af - push bc - call __PRINT_DIGIT - pop bc - djnz __PRINTU_CONT - ret - ENDP -__PRINT_MINUS: ; PRINT the MINUS (-) sign. CALLER must preserve registers - ld a, '-' - jp __PRINT_DIGIT - __PRINT_DIGIT EQU __PRINTCHAR ; PRINTS the char in A register, and puts its attrs - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printi16.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/div16.asm" - ; 16 bit division and modulo functions - ; for both signed and unsigned values -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg16.asm" - ; Negates HL value (16 bit) - push namespace core -__ABS16: - bit 7, h - ret z -__NEGHL: - ld a, l ; HL = -HL - cpl - ld l, a - ld a, h - cpl - ld h, a - inc hl - ret - pop namespace -#line 5 "/zxbasic/src/lib/arch/zx48k/runtime/div16.asm" - push namespace core -__DIVU16: ; 16 bit unsigned division - ; HL = Dividend, Stack Top = Divisor - ; -- OBSOLETE ; Now uses FASTCALL convention - ; ex de, hl - ; pop hl ; Return address - ; ex (sp), hl ; CALLEE Convention -__DIVU16_FAST: - ld a, h - ld c, l - ld hl, 0 - ld b, 16 -__DIV16LOOP: - sll c - rla - adc hl,hl - sbc hl,de - jr nc, __DIV16NOADD - add hl,de - dec c -__DIV16NOADD: - djnz __DIV16LOOP - ex de, hl - ld h, a - ld l, c - ret ; HL = quotient, DE = Mudulus -__MODU16: ; 16 bit modulus - ; HL = Dividend, Stack Top = Divisor - ;ex de, hl - ;pop hl - ;ex (sp), hl ; CALLEE Convention - call __DIVU16_FAST - ex de, hl ; hl = reminder (modulus) - ; de = quotient - ret -__DIVI16: ; 16 bit signed division - ; --- The following is OBSOLETE --- - ; ex de, hl - ; pop hl - ; ex (sp), hl ; CALLEE Convention -__DIVI16_FAST: - ld a, d - xor h - ex af, af' ; BIT 7 of a contains result - bit 7, d ; DE is negative? - jr z, __DIVI16A - ld a, e ; DE = -DE - cpl - ld e, a - ld a, d - cpl - ld d, a - inc de -__DIVI16A: - bit 7, h ; HL is negative? - call nz, __NEGHL -__DIVI16B: - call __DIVU16_FAST - ex af, af' - or a - ret p ; return if positive - jp __NEGHL -__MODI16: ; 16 bit modulus - ; HL = Dividend, Stack Top = Divisor - ;ex de, hl - ;pop hl - ;ex (sp), hl ; CALLEE Convention - call __DIVI16_FAST - ex de, hl ; hl = reminder (modulus) - ; de = quotient - ret - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/printi16.asm" - push namespace core -__PRINTI16: ; Prints a 16bits signed in HL - ; Converts 16 to 32 bits - PROC - LOCAL __PRINTU_LOOP - ld a, h - or a - jp p, __PRINTU16 - call __PRINT_MINUS - call __NEGHL -__PRINTU16: - ld b, 0 -__PRINTU_LOOP: - ld a, h - or l - jp z, __PRINTU_START - push bc - ld de, 10 - call __DIVU16_FAST ; Divides by DE. DE = MODULUS at exit. Since < 256, E = Modulus - pop bc - ld a, e - or '0' ; Stores ASCII digit (must be print in reversed order) - push af - inc b - jp __PRINTU_LOOP ; Uses JP in loops - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printu16.asm" -#line 61 "arch/zx48k/parambyref1.bas" END diff --git a/tests/functional/arch/zx48k/parambyref1.bas b/tests/functional/arch/zx48k/parambyref1.bas index c7e7cde29..4eb3ed8a4 100644 --- a/tests/functional/arch/zx48k/parambyref1.bas +++ b/tests/functional/arch/zx48k/parambyref1.bas @@ -1,6 +1,7 @@ +DIM dummy as Uinteger sub test2(ByRef x as Uinteger) - print x + let dummy = x end sub sub test(ByVal x as Uinteger) diff --git a/tests/functional/arch/zx48k/read.asm b/tests/functional/arch/zx48k/read.asm index febf55304..3fcb17dce 100644 --- a/tests/functional/arch/zx48k/read.asm +++ b/tests/functional/arch/zx48k/read.asm @@ -73,8 +73,8 @@ __DATA__END: DEFB 61h DEFB 6Eh ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa ; (a.k.a. Boriel) @@ -134,7 +134,7 @@ __DATA__END: ; HL = BLOCK Start & DE = Length. ; An init directive is useful for initialization routines. ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" ; Simple error control routines ; vim:ts=4:et: push namespace core @@ -168,8 +168,8 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 69 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +#line 69 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/heapinit.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa ; (a.k.a. Boriel) @@ -276,7 +276,7 @@ __MEM_INIT2: ret ENDP pop namespace -#line 70 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 70 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; --------------------------------------------------------------------- ; MEM_ALLOC ; Allocates a block of memory in the heap. @@ -307,9 +307,9 @@ __MEM_START: __MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE ld a, h ; HL = NULL (No memory available?) or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 113 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 115 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; HL = Pointer to Free block ld e, (hl) inc hl @@ -374,7 +374,7 @@ __MEM_SUBTRACT: ret ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" ; Loads a string (ptr) from HL ; and duplicates it on dynamic memory again ; Finally, it returns result pointer in HL @@ -411,8 +411,8 @@ __LOADSTR: ; __FASTCALL__ entry pop hl ; Recovers destiny in hl as result ret pop namespace -#line 48 "read.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" +#line 48 "arch/zx48k/read.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" ;; This implements READ & RESTORE functions ;; Reads a new element from the DATA Address code ;; Updates the DATA_ADDR read ptr for the next read @@ -430,7 +430,7 @@ __LOADSTR: ; __FASTCALL__ entry ;; 09: Float ;; bit7 is set for a parameter-less function ;; In that case, the next two bytes are the ptr of the function to jump -#line 1 "/zxbasic/src/arch/zx48k/library-asm/iload32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/iload32.asm" ; __FASTCALL__ routine which ; loads a 32 bits integer into DE,HL ; stored at position pointed by POINTER HL @@ -448,8 +448,8 @@ __ILOAD32: ex de, hl ret pop namespace -#line 25 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/iloadf.asm" +#line 25 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/iloadf.asm" ; __FASTCALL__ routine which ; loads a 40 bits floating point into A ED CB ; stored at position pointed by POINTER HL @@ -476,10 +476,10 @@ __LOADF: ; Loads a 40 bits FP number from address pointed by HL ld b, (hl) ret pop namespace -#line 26 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ftof16reg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/neg32.asm" +#line 26 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftof16reg.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg32.asm" push namespace core __ABS32: bit 7, d @@ -504,7 +504,7 @@ __NEG32: ; Negates DEHL (Two's complement) inc de ret pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm" push namespace core __FTOU32REG: ; Converts a Float to (un)signed 32 bit integer (NOTE: It's ALWAYS 32 bit signed) ; Input FP number in A EDCB (A exponent, EDCB mantissa) @@ -576,7 +576,7 @@ __FTOU8: ; Converts float in C ED LH to Unsigned byte in A ld a, l ret pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/ftof16reg.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/ftof16reg.asm" push namespace core __FTOF16REG: ; Converts a Float to 16.16 (32 bit) fixed point decimal ; Input FP number in A EDCB (A exponent, EDCB mantissa) @@ -607,9 +607,9 @@ __FTOF16REG: ; Converts a Float to 16.16 (32 bit) fixed point decimal ld b, a ; Loop counter = exponent - 128 + 16 (we need to shift 16 bit more) jp __FTOU32REG_LOOP ; proceed as an u32 integer pop namespace -#line 27 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/f16tofreg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/u32tofreg.asm" +#line 27 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/f16tofreg.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/u32tofreg.asm" push namespace core __I8TOFREG: ld l, a @@ -679,7 +679,7 @@ __U32TOFREG_END: ret ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/f16tofreg.asm" +#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/f16tofreg.asm" push namespace core __F16TOFREG: ; Converts a 16.16 signed fixed point (stored in DEHL) ; to a Floating Point Number returned in (C ED CB) @@ -714,8 +714,8 @@ __F16TOFREG2: ; Converts an unsigned 32 bit integer (DEHL) jp __U32TOFREG_LOOP ; Proceed as an integer ENDP pop namespace -#line 28 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +#line 28 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa ; (a.k.a. Boriel) @@ -873,16 +873,16 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ret ENDP pop namespace -#line 29 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 31 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 32 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 33 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 34 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 35 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 36 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 37 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 38 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 39 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" +#line 29 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 31 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 32 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 33 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 34 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 35 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 36 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 37 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 38 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 39 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" ;; Updates restore point to the given HL mem. address push namespace core __RESTORE: @@ -1042,6 +1042,13 @@ _from_u16: jp _from_i32 dynamic_cast4: ;; The user type is "shorter" than the read one + ld a, b ;; read type + cp 4 ;; if user type < read type < _i16 => From Ubyte to Byte. Return af' + jr nc, 1f + ex af, af' + ret +1: + ld a, c ;; recover user required type cp 8 ;; required type jr c, before_to_int ;; required < fixed (f16) ex af, af' @@ -1162,8 +1169,8 @@ __DATA_ADDR: ;; Stores current DATA ptr dw .DATA.__DATA__0 ENDP pop namespace -#line 49 "read.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/storef.asm" +#line 49 "arch/zx48k/read.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/storef.asm" push namespace core __PISTOREF: ; Indect Stores a float (A, E, D, C, B) at location stored in memory, pointed by (IX + HL) push de @@ -1191,5 +1198,5 @@ __STOREF: ; Stores the given FP number in A EDCB at address HL ld (hl), b ret pop namespace -#line 50 "read.bas" +#line 50 "arch/zx48k/read.bas" END diff --git a/tests/functional/arch/zx48k/read10.asm b/tests/functional/arch/zx48k/read10.asm deleted file mode 100644 index 90c28a250..000000000 --- a/tests/functional/arch/zx48k/read10.asm +++ /dev/null @@ -1,2357 +0,0 @@ - org 32768 -.core.__START_PROGRAM: - di - push ix - push iy - exx - push hl - exx - ld hl, 0 - add hl, sp - ld (.core.__CALL_BACK__), hl - ei - call .core.__MEM_INIT - call .core.__PRINT_INIT - jp .core.__MAIN_PROGRAM__ -.core.__CALL_BACK__: - DEFW 0 -.core.ZXBASIC_USER_DATA: - ; Defines HEAP SIZE -.core.ZXBASIC_HEAP_SIZE EQU 4768 -.core.ZXBASIC_MEM_HEAP: - DEFS 4768 - ; Defines USER DATA Length in bytes -.core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA - .core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN - .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA -_v: - DEFB 81h - DEFB 40h - DEFB 00h - DEFB 00h - DEFB 00h -.core.ZXBASIC_USER_DATA_END: -.core.__MAIN_PROGRAM__: - ld hl, .DATA.__DATA__0 - call .core.__RESTORE - call _p - ld hl, 0 - ld b, h - ld c, l -.core.__END_PROGRAM: - di - ld hl, (.core.__CALL_BACK__) - ld sp, hl - exx - pop hl - exx - pop iy - pop ix - ei - ret -_p: - push ix - ld ix, 0 - add ix, sp - ld hl, 0 - push hl - push hl - push hl - ld (ix-1), 0 - jp .LABEL.__LABEL0 -.LABEL.__LABEL3: - ld a, 9 - call .core.__READ - ld hl, -6 - call .core.__PSTOREF - call .core.COPY_ATTR - push ix - pop hl - ld de, -6 - add hl, de - call .core.__PLOADF - call .core.__PRINTF - call .core.PRINT_EOL -.LABEL.__LABEL4: - inc (ix-1) -.LABEL.__LABEL0: - ld a, (ix-1) - push af - ld a, 3 - pop hl - cp h - jp nc, .LABEL.__LABEL3 -.LABEL.__LABEL2: -_p__leave: - ld sp, ix - pop ix - ret -___DATA__FUNCPTR__0: - ld a, (_v) - ld de, (_v + 1) - ld bc, (_v + 3) - ld hl, 00000h - push hl - ld hl, 00048h - push hl - ld h, 085h - push hl - call .core.__MULF -___DATA__FUNCPTR__0__leave: - ret -___DATA__FUNCPTR__1: - ld a, (_v) - ld de, (_v + 1) - ld bc, (_v + 3) - call .core.SIN - push bc - push de - push af - ld a, (_v) - ld de, (_v + 1) - ld bc, (_v + 3) - call .core.TAN - push bc - push de - push af - ld a, 082h - ld de, 00000h - ld bc, 00000h - call .core.__POW - call .core.__MULF -___DATA__FUNCPTR__1__leave: - ret -___DATA__FUNCPTR__2: - ld a, (_v) - ld de, (_v + 1) - ld bc, (_v + 3) - ld hl, 0A2DAh - push hl - ld hl, 00F49h - push hl - ld h, 082h - push hl - call .core.__MULF -___DATA__FUNCPTR__2__leave: - ret -.DATA.__DATA__0: - DEFB 3 - DEFB 10 - DEFB 89h - DEFW ___DATA__FUNCPTR__0 - DEFB 89h - DEFW ___DATA__FUNCPTR__1 - DEFB 89h - DEFW ___DATA__FUNCPTR__2 -__DATA__END: - DEFB 00h - ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mulf.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/stackf.asm" - ; ------------------------------------------------------------- - ; Functions to manage FP-Stack of the ZX Spectrum ROM CALC - ; ------------------------------------------------------------- - push namespace core - __FPSTACK_PUSH EQU 2AB6h ; Stores an FP number into the ROM FP stack (A, ED CB) - __FPSTACK_POP EQU 2BF1h ; Pops an FP number out of the ROM FP stack (A, ED CB) -__FPSTACK_PUSH2: ; Pushes Current A ED CB registers and top of the stack on (SP + 4) - ; Second argument to push into the stack calculator is popped out of the stack - ; Since the caller routine also receives the parameters into the top of the stack - ; four bytes must be removed from SP before pop them out - call __FPSTACK_PUSH ; Pushes A ED CB into the FP-STACK - exx - pop hl ; Caller-Caller return addr - exx - pop hl ; Caller return addr - pop af - pop de - pop bc - push hl ; Caller return addr - exx - push hl ; Caller-Caller return addr - exx - jp __FPSTACK_PUSH -__FPSTACK_I16: ; Pushes 16 bits integer in HL into the FP ROM STACK - ; This format is specified in the ZX 48K Manual - ; You can push a 16 bit signed integer as - ; 0 SS LL HH 0, being SS the sign and LL HH the low - ; and High byte respectively - ld a, h - rla ; sign to Carry - sbc a, a ; 0 if positive, FF if negative - ld e, a - ld d, l - ld c, h - xor a - ld b, a - jp __FPSTACK_PUSH - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mulf.asm" - ; ------------------------------------------------------------- - ; Floating point library using the FP ROM Calculator (ZX 48K) - ; All of them uses A EDCB registers as 1st paramter. - ; For binary operators, the 2n operator must be pushed into the - ; stack, in the order A DE BC. - ; - ; Uses CALLEE convention - ; ------------------------------------------------------------- - push namespace core -__MULF: ; Multiplication - call __FPSTACK_PUSH2 - ; ------------- ROM MUL - rst 28h - defb 04h ; - defb 38h; ; END CALC - jp __FPSTACK_POP - pop namespace -#line 116 "arch/zx48k/read10.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" - ; Simple error control routines -; vim:ts=4:et: - push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop - ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a - ret - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 117 "arch/zx48k/read10.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/math/pow.asm" - ; ------------------------------------------------------------- - ; Floating point library using the FP ROM Calculator (ZX 48K) - ; All of them uses A EDCB registers as 1st paramter. - ; For binary operators, the 2n operator must be pushed into the - ; stack, in the order A DE BC. - ; - ; Uses CALLEE convention - ; -; Operands comes swapped: - ; 1 st parameter is the BASE (A ED CB) - ; 2 nd parameter (Top of the stack) is Exponent - ; ------------------------------------------------------------- - push namespace core -__POW: ; Exponentiation - PROC - call __FPSTACK_PUSH2 - ; ------------- ROM POW - rst 28h - defb 01h ; Exchange => 1, Base - defb 06h ; POW - defb 38h; ; END CALC - jp __FPSTACK_POP - ENDP - pop namespace -#line 118 "arch/zx48k/read10.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/math/sin.asm" - push namespace core -SIN: ; Computes SIN using ROM FP-CALC - call __FPSTACK_PUSH - rst 28h ; ROM CALC - defb 1Fh - defb 38h ; END CALC - jp __FPSTACK_POP - pop namespace -#line 119 "arch/zx48k/read10.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/math/tan.asm" - push namespace core -TAN: ; Computes TAN using ROM FP-CALC - call __FPSTACK_PUSH - rst 28h ; ROM CALC - defb 21h ; TAN - defb 38h ; END CALC - jp __FPSTACK_POP - pop namespace -#line 120 "arch/zx48k/read10.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ploadf.asm" - ; Parameter / Local var load - ; A => Offset - ; IX = Stack Frame -; RESULT: HL => IX + DE -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/iloadf.asm" - ; __FASTCALL__ routine which - ; loads a 40 bits floating point into A ED CB - ; stored at position pointed by POINTER HL - ;A DE, BC <-- ((HL)) - push namespace core -__ILOADF: - ld a, (hl) - inc hl - ld h, (hl) - ld l, a - ; __FASTCALL__ routine which - ; loads a 40 bits floating point into A ED CB - ; stored at position pointed by POINTER HL - ;A DE, BC <-- (HL) -__LOADF: ; Loads a 40 bits FP number from address pointed by HL - ld a, (hl) - inc hl - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld c, (hl) - inc hl - ld b, (hl) - ret - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/ploadf.asm" - push namespace core -__PLOADF: - push ix - pop hl - add hl, de - jp __LOADF - pop namespace -#line 121 "arch/zx48k/read10.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printf.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 5 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL - push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later - ld a, h - or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) - ld a, (hl) - call __PRINTCHAR - inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printf.asm" - push namespace core -__PRINTF: ; Prints a Fixed point Number stored in C ED LH - PROC - LOCAL RECLAIM2 - LOCAL STK_END - STK_END EQU 5C65h - ld hl, (ATTR_T) - push hl ; Saves ATTR_T since BUG ROM changes it - ld hl, (STK_END) - push hl ; Stores STK_END - call __FPSTACK_PUSH ; Push number into stack - rst 28h ; # Rom Calculator - defb 2Eh ; # STR$(x) - defb 38h ; # END CALC - call __FPSTACK_POP ; Recovers string parameters to A ED CB - pop hl - ld (STK_END), hl ; Balance STK_END to avoid STR$ bug - pop hl - ld (ATTR_T), hl ; Restores ATTR_T - ex de, hl ; String position now in HL - push bc - xor a ; Avoid the str to be FREED from heap - call __PRINT_STR - pop bc - inc bc - jp RECLAIM2 ; Frees TMP Memory - RECLAIM2 EQU 19E8h - ENDP - pop namespace -#line 123 "arch/zx48k/read10.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/pstoref.asm" - ; Stores FP number in A ED CB at location HL+IX - ; HL = Offset - ; IX = Stack Frame - ; A ED CB = FP Number -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/storef.asm" - push namespace core -__PISTOREF: ; Indect Stores a float (A, E, D, C, B) at location stored in memory, pointed by (IX + HL) - push de - ex de, hl ; DE <- HL - push ix - pop hl ; HL <- IX - add hl, de ; HL <- IX + HL - pop de -__ISTOREF: ; Load address at hl, and stores A,E,D,C,B registers at that address. Modifies A' register - ex af, af' - ld a, (hl) - inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex af, af' -__STOREF: ; Stores the given FP number in A EDCB at address HL - ld (hl), a - inc hl - ld (hl), e - inc hl - ld (hl), d - inc hl - ld (hl), c - inc hl - ld (hl), b - ret - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/pstoref.asm" - ; Stored a float number in A ED CB into the address pointed by IX + HL - push namespace core -__PSTOREF: - push de - ex de, hl ; DE <- HL - push ix - pop hl ; HL <- IX - add hl, de ; HL <- IX + DE - pop de - jp __STOREF - pop namespace -#line 124 "arch/zx48k/read10.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" - ;; This implements READ & RESTORE functions - ;; Reads a new element from the DATA Address code - ;; Updates the DATA_ADDR read ptr for the next read - ;; Data codification is 1 byte for type followed by data bytes - ;; Byte type is encoded as follows -;; 00: End of data -;; 01: String -;; 02: Byte -;; 03: Ubyte -;; 04: Integer -;; 05: UInteger -;; 06: Long -;; 07: ULong -;; 08: Fixed -;; 09: Float - ;; bit7 is set for a parameter-less function - ;; In that case, the next two bytes are the ptr of the function to jump -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the MIT license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the MIT license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be freed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; MEM_ALLOC - ; Allocates a block of memory in the heap. - ; - ; Parameters - ; BC = Length of requested memory block - ; -; Returns: - ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) - ; if the block could not be allocated (out of memory) - ; --------------------------------------------------------------------- - push namespace core -MEM_ALLOC: -__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) - PROC - LOCAL __MEM_LOOP - LOCAL __MEM_DONE - LOCAL __MEM_SUBTRACT - LOCAL __MEM_START - LOCAL TEMP, TEMP0 - TEMP EQU TEMP0 + 1 - ld hl, 0 - ld (TEMP), hl -__MEM_START: - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start - inc bc - inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer -__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE - ld a, h ; HL = NULL (No memory available?) - or l -#line 113 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" - ret z ; NULL -#line 115 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" - ; HL = Pointer to Free block - ld e, (hl) - inc hl - ld d, (hl) - inc hl ; DE = Block Length - push hl ; HL = *pointer to -> next block - ex de, hl - or a ; CF = 0 - sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) - jp nc, __MEM_DONE - pop hl - ld (TEMP), hl - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl - jp __MEM_LOOP -__MEM_DONE: ; A free block has been found. - ; Check if at least 4 bytes remains free (HL >= 4) - push hl - exx ; exx to preserve bc - pop hl - ld bc, 4 - or a - sbc hl, bc - exx - jp nc, __MEM_SUBTRACT - ; At this point... - ; less than 4 bytes remains free. So we return this block entirely - ; We must link the previous block with the next to this one - ; (DE) => Pointer to next block - ; (TEMP) => &(previous->next) - pop hl ; Discard current block pointer - push de - ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer - ld a, (hl) - inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex de, hl ; HL = Previous block pointer; DE = Next block pointer -TEMP0: - ld hl, 0 ; Pre-previous block pointer - ld (hl), e - inc hl - ld (hl), d ; LINKED - pop hl ; Returning block. - ret -__MEM_SUBTRACT: - ; At this point we have to store HL value (Length - BC) into (DE - 2) - ex de, hl - dec hl - ld (hl), d - dec hl - ld (hl), e ; Store new block length - add hl, de ; New length + DE => free-block start - pop de ; Remove previous HL off the stack - ld (hl), c ; Store length on its 1st word - inc hl - ld (hl), b - inc hl ; Return hl - ret - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" - ; Loads a string (ptr) from HL - ; and duplicates it on dynamic memory again - ; Finally, it returns result pointer in HL - push namespace core -__ILOADSTR: ; This is the indirect pointer entry HL = (HL) - ld a, h - or l - ret z - ld a, (hl) - inc hl - ld h, (hl) - ld l, a -__LOADSTR: ; __FASTCALL__ entry - ld a, h - or l - ret z ; Return if NULL - ld c, (hl) - inc hl - ld b, (hl) - dec hl ; BC = LEN(a$) - inc bc - inc bc ; BC = LEN(a$) + 2 (two bytes for length) - push hl - push bc - call __MEM_ALLOC - pop bc ; Recover length - pop de ; Recover origin - ld a, h - or l - ret z ; Return if NULL (No memory) - ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE - push de ; Saves destiny start - ldir ; Copies string (length number included) - pop hl ; Recovers destiny in hl as result - ret - pop namespace -#line 24 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/iload32.asm" - ; __FASTCALL__ routine which - ; loads a 32 bits integer into DE,HL - ; stored at position pointed by POINTER HL - ; DE,HL <-- (HL) - push namespace core -__ILOAD32: - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld a, (hl) - inc hl - ld h, (hl) - ld l, a - ex de, hl - ret - pop namespace -#line 25 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftof16reg.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg32.asm" - push namespace core -__ABS32: - bit 7, d - ret z -__NEG32: ; Negates DEHL (Two's complement) - ld a, l - cpl - ld l, a - ld a, h - cpl - ld h, a - ld a, e - cpl - ld e, a - ld a, d - cpl - ld d, a - inc l - ret nz - inc h - ret nz - inc de - ret - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm" - push namespace core -__FTOU32REG: ; Converts a Float to (un)signed 32 bit integer (NOTE: It's ALWAYS 32 bit signed) - ; Input FP number in A EDCB (A exponent, EDCB mantissa) - ; Output: DEHL 32 bit number (signed) - PROC - LOCAL __IS_FLOAT - LOCAL __NEGATE - or a - jr nz, __IS_FLOAT - ; Here if it is a ZX ROM Integer - ld h, c - ld l, d - ld d, e - ret -__IS_FLOAT: ; Jumps here if it is a true floating point number - ld h, e - push hl ; Stores it for later (Contains Sign in H) - push de - push bc - exx - pop de ; Loads mantissa into C'B' E'D' - pop bc ; - set 7, c ; Highest mantissa bit is always 1 - exx - ld hl, 0 ; DEHL = 0 - ld d, h - ld e, l - ;ld a, c ; Get exponent - sub 128 ; Exponent -= 128 - jr z, __FTOU32REG_END ; If it was <= 128, we are done (Integers must be > 128) - jr c, __FTOU32REG_END ; It was decimal (0.xxx). We are done (return 0) - ld b, a ; Loop counter = exponent - 128 -__FTOU32REG_LOOP: - exx ; Shift C'B' E'D' << 1, output bit stays in Carry - sla d - rl e - rl b - rl c - exx ; Shift DEHL << 1, inserting the carry on the right - rl l - rl h - rl e - rl d - djnz __FTOU32REG_LOOP -__FTOU32REG_END: - pop af ; Take the sign bit - or a ; Sets SGN bit to 1 if negative - jp m, __NEGATE ; Negates DEHL - ret -__NEGATE: - exx - ld a, d - or e - or b - or c - exx - jr z, __END - inc l - jr nz, __END - inc h - jr nz, __END - inc de - LOCAL __END -__END: - jp __NEG32 - ENDP -__FTOU8: ; Converts float in C ED LH to Unsigned byte in A - call __FTOU32REG - ld a, l - ret - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/ftof16reg.asm" - push namespace core -__FTOF16REG: ; Converts a Float to 16.16 (32 bit) fixed point decimal - ; Input FP number in A EDCB (A exponent, EDCB mantissa) - ld l, a ; Saves exponent for later - or d - or e - or b - or c - ld h, e - ret z ; Return if ZERO - push hl ; Stores it for later (Contains sign in H, exponent in L) - push de - push bc - exx - pop de ; Loads mantissa into C'B' E'D' - pop bc ; - set 7, c ; Highest mantissa bit is always 1 - exx - ld hl, 0 ; DEHL = 0 - ld d, h - ld e, l - pop bc - ld a, c ; Get exponent - sub 112 ; Exponent -= 128 + 16 - push bc ; Saves sign in b again - jp z, __FTOU32REG_END ; If it was <= 128, we are done (Integers must be > 128) - jp c, __FTOU32REG_END ; It was decimal (0.xxx). We are done (return 0) - ld b, a ; Loop counter = exponent - 128 + 16 (we need to shift 16 bit more) - jp __FTOU32REG_LOOP ; proceed as an u32 integer - pop namespace -#line 27 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/f16tofreg.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/u32tofreg.asm" - push namespace core -__I8TOFREG: - ld l, a - rlca - sbc a, a ; A = SGN(A) - ld h, a - ld e, a - ld d, a -__I32TOFREG: ; Converts a 32bit signed integer (stored in DEHL) - ; to a Floating Point Number returned in (A ED CB) - ld a, d - or a ; Test sign - jp p, __U32TOFREG ; It was positive, proceed as 32bit unsigned - call __NEG32 ; Convert it to positive - call __U32TOFREG ; Convert it to Floating point - set 7, e ; Put the sign bit (negative) in the 31bit of mantissa - ret -__U8TOFREG: - ; Converts an unsigned 8 bit (A) to Floating point - ld l, a - ld h, 0 - ld e, h - ld d, h -__U32TOFREG: ; Converts an unsigned 32 bit integer (DEHL) - ; to a Floating point number returned in A ED CB - PROC - LOCAL __U32TOFREG_END - ld a, d - or e - or h - or l - ld b, d - ld c, e ; Returns 00 0000 0000 if ZERO - ret z - push de - push hl - exx - pop de ; Loads integer into B'C' D'E' - pop bc - exx - ld l, 128 ; Exponent - ld bc, 0 ; DEBC = 0 - ld d, b - ld e, c -__U32TOFREG_LOOP: ; Also an entry point for __F16TOFREG - exx - ld a, d ; B'C'D'E' == 0 ? - or e - or b - or c - jp z, __U32TOFREG_END ; We are done - srl b ; Shift B'C' D'E' >> 1, output bit stays in Carry - rr c - rr d - rr e - exx - rr e ; Shift EDCB >> 1, inserting the carry on the left - rr d - rr c - rr b - inc l ; Increment exponent - jp __U32TOFREG_LOOP -__U32TOFREG_END: - exx - ld a, l ; Puts the exponent in a - res 7, e ; Sets the sign bit to 0 (positive) - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/f16tofreg.asm" - push namespace core -__F16TOFREG: ; Converts a 16.16 signed fixed point (stored in DEHL) - ; to a Floating Point Number returned in (C ED CB) - PROC - LOCAL __F16TOFREG2 - ld a, d - or a ; Test sign - jp p, __F16TOFREG2 ; It was positive, proceed as 32bit unsigned - call __NEG32 ; Convert it to positive - call __F16TOFREG2 ; Convert it to Floating point - set 7, e ; Put the sign bit (negative) in the 31bit of mantissa - ret -__F16TOFREG2: ; Converts an unsigned 32 bit integer (DEHL) - ; to a Floating point number returned in C DE HL - ld a, d - or e - or h - or l - ld b, h - ld c, l - ret z ; Return 00 0000 0000 if 0 - push de - push hl - exx - pop de ; Loads integer into B'C' D'E' - pop bc - exx - ld l, 112 ; Exponent - ld bc, 0 ; DEBC = 0 - ld d, b - ld e, c - jp __U32TOFREG_LOOP ; Proceed as an integer - ENDP - pop namespace -#line 28 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 31 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 32 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 33 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 34 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 35 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 36 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 37 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 38 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 39 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" - ;; Updates restore point to the given HL mem. address - push namespace core -__RESTORE: - PROC - LOCAL __DATA_ADDR - ld (__DATA_ADDR), hl - ret - ;; Reads a value from the DATA mem area and updates __DATA_ADDR ptr to the - ;; next item. On Out Of Data, restarts - ;; -__READ: - LOCAL read_restart, cont, cont2, table, no_func - LOCAL dynamic_cast, dynamic_cast2, dynamic_cast3, dynamic_cast4 - LOCAL _decode_table, coerce_to_int, coerce_to_int2, promote_to_i16 - LOCAL _from_i8, _from_u8 - LOCAL _from_i16, _from_u16 - LOCAL _from_i32, _from_u32 - LOCAL _from_fixed, __data_error - push af ; type of data to read - ld hl, (__DATA_ADDR) -read_restart: - ld a, (hl) - or a ; 0 => OUT of data - jr nz, cont - ;; Signals out of data - ld hl, .DATA.__DATA__0 - ld (__DATA_ADDR), hl - jr read_restart ; Start again -cont: - and 0x80 - ld a, (hl) - push af - jp z, no_func ;; Loads data directly, not a function - inc hl - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld (__DATA_ADDR), hl ;; Store address of next DATA - ex de, hl -cont2: - ld de, dynamic_cast - push de ; ret address - jp (hl) ; "call (hl)" - ;; Now tries to convert the given result to the expected type or raise an error -dynamic_cast: - exx - ex af, af' - pop af ; type READ - and 0x7F ; clear bit 7 - pop hl ; type requested by USER (type of the READ variable) - ld c, h ; save requested type (save it in register C) - cp h - exx - jr nz, dynamic_cast2 ; Types are identical? - ;; yes, they are - ex af, af' - ret -dynamic_cast2: - cp 1 ; Requested a number, but read a string? - jr nz, dynamic_cast3 - call __MEM_FREE ; Frees str from memory - jr __data_error -dynamic_cast3: - exx - ld b, a ; Read type - ld a, c ; Requested type - cp 1 - jr z, __data_error - cp b - jr c, dynamic_cast4 - ;; here the user expected type is "larger" than the read one - ld a, b - sub 2 - add a, a - ld l, a - ld h, 0 - ld de, _decode_table - add hl, de - ld e, (hl) - inc hl - ld h, (hl) - ld l, e - push hl - ld a, c ; Requested type - exx - ret -__data_error: - ;; When a data is read, but cannot be converted to the requested type - ;; that is, the user asked for a string and we read a number or vice versa - ld a, ERROR_InvalidArg - call __STOP ; The user expected a string, but read a number - xor a - ld h, a - ld l, a - ld e, a - ld d, a - ld b, a - ld c, a - ret -_decode_table: - dw _from_i8 - dw _from_u8 - dw _from_i16 - dw _from_u16 - dw _from_i32 - dw _from_u32 - dw _from_fixed -_from_i8: - cp 4 - jr nc, promote_to_i16 - ex af, af' - ret ;; Was from Byte to Ubyte -promote_to_i16: - ex af, af' - ld l, a - rla - sbc a, a - ld h, a ; copy sgn to h - ex af, af' - jr _before_from_i16 -_from_u8: - ex af, af' - ld l, a - ld h, 0 - ex af, af' - ;; Promoted to i16 -_before_from_i16: -_from_i16: - cp 6 - ret c ;; from i16 to u16 - ;; Promote i16 to i32 - ex af, af' - ld a, h - rla - sbc a, a - ld e, a - ld d, a - ex af, af' -_from_i32: - cp 7 - ret z ;; From i32 to u32 - ret c ;; From u16 to i32 - cp 9 - jp z, __I32TOFREG -_from_u32: - cp 9 - jp z, __U32TOFREG - ex de, hl - ld hl, 0 - cp 8 - ret z -_from_fixed: ;; From fixed to float - jp __F16TOFREG -_from_u16: - ld de, 0 ; HL 0x0000 => 32 bits - jp _from_i32 -dynamic_cast4: - ;; The user type is "shorter" than the read one - cp 8 ;; required type - jr c, before_to_int ;; required < fixed (f16) - ex af, af' - exx ;; Ok, we must convert from float to f16 - jp __FTOF16REG -before_to_int: - ld a, b ;; read type - cp 8 ;; - jr c, coerce_to_int2 - jr nz, coerce_to_int ;; From float to int - ld a, c ;; user type - exx - ;; f16 to Long - ex de, hl - ld a, h - rla - sbc a, a - ld d, a - ld e, a - exx - jr coerce_to_int2 -coerce_to_int: - exx - ex af, af' - call __FTOU32REG - ex af, af' ; a contains user type - exx -coerce_to_int2: ; At this point we have an u/integer in hl - exx - cp 4 - ret nc ; Already done. Return the result - ld a, l ; Truncate to byte - ret -no_func: - exx - ld de, dynamic_cast - push de ; Ret address - dec a ; 0 => string; 1, 2 => byte; 3, 4 => integer; 5, 6 => long, 7 => fixed; 8 => float - ld h, 0 - add a, a - ld l, a - ld de, table - add hl, de - ld e, (hl) - inc hl - ld h, (hl) - ld l, e - push hl ; address to jump to - exx - inc hl - ret ; jp (sp) => jump to table[a - 1] -table: - LOCAL __01_decode_string - LOCAL __02_decode_byte - LOCAL __03_decode_ubyte - LOCAL __04_decode_integer - LOCAL __05_decode_uinteger - LOCAL __06_decode_long - LOCAL __07_decode_ulong - LOCAL __08_decode_fixed - LOCAL __09_decode_float - ;; 1 -> Decode string - ;; 2, 3 -> Decode Byte, UByte - ;; 4, 5 -> Decode Integer, UInteger - ;; 6, 7 -> Decode Long, ULong - ;; 8 -> Decode Fixed - ;; 9 -> Decode Float - dw __01_decode_string - dw __02_decode_byte - dw __03_decode_ubyte - dw __04_decode_integer - dw __05_decode_uinteger - dw __06_decode_long - dw __07_decode_ulong - dw __08_decode_fixed - dw __09_decode_float -__01_decode_string: - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld (__DATA_ADDR), hl ;; Store address of next DATA - ex de, hl - jp __LOADSTR -__02_decode_byte: -__03_decode_ubyte: - ld a, (hl) - inc hl - ld (__DATA_ADDR), hl - ret -__04_decode_integer: -__05_decode_uinteger: - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld (__DATA_ADDR), hl - ex de, hl - ret -__06_decode_long: -__07_decode_ulong: -__08_decode_fixed: - ld b, h - ld c, l - inc bc - inc bc - inc bc - inc bc - ld (__DATA_ADDR), bc - jp __ILOAD32 -__09_decode_float: - call __LOADF - inc hl - ld (__DATA_ADDR), hl - ld h, a ; returns A in H; sets A free - ret -__DATA_ADDR: ;; Stores current DATA ptr - dw .DATA.__DATA__0 - ENDP - pop namespace -#line 125 "arch/zx48k/read10.bas" - END diff --git a/tests/functional/arch/zx48k/read12.asm b/tests/functional/arch/zx48k/read12.asm index 1940b79c2..cbd1a4e4f 100644 --- a/tests/functional/arch/zx48k/read12.asm +++ b/tests/functional/arch/zx48k/read12.asm @@ -1324,7 +1324,7 @@ __PRINT_MINUS: ; PRINT the MINUS (-) sign. CALLER must preserve registers __PRINT_DIGIT EQU __PRINTCHAR ; PRINTS the char in A register, and puts its attrs pop namespace #line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/div8.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div8.asm" ; -------------------------------- push namespace core __DIVU8: ; 8 bit unsigned integer division @@ -2049,6 +2049,13 @@ _from_u16: jp _from_i32 dynamic_cast4: ;; The user type is "shorter" than the read one + ld a, b ;; read type + cp 4 ;; if user type < read type < _i16 => From Ubyte to Byte. Return af' + jr nc, 1f + ex af, af' + ret +1: + ld a, c ;; recover user required type cp 8 ;; required type jr c, before_to_int ;; required < fixed (f16) ex af, af' diff --git a/tests/functional/arch/zx48k/read13.asm b/tests/functional/arch/zx48k/read13.asm deleted file mode 100644 index 2427b8e67..000000000 --- a/tests/functional/arch/zx48k/read13.asm +++ /dev/null @@ -1,2714 +0,0 @@ - org 32768 -.core.__START_PROGRAM: - di - push ix - push iy - exx - push hl - exx - ld hl, 0 - add hl, sp - ld (.core.__CALL_BACK__), hl - ei - call .core.__MEM_INIT - call .core.__PRINT_INIT - jp .core.__MAIN_PROGRAM__ -.core.__CALL_BACK__: - DEFW 0 -.core.ZXBASIC_USER_DATA: - ; Defines HEAP SIZE -.core.ZXBASIC_HEAP_SIZE EQU 4768 -.core.ZXBASIC_MEM_HEAP: - DEFS 4768 - ; Defines USER DATA Length in bytes -.core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA - .core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN - .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA -_v: - DEFB 00h - DEFB 80h - DEFB 01h - DEFB 00h -_i: - DEFB 00 -_c: - DEFW .LABEL.__LABEL5 -_c.__DATA__.__PTR__: - DEFW _c.__DATA__ - DEFW 0 - DEFW 0 -_c.__DATA__: - DEFB 00h - DEFB 00h - DEFB 00h - DEFB 00h - DEFB 00h - DEFB 00h - DEFB 00h - DEFB 00h - DEFB 00h - DEFB 00h - DEFB 00h - DEFB 00h - DEFB 00h - DEFB 00h - DEFB 00h - DEFB 00h -.LABEL.__LABEL5: - DEFW 0000h - DEFB 04h -.core.ZXBASIC_USER_DATA_END: -.core.__MAIN_PROGRAM__: - ld hl, .DATA.__DATA__0 - call .core.__RESTORE - xor a - ld (_i), a - jp .LABEL.__LABEL0 -.LABEL.__LABEL3: - ld a, 8 - call .core.__READ - push de - push hl - ld a, (_i) - ld l, a - ld h, 0 - push hl - ld hl, _c - call .core.__ARRAY - pop bc - pop de - call .core.__STORE32 - call .core.COPY_ATTR - ld a, (_i) - ld l, a - ld h, 0 - push hl - ld hl, _c - call .core.__ARRAY - call .core.__ILOAD32 - call .core.__PRINTF16 - call .core.PRINT_EOL -.LABEL.__LABEL4: - ld hl, _i - inc (hl) -.LABEL.__LABEL0: - ld a, 3 - ld hl, (_i - 1) - cp h - jp nc, .LABEL.__LABEL3 -.LABEL.__LABEL2: - ld hl, 0 - ld b, h - ld c, l -.core.__END_PROGRAM: - di - ld hl, (.core.__CALL_BACK__) - ld sp, hl - exx - pop hl - exx - pop iy - pop ix - ei - ret -___DATA__FUNCPTR__0: - ld hl, (_v) - ld de, (_v + 2) - ld bc, 25 - push bc - ld bc, 0 - push bc - call .core.__MULF16 -___DATA__FUNCPTR__0__leave: - ret -___DATA__FUNCPTR__1: - ld hl, (_v) - ld de, (_v + 2) - call .core.__F16TOFREG - call .core.SIN - push bc - push de - push af - ld hl, (_v) - ld de, (_v + 2) - call .core.__F16TOFREG - call .core.TAN - push bc - push de - push af - ld a, 082h - ld de, 00000h - ld bc, 00000h - call .core.__POW - call .core.__MULF -___DATA__FUNCPTR__1__leave: - ret -___DATA__FUNCPTR__2: - ld hl, (_v) - ld de, (_v + 2) - call .core.__F16TOFREG - ld hl, 0A2DAh - push hl - ld hl, 00F49h - push hl - ld h, 082h - push hl - call .core.__MULF -___DATA__FUNCPTR__2__leave: - ret -.DATA.__DATA__0: - DEFB 3 - DEFB 10 - DEFB 88h - DEFW ___DATA__FUNCPTR__0 - DEFB 89h - DEFW ___DATA__FUNCPTR__1 - DEFB 89h - DEFW ___DATA__FUNCPTR__2 -__DATA__END: - DEFB 00h - ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mulf.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/stackf.asm" - ; ------------------------------------------------------------- - ; Functions to manage FP-Stack of the ZX Spectrum ROM CALC - ; ------------------------------------------------------------- - push namespace core - __FPSTACK_PUSH EQU 2AB6h ; Stores an FP number into the ROM FP stack (A, ED CB) - __FPSTACK_POP EQU 2BF1h ; Pops an FP number out of the ROM FP stack (A, ED CB) -__FPSTACK_PUSH2: ; Pushes Current A ED CB registers and top of the stack on (SP + 4) - ; Second argument to push into the stack calculator is popped out of the stack - ; Since the caller routine also receives the parameters into the top of the stack - ; four bytes must be removed from SP before pop them out - call __FPSTACK_PUSH ; Pushes A ED CB into the FP-STACK - exx - pop hl ; Caller-Caller return addr - exx - pop hl ; Caller return addr - pop af - pop de - pop bc - push hl ; Caller return addr - exx - push hl ; Caller-Caller return addr - exx - jp __FPSTACK_PUSH -__FPSTACK_I16: ; Pushes 16 bits integer in HL into the FP ROM STACK - ; This format is specified in the ZX 48K Manual - ; You can push a 16 bit signed integer as - ; 0 SS LL HH 0, being SS the sign and LL HH the low - ; and High byte respectively - ld a, h - rla ; sign to Carry - sbc a, a ; 0 if positive, FF if negative - ld e, a - ld d, l - ld c, h - xor a - ld b, a - jp __FPSTACK_PUSH - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mulf.asm" - ; ------------------------------------------------------------- - ; Floating point library using the FP ROM Calculator (ZX 48K) - ; All of them uses A EDCB registers as 1st paramter. - ; For binary operators, the 2n operator must be pushed into the - ; stack, in the order A DE BC. - ; - ; Uses CALLEE convention - ; ------------------------------------------------------------- - push namespace core -__MULF: ; Multiplication - call __FPSTACK_PUSH2 - ; ------------- ROM MUL - rst 28h - defb 04h ; - defb 38h; ; END CALC - jp __FPSTACK_POP - pop namespace -#line 111 "arch/zx48k/read13.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mulf16.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg32.asm" - push namespace core -__ABS32: - bit 7, d - ret z -__NEG32: ; Negates DEHL (Two's complement) - ld a, l - cpl - ld l, a - ld a, h - cpl - ld h, a - ld a, e - cpl - ld e, a - ld a, d - cpl - ld d, a - inc l - ret nz - inc h - ret nz - inc de - ret - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mulf16.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/_mul32.asm" -; Ripped from: http://www.andreadrian.de/oldcpu/z80_number_cruncher.html#moztocid784223 - ; Used with permission. - ; Multiplies 32x32 bit integer (DEHL x D'E'H'L') - ; 64bit result is returned in H'L'H L B'C'A C - push namespace core -__MUL32_64START: - push hl - exx - ld b, h - ld c, l ; BC = Low Part (A) - pop hl ; HL = Load Part (B) - ex de, hl ; DE = Low Part (B), HL = HightPart(A) (must be in B'C') - push hl - exx - pop bc ; B'C' = HightPart(A) - exx ; A = B'C'BC , B = D'E'DE - ; multiply routine 32 * 32bit = 64bit - ; h'l'hlb'c'ac = b'c'bc * d'e'de - ; needs register a, changes flags - ; - ; this routine was with tiny differences in the - ; sinclair zx81 rom for the mantissa multiply -__LMUL: - xor a ; reset carry flag - ld h, a ; result bits 32..47 = 0 - ld l, a - exx - ld h, a ; result bits 48..63 = 0 - ld l, a - exx - ld a,b ; mpr is b'c'ac - ld b,33 ; initialize loop counter - jp __LMULSTART -__LMULLOOP: - jr nc,__LMULNOADD ; JP is 2 cycles faster than JR. Since it's inside a LOOP - ; it can save up to 33 * 2 = 66 cycles - ; But JR if 3 cycles faster if JUMP not taken! - add hl,de ; result += mpd - exx - adc hl,de - exx -__LMULNOADD: - exx - rr h ; right shift upper - rr l ; 32bit of result - exx - rr h - rr l -__LMULSTART: - exx - rr b ; right shift mpr/ - rr c ; lower 32bit of result - exx - rra ; equivalent to rr a - rr c - djnz __LMULLOOP - ret ; result in h'l'hlb'c'ac - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mulf16.asm" - push namespace core -__MULF16: ; - ld a, d ; load sgn into a - ex af, af' ; saves it - call __ABS32 ; convert to positive - exx - pop hl ; Return address - pop de ; Low part - ex (sp), hl ; CALLEE caller convention; Now HL = Hight part, (SP) = Return address - ex de, hl ; D'E' = High part (B), H'L' = Low part (B) (must be in DE) - ex af, af' - xor d ; A register contains resulting sgn - ex af, af' - call __ABS32 ; convert to positive - call __MUL32_64START - ; rounding (was not included in zx81) -__ROUND_FIX: ; rounds a 64bit (32.32) fixed point number to 16.16 - ; result returned in dehl - ; input in h'l'hlb'c'ac - sla a ; result bit 47 to carry - exx - ld hl,0 ; ld does not change carry - adc hl,bc ; hl = hl + 0 + carry - push hl - exx - ld bc,0 - adc hl,bc ; hl = hl + 0 + carry - ex de, hl - pop hl ; rounded result in de.hl - ex af, af' ; recovers result sign - or a - jp m, __NEG32 ; if negative, negates it - ret - pop namespace -#line 112 "arch/zx48k/read13.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/array.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; ------------------------------------------------------------------- - ; Simple array Index routine - ; Number of total indexes dimensions - 1 at beginning of memory - ; HL = Start of array memory (First two bytes contains N-1 dimensions) - ; Dimension values on the stack, (top of the stack, highest dimension) - ; E.g. A(2, 4) -> PUSH <4>; PUSH <2> - ; For any array of N dimension A(aN-1, ..., a1, a0) - ; and dimensions D[bN-1, ..., b1, b0], the offset is calculated as - ; O = [a0 + b0 * (a1 + b1 * (a2 + ... bN-2(aN-1)))] -; What I will do here is to calculate the following sequence: - ; ((aN-1 * bN-2) + aN-2) * bN-3 + ... -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mul16.asm" - push namespace core -__MUL16: ; Mutiplies HL with the last value stored into de stack - ; Works for both signed and unsigned - PROC - LOCAL __MUL16LOOP - LOCAL __MUL16NOADD - ex de, hl - pop hl ; Return address - ex (sp), hl ; CALLEE caller convention -__MUL16_FAST: - ld b, 16 - ld a, h - ld c, l - ld hl, 0 -__MUL16LOOP: - add hl, hl ; hl << 1 - sla c - rla ; a,c << 1 - jp nc, __MUL16NOADD - add hl, de -__MUL16NOADD: - djnz __MUL16LOOP - ret ; Result in hl (16 lower bits) - ENDP - pop namespace -#line 20 "/zxbasic/src/lib/arch/zx48k/runtime/array.asm" -#line 24 "/zxbasic/src/lib/arch/zx48k/runtime/array.asm" - push namespace core -__ARRAY_PTR: ;; computes an array offset from a pointer - ld c, (hl) - inc hl - ld h, (hl) - ld l, c ;; HL <-- [HL] -__ARRAY: - PROC - LOCAL LOOP - LOCAL ARRAY_END - LOCAL TMP_ARR_PTR ; Ptr to Array DATA region. Stored temporarily - LOCAL LBOUND_PTR, UBOUND_PTR ; LBound and UBound PTR indexes - LOCAL RET_ADDR ; Contains the return address popped from the stack - LBOUND_PTR EQU 23698 ; Uses MEMBOT as a temporary variable - UBOUND_PTR EQU LBOUND_PTR + 2 ; Next 2 bytes for UBOUND PTR - RET_ADDR EQU UBOUND_PTR + 2 ; Next 2 bytes for RET_ADDR - TMP_ARR_PTR EQU RET_ADDR + 2 ; Next 2 bytes for TMP_ARR_PTR - ld e, (hl) - inc hl - ld d, (hl) - inc hl ; DE <-- PTR to Dim sizes table - ld (TMP_ARR_PTR), hl ; HL = Array __DATA__.__PTR__ - inc hl - inc hl - ld c, (hl) - inc hl - ld b, (hl) ; BC <-- Array __LBOUND__ PTR - ld (LBOUND_PTR), bc ; Store it for later -#line 66 "/zxbasic/src/lib/arch/zx48k/runtime/array.asm" - ex de, hl ; HL <-- PTR to Dim sizes table, DE <-- dummy - ex (sp), hl ; Return address in HL, PTR Dim sizes table onto Stack - ld (RET_ADDR), hl ; Stores it for later - exx - pop hl ; Will use H'L' as the pointer to Dim sizes table - ld c, (hl) ; Loads Number of dimensions from (hl) - inc hl - ld b, (hl) - inc hl ; Ready - exx - ld hl, 0 ; HL = Element Offset "accumulator" -LOOP: - ex de, hl ; DE = Element Offset - ld hl, (LBOUND_PTR) - ld a, h - or l - ld b, h - ld c, l - jr z, 1f - ld c, (hl) - inc hl - ld b, (hl) - inc hl - ld (LBOUND_PTR), hl -1: - pop hl ; Get next index (Ai) from the stack - sbc hl, bc ; Subtract LBOUND -#line 116 "/zxbasic/src/lib/arch/zx48k/runtime/array.asm" - add hl, de ; Adds current index - exx ; Checks if B'C' = 0 - ld a, b ; Which means we must exit (last element is not multiplied by anything) - or c - jr z, ARRAY_END ; if B'Ci == 0 we are done - dec bc ; Decrements loop counter - ld e, (hl) ; Loads next dimension size into D'E' - inc hl - ld d, (hl) - inc hl - push de - exx - pop de ; DE = Max bound Number (i-th dimension) - call __FNMUL ; HL <= HL * DE mod 65536 - jp LOOP -ARRAY_END: - ld a, (hl) - exx -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/array.asm" - LOCAL ARRAY_SIZE_LOOP - ex de, hl - ld hl, 0 - ld b, a -ARRAY_SIZE_LOOP: - add hl, de - djnz ARRAY_SIZE_LOOP -#line 156 "/zxbasic/src/lib/arch/zx48k/runtime/array.asm" - ex de, hl - ld hl, (TMP_ARR_PTR) - ld a, (hl) - inc hl - ld h, (hl) - ld l, a - add hl, de ; Adds element start - ld de, (RET_ADDR) - push de - ret - ;; Performs a faster multiply for little 16bit numbs - LOCAL __FNMUL, __FNMUL2 -__FNMUL: - xor a - or h - jp nz, __MUL16_FAST - or l - ret z - cp 33 - jp nc, __MUL16_FAST - ld b, l - ld l, h ; HL = 0 -__FNMUL2: - add hl, de - djnz __FNMUL2 - ret - ENDP - pop namespace -#line 113 "arch/zx48k/read13.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" - ; Simple error control routines -; vim:ts=4:et: - push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop - ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a - ret - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 114 "arch/zx48k/read13.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/f16tofreg.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/u32tofreg.asm" - push namespace core -__I8TOFREG: - ld l, a - rlca - sbc a, a ; A = SGN(A) - ld h, a - ld e, a - ld d, a -__I32TOFREG: ; Converts a 32bit signed integer (stored in DEHL) - ; to a Floating Point Number returned in (A ED CB) - ld a, d - or a ; Test sign - jp p, __U32TOFREG ; It was positive, proceed as 32bit unsigned - call __NEG32 ; Convert it to positive - call __U32TOFREG ; Convert it to Floating point - set 7, e ; Put the sign bit (negative) in the 31bit of mantissa - ret -__U8TOFREG: - ; Converts an unsigned 8 bit (A) to Floating point - ld l, a - ld h, 0 - ld e, h - ld d, h -__U32TOFREG: ; Converts an unsigned 32 bit integer (DEHL) - ; to a Floating point number returned in A ED CB - PROC - LOCAL __U32TOFREG_END - ld a, d - or e - or h - or l - ld b, d - ld c, e ; Returns 00 0000 0000 if ZERO - ret z - push de - push hl - exx - pop de ; Loads integer into B'C' D'E' - pop bc - exx - ld l, 128 ; Exponent - ld bc, 0 ; DEBC = 0 - ld d, b - ld e, c -__U32TOFREG_LOOP: ; Also an entry point for __F16TOFREG - exx - ld a, d ; B'C'D'E' == 0 ? - or e - or b - or c - jp z, __U32TOFREG_END ; We are done - srl b ; Shift B'C' D'E' >> 1, output bit stays in Carry - rr c - rr d - rr e - exx - rr e ; Shift EDCB >> 1, inserting the carry on the left - rr d - rr c - rr b - inc l ; Increment exponent - jp __U32TOFREG_LOOP -__U32TOFREG_END: - exx - ld a, l ; Puts the exponent in a - res 7, e ; Sets the sign bit to 0 (positive) - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/f16tofreg.asm" - push namespace core -__F16TOFREG: ; Converts a 16.16 signed fixed point (stored in DEHL) - ; to a Floating Point Number returned in (C ED CB) - PROC - LOCAL __F16TOFREG2 - ld a, d - or a ; Test sign - jp p, __F16TOFREG2 ; It was positive, proceed as 32bit unsigned - call __NEG32 ; Convert it to positive - call __F16TOFREG2 ; Convert it to Floating point - set 7, e ; Put the sign bit (negative) in the 31bit of mantissa - ret -__F16TOFREG2: ; Converts an unsigned 32 bit integer (DEHL) - ; to a Floating point number returned in C DE HL - ld a, d - or e - or h - or l - ld b, h - ld c, l - ret z ; Return 00 0000 0000 if 0 - push de - push hl - exx - pop de ; Loads integer into B'C' D'E' - pop bc - exx - ld l, 112 ; Exponent - ld bc, 0 ; DEBC = 0 - ld d, b - ld e, c - jp __U32TOFREG_LOOP ; Proceed as an integer - ENDP - pop namespace -#line 115 "arch/zx48k/read13.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/iload32.asm" - ; __FASTCALL__ routine which - ; loads a 32 bits integer into DE,HL - ; stored at position pointed by POINTER HL - ; DE,HL <-- (HL) - push namespace core -__ILOAD32: - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld a, (hl) - inc hl - ld h, (hl) - ld l, a - ex de, hl - ret - pop namespace -#line 116 "arch/zx48k/read13.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/math/pow.asm" - ; ------------------------------------------------------------- - ; Floating point library using the FP ROM Calculator (ZX 48K) - ; All of them uses A EDCB registers as 1st paramter. - ; For binary operators, the 2n operator must be pushed into the - ; stack, in the order A DE BC. - ; - ; Uses CALLEE convention - ; -; Operands comes swapped: - ; 1 st parameter is the BASE (A ED CB) - ; 2 nd parameter (Top of the stack) is Exponent - ; ------------------------------------------------------------- - push namespace core -__POW: ; Exponentiation - PROC - call __FPSTACK_PUSH2 - ; ------------- ROM POW - rst 28h - defb 01h ; Exchange => 1, Base - defb 06h ; POW - defb 38h; ; END CALC - jp __FPSTACK_POP - ENDP - pop namespace -#line 117 "arch/zx48k/read13.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/math/sin.asm" - push namespace core -SIN: ; Computes SIN using ROM FP-CALC - call __FPSTACK_PUSH - rst 28h ; ROM CALC - defb 1Fh - defb 38h ; END CALC - jp __FPSTACK_POP - pop namespace -#line 118 "arch/zx48k/read13.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/math/tan.asm" - push namespace core -TAN: ; Computes TAN using ROM FP-CALC - call __FPSTACK_PUSH - rst 28h ; ROM CALC - defb 21h ; TAN - defb 38h ; END CALC - jp __FPSTACK_POP - pop namespace -#line 119 "arch/zx48k/read13.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printf16.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printnum.asm" - push namespace core -__PRINTU_START: - PROC - LOCAL __PRINTU_CONT - ld a, b - or a - jp nz, __PRINTU_CONT - ld a, '0' - jp __PRINT_DIGIT -__PRINTU_CONT: - pop af - push bc - call __PRINT_DIGIT - pop bc - djnz __PRINTU_CONT - ret - ENDP -__PRINT_MINUS: ; PRINT the MINUS (-) sign. CALLER must preserve registers - ld a, '-' - jp __PRINT_DIGIT - __PRINT_DIGIT EQU __PRINTCHAR ; PRINTS the char in A register, and puts its attrs - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printf16.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi16.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div16.asm" - ; 16 bit division and modulo functions - ; for both signed and unsigned values -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg16.asm" - ; Negates HL value (16 bit) - push namespace core -__ABS16: - bit 7, h - ret z -__NEGHL: - ld a, l ; HL = -HL - cpl - ld l, a - ld a, h - cpl - ld h, a - inc hl - ret - pop namespace -#line 5 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div16.asm" - push namespace core -__DIVU16: ; 16 bit unsigned division - ; HL = Dividend, Stack Top = Divisor - ; -- OBSOLETE ; Now uses FASTCALL convention - ; ex de, hl - ; pop hl ; Return address - ; ex (sp), hl ; CALLEE Convention -__DIVU16_FAST: - ld a, h - ld c, l - ld hl, 0 - ld b, 16 -__DIV16LOOP: - sll c - rla - adc hl,hl - sbc hl,de - jr nc, __DIV16NOADD - add hl,de - dec c -__DIV16NOADD: - djnz __DIV16LOOP - ex de, hl - ld h, a - ld l, c - ret ; HL = quotient, DE = Mudulus -__MODU16: ; 16 bit modulus - ; HL = Dividend, Stack Top = Divisor - ;ex de, hl - ;pop hl - ;ex (sp), hl ; CALLEE Convention - call __DIVU16_FAST - ex de, hl ; hl = reminder (modulus) - ; de = quotient - ret -__DIVI16: ; 16 bit signed division - ; --- The following is OBSOLETE --- - ; ex de, hl - ; pop hl - ; ex (sp), hl ; CALLEE Convention -__DIVI16_FAST: - ld a, d - xor h - ex af, af' ; BIT 7 of a contains result - bit 7, d ; DE is negative? - jr z, __DIVI16A - ld a, e ; DE = -DE - cpl - ld e, a - ld a, d - cpl - ld d, a - inc de -__DIVI16A: - bit 7, h ; HL is negative? - call nz, __NEGHL -__DIVI16B: - call __DIVU16_FAST - ex af, af' - or a - ret p ; return if positive - jp __NEGHL -__MODI16: ; 16 bit modulus - ; HL = Dividend, Stack Top = Divisor - ;ex de, hl - ;pop hl - ;ex (sp), hl ; CALLEE Convention - call __DIVI16_FAST - ex de, hl ; hl = reminder (modulus) - ; de = quotient - ret - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/printi16.asm" - push namespace core -__PRINTI16: ; Prints a 16bits signed in HL - ; Converts 16 to 32 bits - PROC - LOCAL __PRINTU_LOOP - ld a, h - or a - jp p, __PRINTU16 - call __PRINT_MINUS - call __NEGHL -__PRINTU16: - ld b, 0 -__PRINTU_LOOP: - ld a, h - or l - jp z, __PRINTU_START - push bc - ld de, 10 - call __DIVU16_FAST ; Divides by DE. DE = MODULUS at exit. Since < 256, E = Modulus - pop bc - ld a, e - or '0' ; Stores ASCII digit (must be print in reversed order) - push af - inc b - jp __PRINTU_LOOP ; Uses JP in loops - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/printf16.asm" - push namespace core -__PRINTF16: ; Prints a 32bit 16.16 fixed point number - PROC - LOCAL __PRINT_FIX_LOOP - LOCAL __PRINTF16_2 - bit 7, d - jr z, __PRINTF16_2 - call __NEG32 - call __PRINT_MINUS -__PRINTF16_2: - push hl - ex de, hl - call __PRINTU16 ; Prints integer part - pop hl - ld a, h - or l - ret z ; Returns if integer - push hl - ld a, '.' - call __PRINT_DIGIT ; Prints decimal point - pop hl -__PRINT_FIX_LOOP: - ld a, h - or l - ret z ; Returns if no more decimals - xor a - ld d, h - ld e, l - ; Fast NUM * 10 multiplication - add hl, hl ; - adc a, a ; AHL = AHL * 2 (= X * 2) - add hl, hl ; - adc a, a ; AHL = AHL * 2 (= X * 4) - add hl, de ; - adc a, 0 ; AHL = AHL + DE (= X * 5) - add hl, hl - adc a, a ; AHL = AHL * 2 (= X * 10) - push hl - or '0' - call __PRINT_DIGIT - pop hl - jp __PRINT_FIX_LOOP - ENDP - pop namespace -#line 121 "arch/zx48k/read13.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" - ;; This implements READ & RESTORE functions - ;; Reads a new element from the DATA Address code - ;; Updates the DATA_ADDR read ptr for the next read - ;; Data codification is 1 byte for type followed by data bytes - ;; Byte type is encoded as follows -;; 00: End of data -;; 01: String -;; 02: Byte -;; 03: Ubyte -;; 04: Integer -;; 05: UInteger -;; 06: Long -;; 07: ULong -;; 08: Fixed -;; 09: Float - ;; bit7 is set for a parameter-less function - ;; In that case, the next two bytes are the ptr of the function to jump -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the MIT license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the MIT license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be freed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 70 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" - ; --------------------------------------------------------------------- - ; MEM_ALLOC - ; Allocates a block of memory in the heap. - ; - ; Parameters - ; BC = Length of requested memory block - ; -; Returns: - ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) - ; if the block could not be allocated (out of memory) - ; --------------------------------------------------------------------- - push namespace core -MEM_ALLOC: -__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) - PROC - LOCAL __MEM_LOOP - LOCAL __MEM_DONE - LOCAL __MEM_SUBTRACT - LOCAL __MEM_START - LOCAL TEMP, TEMP0 - TEMP EQU TEMP0 + 1 - ld hl, 0 - ld (TEMP), hl -__MEM_START: - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start - inc bc - inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer -__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE - ld a, h ; HL = NULL (No memory available?) - or l -#line 113 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" - ret z ; NULL -#line 115 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" - ; HL = Pointer to Free block - ld e, (hl) - inc hl - ld d, (hl) - inc hl ; DE = Block Length - push hl ; HL = *pointer to -> next block - ex de, hl - or a ; CF = 0 - sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) - jp nc, __MEM_DONE - pop hl - ld (TEMP), hl - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl - jp __MEM_LOOP -__MEM_DONE: ; A free block has been found. - ; Check if at least 4 bytes remains free (HL >= 4) - push hl - exx ; exx to preserve bc - pop hl - ld bc, 4 - or a - sbc hl, bc - exx - jp nc, __MEM_SUBTRACT - ; At this point... - ; less than 4 bytes remains free. So we return this block entirely - ; We must link the previous block with the next to this one - ; (DE) => Pointer to next block - ; (TEMP) => &(previous->next) - pop hl ; Discard current block pointer - push de - ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer - ld a, (hl) - inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex de, hl ; HL = Previous block pointer; DE = Next block pointer -TEMP0: - ld hl, 0 ; Pre-previous block pointer - ld (hl), e - inc hl - ld (hl), d ; LINKED - pop hl ; Returning block. - ret -__MEM_SUBTRACT: - ; At this point we have to store HL value (Length - BC) into (DE - 2) - ex de, hl - dec hl - ld (hl), d - dec hl - ld (hl), e ; Store new block length - add hl, de ; New length + DE => free-block start - pop de ; Remove previous HL off the stack - ld (hl), c ; Store length on its 1st word - inc hl - ld (hl), b - inc hl ; Return hl - ret - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" - ; Loads a string (ptr) from HL - ; and duplicates it on dynamic memory again - ; Finally, it returns result pointer in HL - push namespace core -__ILOADSTR: ; This is the indirect pointer entry HL = (HL) - ld a, h - or l - ret z - ld a, (hl) - inc hl - ld h, (hl) - ld l, a -__LOADSTR: ; __FASTCALL__ entry - ld a, h - or l - ret z ; Return if NULL - ld c, (hl) - inc hl - ld b, (hl) - dec hl ; BC = LEN(a$) - inc bc - inc bc ; BC = LEN(a$) + 2 (two bytes for length) - push hl - push bc - call __MEM_ALLOC - pop bc ; Recover length - pop de ; Recover origin - ld a, h - or l - ret z ; Return if NULL (No memory) - ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE - push de ; Saves destiny start - ldir ; Copies string (length number included) - pop hl ; Recovers destiny in hl as result - ret - pop namespace -#line 24 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/iloadf.asm" - ; __FASTCALL__ routine which - ; loads a 40 bits floating point into A ED CB - ; stored at position pointed by POINTER HL - ;A DE, BC <-- ((HL)) - push namespace core -__ILOADF: - ld a, (hl) - inc hl - ld h, (hl) - ld l, a - ; __FASTCALL__ routine which - ; loads a 40 bits floating point into A ED CB - ; stored at position pointed by POINTER HL - ;A DE, BC <-- (HL) -__LOADF: ; Loads a 40 bits FP number from address pointed by HL - ld a, (hl) - inc hl - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld c, (hl) - inc hl - ld b, (hl) - ret - pop namespace -#line 26 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftof16reg.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm" - push namespace core -__FTOU32REG: ; Converts a Float to (un)signed 32 bit integer (NOTE: It's ALWAYS 32 bit signed) - ; Input FP number in A EDCB (A exponent, EDCB mantissa) - ; Output: DEHL 32 bit number (signed) - PROC - LOCAL __IS_FLOAT - LOCAL __NEGATE - or a - jr nz, __IS_FLOAT - ; Here if it is a ZX ROM Integer - ld h, c - ld l, d - ld d, e - ret -__IS_FLOAT: ; Jumps here if it is a true floating point number - ld h, e - push hl ; Stores it for later (Contains Sign in H) - push de - push bc - exx - pop de ; Loads mantissa into C'B' E'D' - pop bc ; - set 7, c ; Highest mantissa bit is always 1 - exx - ld hl, 0 ; DEHL = 0 - ld d, h - ld e, l - ;ld a, c ; Get exponent - sub 128 ; Exponent -= 128 - jr z, __FTOU32REG_END ; If it was <= 128, we are done (Integers must be > 128) - jr c, __FTOU32REG_END ; It was decimal (0.xxx). We are done (return 0) - ld b, a ; Loop counter = exponent - 128 -__FTOU32REG_LOOP: - exx ; Shift C'B' E'D' << 1, output bit stays in Carry - sla d - rl e - rl b - rl c - exx ; Shift DEHL << 1, inserting the carry on the right - rl l - rl h - rl e - rl d - djnz __FTOU32REG_LOOP -__FTOU32REG_END: - pop af ; Take the sign bit - or a ; Sets SGN bit to 1 if negative - jp m, __NEGATE ; Negates DEHL - ret -__NEGATE: - exx - ld a, d - or e - or b - or c - exx - jr z, __END - inc l - jr nz, __END - inc h - jr nz, __END - inc de - LOCAL __END -__END: - jp __NEG32 - ENDP -__FTOU8: ; Converts float in C ED LH to Unsigned byte in A - call __FTOU32REG - ld a, l - ret - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/ftof16reg.asm" - push namespace core -__FTOF16REG: ; Converts a Float to 16.16 (32 bit) fixed point decimal - ; Input FP number in A EDCB (A exponent, EDCB mantissa) - ld l, a ; Saves exponent for later - or d - or e - or b - or c - ld h, e - ret z ; Return if ZERO - push hl ; Stores it for later (Contains sign in H, exponent in L) - push de - push bc - exx - pop de ; Loads mantissa into C'B' E'D' - pop bc ; - set 7, c ; Highest mantissa bit is always 1 - exx - ld hl, 0 ; DEHL = 0 - ld d, h - ld e, l - pop bc - ld a, c ; Get exponent - sub 112 ; Exponent -= 128 + 16 - push bc ; Saves sign in b again - jp z, __FTOU32REG_END ; If it was <= 128, we are done (Integers must be > 128) - jp c, __FTOU32REG_END ; It was decimal (0.xxx). We are done (return 0) - ld b, a ; Loop counter = exponent - 128 + 16 (we need to shift 16 bit more) - jp __FTOU32REG_LOOP ; proceed as an u32 integer - pop namespace -#line 27 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 29 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 31 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 32 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 33 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 34 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 35 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 36 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 37 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 38 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 39 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" - ;; Updates restore point to the given HL mem. address - push namespace core -__RESTORE: - PROC - LOCAL __DATA_ADDR - ld (__DATA_ADDR), hl - ret - ;; Reads a value from the DATA mem area and updates __DATA_ADDR ptr to the - ;; next item. On Out Of Data, restarts - ;; -__READ: - LOCAL read_restart, cont, cont2, table, no_func - LOCAL dynamic_cast, dynamic_cast2, dynamic_cast3, dynamic_cast4 - LOCAL _decode_table, coerce_to_int, coerce_to_int2, promote_to_i16 - LOCAL _from_i8, _from_u8 - LOCAL _from_i16, _from_u16 - LOCAL _from_i32, _from_u32 - LOCAL _from_fixed, __data_error - push af ; type of data to read - ld hl, (__DATA_ADDR) -read_restart: - ld a, (hl) - or a ; 0 => OUT of data - jr nz, cont - ;; Signals out of data - ld hl, .DATA.__DATA__0 - ld (__DATA_ADDR), hl - jr read_restart ; Start again -cont: - and 0x80 - ld a, (hl) - push af - jp z, no_func ;; Loads data directly, not a function - inc hl - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld (__DATA_ADDR), hl ;; Store address of next DATA - ex de, hl -cont2: - ld de, dynamic_cast - push de ; ret address - jp (hl) ; "call (hl)" - ;; Now tries to convert the given result to the expected type or raise an error -dynamic_cast: - exx - ex af, af' - pop af ; type READ - and 0x7F ; clear bit 7 - pop hl ; type requested by USER (type of the READ variable) - ld c, h ; save requested type (save it in register C) - cp h - exx - jr nz, dynamic_cast2 ; Types are identical? - ;; yes, they are - ex af, af' - ret -dynamic_cast2: - cp 1 ; Requested a number, but read a string? - jr nz, dynamic_cast3 - call __MEM_FREE ; Frees str from memory - jr __data_error -dynamic_cast3: - exx - ld b, a ; Read type - ld a, c ; Requested type - cp 1 - jr z, __data_error - cp b - jr c, dynamic_cast4 - ;; here the user expected type is "larger" than the read one - ld a, b - sub 2 - add a, a - ld l, a - ld h, 0 - ld de, _decode_table - add hl, de - ld e, (hl) - inc hl - ld h, (hl) - ld l, e - push hl - ld a, c ; Requested type - exx - ret -__data_error: - ;; When a data is read, but cannot be converted to the requested type - ;; that is, the user asked for a string and we read a number or vice versa - ld a, ERROR_InvalidArg - call __STOP ; The user expected a string, but read a number - xor a - ld h, a - ld l, a - ld e, a - ld d, a - ld b, a - ld c, a - ret -_decode_table: - dw _from_i8 - dw _from_u8 - dw _from_i16 - dw _from_u16 - dw _from_i32 - dw _from_u32 - dw _from_fixed -_from_i8: - cp 4 - jr nc, promote_to_i16 - ex af, af' - ret ;; Was from Byte to Ubyte -promote_to_i16: - ex af, af' - ld l, a - rla - sbc a, a - ld h, a ; copy sgn to h - ex af, af' - jr _before_from_i16 -_from_u8: - ex af, af' - ld l, a - ld h, 0 - ex af, af' - ;; Promoted to i16 -_before_from_i16: -_from_i16: - cp 6 - ret c ;; from i16 to u16 - ;; Promote i16 to i32 - ex af, af' - ld a, h - rla - sbc a, a - ld e, a - ld d, a - ex af, af' -_from_i32: - cp 7 - ret z ;; From i32 to u32 - ret c ;; From u16 to i32 - cp 9 - jp z, __I32TOFREG -_from_u32: - cp 9 - jp z, __U32TOFREG - ex de, hl - ld hl, 0 - cp 8 - ret z -_from_fixed: ;; From fixed to float - jp __F16TOFREG -_from_u16: - ld de, 0 ; HL 0x0000 => 32 bits - jp _from_i32 -dynamic_cast4: - ;; The user type is "shorter" than the read one - cp 8 ;; required type - jr c, before_to_int ;; required < fixed (f16) - ex af, af' - exx ;; Ok, we must convert from float to f16 - jp __FTOF16REG -before_to_int: - ld a, b ;; read type - cp 8 ;; - jr c, coerce_to_int2 - jr nz, coerce_to_int ;; From float to int - ld a, c ;; user type - exx - ;; f16 to Long - ex de, hl - ld a, h - rla - sbc a, a - ld d, a - ld e, a - exx - jr coerce_to_int2 -coerce_to_int: - exx - ex af, af' - call __FTOU32REG - ex af, af' ; a contains user type - exx -coerce_to_int2: ; At this point we have an u/integer in hl - exx - cp 4 - ret nc ; Already done. Return the result - ld a, l ; Truncate to byte - ret -no_func: - exx - ld de, dynamic_cast - push de ; Ret address - dec a ; 0 => string; 1, 2 => byte; 3, 4 => integer; 5, 6 => long, 7 => fixed; 8 => float - ld h, 0 - add a, a - ld l, a - ld de, table - add hl, de - ld e, (hl) - inc hl - ld h, (hl) - ld l, e - push hl ; address to jump to - exx - inc hl - ret ; jp (sp) => jump to table[a - 1] -table: - LOCAL __01_decode_string - LOCAL __02_decode_byte - LOCAL __03_decode_ubyte - LOCAL __04_decode_integer - LOCAL __05_decode_uinteger - LOCAL __06_decode_long - LOCAL __07_decode_ulong - LOCAL __08_decode_fixed - LOCAL __09_decode_float - ;; 1 -> Decode string - ;; 2, 3 -> Decode Byte, UByte - ;; 4, 5 -> Decode Integer, UInteger - ;; 6, 7 -> Decode Long, ULong - ;; 8 -> Decode Fixed - ;; 9 -> Decode Float - dw __01_decode_string - dw __02_decode_byte - dw __03_decode_ubyte - dw __04_decode_integer - dw __05_decode_uinteger - dw __06_decode_long - dw __07_decode_ulong - dw __08_decode_fixed - dw __09_decode_float -__01_decode_string: - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld (__DATA_ADDR), hl ;; Store address of next DATA - ex de, hl - jp __LOADSTR -__02_decode_byte: -__03_decode_ubyte: - ld a, (hl) - inc hl - ld (__DATA_ADDR), hl - ret -__04_decode_integer: -__05_decode_uinteger: - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld (__DATA_ADDR), hl - ex de, hl - ret -__06_decode_long: -__07_decode_ulong: -__08_decode_fixed: - ld b, h - ld c, l - inc bc - inc bc - inc bc - inc bc - ld (__DATA_ADDR), bc - jp __ILOAD32 -__09_decode_float: - call __LOADF - inc hl - ld (__DATA_ADDR), hl - ld h, a ; returns A in H; sets A free - ret -__DATA_ADDR: ;; Stores current DATA ptr - dw .DATA.__DATA__0 - ENDP - pop namespace -#line 122 "arch/zx48k/read13.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/store32.asm" - push namespace core -__PISTORE32: - push hl - push ix - pop hl - add hl, bc - pop bc -__ISTORE32: ; Load address at hl, and stores E,D,B,C integer at that address - ld a, (hl) - inc hl - ld h, (hl) - ld l, a -__STORE32: ; Stores the given integer in DEBC at address HL - ld (hl), c - inc hl - ld (hl), b - inc hl - ld (hl), e - inc hl - ld (hl), d - ret - pop namespace -#line 123 "arch/zx48k/read13.bas" - END diff --git a/tests/functional/arch/zx48k/read14.asm b/tests/functional/arch/zx48k/read14.asm index ccb3166a9..d4d43a497 100644 --- a/tests/functional/arch/zx48k/read14.asm +++ b/tests/functional/arch/zx48k/read14.asm @@ -50,7 +50,7 @@ _j: __DATA__END: DEFB 00h ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" ;; This implements READ & RESTORE functions ;; Reads a new element from the DATA Address code ;; Updates the DATA_ADDR read ptr for the next read @@ -68,7 +68,7 @@ __DATA__END: ;; 09: Float ;; bit7 is set for a parameter-less function ;; In that case, the next two bytes are the ptr of the function to jump -#line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" ; Simple error control routines ; vim:ts=4:et: push namespace core @@ -102,9 +102,9 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 23 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 23 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa ; (a.k.a. Boriel) @@ -164,7 +164,7 @@ __STOP: ; HL = BLOCK Start & DE = Length. ; An init directive is useful for initialization routines. ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/heapinit.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa ; (a.k.a. Boriel) @@ -271,7 +271,7 @@ __MEM_INIT2: ret ENDP pop namespace -#line 70 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 70 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; --------------------------------------------------------------------- ; MEM_ALLOC ; Allocates a block of memory in the heap. @@ -302,9 +302,9 @@ __MEM_START: __MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE ld a, h ; HL = NULL (No memory available?) or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 113 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 115 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; HL = Pointer to Free block ld e, (hl) inc hl @@ -369,7 +369,7 @@ __MEM_SUBTRACT: ret ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" ; Loads a string (ptr) from HL ; and duplicates it on dynamic memory again ; Finally, it returns result pointer in HL @@ -406,8 +406,8 @@ __LOADSTR: ; __FASTCALL__ entry pop hl ; Recovers destiny in hl as result ret pop namespace -#line 24 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/iload32.asm" +#line 24 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/iload32.asm" ; __FASTCALL__ routine which ; loads a 32 bits integer into DE,HL ; stored at position pointed by POINTER HL @@ -425,8 +425,8 @@ __ILOAD32: ex de, hl ret pop namespace -#line 25 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/iloadf.asm" +#line 25 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/iloadf.asm" ; __FASTCALL__ routine which ; loads a 40 bits floating point into A ED CB ; stored at position pointed by POINTER HL @@ -453,10 +453,10 @@ __LOADF: ; Loads a 40 bits FP number from address pointed by HL ld b, (hl) ret pop namespace -#line 26 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ftof16reg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/neg32.asm" +#line 26 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftof16reg.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg32.asm" push namespace core __ABS32: bit 7, d @@ -481,7 +481,7 @@ __NEG32: ; Negates DEHL (Two's complement) inc de ret pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm" push namespace core __FTOU32REG: ; Converts a Float to (un)signed 32 bit integer (NOTE: It's ALWAYS 32 bit signed) ; Input FP number in A EDCB (A exponent, EDCB mantissa) @@ -553,7 +553,7 @@ __FTOU8: ; Converts float in C ED LH to Unsigned byte in A ld a, l ret pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/ftof16reg.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/ftof16reg.asm" push namespace core __FTOF16REG: ; Converts a Float to 16.16 (32 bit) fixed point decimal ; Input FP number in A EDCB (A exponent, EDCB mantissa) @@ -584,9 +584,9 @@ __FTOF16REG: ; Converts a Float to 16.16 (32 bit) fixed point decimal ld b, a ; Loop counter = exponent - 128 + 16 (we need to shift 16 bit more) jp __FTOU32REG_LOOP ; proceed as an u32 integer pop namespace -#line 27 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/f16tofreg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/u32tofreg.asm" +#line 27 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/f16tofreg.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/u32tofreg.asm" push namespace core __I8TOFREG: ld l, a @@ -656,7 +656,7 @@ __U32TOFREG_END: ret ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/f16tofreg.asm" +#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/f16tofreg.asm" push namespace core __F16TOFREG: ; Converts a 16.16 signed fixed point (stored in DEHL) ; to a Floating Point Number returned in (C ED CB) @@ -691,8 +691,8 @@ __F16TOFREG2: ; Converts an unsigned 32 bit integer (DEHL) jp __U32TOFREG_LOOP ; Proceed as an integer ENDP pop namespace -#line 28 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +#line 28 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa ; (a.k.a. Boriel) @@ -850,16 +850,16 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ret ENDP pop namespace -#line 29 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 31 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 32 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 33 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 34 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 35 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 36 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 37 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 38 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 39 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" +#line 29 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 31 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 32 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 33 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 34 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 35 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 36 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 37 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 38 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 39 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" ;; Updates restore point to the given HL mem. address push namespace core __RESTORE: @@ -1019,6 +1019,13 @@ _from_u16: jp _from_i32 dynamic_cast4: ;; The user type is "shorter" than the read one + ld a, b ;; read type + cp 4 ;; if user type < read type < _i16 => From Ubyte to Byte. Return af' + jr nc, 1f + ex af, af' + ret +1: + ld a, c ;; recover user required type cp 8 ;; required type jr c, before_to_int ;; required < fixed (f16) ex af, af' @@ -1139,5 +1146,5 @@ __DATA_ADDR: ;; Stores current DATA ptr dw .DATA.__DATA__0 ENDP pop namespace -#line 25 "read14.bas" +#line 25 "arch/zx48k/read14.bas" END diff --git a/tests/functional/arch/zx48k/read4.asm b/tests/functional/arch/zx48k/read4.asm index 72d4d2b52..a7ebf2aa9 100644 --- a/tests/functional/arch/zx48k/read4.asm +++ b/tests/functional/arch/zx48k/read4.asm @@ -1255,6 +1255,13 @@ _from_u16: jp _from_i32 dynamic_cast4: ;; The user type is "shorter" than the read one + ld a, b ;; read type + cp 4 ;; if user type < read type < _i16 => From Ubyte to Byte. Return af' + jr nc, 1f + ex af, af' + ret +1: + ld a, c ;; recover user required type cp 8 ;; required type jr c, before_to_int ;; required < fixed (f16) ex af, af' diff --git a/tests/functional/arch/zx48k/read5.asm b/tests/functional/arch/zx48k/read5.asm deleted file mode 100644 index 35ce4c0b1..000000000 --- a/tests/functional/arch/zx48k/read5.asm +++ /dev/null @@ -1,2327 +0,0 @@ - org 32768 -.core.__START_PROGRAM: - di - push ix - push iy - exx - push hl - exx - ld hl, 0 - add hl, sp - ld (.core.__CALL_BACK__), hl - ei - call .core.__MEM_INIT - call .core.__PRINT_INIT - jp .core.__MAIN_PROGRAM__ -.core.__CALL_BACK__: - DEFW 0 -.core.ZXBASIC_USER_DATA: - ; Defines HEAP SIZE -.core.ZXBASIC_HEAP_SIZE EQU 4768 -.core.ZXBASIC_MEM_HEAP: - DEFS 4768 - ; Defines USER DATA Length in bytes -.core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA - .core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN - .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA -_v: - DEFB 81h - DEFB 40h - DEFB 00h - DEFB 00h - DEFB 00h -_c: - DEFB 00, 00, 00, 00, 00 -_d: - DEFB 00, 00, 00, 00, 00 -_i: - DEFB 00 -.core.ZXBASIC_USER_DATA_END: -.core.__MAIN_PROGRAM__: - ld hl, .DATA.__DATA__0 - call .core.__RESTORE - ld a, 1 - ld (_i), a - jp .LABEL.__LABEL0 -.LABEL.__LABEL3: - ld a, 9 - call .core.__READ - ld hl, _c - call .core.__STOREF - ld a, 9 - call .core.__READ - ld hl, _d - call .core.__STOREF - call .core.COPY_ATTR - ld a, (_c) - ld de, (_c + 1) - ld bc, (_c + 3) - call .core.__PRINTF - call .core.PRINT_COMMA - ld a, (_d) - ld de, (_d + 1) - ld bc, (_d + 3) - call .core.__PRINTF - call .core.PRINT_EOL -.LABEL.__LABEL4: - ld hl, _i - inc (hl) -.LABEL.__LABEL0: - ld a, 4 - ld hl, (_i - 1) - cp h - jp nc, .LABEL.__LABEL3 -.LABEL.__LABEL2: - ld hl, 0 - ld b, h - ld c, l -.core.__END_PROGRAM: - di - ld hl, (.core.__CALL_BACK__) - ld sp, hl - exx - pop hl - exx - pop iy - pop ix - ei - ret -___DATA__FUNCPTR__0: - ld a, (_v) - ld de, (_v + 1) - ld bc, (_v + 3) - ld hl, 00000h - push hl - ld hl, 00048h - push hl - ld h, 085h - push hl - call .core.__MULF -___DATA__FUNCPTR__0__leave: - ret -___DATA__FUNCPTR__1: - ld a, (_v) - ld de, (_v + 1) - ld bc, (_v + 3) - call .core.SIN - push bc - push de - push af - ld a, (_v) - ld de, (_v + 1) - ld bc, (_v + 3) - call .core.TAN - push bc - push de - push af - ld a, 082h - ld de, 00000h - ld bc, 00000h - call .core.__POW - call .core.__MULF -___DATA__FUNCPTR__1__leave: - ret -___DATA__FUNCPTR__2: - ld a, (_v) - ld de, (_v + 1) - ld bc, (_v + 3) - ld hl, 0A2DAh - push hl - ld hl, 00F49h - push hl - ld h, 082h - push hl - call .core.__MULF -___DATA__FUNCPTR__2__leave: - ret -.DATA.__DATA__0: - DEFB 3 - DEFB 10 - DEFB 89h - DEFW ___DATA__FUNCPTR__0 - DEFB 89h - DEFW ___DATA__FUNCPTR__1 - DEFB 89h - DEFW ___DATA__FUNCPTR__2 -__DATA__END: - DEFB 00h - ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mulf.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/stackf.asm" - ; ------------------------------------------------------------- - ; Functions to manage FP-Stack of the ZX Spectrum ROM CALC - ; ------------------------------------------------------------- - push namespace core - __FPSTACK_PUSH EQU 2AB6h ; Stores an FP number into the ROM FP stack (A, ED CB) - __FPSTACK_POP EQU 2BF1h ; Pops an FP number out of the ROM FP stack (A, ED CB) -__FPSTACK_PUSH2: ; Pushes Current A ED CB registers and top of the stack on (SP + 4) - ; Second argument to push into the stack calculator is popped out of the stack - ; Since the caller routine also receives the parameters into the top of the stack - ; four bytes must be removed from SP before pop them out - call __FPSTACK_PUSH ; Pushes A ED CB into the FP-STACK - exx - pop hl ; Caller-Caller return addr - exx - pop hl ; Caller return addr - pop af - pop de - pop bc - push hl ; Caller return addr - exx - push hl ; Caller-Caller return addr - exx - jp __FPSTACK_PUSH -__FPSTACK_I16: ; Pushes 16 bits integer in HL into the FP ROM STACK - ; This format is specified in the ZX 48K Manual - ; You can push a 16 bit signed integer as - ; 0 SS LL HH 0, being SS the sign and LL HH the low - ; and High byte respectively - ld a, h - rla ; sign to Carry - sbc a, a ; 0 if positive, FF if negative - ld e, a - ld d, l - ld c, h - xor a - ld b, a - jp __FPSTACK_PUSH - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mulf.asm" - ; ------------------------------------------------------------- - ; Floating point library using the FP ROM Calculator (ZX 48K) - ; All of them uses A EDCB registers as 1st paramter. - ; For binary operators, the 2n operator must be pushed into the - ; stack, in the order A DE BC. - ; - ; Uses CALLEE convention - ; ------------------------------------------------------------- - push namespace core -__MULF: ; Multiplication - call __FPSTACK_PUSH2 - ; ------------- ROM MUL - rst 28h - defb 04h ; - defb 38h; ; END CALC - jp __FPSTACK_POP - pop namespace -#line 110 "arch/zx48k/read5.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" - ;; ----------------------------------------------------------------------- - ;; ZX Basic System Vars - ;; Some of them will be mapped over Sinclair ROM ones for compatibility - ;; ----------------------------------------------------------------------- - push namespace core -SCREEN_ADDR: DW 16384 ; Screen address (can be pointed to other place to use a screen buffer) -SCREEN_ATTR_ADDR: DW 22528 ; Screen attribute address (ditto.) - ; These are mapped onto ZX Spectrum ROM VARS - CHARS EQU 23606 ; Pointer to ROM/RAM Charset - TV_FLAG EQU 23612 ; Flags for controlling output to screen - UDG EQU 23675 ; Pointer to UDG Charset - COORDS EQU 23677 ; Last PLOT coordinates - FLAGS2 EQU 23681 ; - ECHO_E EQU 23682 ; - DFCC EQU 23684 ; Next screen addr for PRINT - DFCCL EQU 23686 ; Next screen attr for PRINT - S_POSN EQU 23688 - ATTR_P EQU 23693 ; Current Permanent ATTRS set with INK, PAPER, etc commands - ATTR_T EQU 23695 ; temporary ATTRIBUTES - P_FLAG EQU 23697 ; - MEM0 EQU 23698 ; Temporary memory buffer used by ROM chars - SCR_COLS EQU 33 ; Screen with in columns + 1 - SCR_ROWS EQU 24 ; Screen height in rows - SCR_SIZE EQU (SCR_ROWS << 8) + SCR_COLS - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" - ; Simple error control routines -; vim:ts=4:et: - push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop - ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a - ret - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 111 "arch/zx48k/read5.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/math/pow.asm" - ; ------------------------------------------------------------- - ; Floating point library using the FP ROM Calculator (ZX 48K) - ; All of them uses A EDCB registers as 1st paramter. - ; For binary operators, the 2n operator must be pushed into the - ; stack, in the order A DE BC. - ; - ; Uses CALLEE convention - ; -; Operands comes swapped: - ; 1 st parameter is the BASE (A ED CB) - ; 2 nd parameter (Top of the stack) is Exponent - ; ------------------------------------------------------------- - push namespace core -__POW: ; Exponentiation - PROC - call __FPSTACK_PUSH2 - ; ------------- ROM POW - rst 28h - defb 01h ; Exchange => 1, Base - defb 06h ; POW - defb 38h; ; END CALC - jp __FPSTACK_POP - ENDP - pop namespace -#line 112 "arch/zx48k/read5.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/math/sin.asm" - push namespace core -SIN: ; Computes SIN using ROM FP-CALC - call __FPSTACK_PUSH - rst 28h ; ROM CALC - defb 1Fh - defb 38h ; END CALC - jp __FPSTACK_POP - pop namespace -#line 113 "arch/zx48k/read5.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/math/tan.asm" - push namespace core -TAN: ; Computes TAN using ROM FP-CALC - call __FPSTACK_PUSH - rst 28h ; ROM CALC - defb 21h ; TAN - defb 38h ; END CALC - jp __FPSTACK_POP - pop namespace -#line 114 "arch/zx48k/read5.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printf.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 5 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL - push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later - ld a, h - or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) - ld a, (hl) - call __PRINTCHAR - inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printf.asm" - push namespace core -__PRINTF: ; Prints a Fixed point Number stored in C ED LH - PROC - LOCAL RECLAIM2 - LOCAL STK_END - STK_END EQU 5C65h - ld hl, (ATTR_T) - push hl ; Saves ATTR_T since BUG ROM changes it - ld hl, (STK_END) - push hl ; Stores STK_END - call __FPSTACK_PUSH ; Push number into stack - rst 28h ; # Rom Calculator - defb 2Eh ; # STR$(x) - defb 38h ; # END CALC - call __FPSTACK_POP ; Recovers string parameters to A ED CB - pop hl - ld (STK_END), hl ; Balance STK_END to avoid STR$ bug - pop hl - ld (ATTR_T), hl ; Restores ATTR_T - ex de, hl ; String position now in HL - push bc - xor a ; Avoid the str to be FREED from heap - call __PRINT_STR - pop bc - inc bc - jp RECLAIM2 ; Frees TMP Memory - RECLAIM2 EQU 19E8h - ENDP - pop namespace -#line 116 "arch/zx48k/read5.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" - ;; This implements READ & RESTORE functions - ;; Reads a new element from the DATA Address code - ;; Updates the DATA_ADDR read ptr for the next read - ;; Data codification is 1 byte for type followed by data bytes - ;; Byte type is encoded as follows -;; 00: End of data -;; 01: String -;; 02: Byte -;; 03: Ubyte -;; 04: Integer -;; 05: UInteger -;; 06: Long -;; 07: ULong -;; 08: Fixed -;; 09: Float - ;; bit7 is set for a parameter-less function - ;; In that case, the next two bytes are the ptr of the function to jump -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the MIT license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the MIT license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be freed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; MEM_ALLOC - ; Allocates a block of memory in the heap. - ; - ; Parameters - ; BC = Length of requested memory block - ; -; Returns: - ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) - ; if the block could not be allocated (out of memory) - ; --------------------------------------------------------------------- - push namespace core -MEM_ALLOC: -__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) - PROC - LOCAL __MEM_LOOP - LOCAL __MEM_DONE - LOCAL __MEM_SUBTRACT - LOCAL __MEM_START - LOCAL TEMP, TEMP0 - TEMP EQU TEMP0 + 1 - ld hl, 0 - ld (TEMP), hl -__MEM_START: - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start - inc bc - inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer -__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE - ld a, h ; HL = NULL (No memory available?) - or l -#line 113 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" - ret z ; NULL -#line 115 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" - ; HL = Pointer to Free block - ld e, (hl) - inc hl - ld d, (hl) - inc hl ; DE = Block Length - push hl ; HL = *pointer to -> next block - ex de, hl - or a ; CF = 0 - sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) - jp nc, __MEM_DONE - pop hl - ld (TEMP), hl - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl - jp __MEM_LOOP -__MEM_DONE: ; A free block has been found. - ; Check if at least 4 bytes remains free (HL >= 4) - push hl - exx ; exx to preserve bc - pop hl - ld bc, 4 - or a - sbc hl, bc - exx - jp nc, __MEM_SUBTRACT - ; At this point... - ; less than 4 bytes remains free. So we return this block entirely - ; We must link the previous block with the next to this one - ; (DE) => Pointer to next block - ; (TEMP) => &(previous->next) - pop hl ; Discard current block pointer - push de - ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer - ld a, (hl) - inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex de, hl ; HL = Previous block pointer; DE = Next block pointer -TEMP0: - ld hl, 0 ; Pre-previous block pointer - ld (hl), e - inc hl - ld (hl), d ; LINKED - pop hl ; Returning block. - ret -__MEM_SUBTRACT: - ; At this point we have to store HL value (Length - BC) into (DE - 2) - ex de, hl - dec hl - ld (hl), d - dec hl - ld (hl), e ; Store new block length - add hl, de ; New length + DE => free-block start - pop de ; Remove previous HL off the stack - ld (hl), c ; Store length on its 1st word - inc hl - ld (hl), b - inc hl ; Return hl - ret - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" - ; Loads a string (ptr) from HL - ; and duplicates it on dynamic memory again - ; Finally, it returns result pointer in HL - push namespace core -__ILOADSTR: ; This is the indirect pointer entry HL = (HL) - ld a, h - or l - ret z - ld a, (hl) - inc hl - ld h, (hl) - ld l, a -__LOADSTR: ; __FASTCALL__ entry - ld a, h - or l - ret z ; Return if NULL - ld c, (hl) - inc hl - ld b, (hl) - dec hl ; BC = LEN(a$) - inc bc - inc bc ; BC = LEN(a$) + 2 (two bytes for length) - push hl - push bc - call __MEM_ALLOC - pop bc ; Recover length - pop de ; Recover origin - ld a, h - or l - ret z ; Return if NULL (No memory) - ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE - push de ; Saves destiny start - ldir ; Copies string (length number included) - pop hl ; Recovers destiny in hl as result - ret - pop namespace -#line 24 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/iload32.asm" - ; __FASTCALL__ routine which - ; loads a 32 bits integer into DE,HL - ; stored at position pointed by POINTER HL - ; DE,HL <-- (HL) - push namespace core -__ILOAD32: - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld a, (hl) - inc hl - ld h, (hl) - ld l, a - ex de, hl - ret - pop namespace -#line 25 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/iloadf.asm" - ; __FASTCALL__ routine which - ; loads a 40 bits floating point into A ED CB - ; stored at position pointed by POINTER HL - ;A DE, BC <-- ((HL)) - push namespace core -__ILOADF: - ld a, (hl) - inc hl - ld h, (hl) - ld l, a - ; __FASTCALL__ routine which - ; loads a 40 bits floating point into A ED CB - ; stored at position pointed by POINTER HL - ;A DE, BC <-- (HL) -__LOADF: ; Loads a 40 bits FP number from address pointed by HL - ld a, (hl) - inc hl - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld c, (hl) - inc hl - ld b, (hl) - ret - pop namespace -#line 26 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftof16reg.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg32.asm" - push namespace core -__ABS32: - bit 7, d - ret z -__NEG32: ; Negates DEHL (Two's complement) - ld a, l - cpl - ld l, a - ld a, h - cpl - ld h, a - ld a, e - cpl - ld e, a - ld a, d - cpl - ld d, a - inc l - ret nz - inc h - ret nz - inc de - ret - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm" - push namespace core -__FTOU32REG: ; Converts a Float to (un)signed 32 bit integer (NOTE: It's ALWAYS 32 bit signed) - ; Input FP number in A EDCB (A exponent, EDCB mantissa) - ; Output: DEHL 32 bit number (signed) - PROC - LOCAL __IS_FLOAT - LOCAL __NEGATE - or a - jr nz, __IS_FLOAT - ; Here if it is a ZX ROM Integer - ld h, c - ld l, d - ld d, e - ret -__IS_FLOAT: ; Jumps here if it is a true floating point number - ld h, e - push hl ; Stores it for later (Contains Sign in H) - push de - push bc - exx - pop de ; Loads mantissa into C'B' E'D' - pop bc ; - set 7, c ; Highest mantissa bit is always 1 - exx - ld hl, 0 ; DEHL = 0 - ld d, h - ld e, l - ;ld a, c ; Get exponent - sub 128 ; Exponent -= 128 - jr z, __FTOU32REG_END ; If it was <= 128, we are done (Integers must be > 128) - jr c, __FTOU32REG_END ; It was decimal (0.xxx). We are done (return 0) - ld b, a ; Loop counter = exponent - 128 -__FTOU32REG_LOOP: - exx ; Shift C'B' E'D' << 1, output bit stays in Carry - sla d - rl e - rl b - rl c - exx ; Shift DEHL << 1, inserting the carry on the right - rl l - rl h - rl e - rl d - djnz __FTOU32REG_LOOP -__FTOU32REG_END: - pop af ; Take the sign bit - or a ; Sets SGN bit to 1 if negative - jp m, __NEGATE ; Negates DEHL - ret -__NEGATE: - exx - ld a, d - or e - or b - or c - exx - jr z, __END - inc l - jr nz, __END - inc h - jr nz, __END - inc de - LOCAL __END -__END: - jp __NEG32 - ENDP -__FTOU8: ; Converts float in C ED LH to Unsigned byte in A - call __FTOU32REG - ld a, l - ret - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/ftof16reg.asm" - push namespace core -__FTOF16REG: ; Converts a Float to 16.16 (32 bit) fixed point decimal - ; Input FP number in A EDCB (A exponent, EDCB mantissa) - ld l, a ; Saves exponent for later - or d - or e - or b - or c - ld h, e - ret z ; Return if ZERO - push hl ; Stores it for later (Contains sign in H, exponent in L) - push de - push bc - exx - pop de ; Loads mantissa into C'B' E'D' - pop bc ; - set 7, c ; Highest mantissa bit is always 1 - exx - ld hl, 0 ; DEHL = 0 - ld d, h - ld e, l - pop bc - ld a, c ; Get exponent - sub 112 ; Exponent -= 128 + 16 - push bc ; Saves sign in b again - jp z, __FTOU32REG_END ; If it was <= 128, we are done (Integers must be > 128) - jp c, __FTOU32REG_END ; It was decimal (0.xxx). We are done (return 0) - ld b, a ; Loop counter = exponent - 128 + 16 (we need to shift 16 bit more) - jp __FTOU32REG_LOOP ; proceed as an u32 integer - pop namespace -#line 27 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/f16tofreg.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/u32tofreg.asm" - push namespace core -__I8TOFREG: - ld l, a - rlca - sbc a, a ; A = SGN(A) - ld h, a - ld e, a - ld d, a -__I32TOFREG: ; Converts a 32bit signed integer (stored in DEHL) - ; to a Floating Point Number returned in (A ED CB) - ld a, d - or a ; Test sign - jp p, __U32TOFREG ; It was positive, proceed as 32bit unsigned - call __NEG32 ; Convert it to positive - call __U32TOFREG ; Convert it to Floating point - set 7, e ; Put the sign bit (negative) in the 31bit of mantissa - ret -__U8TOFREG: - ; Converts an unsigned 8 bit (A) to Floating point - ld l, a - ld h, 0 - ld e, h - ld d, h -__U32TOFREG: ; Converts an unsigned 32 bit integer (DEHL) - ; to a Floating point number returned in A ED CB - PROC - LOCAL __U32TOFREG_END - ld a, d - or e - or h - or l - ld b, d - ld c, e ; Returns 00 0000 0000 if ZERO - ret z - push de - push hl - exx - pop de ; Loads integer into B'C' D'E' - pop bc - exx - ld l, 128 ; Exponent - ld bc, 0 ; DEBC = 0 - ld d, b - ld e, c -__U32TOFREG_LOOP: ; Also an entry point for __F16TOFREG - exx - ld a, d ; B'C'D'E' == 0 ? - or e - or b - or c - jp z, __U32TOFREG_END ; We are done - srl b ; Shift B'C' D'E' >> 1, output bit stays in Carry - rr c - rr d - rr e - exx - rr e ; Shift EDCB >> 1, inserting the carry on the left - rr d - rr c - rr b - inc l ; Increment exponent - jp __U32TOFREG_LOOP -__U32TOFREG_END: - exx - ld a, l ; Puts the exponent in a - res 7, e ; Sets the sign bit to 0 (positive) - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/f16tofreg.asm" - push namespace core -__F16TOFREG: ; Converts a 16.16 signed fixed point (stored in DEHL) - ; to a Floating Point Number returned in (C ED CB) - PROC - LOCAL __F16TOFREG2 - ld a, d - or a ; Test sign - jp p, __F16TOFREG2 ; It was positive, proceed as 32bit unsigned - call __NEG32 ; Convert it to positive - call __F16TOFREG2 ; Convert it to Floating point - set 7, e ; Put the sign bit (negative) in the 31bit of mantissa - ret -__F16TOFREG2: ; Converts an unsigned 32 bit integer (DEHL) - ; to a Floating point number returned in C DE HL - ld a, d - or e - or h - or l - ld b, h - ld c, l - ret z ; Return 00 0000 0000 if 0 - push de - push hl - exx - pop de ; Loads integer into B'C' D'E' - pop bc - exx - ld l, 112 ; Exponent - ld bc, 0 ; DEBC = 0 - ld d, b - ld e, c - jp __U32TOFREG_LOOP ; Proceed as an integer - ENDP - pop namespace -#line 28 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 31 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 32 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 33 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 34 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 35 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 36 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 37 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 38 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" -#line 39 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" - ;; Updates restore point to the given HL mem. address - push namespace core -__RESTORE: - PROC - LOCAL __DATA_ADDR - ld (__DATA_ADDR), hl - ret - ;; Reads a value from the DATA mem area and updates __DATA_ADDR ptr to the - ;; next item. On Out Of Data, restarts - ;; -__READ: - LOCAL read_restart, cont, cont2, table, no_func - LOCAL dynamic_cast, dynamic_cast2, dynamic_cast3, dynamic_cast4 - LOCAL _decode_table, coerce_to_int, coerce_to_int2, promote_to_i16 - LOCAL _from_i8, _from_u8 - LOCAL _from_i16, _from_u16 - LOCAL _from_i32, _from_u32 - LOCAL _from_fixed, __data_error - push af ; type of data to read - ld hl, (__DATA_ADDR) -read_restart: - ld a, (hl) - or a ; 0 => OUT of data - jr nz, cont - ;; Signals out of data - ld hl, .DATA.__DATA__0 - ld (__DATA_ADDR), hl - jr read_restart ; Start again -cont: - and 0x80 - ld a, (hl) - push af - jp z, no_func ;; Loads data directly, not a function - inc hl - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld (__DATA_ADDR), hl ;; Store address of next DATA - ex de, hl -cont2: - ld de, dynamic_cast - push de ; ret address - jp (hl) ; "call (hl)" - ;; Now tries to convert the given result to the expected type or raise an error -dynamic_cast: - exx - ex af, af' - pop af ; type READ - and 0x7F ; clear bit 7 - pop hl ; type requested by USER (type of the READ variable) - ld c, h ; save requested type (save it in register C) - cp h - exx - jr nz, dynamic_cast2 ; Types are identical? - ;; yes, they are - ex af, af' - ret -dynamic_cast2: - cp 1 ; Requested a number, but read a string? - jr nz, dynamic_cast3 - call __MEM_FREE ; Frees str from memory - jr __data_error -dynamic_cast3: - exx - ld b, a ; Read type - ld a, c ; Requested type - cp 1 - jr z, __data_error - cp b - jr c, dynamic_cast4 - ;; here the user expected type is "larger" than the read one - ld a, b - sub 2 - add a, a - ld l, a - ld h, 0 - ld de, _decode_table - add hl, de - ld e, (hl) - inc hl - ld h, (hl) - ld l, e - push hl - ld a, c ; Requested type - exx - ret -__data_error: - ;; When a data is read, but cannot be converted to the requested type - ;; that is, the user asked for a string and we read a number or vice versa - ld a, ERROR_InvalidArg - call __STOP ; The user expected a string, but read a number - xor a - ld h, a - ld l, a - ld e, a - ld d, a - ld b, a - ld c, a - ret -_decode_table: - dw _from_i8 - dw _from_u8 - dw _from_i16 - dw _from_u16 - dw _from_i32 - dw _from_u32 - dw _from_fixed -_from_i8: - cp 4 - jr nc, promote_to_i16 - ex af, af' - ret ;; Was from Byte to Ubyte -promote_to_i16: - ex af, af' - ld l, a - rla - sbc a, a - ld h, a ; copy sgn to h - ex af, af' - jr _before_from_i16 -_from_u8: - ex af, af' - ld l, a - ld h, 0 - ex af, af' - ;; Promoted to i16 -_before_from_i16: -_from_i16: - cp 6 - ret c ;; from i16 to u16 - ;; Promote i16 to i32 - ex af, af' - ld a, h - rla - sbc a, a - ld e, a - ld d, a - ex af, af' -_from_i32: - cp 7 - ret z ;; From i32 to u32 - ret c ;; From u16 to i32 - cp 9 - jp z, __I32TOFREG -_from_u32: - cp 9 - jp z, __U32TOFREG - ex de, hl - ld hl, 0 - cp 8 - ret z -_from_fixed: ;; From fixed to float - jp __F16TOFREG -_from_u16: - ld de, 0 ; HL 0x0000 => 32 bits - jp _from_i32 -dynamic_cast4: - ;; The user type is "shorter" than the read one - cp 8 ;; required type - jr c, before_to_int ;; required < fixed (f16) - ex af, af' - exx ;; Ok, we must convert from float to f16 - jp __FTOF16REG -before_to_int: - ld a, b ;; read type - cp 8 ;; - jr c, coerce_to_int2 - jr nz, coerce_to_int ;; From float to int - ld a, c ;; user type - exx - ;; f16 to Long - ex de, hl - ld a, h - rla - sbc a, a - ld d, a - ld e, a - exx - jr coerce_to_int2 -coerce_to_int: - exx - ex af, af' - call __FTOU32REG - ex af, af' ; a contains user type - exx -coerce_to_int2: ; At this point we have an u/integer in hl - exx - cp 4 - ret nc ; Already done. Return the result - ld a, l ; Truncate to byte - ret -no_func: - exx - ld de, dynamic_cast - push de ; Ret address - dec a ; 0 => string; 1, 2 => byte; 3, 4 => integer; 5, 6 => long, 7 => fixed; 8 => float - ld h, 0 - add a, a - ld l, a - ld de, table - add hl, de - ld e, (hl) - inc hl - ld h, (hl) - ld l, e - push hl ; address to jump to - exx - inc hl - ret ; jp (sp) => jump to table[a - 1] -table: - LOCAL __01_decode_string - LOCAL __02_decode_byte - LOCAL __03_decode_ubyte - LOCAL __04_decode_integer - LOCAL __05_decode_uinteger - LOCAL __06_decode_long - LOCAL __07_decode_ulong - LOCAL __08_decode_fixed - LOCAL __09_decode_float - ;; 1 -> Decode string - ;; 2, 3 -> Decode Byte, UByte - ;; 4, 5 -> Decode Integer, UInteger - ;; 6, 7 -> Decode Long, ULong - ;; 8 -> Decode Fixed - ;; 9 -> Decode Float - dw __01_decode_string - dw __02_decode_byte - dw __03_decode_ubyte - dw __04_decode_integer - dw __05_decode_uinteger - dw __06_decode_long - dw __07_decode_ulong - dw __08_decode_fixed - dw __09_decode_float -__01_decode_string: - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld (__DATA_ADDR), hl ;; Store address of next DATA - ex de, hl - jp __LOADSTR -__02_decode_byte: -__03_decode_ubyte: - ld a, (hl) - inc hl - ld (__DATA_ADDR), hl - ret -__04_decode_integer: -__05_decode_uinteger: - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld (__DATA_ADDR), hl - ex de, hl - ret -__06_decode_long: -__07_decode_ulong: -__08_decode_fixed: - ld b, h - ld c, l - inc bc - inc bc - inc bc - inc bc - ld (__DATA_ADDR), bc - jp __ILOAD32 -__09_decode_float: - call __LOADF - inc hl - ld (__DATA_ADDR), hl - ld h, a ; returns A in H; sets A free - ret -__DATA_ADDR: ;; Stores current DATA ptr - dw .DATA.__DATA__0 - ENDP - pop namespace -#line 117 "arch/zx48k/read5.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/storef.asm" - push namespace core -__PISTOREF: ; Indect Stores a float (A, E, D, C, B) at location stored in memory, pointed by (IX + HL) - push de - ex de, hl ; DE <- HL - push ix - pop hl ; HL <- IX - add hl, de ; HL <- IX + HL - pop de -__ISTOREF: ; Load address at hl, and stores A,E,D,C,B registers at that address. Modifies A' register - ex af, af' - ld a, (hl) - inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex af, af' -__STOREF: ; Stores the given FP number in A EDCB at address HL - ld (hl), a - inc hl - ld (hl), e - inc hl - ld (hl), d - inc hl - ld (hl), c - inc hl - ld (hl), b - ret - pop namespace -#line 118 "arch/zx48k/read5.bas" - END diff --git a/tests/functional/arch/zx48k/read8.asm b/tests/functional/arch/zx48k/read8.asm index 64f563a16..46943918e 100644 --- a/tests/functional/arch/zx48k/read8.asm +++ b/tests/functional/arch/zx48k/read8.asm @@ -2191,6 +2191,13 @@ _from_u16: jp _from_i32 dynamic_cast4: ;; The user type is "shorter" than the read one + ld a, b ;; read type + cp 4 ;; if user type < read type < _i16 => From Ubyte to Byte. Return af' + jr nc, 1f + ex af, af' + ret +1: + ld a, c ;; recover user required type cp 8 ;; required type jr c, before_to_int ;; required < fixed (f16) ex af, af' diff --git a/tests/functional/arch/zx48k/read9.asm b/tests/functional/arch/zx48k/read9.asm index 254b8460d..0a4b91be2 100644 --- a/tests/functional/arch/zx48k/read9.asm +++ b/tests/functional/arch/zx48k/read9.asm @@ -2363,6 +2363,13 @@ _from_u16: jp _from_i32 dynamic_cast4: ;; The user type is "shorter" than the read one + ld a, b ;; read type + cp 4 ;; if user type < read type < _i16 => From Ubyte to Byte. Return af' + jr nc, 1f + ex af, af' + ret +1: + ld a, c ;; recover user required type cp 8 ;; required type jr c, before_to_int ;; required < fixed (f16) ex af, af' diff --git a/tests/functional/arch/zx48k/readbug.asm b/tests/functional/arch/zx48k/readbug.asm deleted file mode 100644 index 2254415c6..000000000 --- a/tests/functional/arch/zx48k/readbug.asm +++ /dev/null @@ -1,1141 +0,0 @@ - org 32768 -.core.__START_PROGRAM: - di - push ix - push iy - exx - push hl - exx - ld hl, 0 - add hl, sp - ld (.core.__CALL_BACK__), hl - ei - call .core.__MEM_INIT - jp .core.__MAIN_PROGRAM__ -.core.__CALL_BACK__: - DEFW 0 -.core.ZXBASIC_USER_DATA: - ; Defines HEAP SIZE -.core.ZXBASIC_HEAP_SIZE EQU 4768 -.core.ZXBASIC_MEM_HEAP: - DEFS 4768 - ; Defines USER DATA Length in bytes -.core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA - .core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN - .core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA -_r1: - DEFB 00 -.core.ZXBASIC_USER_DATA_END: -.core.__MAIN_PROGRAM__: - ld a, 3 - call .core.__READ - ld (_r1), a - ld hl, 0 - ld b, h - ld c, l -.core.__END_PROGRAM: - di - ld hl, (.core.__CALL_BACK__) - ld sp, hl - exx - pop hl - exx - pop iy - pop ix - ei - ret -__DATA__0: -__DATA__END: - DEFB 00h - ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" - ;; This implements READ & RESTORE functions - ;; Reads a new element from the DATA Address code - ;; Updates the DATA_ADDR read ptr for the next read - ;; Data codification is 1 byte for type followed by data bytes - ;; Byte type is encoded as follows -;; 00: End of data -;; 01: String -;; 02: Byte -;; 03: Ubyte -;; 04: Integer -;; 05: UInteger -;; 06: Long -;; 07: ULong -;; 08: Fixed -;; 09: Float - ;; bit7 is set for a parameter-less function - ;; In that case, the next two bytes are the ptr of the function to jump -#line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" - ; Simple error control routines -; vim:ts=4:et: - push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop - ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a - ret - pop namespace -#line 23 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the MIT license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the MIT license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be freed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 70 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; --------------------------------------------------------------------- - ; MEM_ALLOC - ; Allocates a block of memory in the heap. - ; - ; Parameters - ; BC = Length of requested memory block - ; -; Returns: - ; HL = Pointer to the allocated block in memory. Returns 0 (NULL) - ; if the block could not be allocated (out of memory) - ; --------------------------------------------------------------------- - push namespace core -MEM_ALLOC: -__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC) - PROC - LOCAL __MEM_LOOP - LOCAL __MEM_DONE - LOCAL __MEM_SUBTRACT - LOCAL __MEM_START - LOCAL TEMP, TEMP0 - TEMP EQU TEMP0 + 1 - ld hl, 0 - ld (TEMP), hl -__MEM_START: - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start - inc bc - inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer -__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE - ld a, h ; HL = NULL (No memory available?) - or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" - ; HL = Pointer to Free block - ld e, (hl) - inc hl - ld d, (hl) - inc hl ; DE = Block Length - push hl ; HL = *pointer to -> next block - ex de, hl - or a ; CF = 0 - sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length) - jp nc, __MEM_DONE - pop hl - ld (TEMP), hl - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl - jp __MEM_LOOP -__MEM_DONE: ; A free block has been found. - ; Check if at least 4 bytes remains free (HL >= 4) - push hl - exx ; exx to preserve bc - pop hl - ld bc, 4 - or a - sbc hl, bc - exx - jp nc, __MEM_SUBTRACT - ; At this point... - ; less than 4 bytes remains free. So we return this block entirely - ; We must link the previous block with the next to this one - ; (DE) => Pointer to next block - ; (TEMP) => &(previous->next) - pop hl ; Discard current block pointer - push de - ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer - ld a, (hl) - inc hl - ld h, (hl) - ld l, a ; HL = (HL) - ex de, hl ; HL = Previous block pointer; DE = Next block pointer -TEMP0: - ld hl, 0 ; Pre-previous block pointer - ld (hl), e - inc hl - ld (hl), d ; LINKED - pop hl ; Returning block. - ret -__MEM_SUBTRACT: - ; At this point we have to store HL value (Length - BC) into (DE - 2) - ex de, hl - dec hl - ld (hl), d - dec hl - ld (hl), e ; Store new block length - add hl, de ; New length + DE => free-block start - pop de ; Remove previous HL off the stack - ld (hl), c ; Store length on its 1st word - inc hl - ld (hl), b - inc hl ; Return hl - ret - ENDP - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" - ; Loads a string (ptr) from HL - ; and duplicates it on dynamic memory again - ; Finally, it returns result pointer in HL - push namespace core -__ILOADSTR: ; This is the indirect pointer entry HL = (HL) - ld a, h - or l - ret z - ld a, (hl) - inc hl - ld h, (hl) - ld l, a -__LOADSTR: ; __FASTCALL__ entry - ld a, h - or l - ret z ; Return if NULL - ld c, (hl) - inc hl - ld b, (hl) - dec hl ; BC = LEN(a$) - inc bc - inc bc ; BC = LEN(a$) + 2 (two bytes for length) - push hl - push bc - call __MEM_ALLOC - pop bc ; Recover length - pop de ; Recover origin - ld a, h - or l - ret z ; Return if NULL (No memory) - ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE - push de ; Saves destiny start - ldir ; Copies string (length number included) - pop hl ; Recovers destiny in hl as result - ret - pop namespace -#line 24 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/iload32.asm" - ; __FASTCALL__ routine which - ; loads a 32 bits integer into DE,HL - ; stored at position pointed by POINTER HL - ; DE,HL <-- (HL) - push namespace core -__ILOAD32: - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld a, (hl) - inc hl - ld h, (hl) - ld l, a - ex de, hl - ret - pop namespace -#line 25 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/iloadf.asm" - ; __FASTCALL__ routine which - ; loads a 40 bits floating point into A ED CB - ; stored at position pointed by POINTER HL - ;A DE, BC <-- ((HL)) - push namespace core -__ILOADF: - ld a, (hl) - inc hl - ld h, (hl) - ld l, a - ; __FASTCALL__ routine which - ; loads a 40 bits floating point into A ED CB - ; stored at position pointed by POINTER HL - ;A DE, BC <-- (HL) -__LOADF: ; Loads a 40 bits FP number from address pointed by HL - ld a, (hl) - inc hl - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld c, (hl) - inc hl - ld b, (hl) - ret - pop namespace -#line 26 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ftof16reg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/neg32.asm" - push namespace core -__ABS32: - bit 7, d - ret z -__NEG32: ; Negates DEHL (Two's complement) - ld a, l - cpl - ld l, a - ld a, h - cpl - ld h, a - ld a, e - cpl - ld e, a - ld a, d - cpl - ld d, a - inc l - ret nz - inc h - ret nz - inc de - ret - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" - push namespace core -__FTOU32REG: ; Converts a Float to (un)signed 32 bit integer (NOTE: It's ALWAYS 32 bit signed) - ; Input FP number in A EDCB (A exponent, EDCB mantissa) - ; Output: DEHL 32 bit number (signed) - PROC - LOCAL __IS_FLOAT - LOCAL __NEGATE - or a - jr nz, __IS_FLOAT - ; Here if it is a ZX ROM Integer - ld h, c - ld l, d - ld d, e - ret -__IS_FLOAT: ; Jumps here if it is a true floating point number - ld h, e - push hl ; Stores it for later (Contains Sign in H) - push de - push bc - exx - pop de ; Loads mantissa into C'B' E'D' - pop bc ; - set 7, c ; Highest mantissa bit is always 1 - exx - ld hl, 0 ; DEHL = 0 - ld d, h - ld e, l - ;ld a, c ; Get exponent - sub 128 ; Exponent -= 128 - jr z, __FTOU32REG_END ; If it was <= 128, we are done (Integers must be > 128) - jr c, __FTOU32REG_END ; It was decimal (0.xxx). We are done (return 0) - ld b, a ; Loop counter = exponent - 128 -__FTOU32REG_LOOP: - exx ; Shift C'B' E'D' << 1, output bit stays in Carry - sla d - rl e - rl b - rl c - exx ; Shift DEHL << 1, inserting the carry on the right - rl l - rl h - rl e - rl d - djnz __FTOU32REG_LOOP -__FTOU32REG_END: - pop af ; Take the sign bit - or a ; Sets SGN bit to 1 if negative - jp m, __NEGATE ; Negates DEHL - ret -__NEGATE: - exx - ld a, d - or e - or b - or c - exx - jr z, __END - inc l - jr nz, __END - inc h - jr nz, __END - inc de - LOCAL __END -__END: - jp __NEG32 - ENDP -__FTOU8: ; Converts float in C ED LH to Unsigned byte in A - call __FTOU32REG - ld a, l - ret - pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/ftof16reg.asm" - push namespace core -__FTOF16REG: ; Converts a Float to 16.16 (32 bit) fixed point decimal - ; Input FP number in A EDCB (A exponent, EDCB mantissa) - ld l, a ; Saves exponent for later - or d - or e - or b - or c - ld h, e - ret z ; Return if ZERO - push hl ; Stores it for later (Contains sign in H, exponent in L) - push de - push bc - exx - pop de ; Loads mantissa into C'B' E'D' - pop bc ; - set 7, c ; Highest mantissa bit is always 1 - exx - ld hl, 0 ; DEHL = 0 - ld d, h - ld e, l - pop bc - ld a, c ; Get exponent - sub 112 ; Exponent -= 128 + 16 - push bc ; Saves sign in b again - jp z, __FTOU32REG_END ; If it was <= 128, we are done (Integers must be > 128) - jp c, __FTOU32REG_END ; It was decimal (0.xxx). We are done (return 0) - ld b, a ; Loop counter = exponent - 128 + 16 (we need to shift 16 bit more) - jp __FTOU32REG_LOOP ; proceed as an u32 integer - pop namespace -#line 27 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/f16tofreg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/u32tofreg.asm" - push namespace core -__I8TOFREG: - ld l, a - rlca - sbc a, a ; A = SGN(A) - ld h, a - ld e, a - ld d, a -__I32TOFREG: ; Converts a 32bit signed integer (stored in DEHL) - ; to a Floating Point Number returned in (A ED CB) - ld a, d - or a ; Test sign - jp p, __U32TOFREG ; It was positive, proceed as 32bit unsigned - call __NEG32 ; Convert it to positive - call __U32TOFREG ; Convert it to Floating point - set 7, e ; Put the sign bit (negative) in the 31bit of mantissa - ret -__U8TOFREG: - ; Converts an unsigned 8 bit (A) to Floating point - ld l, a - ld h, 0 - ld e, h - ld d, h -__U32TOFREG: ; Converts an unsigned 32 bit integer (DEHL) - ; to a Floating point number returned in A ED CB - PROC - LOCAL __U32TOFREG_END - ld a, d - or e - or h - or l - ld b, d - ld c, e ; Returns 00 0000 0000 if ZERO - ret z - push de - push hl - exx - pop de ; Loads integer into B'C' D'E' - pop bc - exx - ld l, 128 ; Exponent - ld bc, 0 ; DEBC = 0 - ld d, b - ld e, c -__U32TOFREG_LOOP: ; Also an entry point for __F16TOFREG - exx - ld a, d ; B'C'D'E' == 0 ? - or e - or b - or c - jp z, __U32TOFREG_END ; We are done - srl b ; Shift B'C' D'E' >> 1, output bit stays in Carry - rr c - rr d - rr e - exx - rr e ; Shift EDCB >> 1, inserting the carry on the left - rr d - rr c - rr b - inc l ; Increment exponent - jp __U32TOFREG_LOOP -__U32TOFREG_END: - exx - ld a, l ; Puts the exponent in a - res 7, e ; Sets the sign bit to 0 (positive) - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/f16tofreg.asm" - push namespace core -__F16TOFREG: ; Converts a 16.16 signed fixed point (stored in DEHL) - ; to a Floating Point Number returned in (C ED CB) - PROC - LOCAL __F16TOFREG2 - ld a, d - or a ; Test sign - jp p, __F16TOFREG2 ; It was positive, proceed as 32bit unsigned - call __NEG32 ; Convert it to positive - call __F16TOFREG2 ; Convert it to Floating point - set 7, e ; Put the sign bit (negative) in the 31bit of mantissa - ret -__F16TOFREG2: ; Converts an unsigned 32 bit integer (DEHL) - ; to a Floating point number returned in C DE HL - ld a, d - or e - or h - or l - ld b, h - ld c, l - ret z ; Return 00 0000 0000 if 0 - push de - push hl - exx - pop de ; Loads integer into B'C' D'E' - pop bc - exx - ld l, 112 ; Exponent - ld bc, 0 ; DEBC = 0 - ld d, b - ld e, c - jp __U32TOFREG_LOOP ; Proceed as an integer - ENDP - pop namespace -#line 28 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 29 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 31 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 32 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 33 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 34 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 35 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 36 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 37 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 38 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 39 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" - ;; Updates restore point to the given HL mem. address - push namespace core -__RESTORE: - PROC - LOCAL __DATA_ADDR - ld (__DATA_ADDR), hl - ret - ;; Reads a value from the DATA mem area and updates __DATA_ADDR ptr to the - ;; next item. On Out Of Data, restarts - ;; -__READ: - LOCAL read_restart, cont, cont2, table, no_func - LOCAL dynamic_cast, dynamic_cast2, dynamic_cast3, dynamic_cast4 - LOCAL _decode_table, coerce_to_int, coerce_to_int2, promote_to_i16 - LOCAL _from_i8, _from_u8 - LOCAL _from_i16, _from_u16 - LOCAL _from_i32, _from_u32 - LOCAL _from_fixed, __data_error - push af ; type of data to read - ld hl, (__DATA_ADDR) -read_restart: - ld a, (hl) - or a ; 0 => OUT of data - jr nz, cont - ;; Signals out of data - ld hl, .DATA.__DATA__0 - ld (__DATA_ADDR), hl - jr read_restart ; Start again -cont: - and 0x80 - ld a, (hl) - push af - jp z, no_func ;; Loads data directly, not a function - inc hl - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld (__DATA_ADDR), hl ;; Store address of next DATA - ex de, hl -cont2: - ld de, dynamic_cast - push de ; ret address - jp (hl) ; "call (hl)" - ;; Now tries to convert the given result to the expected type or raise an error -dynamic_cast: - exx - ex af, af' - pop af ; type READ - and 0x7F ; clear bit 7 - pop hl ; type requested by USER (type of the READ variable) - ld c, h ; save requested type (save it in register C) - cp h - exx - jr nz, dynamic_cast2 ; Types are identical? - ;; yes, they are - ex af, af' - ret -dynamic_cast2: - cp 1 ; Requested a number, but read a string? - jr nz, dynamic_cast3 - call __MEM_FREE ; Frees str from memory - jr __data_error -dynamic_cast3: - exx - ld b, a ; Read type - ld a, c ; Requested type - cp 1 - jr z, __data_error - cp b - jr c, dynamic_cast4 - ;; here the user expected type is "larger" than the read one - ld a, b - sub 2 - add a, a - ld l, a - ld h, 0 - ld de, _decode_table - add hl, de - ld e, (hl) - inc hl - ld h, (hl) - ld l, e - push hl - ld a, c ; Requested type - exx - ret -__data_error: - ;; When a data is read, but cannot be converted to the requested type - ;; that is, the user asked for a string and we read a number or vice versa - ld a, ERROR_InvalidArg - call __STOP ; The user expected a string, but read a number - xor a - ld h, a - ld l, a - ld e, a - ld d, a - ld b, a - ld c, a - ret -_decode_table: - dw _from_i8 - dw _from_u8 - dw _from_i16 - dw _from_u16 - dw _from_i32 - dw _from_u32 - dw _from_fixed -_from_i8: - cp 4 - jr nc, promote_to_i16 - ex af, af' - ret ;; Was from Byte to Ubyte -promote_to_i16: - ex af, af' - ld l, a - rla - sbc a, a - ld h, a ; copy sgn to h - ex af, af' - jr _before_from_i16 -_from_u8: - ex af, af' - ld l, a - ld h, 0 - ex af, af' - ;; Promoted to i16 -_before_from_i16: -_from_i16: - cp 6 - ret c ;; from i16 to u16 - ;; Promote i16 to i32 - ex af, af' - ld a, h - rla - sbc a, a - ld e, a - ld d, a - ex af, af' -_from_i32: - cp 7 - ret z ;; From i32 to u32 - ret c ;; From u16 to i32 - cp 9 - jp z, __I32TOFREG -_from_u32: - cp 9 - jp z, __U32TOFREG - ex de, hl - ld hl, 0 - cp 8 - ret z -_from_fixed: ;; From fixed to float - jp __F16TOFREG -_from_u16: - ld de, 0 ; HL 0x0000 => 32 bits - jp _from_i32 -dynamic_cast4: - ;; The user type is "shorter" than the read one - cp 8 ;; required type - jr c, before_to_int ;; required < fixed (f16) - ex af, af' - exx ;; Ok, we must convert from float to f16 - jp __FTOF16REG -before_to_int: - ld a, b ;; read type - cp 8 ;; - jr c, coerce_to_int2 - jr nz, coerce_to_int ;; From float to int - ld a, c ;; user type - exx - ;; f16 to Long - ex de, hl - ld a, h - rla - sbc a, a - ld d, a - ld e, a - exx - jr coerce_to_int2 -coerce_to_int: - exx - ex af, af' - call __FTOU32REG - ex af, af' ; a contains user type - exx -coerce_to_int2: ; At this point we have an u/integer in hl - exx - cp 4 - ret nc ; Already done. Return the result - ld a, l ; Truncate to byte - ret -no_func: - exx - ld de, dynamic_cast - push de ; Ret address - dec a ; 0 => string; 1, 2 => byte; 3, 4 => integer; 5, 6 => long, 7 => fixed; 8 => float - ld h, 0 - add a, a - ld l, a - ld de, table - add hl, de - ld e, (hl) - inc hl - ld h, (hl) - ld l, e - push hl ; address to jump to - exx - inc hl - ret ; jp (sp) => jump to table[a - 1] -table: - LOCAL __01_decode_string - LOCAL __02_decode_byte - LOCAL __03_decode_ubyte - LOCAL __04_decode_integer - LOCAL __05_decode_uinteger - LOCAL __06_decode_long - LOCAL __07_decode_ulong - LOCAL __08_decode_fixed - LOCAL __09_decode_float - ;; 1 -> Decode string - ;; 2, 3 -> Decode Byte, UByte - ;; 4, 5 -> Decode Integer, UInteger - ;; 6, 7 -> Decode Long, ULong - ;; 8 -> Decode Fixed - ;; 9 -> Decode Float - dw __01_decode_string - dw __02_decode_byte - dw __03_decode_ubyte - dw __04_decode_integer - dw __05_decode_uinteger - dw __06_decode_long - dw __07_decode_ulong - dw __08_decode_fixed - dw __09_decode_float -__01_decode_string: - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld (__DATA_ADDR), hl ;; Store address of next DATA - ex de, hl - jp __LOADSTR -__02_decode_byte: -__03_decode_ubyte: - ld a, (hl) - inc hl - ld (__DATA_ADDR), hl - ret -__04_decode_integer: -__05_decode_uinteger: - ld e, (hl) - inc hl - ld d, (hl) - inc hl - ld (__DATA_ADDR), hl - ex de, hl - ret -__06_decode_long: -__07_decode_ulong: -__08_decode_fixed: - ld b, h - ld c, l - inc bc - inc bc - inc bc - inc bc - ld (__DATA_ADDR), bc - jp __ILOAD32 -__09_decode_float: - call __LOADF - inc hl - ld (__DATA_ADDR), hl - ld h, a ; returns A in H; sets A free - ret -__DATA_ADDR: ;; Stores current DATA ptr - dw .DATA.__DATA__0 - ENDP - pop namespace -#line 23 "readbug.bas" - END diff --git a/tests/functional/arch/zx48k/readbug.bas b/tests/functional/arch/zx48k/readbug.bas index ca257f122..505514dc7 100644 --- a/tests/functional/arch/zx48k/readbug.bas +++ b/tests/functional/arch/zx48k/readbug.bas @@ -1,2 +1,2 @@ DIM r1 as UByte -READ r1 +READ r1 'Error: No DATA defined diff --git a/tests/functional/arch/zx48k/readokdown.asm b/tests/functional/arch/zx48k/readokdown.asm index bb26b2cba..98561df35 100644 --- a/tests/functional/arch/zx48k/readokdown.asm +++ b/tests/functional/arch/zx48k/readokdown.asm @@ -1466,7 +1466,7 @@ __PRINT_MINUS: ; PRINT the MINUS (-) sign. CALLER must preserve registers pop namespace #line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printf16.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi16.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/div16.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div16.asm" ; 16 bit division and modulo functions ; for both signed and unsigned values #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg16.asm" @@ -1485,7 +1485,7 @@ __NEGHL: inc hl ret pop namespace -#line 5 "/zxbasic/src/lib/arch/zx48k/runtime/div16.asm" +#line 5 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div16.asm" push namespace core __DIVU16: ; 16 bit unsigned division ; HL = Dividend, Stack Top = Divisor @@ -1659,7 +1659,7 @@ __PRINT_FIX_LOOP: pop namespace #line 107 "arch/zx48k/readokdown.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi32.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/div32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div32.asm" ; --------------------------------------------------------- push namespace core __DIVU32: ; 32 bit unsigned division @@ -1808,7 +1808,7 @@ __PRINTU_LOOP: pop namespace #line 109 "arch/zx48k/readokdown.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/div8.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div8.asm" ; -------------------------------- push namespace core __DIVU8: ; 8 bit unsigned integer division @@ -2550,6 +2550,13 @@ _from_u16: jp _from_i32 dynamic_cast4: ;; The user type is "shorter" than the read one + ld a, b ;; read type + cp 4 ;; if user type < read type < _i16 => From Ubyte to Byte. Return af' + jr nc, 1f + ex af, af' + ret +1: + ld a, c ;; recover user required type cp 8 ;; required type jr c, before_to_int ;; required < fixed (f16) ex af, af' diff --git a/tests/functional/arch/zx48k/readokup.asm b/tests/functional/arch/zx48k/readokup.asm index 5a4fe876f..2da02e334 100644 --- a/tests/functional/arch/zx48k/readokup.asm +++ b/tests/functional/arch/zx48k/readokup.asm @@ -1465,7 +1465,7 @@ __PRINT_MINUS: ; PRINT the MINUS (-) sign. CALLER must preserve registers pop namespace #line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printf16.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi16.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/div16.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div16.asm" ; 16 bit division and modulo functions ; for both signed and unsigned values #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg16.asm" @@ -1484,7 +1484,7 @@ __NEGHL: inc hl ret pop namespace -#line 5 "/zxbasic/src/lib/arch/zx48k/runtime/div16.asm" +#line 5 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div16.asm" push namespace core __DIVU16: ; 16 bit unsigned division ; HL = Dividend, Stack Top = Divisor @@ -1658,7 +1658,7 @@ __PRINT_FIX_LOOP: pop namespace #line 106 "arch/zx48k/readokup.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi32.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/div32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div32.asm" ; --------------------------------------------------------- push namespace core __DIVU32: ; 32 bit unsigned division @@ -1807,7 +1807,7 @@ __PRINTU_LOOP: pop namespace #line 108 "arch/zx48k/readokup.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/div8.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div8.asm" ; -------------------------------- push namespace core __DIVU8: ; 8 bit unsigned integer division @@ -2549,6 +2549,13 @@ _from_u16: jp _from_i32 dynamic_cast4: ;; The user type is "shorter" than the read one + ld a, b ;; read type + cp 4 ;; if user type < read type < _i16 => From Ubyte to Byte. Return af' + jr nc, 1f + ex af, af' + ret +1: + ld a, c ;; recover user required type cp 8 ;; required type jr c, before_to_int ;; required < fixed (f16) ex af, af' diff --git a/tests/functional/arch/zx48k/restore1.asm b/tests/functional/arch/zx48k/restore1.asm index f4115645d..9736d1379 100644 --- a/tests/functional/arch/zx48k/restore1.asm +++ b/tests/functional/arch/zx48k/restore1.asm @@ -55,7 +55,7 @@ _a: __DATA__END: DEFB 00h ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" ;; This implements READ & RESTORE functions ;; Reads a new element from the DATA Address code ;; Updates the DATA_ADDR read ptr for the next read @@ -73,7 +73,7 @@ __DATA__END: ;; 09: Float ;; bit7 is set for a parameter-less function ;; In that case, the next two bytes are the ptr of the function to jump -#line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" ; Simple error control routines ; vim:ts=4:et: push namespace core @@ -107,9 +107,9 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 23 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 23 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa ; (a.k.a. Boriel) @@ -169,7 +169,7 @@ __STOP: ; HL = BLOCK Start & DE = Length. ; An init directive is useful for initialization routines. ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/heapinit.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa ; (a.k.a. Boriel) @@ -276,7 +276,7 @@ __MEM_INIT2: ret ENDP pop namespace -#line 70 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 70 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; --------------------------------------------------------------------- ; MEM_ALLOC ; Allocates a block of memory in the heap. @@ -307,9 +307,9 @@ __MEM_START: __MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE ld a, h ; HL = NULL (No memory available?) or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 113 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 115 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; HL = Pointer to Free block ld e, (hl) inc hl @@ -374,7 +374,7 @@ __MEM_SUBTRACT: ret ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" ; Loads a string (ptr) from HL ; and duplicates it on dynamic memory again ; Finally, it returns result pointer in HL @@ -411,8 +411,8 @@ __LOADSTR: ; __FASTCALL__ entry pop hl ; Recovers destiny in hl as result ret pop namespace -#line 24 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/iload32.asm" +#line 24 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/iload32.asm" ; __FASTCALL__ routine which ; loads a 32 bits integer into DE,HL ; stored at position pointed by POINTER HL @@ -430,8 +430,8 @@ __ILOAD32: ex de, hl ret pop namespace -#line 25 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/iloadf.asm" +#line 25 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/iloadf.asm" ; __FASTCALL__ routine which ; loads a 40 bits floating point into A ED CB ; stored at position pointed by POINTER HL @@ -458,10 +458,10 @@ __LOADF: ; Loads a 40 bits FP number from address pointed by HL ld b, (hl) ret pop namespace -#line 26 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ftof16reg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/neg32.asm" +#line 26 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftof16reg.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg32.asm" push namespace core __ABS32: bit 7, d @@ -486,7 +486,7 @@ __NEG32: ; Negates DEHL (Two's complement) inc de ret pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm" push namespace core __FTOU32REG: ; Converts a Float to (un)signed 32 bit integer (NOTE: It's ALWAYS 32 bit signed) ; Input FP number in A EDCB (A exponent, EDCB mantissa) @@ -558,7 +558,7 @@ __FTOU8: ; Converts float in C ED LH to Unsigned byte in A ld a, l ret pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/ftof16reg.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/ftof16reg.asm" push namespace core __FTOF16REG: ; Converts a Float to 16.16 (32 bit) fixed point decimal ; Input FP number in A EDCB (A exponent, EDCB mantissa) @@ -589,9 +589,9 @@ __FTOF16REG: ; Converts a Float to 16.16 (32 bit) fixed point decimal ld b, a ; Loop counter = exponent - 128 + 16 (we need to shift 16 bit more) jp __FTOU32REG_LOOP ; proceed as an u32 integer pop namespace -#line 27 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/f16tofreg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/u32tofreg.asm" +#line 27 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/f16tofreg.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/u32tofreg.asm" push namespace core __I8TOFREG: ld l, a @@ -661,7 +661,7 @@ __U32TOFREG_END: ret ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/f16tofreg.asm" +#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/f16tofreg.asm" push namespace core __F16TOFREG: ; Converts a 16.16 signed fixed point (stored in DEHL) ; to a Floating Point Number returned in (C ED CB) @@ -696,8 +696,8 @@ __F16TOFREG2: ; Converts an unsigned 32 bit integer (DEHL) jp __U32TOFREG_LOOP ; Proceed as an integer ENDP pop namespace -#line 28 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +#line 28 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa ; (a.k.a. Boriel) @@ -855,16 +855,16 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ret ENDP pop namespace -#line 29 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 31 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 32 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 33 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 34 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 35 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 36 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 37 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 38 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 39 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" +#line 29 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 31 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 32 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 33 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 34 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 35 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 36 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 37 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 38 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 39 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" ;; Updates restore point to the given HL mem. address push namespace core __RESTORE: @@ -1024,6 +1024,13 @@ _from_u16: jp _from_i32 dynamic_cast4: ;; The user type is "shorter" than the read one + ld a, b ;; read type + cp 4 ;; if user type < read type < _i16 => From Ubyte to Byte. Return af' + jr nc, 1f + ex af, af' + ret +1: + ld a, c ;; recover user required type cp 8 ;; required type jr c, before_to_int ;; required < fixed (f16) ex af, af' @@ -1144,8 +1151,8 @@ __DATA_ADDR: ;; Stores current DATA ptr dw .DATA.__DATA__0 ENDP pop namespace -#line 30 "restore1.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/storef.asm" +#line 30 "arch/zx48k/restore1.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/storef.asm" push namespace core __PISTOREF: ; Indect Stores a float (A, E, D, C, B) at location stored in memory, pointed by (IX + HL) push de @@ -1173,5 +1180,5 @@ __STOREF: ; Stores the given FP number in A EDCB at address HL ld (hl), b ret pop namespace -#line 31 "restore1.bas" +#line 31 "arch/zx48k/restore1.bas" END diff --git a/tests/functional/arch/zx48k/restore3.asm b/tests/functional/arch/zx48k/restore3.asm index 954332a15..6c3b98364 100644 --- a/tests/functional/arch/zx48k/restore3.asm +++ b/tests/functional/arch/zx48k/restore3.asm @@ -53,7 +53,7 @@ _a: __DATA__END: DEFB 00h ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" ;; This implements READ & RESTORE functions ;; Reads a new element from the DATA Address code ;; Updates the DATA_ADDR read ptr for the next read @@ -71,7 +71,7 @@ __DATA__END: ;; 09: Float ;; bit7 is set for a parameter-less function ;; In that case, the next two bytes are the ptr of the function to jump -#line 1 "/zxbasic/src/arch/zx48k/library-asm/error.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" ; Simple error control routines ; vim:ts=4:et: push namespace core @@ -105,9 +105,9 @@ __STOP: ld (ERR_NR), a ret pop namespace -#line 23 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 23 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa ; (a.k.a. Boriel) @@ -167,7 +167,7 @@ __STOP: ; HL = BLOCK Start & DE = Length. ; An init directive is useful for initialization routines. ; They will be added automatically if needed. -#line 1 "/zxbasic/src/arch/zx48k/library-asm/heapinit.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/heapinit.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa ; (a.k.a. Boriel) @@ -274,7 +274,7 @@ __MEM_INIT2: ret ENDP pop namespace -#line 70 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 70 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; --------------------------------------------------------------------- ; MEM_ALLOC ; Allocates a block of memory in the heap. @@ -305,9 +305,9 @@ __MEM_START: __MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE ld a, h ; HL = NULL (No memory available?) or l -#line 113 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 113 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ret z ; NULL -#line 115 "/zxbasic/src/arch/zx48k/library-asm/alloc.asm" +#line 115 "/zxbasic/src/lib/arch/zx48k/runtime/alloc.asm" ; HL = Pointer to Free block ld e, (hl) inc hl @@ -372,7 +372,7 @@ __MEM_SUBTRACT: ret ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/loadstr.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/loadstr.asm" ; Loads a string (ptr) from HL ; and duplicates it on dynamic memory again ; Finally, it returns result pointer in HL @@ -409,8 +409,8 @@ __LOADSTR: ; __FASTCALL__ entry pop hl ; Recovers destiny in hl as result ret pop namespace -#line 24 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/iload32.asm" +#line 24 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/iload32.asm" ; __FASTCALL__ routine which ; loads a 32 bits integer into DE,HL ; stored at position pointed by POINTER HL @@ -428,8 +428,8 @@ __ILOAD32: ex de, hl ret pop namespace -#line 25 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/iloadf.asm" +#line 25 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/iloadf.asm" ; __FASTCALL__ routine which ; loads a 40 bits floating point into A ED CB ; stored at position pointed by POINTER HL @@ -456,10 +456,10 @@ __LOADF: ; Loads a 40 bits FP number from address pointed by HL ld b, (hl) ret pop namespace -#line 26 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ftof16reg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/neg32.asm" +#line 26 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftof16reg.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg32.asm" push namespace core __ABS32: bit 7, d @@ -484,7 +484,7 @@ __NEG32: ; Negates DEHL (Two's complement) inc de ret pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm" push namespace core __FTOU32REG: ; Converts a Float to (un)signed 32 bit integer (NOTE: It's ALWAYS 32 bit signed) ; Input FP number in A EDCB (A exponent, EDCB mantissa) @@ -556,7 +556,7 @@ __FTOU8: ; Converts float in C ED LH to Unsigned byte in A ld a, l ret pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/ftof16reg.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/ftof16reg.asm" push namespace core __FTOF16REG: ; Converts a Float to 16.16 (32 bit) fixed point decimal ; Input FP number in A EDCB (A exponent, EDCB mantissa) @@ -587,9 +587,9 @@ __FTOF16REG: ; Converts a Float to 16.16 (32 bit) fixed point decimal ld b, a ; Loop counter = exponent - 128 + 16 (we need to shift 16 bit more) jp __FTOU32REG_LOOP ; proceed as an u32 integer pop namespace -#line 27 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/f16tofreg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/u32tofreg.asm" +#line 27 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/f16tofreg.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/u32tofreg.asm" push namespace core __I8TOFREG: ld l, a @@ -659,7 +659,7 @@ __U32TOFREG_END: ret ENDP pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/f16tofreg.asm" +#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/f16tofreg.asm" push namespace core __F16TOFREG: ; Converts a 16.16 signed fixed point (stored in DEHL) ; to a Floating Point Number returned in (C ED CB) @@ -694,8 +694,8 @@ __F16TOFREG2: ; Converts an unsigned 32 bit integer (DEHL) jp __U32TOFREG_LOOP ; Proceed as an integer ENDP pop namespace -#line 28 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/free.asm" +#line 28 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" ; vim: ts=4:et:sw=4: ; Copyleft (K) by Jose M. Rodriguez de la Rosa ; (a.k.a. Boriel) @@ -853,16 +853,16 @@ __MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed ret ENDP pop namespace -#line 29 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 31 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 32 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 33 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 34 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 35 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 36 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 37 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 38 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" -#line 39 "/zxbasic/src/arch/zx48k/library-asm/read_restore.asm" +#line 29 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 31 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 32 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 33 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 34 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 35 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 36 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 37 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 38 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" +#line 39 "/zxbasic/src/lib/arch/zx48k/runtime/read_restore.asm" ;; Updates restore point to the given HL mem. address push namespace core __RESTORE: @@ -1022,6 +1022,13 @@ _from_u16: jp _from_i32 dynamic_cast4: ;; The user type is "shorter" than the read one + ld a, b ;; read type + cp 4 ;; if user type < read type < _i16 => From Ubyte to Byte. Return af' + jr nc, 1f + ex af, af' + ret +1: + ld a, c ;; recover user required type cp 8 ;; required type jr c, before_to_int ;; required < fixed (f16) ex af, af' @@ -1142,8 +1149,8 @@ __DATA_ADDR: ;; Stores current DATA ptr dw .DATA.__DATA__0 ENDP pop namespace -#line 28 "restore3.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/storef.asm" +#line 28 "arch/zx48k/restore3.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/storef.asm" push namespace core __PISTOREF: ; Indect Stores a float (A, E, D, C, B) at location stored in memory, pointed by (IX + HL) push de @@ -1171,5 +1178,5 @@ __STOREF: ; Stores the given FP number in A EDCB at address HL ld (hl), b ret pop namespace -#line 29 "restore3.bas" +#line 29 "arch/zx48k/restore3.bas" END diff --git a/tests/functional/arch/zx48k/streq00.asm b/tests/functional/arch/zx48k/streq00.asm index e5a29e5a0..b2e962c67 100644 --- a/tests/functional/arch/zx48k/streq00.asm +++ b/tests/functional/arch/zx48k/streq00.asm @@ -1020,16 +1020,16 @@ __STREQ: ; Compares a$ == b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 pop de pop hl sub 1 - sbc a, a + sbc a, a ; 0 if A register was 0, 0xFF if A was 1 or -1 jp __FREE_STR -__STRNE: ; Compares a$ != b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRNE: ; Compares a$ != b$ (HL = ptr a$, DE = ptr b$). Returns 1 (True) or 0 (False) push hl push de call __STRCMP pop de pop hl jp __FREE_STR -__STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FE (True) or 0 (False) push hl push de call __STRCMP @@ -1039,7 +1039,7 @@ __STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 ( jp z, __FREE_STR ; Returns 0 if A == B dec a ; Returns 0 if A == 1 => a$ > b$ jp __FREE_STR -__STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF or FE (True) or 0 (False) push hl push de call __STRCMP @@ -1047,7 +1047,7 @@ __STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 pop hl dec a ; Returns 0 if A == 1 => a$ < b$ jp __FREE_STR -__STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns 2 (True) or 0 (False) push hl push de call __STRCMP @@ -1057,7 +1057,7 @@ __STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 ( jp z, __FREE_STR ; Returns 0 if A == B inc a ; Returns 0 if A == -1 => a$ < b$ jp __FREE_STR -__STRGE: ; Compares a$ >= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRGE: ; Compares a$ >= b$ (HL = ptr a$, DE = ptr b$). Returns 1 or 2 (True) or 0 (False) push hl push de call __STRCMP @@ -1071,6 +1071,10 @@ __FREE_STR: ; This exit point will test A' for bits 0 and 1 PROC LOCAL __FREE_STR2 LOCAL __FREE_END + ;; normalize boolean + sub 1 + sbc a, a + inc a ex af, af' bit 0, a jr z, __FREE_STR2 diff --git a/tests/functional/arch/zx48k/strge00.asm b/tests/functional/arch/zx48k/strge00.asm index 9b37c9679..13eaebc85 100644 --- a/tests/functional/arch/zx48k/strge00.asm +++ b/tests/functional/arch/zx48k/strge00.asm @@ -1020,16 +1020,16 @@ __STREQ: ; Compares a$ == b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 pop de pop hl sub 1 - sbc a, a + sbc a, a ; 0 if A register was 0, 0xFF if A was 1 or -1 jp __FREE_STR -__STRNE: ; Compares a$ != b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRNE: ; Compares a$ != b$ (HL = ptr a$, DE = ptr b$). Returns 1 (True) or 0 (False) push hl push de call __STRCMP pop de pop hl jp __FREE_STR -__STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FE (True) or 0 (False) push hl push de call __STRCMP @@ -1039,7 +1039,7 @@ __STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 ( jp z, __FREE_STR ; Returns 0 if A == B dec a ; Returns 0 if A == 1 => a$ > b$ jp __FREE_STR -__STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF or FE (True) or 0 (False) push hl push de call __STRCMP @@ -1047,7 +1047,7 @@ __STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 pop hl dec a ; Returns 0 if A == 1 => a$ < b$ jp __FREE_STR -__STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns 2 (True) or 0 (False) push hl push de call __STRCMP @@ -1057,7 +1057,7 @@ __STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 ( jp z, __FREE_STR ; Returns 0 if A == B inc a ; Returns 0 if A == -1 => a$ < b$ jp __FREE_STR -__STRGE: ; Compares a$ >= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRGE: ; Compares a$ >= b$ (HL = ptr a$, DE = ptr b$). Returns 1 or 2 (True) or 0 (False) push hl push de call __STRCMP @@ -1071,6 +1071,10 @@ __FREE_STR: ; This exit point will test A' for bits 0 and 1 PROC LOCAL __FREE_STR2 LOCAL __FREE_END + ;; normalize boolean + sub 1 + sbc a, a + inc a ex af, af' bit 0, a jr z, __FREE_STR2 diff --git a/tests/functional/arch/zx48k/strgt00.asm b/tests/functional/arch/zx48k/strgt00.asm index 11573c746..c73282dcc 100644 --- a/tests/functional/arch/zx48k/strgt00.asm +++ b/tests/functional/arch/zx48k/strgt00.asm @@ -1020,16 +1020,16 @@ __STREQ: ; Compares a$ == b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 pop de pop hl sub 1 - sbc a, a + sbc a, a ; 0 if A register was 0, 0xFF if A was 1 or -1 jp __FREE_STR -__STRNE: ; Compares a$ != b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRNE: ; Compares a$ != b$ (HL = ptr a$, DE = ptr b$). Returns 1 (True) or 0 (False) push hl push de call __STRCMP pop de pop hl jp __FREE_STR -__STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FE (True) or 0 (False) push hl push de call __STRCMP @@ -1039,7 +1039,7 @@ __STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 ( jp z, __FREE_STR ; Returns 0 if A == B dec a ; Returns 0 if A == 1 => a$ > b$ jp __FREE_STR -__STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF or FE (True) or 0 (False) push hl push de call __STRCMP @@ -1047,7 +1047,7 @@ __STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 pop hl dec a ; Returns 0 if A == 1 => a$ < b$ jp __FREE_STR -__STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns 2 (True) or 0 (False) push hl push de call __STRCMP @@ -1057,7 +1057,7 @@ __STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 ( jp z, __FREE_STR ; Returns 0 if A == B inc a ; Returns 0 if A == -1 => a$ < b$ jp __FREE_STR -__STRGE: ; Compares a$ >= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRGE: ; Compares a$ >= b$ (HL = ptr a$, DE = ptr b$). Returns 1 or 2 (True) or 0 (False) push hl push de call __STRCMP @@ -1071,6 +1071,10 @@ __FREE_STR: ; This exit point will test A' for bits 0 and 1 PROC LOCAL __FREE_STR2 LOCAL __FREE_END + ;; normalize boolean + sub 1 + sbc a, a + inc a ex af, af' bit 0, a jr z, __FREE_STR2 diff --git a/tests/functional/arch/zx48k/strict_bool.asm b/tests/functional/arch/zx48k/strict_bool.asm index 5014400ff..ba1df01c5 100644 --- a/tests/functional/arch/zx48k/strict_bool.asm +++ b/tests/functional/arch/zx48k/strict_bool.asm @@ -28,7 +28,6 @@ _a: ld de, 00020h ld bc, 00000h call .core.__LTF - call .core.__NORMALIZE_BOOLEAN call .core.__U8TOFREG ld hl, _a call .core.__STOREF @@ -47,9 +46,9 @@ _a: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ltf.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/u32tofreg.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/neg32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/ltf.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/u32tofreg.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg32.asm" push namespace core __ABS32: bit 7, d @@ -74,7 +73,7 @@ __NEG32: ; Negates DEHL (Two's complement) inc de ret pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/u32tofreg.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/u32tofreg.asm" push namespace core __I8TOFREG: ld l, a @@ -144,8 +143,8 @@ __U32TOFREG_END: ret ENDP pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/ltf.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ftou32reg.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/ltf.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ftou32reg.asm" push namespace core __FTOU32REG: ; Converts a Float to (un)signed 32 bit integer (NOTE: It's ALWAYS 32 bit signed) ; Input FP number in A EDCB (A exponent, EDCB mantissa) @@ -217,8 +216,8 @@ __FTOU8: ; Converts float in C ED LH to Unsigned byte in A ld a, l ret pop namespace -#line 3 "/zxbasic/src/arch/zx48k/library-asm/ltf.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/stackf.asm" +#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/ltf.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/stackf.asm" ; ------------------------------------------------------------- ; Functions to manage FP-Stack of the ZX Spectrum ROM CALC ; ------------------------------------------------------------- @@ -257,7 +256,7 @@ __FPSTACK_I16: ; Pushes 16 bits integer in HL into the FP ROM STACK ld b, a jp __FPSTACK_PUSH pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/ltf.asm" +#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/cmp/ltf.asm" ; ------------------------------------------------------------- ; Floating point library using the FP ROM Calculator (ZX 48K) ; All of them uses A EDCB registers as 1st paramter. @@ -277,8 +276,8 @@ __LTF: ; A < B call __FPSTACK_POP jp __FTOU8 ; Convert to 8 bits pop namespace -#line 27 "strict_bool.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/pushf.asm" +#line 26 "arch/zx48k/strict_bool.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/pushf.asm" ; Routine to push Float pointed by HL ; Into the stack. Notice that the hl points to the last ; byte of the FP number. @@ -305,8 +304,8 @@ __FP_PUSH_REV: exx ret pop namespace -#line 28 "strict_bool.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/storef.asm" +#line 27 "arch/zx48k/strict_bool.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/storef.asm" push namespace core __PISTOREF: ; Indect Stores a float (A, E, D, C, B) at location stored in memory, pointed by (IX + HL) push de @@ -334,16 +333,5 @@ __STOREF: ; Stores the given FP number in A EDCB at address HL ld (hl), b ret pop namespace -#line 29 "strict_bool.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/strictbool.asm" - ; This routine is called if --strict-boolean was set at the command line. - ; It will make any boolean result to be always 0 or 1 - push namespace core -__NORMALIZE_BOOLEAN: - or a - ret z - ld a, 1 - ret - pop namespace -#line 30 "strict_bool.bas" +#line 28 "arch/zx48k/strict_bool.bas" END diff --git a/tests/functional/arch/zx48k/strle00.asm b/tests/functional/arch/zx48k/strle00.asm index 94b047476..a3b4bb994 100644 --- a/tests/functional/arch/zx48k/strle00.asm +++ b/tests/functional/arch/zx48k/strle00.asm @@ -1020,16 +1020,16 @@ __STREQ: ; Compares a$ == b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 pop de pop hl sub 1 - sbc a, a + sbc a, a ; 0 if A register was 0, 0xFF if A was 1 or -1 jp __FREE_STR -__STRNE: ; Compares a$ != b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRNE: ; Compares a$ != b$ (HL = ptr a$, DE = ptr b$). Returns 1 (True) or 0 (False) push hl push de call __STRCMP pop de pop hl jp __FREE_STR -__STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FE (True) or 0 (False) push hl push de call __STRCMP @@ -1039,7 +1039,7 @@ __STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 ( jp z, __FREE_STR ; Returns 0 if A == B dec a ; Returns 0 if A == 1 => a$ > b$ jp __FREE_STR -__STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF or FE (True) or 0 (False) push hl push de call __STRCMP @@ -1047,7 +1047,7 @@ __STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 pop hl dec a ; Returns 0 if A == 1 => a$ < b$ jp __FREE_STR -__STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns 2 (True) or 0 (False) push hl push de call __STRCMP @@ -1057,7 +1057,7 @@ __STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 ( jp z, __FREE_STR ; Returns 0 if A == B inc a ; Returns 0 if A == -1 => a$ < b$ jp __FREE_STR -__STRGE: ; Compares a$ >= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRGE: ; Compares a$ >= b$ (HL = ptr a$, DE = ptr b$). Returns 1 or 2 (True) or 0 (False) push hl push de call __STRCMP @@ -1071,6 +1071,10 @@ __FREE_STR: ; This exit point will test A' for bits 0 and 1 PROC LOCAL __FREE_STR2 LOCAL __FREE_END + ;; normalize boolean + sub 1 + sbc a, a + inc a ex af, af' bit 0, a jr z, __FREE_STR2 diff --git a/tests/functional/arch/zx48k/strlt00.asm b/tests/functional/arch/zx48k/strlt00.asm index 7f2ead39f..276662b03 100644 --- a/tests/functional/arch/zx48k/strlt00.asm +++ b/tests/functional/arch/zx48k/strlt00.asm @@ -1020,16 +1020,16 @@ __STREQ: ; Compares a$ == b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 pop de pop hl sub 1 - sbc a, a + sbc a, a ; 0 if A register was 0, 0xFF if A was 1 or -1 jp __FREE_STR -__STRNE: ; Compares a$ != b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRNE: ; Compares a$ != b$ (HL = ptr a$, DE = ptr b$). Returns 1 (True) or 0 (False) push hl push de call __STRCMP pop de pop hl jp __FREE_STR -__STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FE (True) or 0 (False) push hl push de call __STRCMP @@ -1039,7 +1039,7 @@ __STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 ( jp z, __FREE_STR ; Returns 0 if A == B dec a ; Returns 0 if A == 1 => a$ > b$ jp __FREE_STR -__STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF or FE (True) or 0 (False) push hl push de call __STRCMP @@ -1047,7 +1047,7 @@ __STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 pop hl dec a ; Returns 0 if A == 1 => a$ < b$ jp __FREE_STR -__STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns 2 (True) or 0 (False) push hl push de call __STRCMP @@ -1057,7 +1057,7 @@ __STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 ( jp z, __FREE_STR ; Returns 0 if A == B inc a ; Returns 0 if A == -1 => a$ < b$ jp __FREE_STR -__STRGE: ; Compares a$ >= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRGE: ; Compares a$ >= b$ (HL = ptr a$, DE = ptr b$). Returns 1 or 2 (True) or 0 (False) push hl push de call __STRCMP @@ -1071,6 +1071,10 @@ __FREE_STR: ; This exit point will test A' for bits 0 and 1 PROC LOCAL __FREE_STR2 LOCAL __FREE_END + ;; normalize boolean + sub 1 + sbc a, a + inc a ex af, af' bit 0, a jr z, __FREE_STR2 diff --git a/tests/functional/arch/zx48k/strne00.asm b/tests/functional/arch/zx48k/strne00.asm index 5736ca2f7..cb6c13891 100644 --- a/tests/functional/arch/zx48k/strne00.asm +++ b/tests/functional/arch/zx48k/strne00.asm @@ -1020,16 +1020,16 @@ __STREQ: ; Compares a$ == b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 pop de pop hl sub 1 - sbc a, a + sbc a, a ; 0 if A register was 0, 0xFF if A was 1 or -1 jp __FREE_STR -__STRNE: ; Compares a$ != b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRNE: ; Compares a$ != b$ (HL = ptr a$, DE = ptr b$). Returns 1 (True) or 0 (False) push hl push de call __STRCMP pop de pop hl jp __FREE_STR -__STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FE (True) or 0 (False) push hl push de call __STRCMP @@ -1039,7 +1039,7 @@ __STRLT: ; Compares a$ < b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 ( jp z, __FREE_STR ; Returns 0 if A == B dec a ; Returns 0 if A == 1 => a$ > b$ jp __FREE_STR -__STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF or FE (True) or 0 (False) push hl push de call __STRCMP @@ -1047,7 +1047,7 @@ __STRLE: ; Compares a$ <= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 pop hl dec a ; Returns 0 if A == 1 => a$ < b$ jp __FREE_STR -__STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns 2 (True) or 0 (False) push hl push de call __STRCMP @@ -1057,7 +1057,7 @@ __STRGT: ; Compares a$ > b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 ( jp z, __FREE_STR ; Returns 0 if A == B inc a ; Returns 0 if A == -1 => a$ < b$ jp __FREE_STR -__STRGE: ; Compares a$ >= b$ (HL = ptr a$, DE = ptr b$). Returns FF (True) or 0 (False) +__STRGE: ; Compares a$ >= b$ (HL = ptr a$, DE = ptr b$). Returns 1 or 2 (True) or 0 (False) push hl push de call __STRCMP @@ -1071,6 +1071,10 @@ __FREE_STR: ; This exit point will test A' for bits 0 and 1 PROC LOCAL __FREE_STR2 LOCAL __FREE_END + ;; normalize boolean + sub 1 + sbc a, a + inc a ex af, af' bit 0, a jr z, __FREE_STR2 diff --git a/tests/functional/arch/zx48k/subrec.asm b/tests/functional/arch/zx48k/subrec.asm index e78b2c5d9..5e74bb355 100644 --- a/tests/functional/arch/zx48k/subrec.asm +++ b/tests/functional/arch/zx48k/subrec.asm @@ -10,16 +10,10 @@ add hl, sp ld (.core.__CALL_BACK__), hl ei - call .core.__MEM_INIT - call .core.__PRINT_INIT jp .core.__MAIN_PROGRAM__ .core.__CALL_BACK__: DEFW 0 .core.ZXBASIC_USER_DATA: - ; Defines HEAP SIZE -.core.ZXBASIC_HEAP_SIZE EQU 4768 -.core.ZXBASIC_MEM_HEAP: - DEFS 4768 ; Defines USER DATA Length in bytes .core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA .core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN @@ -29,6 +23,8 @@ _result: DEFB 00h DEFB 00h DEFB 00h +_dummy: + DEFB 00, 00, 00, 00 _x: DEFB 00 .core.ZXBASIC_USER_DATA_END: @@ -50,19 +46,10 @@ _x: push de push hl call _fact - call .core.COPY_ATTR - ld hl, .LABEL.__LABEL5 - xor a - call .core.__PRINTSTR - ld a, (_x) - call .core.__PRINTU8 - ld hl, .LABEL.__LABEL6 - xor a - call .core.__PRINTSTR ld hl, (_result) ld de, (_result + 2) - call .core.__PRINTU32 - call .core.PRINT_EOL + ld (_dummy), hl + ld (_dummy + 2), de .LABEL.__LABEL4: ld hl, _x inc (hl) @@ -100,7 +87,7 @@ _fact: ld hl, 2 call .core.__SUB32 jp c, _fact__leave -.LABEL.__LABEL8: +.LABEL.__LABEL6: ld l, (ix+4) ld h, (ix+5) ld e, (ix+6) @@ -133,20 +120,6 @@ _fact__leave: ex (sp), hl exx ret -.LABEL.__LABEL5: - DEFW 0006h - DEFB 46h - DEFB 61h - DEFB 63h - DEFB 74h - DEFB 20h - DEFB 28h -.LABEL.__LABEL6: - DEFW 0004h - DEFB 29h - DEFB 20h - DEFB 3Dh - DEFB 20h ;; --- end of user code --- #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mul32.asm" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/_mul32.asm" @@ -231,7 +204,7 @@ __TO32BIT: ; Converts H'L'HLB'C'AC to DEHL (Discards H'L'HL) ret pop namespace f -#line 117 "arch/zx48k/subrec.bas" +#line 94 "arch/zx48k/subrec.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/sub32.asm" ; SUB32 ; Perform TOP of the stack - DEHL @@ -258,7 +231,7 @@ __SUB32: exx ret pop namespace -#line 118 "arch/zx48k/subrec.bas" +#line 95 "arch/zx48k/subrec.bas" #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/cls.asm" ;; Clears the user screen (24 rows) #line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sysvars.asm" @@ -316,1502 +289,5 @@ CLS: ret ENDP pop namespace -#line 119 "arch/zx48k/subrec.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -; vim:ts=4:sw=4:et: - ; PRINT command routine - ; Does not print attribute. Use PRINT_STR or PRINT_NUM for that -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - ; Attribute routines -; vim:ts=4:et:sw: -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/error.asm" - ; Simple error control routines -; vim:ts=4:et: - push namespace core - ERR_NR EQU 23610 ; Error code system variable - ; Error code definitions (as in ZX spectrum manual) -; Set error code with: - ; ld a, ERROR_CODE - ; ld (ERR_NR), a - ERROR_Ok EQU -1 - ERROR_SubscriptWrong EQU 2 - ERROR_OutOfMemory EQU 3 - ERROR_OutOfScreen EQU 4 - ERROR_NumberTooBig EQU 5 - ERROR_InvalidArg EQU 9 - ERROR_IntOutOfRange EQU 10 - ERROR_NonsenseInBasic EQU 11 - ERROR_InvalidFileName EQU 14 - ERROR_InvalidColour EQU 19 - ERROR_BreakIntoProgram EQU 20 - ERROR_TapeLoadingErr EQU 26 - ; Raises error using RST #8 -__ERROR: - ld (__ERROR_CODE), a - rst 8 -__ERROR_CODE: - nop - ret - ; Sets the error system variable, but keeps running. - ; Usually this instruction if followed by the END intermediate instruction. -__STOP: - ld (ERR_NR), a - ret - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/in_screen.asm" - push namespace core -__IN_SCREEN: - ; Returns NO carry if current coords (D, E) - ; are OUT of the screen limits - PROC - LOCAL __IN_SCREEN_ERR - ld hl, SCR_SIZE - ld a, e - cp l - jr nc, __IN_SCREEN_ERR ; Do nothing and return if out of range - ld a, d - cp h - ret c ; Return if carry (OK) -__IN_SCREEN_ERR: -__OUT_OF_SCREEN_ERR: - ; Jumps here if out of screen - ld a, ERROR_OutOfScreen - jp __STOP ; Saves error code and exits - ENDP - pop namespace -#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/attr.asm" - push namespace core -__ATTR_ADDR: - ; calc start address in DE (as (32 * d) + e) - ; Contributed by Santiago Romero at http://www.speccy.org - ld h, 0 ; 7 T-States - ld a, d ; 4 T-States - ld d, h - add a, a ; a * 2 ; 4 T-States - add a, a ; a * 4 ; 4 T-States - ld l, a ; HL = A * 4 ; 4 T-States - add hl, hl ; HL = A * 8 ; 15 T-States - add hl, hl ; HL = A * 16 ; 15 T-States - add hl, hl ; HL = A * 32 ; 15 T-States - add hl, de - ld de, (SCREEN_ATTR_ADDR) ; Adds the screen address - add hl, de - ; Return current screen address in HL - ret - ; Sets the attribute at a given screen coordinate (D, E). - ; The attribute is taken from the ATTR_T memory variable - ; Used by PRINT routines -SET_ATTR: - ; Checks for valid coords - call __IN_SCREEN - ret nc - call __ATTR_ADDR -__SET_ATTR: - ; Internal __FASTCALL__ Entry used by printing routines - ; HL contains the address of the ATTR cell to set - PROC -__SET_ATTR2: ; Sets attr from ATTR_T to (HL) which points to the scr address - ld de, (ATTR_T) ; E = ATTR_T, D = MASK_T - ld a, d - and (hl) - ld c, a ; C = current screen color, masked - ld a, d - cpl ; Negate mask - and e ; Mask current attributes - or c ; Mix them - ld (hl), a ; Store result in screen - ret - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/sposn.asm" - ; Printing positioning library. - push namespace core - ; Loads into DE current ROW, COL print position from S_POSN mem var. -__LOAD_S_POSN: - PROC - ld de, (S_POSN) - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - ret - ENDP - ; Saves ROW, COL from DE into S_POSN mem var. -__SAVE_S_POSN: - PROC - ld hl, SCR_SIZE - or a - sbc hl, de - ld (S_POSN), hl ; saves it again -__SET_SCR_PTR: ;; Fast - push de - call __ATTR_ADDR - ld (DFCCL), hl - pop de - ld a, d - ld c, a ; Saves it for later - and 0F8h ; Masks 3 lower bit ; zy - ld d, a - ld a, c ; Recovers it - and 07h ; MOD 7 ; y1 - rrca - rrca - rrca - or e - ld e, a - ld hl, (SCREEN_ADDR) - add hl, de ; HL = Screen address + DE - ld (DFCC), hl - ret - ENDP - pop namespace -#line 6 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/table_jump.asm" - push namespace core -JUMP_HL_PLUS_2A: ; Does JP (HL + A*2) Modifies DE. Modifies A - add a, a -JUMP_HL_PLUS_A: ; Does JP (HL + A) Modifies DE - ld e, a - ld d, 0 -JUMP_HL_PLUS_DE: ; Does JP (HL + DE) - add hl, de - ld e, (hl) - inc hl - ld d, (hl) - ex de, hl -CALL_HL: - jp (hl) - pop namespace -#line 8 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ink.asm" - ; Sets ink color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -INK: - PROC - LOCAL __SET_INK - LOCAL __SET_INK2 - ld de, ATTR_P -__SET_INK: - cp 8 - jr nz, __SET_INK2 - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - or 7 ; Set bits 0,1,2 to enable transparency - ld (de), a - ret -__SET_INK2: - ; Another entry. This will set the ink color at location pointer by DE - and 7 ; # Gets color mod 8 - ld b, a ; Saves the color - ld a, (de) - and 0F8h ; Clears previous value - or b - ld (de), a - inc de ; Points DE to MASK_T or MASK_P - ld a, (de) - and 0F8h ; Reset bits 0,1,2 sign to disable transparency - ld (de), a ; Store new attr - ret - ; Sets the INK color passed in A register in the ATTR_T variable -INK_TMP: - ld de, ATTR_T - jp __SET_INK - ENDP - pop namespace -#line 9 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/paper.asm" - ; Sets paper color in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -PAPER: - PROC - LOCAL __SET_PAPER - LOCAL __SET_PAPER2 - ld de, ATTR_P -__SET_PAPER: - cp 8 - jr nz, __SET_PAPER2 - inc de - ld a, (de) - or 038h - ld (de), a - ret - ; Another entry. This will set the paper color at location pointer by DE -__SET_PAPER2: - and 7 ; # Remove - rlca - rlca - rlca ; a *= 8 - ld b, a ; Saves the color - ld a, (de) - and 0C7h ; Clears previous value - or b - ld (de), a - inc de ; Points to MASK_T or MASK_P accordingly - ld a, (de) - and 0C7h ; Resets bits 3,4,5 - ld (de), a - ret - ; Sets the PAPER color passed in A register in the ATTR_T variable -PAPER_TMP: - ld de, ATTR_T - jp __SET_PAPER - ENDP - pop namespace -#line 10 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/flash.asm" - ; Sets flash flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -FLASH: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_FLASH: - ; Another entry. This will set the flash flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x80 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 07Fh ; Clears previous value - or b - ld (hl), a - inc hl - res 7, (hl) ;Reset bit 7 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 7, (hl) ;Set bit 7 to enable transparency - ret - ; Sets the FLASH flag passed in A register in the ATTR_T variable -FLASH_TMP: - ld hl, ATTR_T - jr __SET_FLASH - ENDP - pop namespace -#line 11 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bright.asm" - ; Sets bright flag in ATTR_P permanently -; Parameter: Paper color in A register - push namespace core -BRIGHT: - ld hl, ATTR_P - PROC - LOCAL IS_TR - LOCAL IS_ZERO -__SET_BRIGHT: - ; Another entry. This will set the bright flag at location pointer by DE - cp 8 - jr z, IS_TR - ; # Convert to 0/1 - or a - jr z, IS_ZERO - ld a, 0x40 -IS_ZERO: - ld b, a ; Saves the color - ld a, (hl) - and 0BFh ; Clears previous value - or b - ld (hl), a - inc hl - res 6, (hl) ;Reset bit 6 to disable transparency - ret -IS_TR: ; transparent - inc hl ; Points DE to MASK_T or MASK_P - set 6, (hl) ;Set bit 6 to enable transparency - ret - ; Sets the BRIGHT flag passed in A register in the ATTR_T variable -BRIGHT_TMP: - ld hl, ATTR_T - jr __SET_BRIGHT - ENDP - pop namespace -#line 12 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/over.asm" - ; Sets OVER flag in P_FLAG permanently -; Parameter: OVER flag in bit 0 of A register - push namespace core -OVER: - PROC - ld c, a ; saves it for later - and 2 - ld hl, FLAGS2 - res 1, (HL) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 ; # Convert to 0/1 - add a, a; # Shift left 1 bit for permanent - ld hl, P_FLAG - res 1, (hl) - or (hl) - ld (hl), a - ret - ; Sets OVER flag in P_FLAG temporarily -OVER_TMP: - ld c, a ; saves it for later - and 2 ; gets bit 1; clears carry - rra - ld hl, FLAGS2 - res 0, (hl) - or (hl) - ld (hl), a - ld a, c ; Recovers previous value - and 1 - ld hl, P_FLAG - res 0, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 13 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/inverse.asm" - ; Sets INVERSE flag in P_FLAG permanently -; Parameter: INVERSE flag in bit 0 of A register - push namespace core -INVERSE: - PROC - and 1 ; # Convert to 0/1 - add a, a; # Shift left 3 bits for permanent - add a, a - add a, a - ld hl, P_FLAG - res 3, (hl) - or (hl) - ld (hl), a - ret - ; Sets INVERSE flag in P_FLAG temporarily -INVERSE_TMP: - and 1 - add a, a - add a, a; # Shift left 2 bits for temporary - ld hl, P_FLAG - res 2, (hl) - or (hl) - ld (hl), a - jp __SET_ATTR_MODE - ENDP - pop namespace -#line 14 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bold.asm" - ; Sets BOLD flag in P_FLAG permanently -; Parameter: BOLD flag in bit 0 of A register - push namespace core -BOLD: - PROC - and 1 - rlca - rlca - rlca - ld hl, FLAGS2 - res 3, (HL) - or (hl) - ld (hl), a - ret - ; Sets BOLD flag in P_FLAG temporarily -BOLD_TMP: - and 1 - rlca - rlca - ld hl, FLAGS2 - res 2, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 15 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/italic.asm" - ; Sets ITALIC flag in P_FLAG permanently -; Parameter: ITALIC flag in bit 0 of A register - push namespace core -ITALIC: - PROC - and 1 - rrca - rrca - rrca - ld hl, FLAGS2 - res 5, (HL) - or (hl) - ld (hl), a - ret - ; Sets ITALIC flag in P_FLAG temporarily -ITALIC_TMP: - and 1 - rrca - rrca - rrca - rrca - ld hl, FLAGS2 - res 4, (hl) - or (hl) - ld (hl), a - ret - ENDP - pop namespace -#line 16 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ; Putting a comment starting with @INIT
- ; will make the compiler to add a CALL to
- ; It is useful for initialization routines. - push namespace core -__PRINT_INIT: ; To be called before program starts (initializes library) - PROC - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - ;; Clears ATTR2 flags (OVER 2, etc) - xor a - ld (FLAGS2), a - ld hl, TV_FLAG - res 0, (hl) - LOCAL SET_SCR_ADDR - call __LOAD_S_POSN - jp __SET_SCR_PTR - ;; Receives HL = future value of S_POSN - ;; Stores it at (S_POSN) and refresh screen pointers (ATTR, SCR) -SET_SCR_ADDR: - ld (S_POSN), hl - ex de, hl - ld hl, SCR_SIZE - or a - sbc hl, de - ex de, hl - dec e - jp __SET_SCR_PTR -__PRINTCHAR: ; Print character store in accumulator (A register) - ; Modifies H'L', B'C', A'F', D'E', A - LOCAL PO_GR_1 - LOCAL __PRCHAR - LOCAL __PRINT_JUMP - LOCAL __SRCADDR - LOCAL __PRINT_UDG - LOCAL __PRGRAPH - LOCAL __PRINT_START - PRINT_JUMP_STATE EQU __PRINT_JUMP + 2 -__PRINT_JUMP: - exx ; Switch to alternative registers - jp __PRINT_START ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively -__PRINT_START: -__PRINT_CHR: - cp ' ' - jr c, __PRINT_SPECIAL ; Characters below ' ' are special ones - ex af, af' ; Saves a value (char to print) for later - ld hl, (S_POSN) - dec l - jr nz, 1f - ld l, SCR_COLS - 1 - dec h - jr nz, 2f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 94 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -2: - call SET_SCR_ADDR - jr 4f -1: - ld (S_POSN), hl -4: - ex af, af' - cp 80h ; Is it a "normal" (printable) char - jr c, __SRCADDR - cp 90h ; Is it an UDG? - jr nc, __PRINT_UDG - ; Print an 8 bit pattern (80h to 8Fh) - ld b, a - call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0 - ld hl, MEM0 - jp __PRGRAPH - PO_GR_1 EQU 0B38h -__PRINT_UDG: - sub 90h ; Sub ASC code - ld bc, (UDG) - jr __PRGRAPH0 - __SOURCEADDR EQU (__SRCADDR + 1) ; Address of the pointer to chars source -__SRCADDR: - ld bc, (CHARS) -__PRGRAPH0: - add a, a ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org - ld l, a - ld h, 0 ; HL = a * 2 (accumulator) - add hl, hl - add hl, hl ; HL = a * 8 - add hl, bc ; HL = CHARS address -__PRGRAPH: - ex de, hl ; HL = Write Address, DE = CHARS address - bit 2, (iy + $47) - call nz, __BOLD -#line 141 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - bit 4, (iy + $47) - call nz, __ITALIC -#line 146 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - ld hl, (DFCC) - push hl - ld b, 8 ; 8 bytes per char -__PRCHAR: - ld a, (de) ; DE *must* be source, and HL destiny -PRINT_MODE: ; Which operation is used to write on the screen - ; Set it with: - ; LD A, - ; LD (PRINT_MODE), A - ; - ; Available operations: - ; NORMAL : 0h --> NOP ; OVER 0 - ; XOR : AEh --> XOR (HL) ; OVER 1 - ; OR : B6h --> OR (HL) ; PUTSPRITE - ; AND : A6h --> AND (HL) ; PUTMASK - nop ; Set to one of the values above -INVERSE_MODE: ; 00 -> NOP -> INVERSE 0 - nop ; 2F -> CPL -> INVERSE 1 - ld (hl), a - inc de - inc h ; Next line - djnz __PRCHAR - pop hl - inc hl - ld (DFCC), hl - ld hl, (DFCCL) ; current ATTR Pos - inc hl - ld (DFCCL), hl - dec hl - call __SET_ATTR - exx - ret - ; ------------- SPECIAL CHARS (< 32) ----------------- -__PRINT_SPECIAL: ; Jumps here if it is a special char - ld hl, __PRINT_TABLE - jp JUMP_HL_PLUS_2A -PRINT_EOL: ; Called WHENEVER there is no ";" at end of PRINT sentence - exx -__PRINT_0Dh: ; Called WHEN printing CHR$(13) - ld hl, (S_POSN) - dec l - jr nz, 1f - dec h - jr nz, 1f - inc h - push hl - call __SCROLL_SCR - pop hl -#line 211 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -1: - ld l, 1 -__PRINT_EOL_END: - call SET_SCR_ADDR - exx - ret -__PRINT_COM: - exx - push hl - push de - push bc - call PRINT_COMMA - pop bc - pop de - pop hl - ret -__PRINT_TAB: - ld hl, __PRINT_TAB1 - jr __PRINT_SET_STATE -__PRINT_TAB1: - ld (MEM0), a - ld hl, __PRINT_TAB2 - jr __PRINT_SET_STATE -__PRINT_TAB2: - ld a, (MEM0) ; Load tab code (ignore the current one) - ld hl, __PRINT_START - ld (PRINT_JUMP_STATE), hl - exx - push hl - push bc - push de - call PRINT_TAB - pop de - pop bc - pop hl - ret -__PRINT_AT: - ld hl, __PRINT_AT1 - jr __PRINT_SET_STATE -__PRINT_NOP: -__PRINT_RESTART: - ld hl, __PRINT_START -__PRINT_SET_STATE: - ld (PRINT_JUMP_STATE), hl ; Saves next entry call - exx - ret -__PRINT_AT1: ; Jumps here if waiting for 1st parameter - ld hl, (S_POSN) - ld h, a - ld a, SCR_ROWS - sub h - ld (S_POSN + 1), a - ld hl, __PRINT_AT2 - jr __PRINT_SET_STATE -__PRINT_AT2: - call __LOAD_S_POSN - ld e, a - call __SAVE_S_POSN - jr __PRINT_RESTART -__PRINT_DEL: - call __LOAD_S_POSN ; Gets current screen position - dec e - ld a, -1 - cp e - jr nz, 3f - ld e, SCR_COLS - 2 - dec d - cp d - jr nz, 3f - ld d, SCR_ROWS - 1 -3: - call __SAVE_S_POSN - exx - ret -__PRINT_INK: - ld hl, __PRINT_INK2 - jr __PRINT_SET_STATE -__PRINT_INK2: - call INK_TMP - jr __PRINT_RESTART -__PRINT_PAP: - ld hl, __PRINT_PAP2 - jr __PRINT_SET_STATE -__PRINT_PAP2: - call PAPER_TMP - jr __PRINT_RESTART -__PRINT_FLA: - ld hl, __PRINT_FLA2 - jr __PRINT_SET_STATE -__PRINT_FLA2: - call FLASH_TMP - jr __PRINT_RESTART -__PRINT_BRI: - ld hl, __PRINT_BRI2 - jr __PRINT_SET_STATE -__PRINT_BRI2: - call BRIGHT_TMP - jr __PRINT_RESTART -__PRINT_INV: - ld hl, __PRINT_INV2 - jr __PRINT_SET_STATE -__PRINT_INV2: - call INVERSE_TMP - jr __PRINT_RESTART -__PRINT_OVR: - ld hl, __PRINT_OVR2 - jr __PRINT_SET_STATE -__PRINT_OVR2: - call OVER_TMP - jr __PRINT_RESTART -__PRINT_BOLD: - ld hl, __PRINT_BOLD2 - jp __PRINT_SET_STATE -__PRINT_BOLD2: - call BOLD_TMP - jp __PRINT_RESTART -#line 355 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_ITA: - ld hl, __PRINT_ITA2 - jp __PRINT_SET_STATE -__PRINT_ITA2: - call ITALIC_TMP - jp __PRINT_RESTART -#line 365 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __BOLD -__BOLD: - push hl - ld hl, MEM0 - ld b, 8 -1: - ld a, (de) - ld c, a - rlca - or c - ld (hl), a - inc hl - inc de - djnz 1b - pop hl - ld de, MEM0 - ret -#line 386 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __ITALIC -__ITALIC: - push hl - ld hl, MEM0 - ex de, hl - ld bc, 8 - ldir - ld hl, MEM0 - srl (hl) - inc hl - srl (hl) - inc hl - srl (hl) - inc hl - inc hl - inc hl - sla (hl) - inc hl - sla (hl) - inc hl - sla (hl) - pop hl - ld de, MEM0 - ret -#line 414 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __SCROLL_SCR -#line 488 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - __SCROLL_SCR EQU 0DFEh ; Use ROM SCROLL -#line 490 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -#line 491 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -PRINT_COMMA: - call __LOAD_S_POSN - ld a, e - and 16 - add a, 16 -PRINT_TAB: - ; Tabulates the number of spaces in A register - ; If the current cursor position is already A, does nothing - PROC - LOCAL LOOP - call __LOAD_S_POSN ; e = current row - sub e - and 31 - ret z - ld b, a -LOOP: - ld a, ' ' - call __PRINTCHAR - djnz LOOP - ret - ENDP -PRINT_AT: ; Changes cursor to ROW, COL - ; COL in A register - ; ROW in stack - pop hl ; Ret address - ex (sp), hl ; callee H = ROW - ld l, a - ex de, hl - call __IN_SCREEN - ret nc ; Return if out of screen - jp __SAVE_S_POSN - LOCAL __PRINT_COM - LOCAL __PRINT_AT1 - LOCAL __PRINT_AT2 - LOCAL __PRINT_BOLD - LOCAL __PRINT_ITA - LOCAL __PRINT_INK - LOCAL __PRINT_PAP - LOCAL __PRINT_SET_STATE - LOCAL __PRINT_TABLE - LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2 - LOCAL __PRINT_ITA2 -#line 547 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" - LOCAL __PRINT_BOLD2 -#line 553 "/zxbasic/src/lib/arch/zx48k/runtime/print.asm" -__PRINT_TABLE: ; Jump table for 0 .. 22 codes - DW __PRINT_NOP ; 0 - DW __PRINT_NOP ; 1 - DW __PRINT_NOP ; 2 - DW __PRINT_NOP ; 3 - DW __PRINT_NOP ; 4 - DW __PRINT_NOP ; 5 - DW __PRINT_COM ; 6 COMMA - DW __PRINT_NOP ; 7 - DW __PRINT_DEL ; 8 DEL - DW __PRINT_NOP ; 9 - DW __PRINT_NOP ; 10 - DW __PRINT_NOP ; 11 - DW __PRINT_NOP ; 12 - DW __PRINT_0Dh ; 13 - DW __PRINT_BOLD ; 14 - DW __PRINT_ITA ; 15 - DW __PRINT_INK ; 16 - DW __PRINT_PAP ; 17 - DW __PRINT_FLA ; 18 - DW __PRINT_BRI ; 19 - DW __PRINT_INV ; 20 - DW __PRINT_OVR ; 21 - DW __PRINT_AT ; 22 AT - DW __PRINT_TAB ; 23 TAB - ENDP - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" - push namespace core -COPY_ATTR: - ; Just copies current permanent attribs into temporal attribs - ; and sets print mode - PROC - LOCAL INVERSE1 - LOCAL __REFRESH_TMP - INVERSE1 EQU 02Fh - ld hl, (ATTR_P) - ld (ATTR_T), hl - ld hl, FLAGS2 - call __REFRESH_TMP - ld hl, P_FLAG - call __REFRESH_TMP -__SET_ATTR_MODE: ; Another entry to set print modes. A contains (P_FLAG) - LOCAL TABLE - LOCAL CONT2 - rra ; Over bit to carry - ld a, (FLAGS2) - rla ; Over bit in bit 1, Over2 bit in bit 2 - and 3 ; Only bit 0 and 1 (OVER flag) - ld c, a - ld b, 0 - ld hl, TABLE - add hl, bc - ld a, (hl) - ld (PRINT_MODE), a - ld hl, (P_FLAG) - xor a ; NOP -> INVERSE0 - bit 2, l - jr z, CONT2 - ld a, INVERSE1 ; CPL -> INVERSE1 -CONT2: - ld (INVERSE_MODE), a - ret -TABLE: - nop ; NORMAL MODE - xor (hl) ; OVER 1 MODE - and (hl) ; OVER 2 MODE - or (hl) ; OVER 3 MODE -#line 67 "/zxbasic/src/lib/arch/zx48k/runtime/copy_attr.asm" -__REFRESH_TMP: - ld a, (hl) - and 0b10101010 - ld c, a - rra - or c - ld (hl), a - ret - ENDP - pop namespace -#line 120 "arch/zx48k/subrec.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/heapinit.asm" -; vim: ts=4:et:sw=4: - ; Copyleft (K) by Jose M. Rodriguez de la Rosa - ; (a.k.a. Boriel) -; http://www.boriel.com - ; - ; This ASM library is licensed under the BSD license - ; you can use it for any purpose (even for commercial - ; closed source programs). - ; - ; Please read the BSD license on the internet - ; ----- IMPLEMENTATION NOTES ------ - ; The heap is implemented as a linked list of free blocks. -; Each free block contains this info: - ; - ; +----------------+ <-- HEAP START - ; | Size (2 bytes) | - ; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | <-- If Size > 4, then this contains (size - 4) bytes - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ | - ; | <-- This zone is in use (Already allocated) - ; +----------------+ <-+ - ; | Size (2 bytes) | - ; +----------------+ - ; | Next (2 bytes) |---+ - ; +----------------+ | - ; | | | - ; | (0 if Size = 4)| | - ; +----------------+ <-+ - ; | Next (2 bytes) |--> NULL => END OF LIST - ; | 0 = NULL | - ; +----------------+ - ; | | - ; | (0 if Size = 4)| - ; +----------------+ - ; When a block is FREED, the previous and next pointers are examined to see - ; if we can defragment the heap. If the block to be breed is just next to the - ; previous, or to the next (or both) they will be converted into a single - ; block (so defragmented). - ; MEMORY MANAGER - ; - ; This library must be initialized calling __MEM_INIT with - ; HL = BLOCK Start & DE = Length. - ; An init directive is useful for initialization routines. - ; They will be added automatically if needed. - ; --------------------------------------------------------------------- - ; __MEM_INIT must be called to initalize this library with the - ; standard parameters - ; --------------------------------------------------------------------- - push namespace core -__MEM_INIT: ; Initializes the library using (RAMTOP) as start, and - ld hl, ZXBASIC_MEM_HEAP ; Change this with other address of heap start - ld de, ZXBASIC_HEAP_SIZE ; Change this with your size - ; --------------------------------------------------------------------- - ; __MEM_INIT2 initalizes this library -; Parameters: -; HL : Memory address of 1st byte of the memory heap -; DE : Length in bytes of the Memory Heap - ; --------------------------------------------------------------------- -__MEM_INIT2: - ; HL as TOP - PROC - dec de - dec de - dec de - dec de ; DE = length - 4; HL = start - ; This is done, because we require 4 bytes for the empty dummy-header block - xor a - ld (hl), a - inc hl - ld (hl), a ; First "free" block is a header: size=0, Pointer=&(Block) + 4 - inc hl - ld b, h - ld c, l - inc bc - inc bc ; BC = starts of next block - ld (hl), c - inc hl - ld (hl), b - inc hl ; Pointer to next block - ld (hl), e - inc hl - ld (hl), d - inc hl ; Block size (should be length - 4 at start); This block contains all the available memory - ld (hl), a ; NULL (0000h) ; No more blocks (a list with a single block) - inc hl - ld (hl), a - ld a, 201 - ld (__MEM_INIT), a; "Pokes" with a RET so ensure this routine is not called again - ret - ENDP - pop namespace -#line 69 "/zxbasic/src/lib/arch/zx48k/runtime/free.asm" - ; --------------------------------------------------------------------- - ; MEM_FREE - ; Frees a block of memory - ; -; Parameters: - ; HL = Pointer to the block to be freed. If HL is NULL (0) nothing - ; is done - ; --------------------------------------------------------------------- - push namespace core -MEM_FREE: -__MEM_FREE: ; Frees the block pointed by HL - ; HL DE BC & AF modified - PROC - LOCAL __MEM_LOOP2 - LOCAL __MEM_LINK_PREV - LOCAL __MEM_JOIN_TEST - LOCAL __MEM_BLOCK_JOIN - ld a, h - or l - ret z ; Return if NULL pointer - dec hl - dec hl - ld b, h - ld c, l ; BC = Block pointer - ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start -__MEM_LOOP2: - inc hl - inc hl ; Next block ptr - ld e, (hl) - inc hl - ld d, (hl) ; Block next ptr - ex de, hl ; DE = &(block->next); HL = block->next - ld a, h ; HL == NULL? - or l - jp z, __MEM_LINK_PREV; if so, link with previous - or a ; Clear carry flag - sbc hl, bc ; Carry if BC > HL => This block if before - add hl, bc ; Restores HL, preserving Carry flag - jp c, __MEM_LOOP2 ; This block is before. Keep searching PASS the block - ;------ At this point current HL is PAST BC, so we must link (DE) with BC, and HL in BC->next -__MEM_LINK_PREV: ; Link (DE) with BC, and BC->next with HL - ex de, hl - push hl - dec hl - ld (hl), c - inc hl - ld (hl), b ; (DE) <- BC - ld h, b ; HL <- BC (Free block ptr) - ld l, c - inc hl ; Skip block length (2 bytes) - inc hl - ld (hl), e ; Block->next = DE - inc hl - ld (hl), d - ; --- LINKED ; HL = &(BC->next) + 2 - call __MEM_JOIN_TEST - pop hl -__MEM_JOIN_TEST: ; Checks for fragmented contiguous blocks and joins them - ; hl = Ptr to current block + 2 - ld d, (hl) - dec hl - ld e, (hl) - dec hl - ld b, (hl) ; Loads block length into BC - dec hl - ld c, (hl) ; - push hl ; Saves it for later - add hl, bc ; Adds its length. If HL == DE now, it must be joined - or a - sbc hl, de ; If Z, then HL == DE => We must join - pop hl - ret nz -__MEM_BLOCK_JOIN: ; Joins current block (pointed by HL) with next one (pointed by DE). HL->length already in BC - push hl ; Saves it for later - ex de, hl - ld e, (hl) ; DE -> block->next->length - inc hl - ld d, (hl) - inc hl - ex de, hl ; DE = &(block->next) - add hl, bc ; HL = Total Length - ld b, h - ld c, l ; BC = Total Length - ex de, hl - ld e, (hl) - inc hl - ld d, (hl) ; DE = block->next - pop hl ; Recovers Pointer to block - ld (hl), c - inc hl - ld (hl), b ; Length Saved - inc hl - ld (hl), e - inc hl - ld (hl), d ; Next saved - ret - ENDP - pop namespace -#line 5 "/zxbasic/src/lib/arch/zx48k/runtime/printstr.asm" - ; PRINT command routine - ; Prints string pointed by HL - push namespace core -PRINT_STR: -__PRINTSTR: ; __FASTCALL__ Entry to print_string - PROC - LOCAL __PRINT_STR_LOOP - LOCAL __PRINT_STR_END - ld d, a ; Saves A reg (Flag) for later - ld a, h - or l - ret z ; Return if the pointer is NULL - push hl - ld c, (hl) - inc hl - ld b, (hl) - inc hl ; BC = LEN(a$); HL = &a$ -__PRINT_STR_LOOP: - ld a, b - or c - jr z, __PRINT_STR_END ; END if BC (counter = 0) - ld a, (hl) - call __PRINTCHAR - inc hl - dec bc - jp __PRINT_STR_LOOP -__PRINT_STR_END: - pop hl - ld a, d ; Recovers A flag - or a ; If not 0 this is a temporary string. Free it - ret z - jp __MEM_FREE ; Frees str from heap and return from there -__PRINT_STR: - ; Fastcall Entry - ; It ONLY prints strings - ; HL = String start - ; BC = String length (Number of chars) - push hl ; Push str address for later - ld d, a ; Saves a FLAG - jp __PRINT_STR_LOOP - ENDP - pop namespace -#line 122 "arch/zx48k/subrec.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printu32.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi32.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printnum.asm" - push namespace core -__PRINTU_START: - PROC - LOCAL __PRINTU_CONT - ld a, b - or a - jp nz, __PRINTU_CONT - ld a, '0' - jp __PRINT_DIGIT -__PRINTU_CONT: - pop af - push bc - call __PRINT_DIGIT - pop bc - djnz __PRINTU_CONT - ret - ENDP -__PRINT_MINUS: ; PRINT the MINUS (-) sign. CALLER must preserve registers - ld a, '-' - jp __PRINT_DIGIT - __PRINT_DIGIT EQU __PRINTCHAR ; PRINTS the char in A register, and puts its attrs - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printi32.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/neg32.asm" - push namespace core -__ABS32: - bit 7, d - ret z -__NEG32: ; Negates DEHL (Two's complement) - ld a, l - cpl - ld l, a - ld a, h - cpl - ld h, a - ld a, e - cpl - ld e, a - ld a, d - cpl - ld d, a - inc l - ret nz - inc h - ret nz - inc de - ret - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/printi32.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div32.asm" - ; --------------------------------------------------------- - push namespace core -__DIVU32: ; 32 bit unsigned division - ; DEHL = Dividend, Stack Top = Divisor - ; OPERANDS P = Dividend, Q = Divisor => OPERATION => P / Q - ; - ; Changes A, BC DE HL B'C' D'E' H'L' - ; --------------------------------------------------------- - exx - pop hl ; return address - pop de ; low part - ex (sp), hl ; CALLEE Convention ; H'L'D'E' => Dividend -__DIVU32START: ; Performs D'E'H'L' / HLDE - ; Now switch to DIVIDEND = B'C'BC / DIVISOR = D'E'DE (A / B) - push de ; push Lowpart(Q) - ex de, hl ; DE = HL - ld hl, 0 - exx - ld b, h - ld c, l - pop hl - push de - ex de, hl - ld hl, 0 ; H'L'HL = 0 - exx - pop bc ; Pop HightPart(B) => B = B'C'BC - exx - ld a, 32 ; Loop count -__DIV32LOOP: - sll c ; B'C'BC << 1 ; Output most left bit to carry - rl b - exx - rl c - rl b - exx - adc hl, hl - exx - adc hl, hl - exx - sbc hl,de - exx - sbc hl,de - exx - jp nc, __DIV32NOADD ; use JP inside a loop for being faster - add hl, de - exx - adc hl, de - exx - dec bc -__DIV32NOADD: - dec a - jp nz, __DIV32LOOP ; use JP inside a loop for being faster - ; At this point, quotient is stored in B'C'BC and the reminder in H'L'HL - push hl - exx - pop de - ex de, hl ; D'E'H'L' = 32 bits modulus - push bc - exx - pop de ; DE = B'C' - ld h, b - ld l, c ; DEHL = quotient D'E'H'L' = Modulus - ret ; DEHL = quotient, D'E'H'L' = Modulus -__MODU32: ; 32 bit modulus for 32bit unsigned division - ; DEHL = Dividend, Stack Top = Divisor (DE, HL) - exx - pop hl ; return address - pop de ; low part - ex (sp), hl ; CALLEE Convention ; H'L'D'E' => Dividend - call __DIVU32START ; At return, modulus is at D'E'H'L' -__MODU32START: - exx - push de - push hl - exx - pop hl - pop de - ret -__DIVI32: ; 32 bit signed division - ; DEHL = Dividend, Stack Top = Divisor - ; A = Dividend, B = Divisor => A / B - exx - pop hl ; return address - pop de ; low part - ex (sp), hl ; CALLEE Convention ; H'L'D'E' => Dividend -__DIVI32START: - exx - ld a, d ; Save sign - ex af, af' - bit 7, d ; Negative? - call nz, __NEG32 ; Negates DEHL - exx ; Now works with H'L'D'E' - ex af, af' - xor h - ex af, af' ; Stores sign of the result for later - bit 7, h ; Negative? - ex de, hl ; HLDE = DEHL - call nz, __NEG32 - ex de, hl - call __DIVU32START - ex af, af' ; Recovers sign - and 128 ; positive? - ret z - jp __NEG32 ; Negates DEHL and returns from there -__MODI32: ; 32bits signed division modulus - exx - pop hl ; return address - pop de ; low part - ex (sp), hl ; CALLEE Convention ; H'L'D'E' => Dividend - call __DIVI32START - jp __MODU32START - pop namespace -#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/printi32.asm" - push namespace core -__PRINTI32: - ld a, d - or a - jp p, __PRINTU32 - call __PRINT_MINUS - call __NEG32 -__PRINTU32: - PROC - LOCAL __PRINTU_LOOP - ld b, 0 ; Counter -__PRINTU_LOOP: - ld a, h - or l - or d - or e - jp z, __PRINTU_START - push bc - ld bc, 0 - push bc - ld bc, 10 - push bc ; Push 00 0A (10 Dec) into the stack = divisor - call __DIVU32 ; Divides by 32. D'E'H'L' contains modulo (L' since < 10) - pop bc - exx - ld a, l - or '0' ; Stores ASCII digit (must be print in reversed order) - push af - exx - inc b - jp __PRINTU_LOOP ; Uses JP in loops - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printu32.asm" -#line 123 "arch/zx48k/subrec.bas" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" -#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/div8.asm" - ; -------------------------------- - push namespace core -__DIVU8: ; 8 bit unsigned integer division - ; Divides (Top of stack, High Byte) / A - pop hl ; -------------------------------- - ex (sp), hl ; CALLEE -__DIVU8_FAST: ; Does A / H - ld l, h - ld h, a ; At this point do H / L - ld b, 8 - xor a ; A = 0, Carry Flag = 0 -__DIV8LOOP: - sla h - rla - cp l - jr c, __DIV8NOSUB - sub l - inc h -__DIV8NOSUB: - djnz __DIV8LOOP - ld l, a ; save remainder - ld a, h ; - ret ; a = Quotient, - ; -------------------------------- -__DIVI8: ; 8 bit signed integer division Divides (Top of stack) / A - pop hl ; -------------------------------- - ex (sp), hl -__DIVI8_FAST: - ld e, a ; store operands for later - ld c, h - or a ; negative? - jp p, __DIV8A - neg ; Make it positive -__DIV8A: - ex af, af' - ld a, h - or a - jp p, __DIV8B - neg - ld h, a ; make it positive -__DIV8B: - ex af, af' - call __DIVU8_FAST - ld a, c - xor l ; bit 7 of A = 1 if result is negative - ld a, h ; Quotient - ret p ; return if positive - neg - ret -__MODU8: ; 8 bit module. REturns A mod (Top of stack) (unsigned operands) - pop hl - ex (sp), hl ; CALLEE -__MODU8_FAST: ; __FASTCALL__ entry - call __DIVU8_FAST - ld a, l ; Remainder - ret ; a = Modulus -__MODI8: ; 8 bit module. REturns A mod (Top of stack) (For singed operands) - pop hl - ex (sp), hl ; CALLEE -__MODI8_FAST: ; __FASTCALL__ entry - call __DIVI8_FAST - ld a, l ; remainder - ret ; a = Modulus - pop namespace -#line 3 "/zxbasic/src/lib/arch/zx48k/runtime/printi8.asm" - push namespace core -__PRINTI8: ; Prints an 8 bits number in Accumulator (A) - ; Converts 8 to 32 bits - or a - jp p, __PRINTU8 - push af - call __PRINT_MINUS - pop af - neg -__PRINTU8: - PROC - LOCAL __PRINTU_LOOP - ld b, 0 ; Counter -__PRINTU_LOOP: - or a - jp z, __PRINTU_START - push bc - ld h, 10 - call __DIVU8_FAST ; Divides by 10. D'E'H'L' contains modulo (L' since < 10) - pop bc - ld a, l - or '0' ; Stores ASCII digit (must be print in reversed order) - push af - ld a, h - inc b - jp __PRINTU_LOOP ; Uses JP in loops - ENDP - pop namespace -#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/printu8.asm" -#line 124 "arch/zx48k/subrec.bas" +#line 96 "arch/zx48k/subrec.bas" END diff --git a/tests/functional/arch/zx48k/subrec.bas b/tests/functional/arch/zx48k/subrec.bas index c568298e0..244558ae7 100644 --- a/tests/functional/arch/zx48k/subrec.bas +++ b/tests/functional/arch/zx48k/subrec.bas @@ -1,6 +1,7 @@ REM Factorial recursive test DIM result as ulong = 1 +DIM dummy as ulong sub fact(x as ulong) if x < 2 then @@ -15,5 +16,5 @@ cls for x = 1 To 10: result = 1 fact(x) - print "Fact ("; x; ") = "; result + dummy = result next x diff --git a/tests/functional/arch/zx48k/xor16.asm b/tests/functional/arch/zx48k/xor16.asm index 90c96b860..32701f831 100644 --- a/tests/functional/arch/zx48k/xor16.asm +++ b/tests/functional/arch/zx48k/xor16.asm @@ -27,26 +27,35 @@ _b: ld hl, (_a) ld a, h or l + sub 1 + sbc a, a + inc a ld (_b), a ld hl, (_a) ld a, h or l sub 1 sbc a, a + neg ld (_b), a ld hl, (_a) ld a, h or l + sub 1 + sbc a, a + inc a ld (_b), a ld hl, (_a) ld a, h or l sub 1 sbc a, a + neg ld (_b), a ld de, (_a) ld hl, (_a) call .core.__XOR16 + neg ld (_b), a ld hl, 0 ld b, h @@ -63,9 +72,9 @@ _b: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/xor16.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bool/xor16.asm" ; XOR16 implemented in XOR8.ASM file -#line 1 "/zxbasic/src/arch/zx48k/library-asm/xor8.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bool/xor8.asm" ; vim:ts=4:et: ; FASTCALL boolean xor 8 version. ; result in Accumulator (0 False, not 0 True) @@ -88,6 +97,6 @@ __XOR8: xor l ret pop namespace -#line 4 "/zxbasic/src/arch/zx48k/library-asm/xor16.asm" -#line 41 "xor16.bas" +#line 4 "/zxbasic/src/lib/arch/zx48k/runtime/bool/xor16.asm" +#line 50 "arch/zx48k/xor16.bas" END diff --git a/tests/functional/arch/zx48k/xor32.asm b/tests/functional/arch/zx48k/xor32.asm index 6bd0d98f7..ae23a362d 100644 --- a/tests/functional/arch/zx48k/xor32.asm +++ b/tests/functional/arch/zx48k/xor32.asm @@ -31,6 +31,7 @@ _b: ld de, 0 ld hl, 0 call .core.__XOR32 + neg ld (_b), a ld hl, (_a + 2) push hl @@ -39,6 +40,7 @@ _b: ld de, 0 ld hl, 1 call .core.__XOR32 + neg ld (_b), a ld hl, (_a) ld de, (_a + 2) @@ -47,6 +49,7 @@ _b: ld bc, 0 push bc call .core.__XOR32 + neg ld (_b), a ld hl, (_a) ld de, (_a + 2) @@ -55,6 +58,7 @@ _b: ld bc, 1 push bc call .core.__XOR32 + neg ld (_b), a ld hl, (_a + 2) push hl @@ -63,6 +67,7 @@ _b: ld hl, (_a) ld de, (_a + 2) call .core.__XOR32 + neg ld (_b), a ld hl, 0 ld b, h @@ -79,12 +84,12 @@ _b: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/xor32.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bool/xor32.asm" ; FASTCALL boolean xor 8 version. ; result in Accumulator (0 False, not 0 True) ; __FASTCALL__ version (operands: A, H) ; Performs 32bit xor 32bit and returns the boolean -#line 1 "/zxbasic/src/arch/zx48k/library-asm/xor8.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bool/xor8.asm" ; vim:ts=4:et: ; FASTCALL boolean xor 8 version. ; result in Accumulator (0 False, not 0 True) @@ -107,7 +112,7 @@ __XOR8: xor l ret pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/xor32.asm" +#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/bool/xor32.asm" push namespace core __XOR32: ld a, h @@ -125,5 +130,5 @@ __XOR32: ld h, c jp __XOR8 pop namespace -#line 57 "xor32.bas" +#line 62 "arch/zx48k/xor32.bas" END diff --git a/tests/functional/arch/zx48k/xor8.asm b/tests/functional/arch/zx48k/xor8.asm index 6fe10b2ef..1cf54ce1b 100644 --- a/tests/functional/arch/zx48k/xor8.asm +++ b/tests/functional/arch/zx48k/xor8.asm @@ -25,20 +25,29 @@ _b: .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: ld a, (_a) + sub 1 + sbc a, a + inc a ld (_b), a ld a, (_a) sub 1 sbc a, a + neg ld (_b), a ld a, (_a) + sub 1 + sbc a, a + inc a ld (_b), a ld a, (_a) sub 1 sbc a, a + neg ld (_b), a ld hl, (_a - 1) ld a, (_a) call .core.__XOR8 + neg ld (_b), a ld hl, 0 ld b, h @@ -55,7 +64,7 @@ _b: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/xor8.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/bool/xor8.asm" ; vim:ts=4:et: ; FASTCALL boolean xor 8 version. ; result in Accumulator (0 False, not 0 True) @@ -78,5 +87,5 @@ __XOR8: xor l ret pop namespace -#line 33 "xor8.bas" +#line 42 "arch/zx48k/xor8.bas" END diff --git a/tests/functional/arch/zxnext/gef16.asm b/tests/functional/arch/zxnext/gef16.asm index 01c953e58..ddebc2790 100644 --- a/tests/functional/arch/zxnext/gef16.asm +++ b/tests/functional/arch/zxnext/gef16.asm @@ -39,6 +39,7 @@ _l: call .core.__LTI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ex de, hl @@ -54,6 +55,7 @@ _l: call .core.__LTI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ex de, hl @@ -69,6 +71,7 @@ _l: call .core.__LTI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ex de, hl @@ -84,6 +87,7 @@ _l: call .core.__LTI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ex de, hl @@ -101,7 +105,7 @@ _l: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zxnext/runtime/lti32.asm" +#line 1 "/zxbasic/src/lib/arch/zxnext/runtime/cmp/lti32.asm" #line 1 "/zxbasic/src/lib/arch/zxnext/runtime/arith/sub32.asm" ; SUB32 ; Perform TOP of the stack - DEHL @@ -128,7 +132,7 @@ __SUB32: exx ret pop namespace -#line 3 "/zxbasic/src/lib/arch/zxnext/runtime/lti32.asm" +#line 3 "/zxbasic/src/lib/arch/zxnext/runtime/cmp/lti32.asm" push namespace core __LTI32: ; Test 32 bit values in Top of the stack < HLDE PROC @@ -150,7 +154,7 @@ checkParity: ret ENDP pop namespace -#line 74 "arch/zxnext/gef16.bas" +#line 78 "arch/zxnext/gef16.bas" #line 1 "/zxbasic/src/lib/arch/zxnext/runtime/swap32.asm" ; Exchanges current DE HL with the ; ones in the stack @@ -168,5 +172,5 @@ __SWAP32: push bc ret pop namespace -#line 75 "arch/zxnext/gef16.bas" +#line 79 "arch/zxnext/gef16.bas" END diff --git a/tests/functional/arch/zxnext/gei32.asm b/tests/functional/arch/zxnext/gei32.asm index 547971c08..6b8d9bb0b 100644 --- a/tests/functional/arch/zxnext/gei32.asm +++ b/tests/functional/arch/zxnext/gei32.asm @@ -39,6 +39,7 @@ _l: call .core.__LTI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -54,6 +55,7 @@ _l: call .core.__LTI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -69,6 +71,7 @@ _l: call .core.__LTI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -84,6 +87,7 @@ _l: call .core.__LTI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -99,6 +103,7 @@ _l: call .core.__LTI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -116,7 +121,7 @@ _l: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zxnext/runtime/lti32.asm" +#line 1 "/zxbasic/src/lib/arch/zxnext/runtime/cmp/lti32.asm" #line 1 "/zxbasic/src/lib/arch/zxnext/runtime/arith/sub32.asm" ; SUB32 ; Perform TOP of the stack - DEHL @@ -143,7 +148,7 @@ __SUB32: exx ret pop namespace -#line 3 "/zxbasic/src/lib/arch/zxnext/runtime/lti32.asm" +#line 3 "/zxbasic/src/lib/arch/zxnext/runtime/cmp/lti32.asm" push namespace core __LTI32: ; Test 32 bit values in Top of the stack < HLDE PROC @@ -165,7 +170,7 @@ checkParity: ret ENDP pop namespace -#line 89 "arch/zxnext/gei32.bas" +#line 94 "arch/zxnext/gei32.bas" #line 1 "/zxbasic/src/lib/arch/zxnext/runtime/swap32.asm" ; Exchanges current DE HL with the ; ones in the stack @@ -183,5 +188,5 @@ __SWAP32: push bc ret pop namespace -#line 90 "arch/zxnext/gei32.bas" +#line 95 "arch/zxnext/gei32.bas" END diff --git a/tests/functional/arch/zxnext/geu16.asm b/tests/functional/arch/zxnext/geu16.asm index a5f4d06c6..5395c35b6 100644 --- a/tests/functional/arch/zxnext/geu16.asm +++ b/tests/functional/arch/zxnext/geu16.asm @@ -32,6 +32,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -41,6 +42,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -52,6 +54,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -64,6 +67,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -74,6 +78,7 @@ _l: sbc hl, de ccf sbc a, a + neg ld l, a ld h, 0 ld (_l), hl diff --git a/tests/functional/arch/zxnext/geu32.asm b/tests/functional/arch/zxnext/geu32.asm index b55a443ec..8fdc17539 100644 --- a/tests/functional/arch/zxnext/geu32.asm +++ b/tests/functional/arch/zxnext/geu32.asm @@ -39,6 +39,7 @@ _l: call .core.__SUB32 ccf sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -54,6 +55,7 @@ _l: call .core.__SUB32 ccf sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -69,6 +71,7 @@ _l: call .core.__SUB32 ccf sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -84,6 +87,7 @@ _l: call .core.__SUB32 ccf sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -99,6 +103,7 @@ _l: call .core.__SUB32 ccf sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -142,7 +147,7 @@ __SUB32: exx ret pop namespace -#line 89 "arch/zxnext/geu32.bas" +#line 94 "arch/zxnext/geu32.bas" #line 1 "/zxbasic/src/lib/arch/zxnext/runtime/swap32.asm" ; Exchanges current DE HL with the ; ones in the stack @@ -160,5 +165,5 @@ __SWAP32: push bc ret pop namespace -#line 90 "arch/zxnext/geu32.bas" +#line 95 "arch/zxnext/geu32.bas" END diff --git a/tests/functional/arch/zxnext/geu8.asm b/tests/functional/arch/zxnext/geu8.asm index 68fcdcdab..9ecf7b623 100644 --- a/tests/functional/arch/zxnext/geu8.asm +++ b/tests/functional/arch/zxnext/geu8.asm @@ -29,12 +29,14 @@ _l: sub h ccf sbc a, a + neg ld (_l), a ld hl, (_level - 1) ld a, (_le) sub h ccf sbc a, a + neg ld (_l), a ld a, (_le) push af @@ -43,12 +45,14 @@ _l: sub h ccf sbc a, a + neg ld (_l), a ld a, (_le) ld hl, (_level - 1) sub h ccf sbc a, a + neg ld (_l), a ld a, (_level) ld h, a @@ -56,6 +60,7 @@ _l: sub h ccf sbc a, a + neg ld (_l), a ld hl, 0 ld b, h diff --git a/tests/functional/arch/zxnext/gtf16.asm b/tests/functional/arch/zxnext/gtf16.asm index bfda0fdde..bea145f4e 100644 --- a/tests/functional/arch/zxnext/gtf16.asm +++ b/tests/functional/arch/zxnext/gtf16.asm @@ -39,6 +39,7 @@ _l: call .core.__LEI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ex de, hl @@ -54,6 +55,7 @@ _l: call .core.__LEI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ex de, hl @@ -69,6 +71,7 @@ _l: call .core.__LEI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ex de, hl @@ -84,6 +87,7 @@ _l: call .core.__LEI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ex de, hl @@ -101,7 +105,7 @@ _l: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zxnext/runtime/lei32.asm" +#line 1 "/zxbasic/src/lib/arch/zxnext/runtime/cmp/lei32.asm" #line 1 "/zxbasic/src/lib/arch/zxnext/runtime/arith/sub32.asm" ; SUB32 ; Perform TOP of the stack - DEHL @@ -128,7 +132,7 @@ __SUB32: exx ret pop namespace -#line 3 "/zxbasic/src/lib/arch/zxnext/runtime/lei32.asm" +#line 3 "/zxbasic/src/lib/arch/zxnext/runtime/cmp/lei32.asm" push namespace core __LEI32: ; Test 32 bit values Top of the stack <= HL,DE PROC @@ -158,7 +162,7 @@ checkParity: ret ENDP pop namespace -#line 74 "arch/zxnext/gtf16.bas" +#line 78 "arch/zxnext/gtf16.bas" #line 1 "/zxbasic/src/lib/arch/zxnext/runtime/swap32.asm" ; Exchanges current DE HL with the ; ones in the stack @@ -176,5 +180,5 @@ __SWAP32: push bc ret pop namespace -#line 75 "arch/zxnext/gtf16.bas" +#line 79 "arch/zxnext/gtf16.bas" END diff --git a/tests/functional/arch/zxnext/gti32.asm b/tests/functional/arch/zxnext/gti32.asm index 3b8686ef0..c5c11c0c6 100644 --- a/tests/functional/arch/zxnext/gti32.asm +++ b/tests/functional/arch/zxnext/gti32.asm @@ -39,6 +39,7 @@ _l: call .core.__LEI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -54,6 +55,7 @@ _l: call .core.__LEI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -69,6 +71,7 @@ _l: call .core.__LEI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -84,6 +87,7 @@ _l: call .core.__LEI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -99,6 +103,7 @@ _l: call .core.__LEI32 sub 1 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -116,7 +121,7 @@ _l: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/lib/arch/zxnext/runtime/lei32.asm" +#line 1 "/zxbasic/src/lib/arch/zxnext/runtime/cmp/lei32.asm" #line 1 "/zxbasic/src/lib/arch/zxnext/runtime/arith/sub32.asm" ; SUB32 ; Perform TOP of the stack - DEHL @@ -143,7 +148,7 @@ __SUB32: exx ret pop namespace -#line 3 "/zxbasic/src/lib/arch/zxnext/runtime/lei32.asm" +#line 3 "/zxbasic/src/lib/arch/zxnext/runtime/cmp/lei32.asm" push namespace core __LEI32: ; Test 32 bit values Top of the stack <= HL,DE PROC @@ -173,7 +178,7 @@ checkParity: ret ENDP pop namespace -#line 89 "arch/zxnext/gti32.bas" +#line 94 "arch/zxnext/gti32.bas" #line 1 "/zxbasic/src/lib/arch/zxnext/runtime/swap32.asm" ; Exchanges current DE HL with the ; ones in the stack @@ -191,5 +196,5 @@ __SWAP32: push bc ret pop namespace -#line 90 "arch/zxnext/gti32.bas" +#line 95 "arch/zxnext/gti32.bas" END diff --git a/tests/functional/arch/zxnext/gtu16.asm b/tests/functional/arch/zxnext/gtu16.asm index df9fe49f5..b723f52c5 100644 --- a/tests/functional/arch/zxnext/gtu16.asm +++ b/tests/functional/arch/zxnext/gtu16.asm @@ -30,6 +30,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -38,6 +39,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -46,6 +48,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -54,6 +57,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -62,6 +66,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl diff --git a/tests/functional/arch/zxnext/gtu32.asm b/tests/functional/arch/zxnext/gtu32.asm index 20cc9e923..cb6a257fc 100644 --- a/tests/functional/arch/zxnext/gtu32.asm +++ b/tests/functional/arch/zxnext/gtu32.asm @@ -43,6 +43,7 @@ _l: pop de sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -62,6 +63,7 @@ _l: pop de sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -81,6 +83,7 @@ _l: pop de sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -100,6 +103,7 @@ _l: pop de sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -117,6 +121,7 @@ _l: pop de sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -151,5 +156,5 @@ __SWAP32: push bc ret pop namespace -#line 107 "arch/zxnext/gtu32.bas" +#line 112 "arch/zxnext/gtu32.bas" END diff --git a/tests/functional/arch/zxnext/leu8.asm b/tests/functional/arch/zxnext/leu8.asm index 45c3dcdfa..f4c9678a8 100644 --- a/tests/functional/arch/zxnext/leu8.asm +++ b/tests/functional/arch/zxnext/leu8.asm @@ -28,12 +28,14 @@ _l: sub h ccf sbc a, a + neg ld (_l), a ld a, (_level) ld hl, (_le - 1) sub h ccf sbc a, a + neg ld (_l), a ld a, (_le) push af @@ -42,6 +44,7 @@ _l: sub h ccf sbc a, a + neg ld (_l), a ld a, (_le) push af @@ -50,11 +53,13 @@ _l: sub h ccf sbc a, a + neg ld (_l), a ld a, (_level) or a ccf sbc a, a + neg ld (_l), a ld hl, 0 ld b, h diff --git a/tests/functional/arch/zxnext/ltu16.asm b/tests/functional/arch/zxnext/ltu16.asm index b13bfbe21..323aece6d 100644 --- a/tests/functional/arch/zxnext/ltu16.asm +++ b/tests/functional/arch/zxnext/ltu16.asm @@ -31,6 +31,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -39,6 +40,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -49,6 +51,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -60,6 +63,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl @@ -69,6 +73,7 @@ _l: or a sbc hl, de sbc a, a + neg ld l, a ld h, 0 ld (_l), hl diff --git a/tests/functional/arch/zxnext/ltu32.asm b/tests/functional/arch/zxnext/ltu32.asm index 485667aa2..0ce158060 100644 --- a/tests/functional/arch/zxnext/ltu32.asm +++ b/tests/functional/arch/zxnext/ltu32.asm @@ -38,6 +38,7 @@ _l: call .core.__SWAP32 call .core.__SUB32 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -52,6 +53,7 @@ _l: ld de, (_level + 2) call .core.__SUB32 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -66,6 +68,7 @@ _l: ld de, (_level + 2) call .core.__SUB32 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -80,6 +83,7 @@ _l: ld de, (_level + 2) call .core.__SUB32 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -94,6 +98,7 @@ _l: push bc call .core.__SUB32 sbc a, a + neg ld l, a ld h, 0 ld e, h @@ -137,7 +142,7 @@ __SUB32: exx ret pop namespace -#line 84 "arch/zxnext/ltu32.bas" +#line 89 "arch/zxnext/ltu32.bas" #line 1 "/zxbasic/src/lib/arch/zxnext/runtime/swap32.asm" ; Exchanges current DE HL with the ; ones in the stack @@ -155,5 +160,5 @@ __SWAP32: push bc ret pop namespace -#line 85 "arch/zxnext/ltu32.bas" +#line 90 "arch/zxnext/ltu32.bas" END diff --git a/tests/functional/arch/zxnext/ltu8.asm b/tests/functional/arch/zxnext/ltu8.asm index e2fa7ddb8..86f2eb562 100644 --- a/tests/functional/arch/zxnext/ltu8.asm +++ b/tests/functional/arch/zxnext/ltu8.asm @@ -28,11 +28,13 @@ _l: ld a, (_le) cp h sbc a, a + neg ld (_l), a ld hl, (_level - 1) ld a, (_le) cp h sbc a, a + neg ld (_l), a ld a, (_le) push af @@ -40,17 +42,20 @@ _l: pop af cp h sbc a, a + neg ld (_l), a ld a, (_le) ld hl, (_level - 1) cp h sbc a, a + neg ld (_l), a ld a, (_level) ld h, a xor a cp h sbc a, a + neg ld (_l), a ld hl, 0 ld b, h diff --git a/tests/functional/arch/zxnext/nef16.asm b/tests/functional/arch/zxnext/nef16.asm index 42ca9bc2a..e7db86298 100644 --- a/tests/functional/arch/zxnext/nef16.asm +++ b/tests/functional/arch/zxnext/nef16.asm @@ -28,6 +28,7 @@ _t: call .core.__EQ32 sub 1 sbc a, a + neg ld (0), a ld hl, 0 ld b, h @@ -65,5 +66,5 @@ __EQ32: ; Test if 32bit value HLDE equals top of the stack xor a ret pop namespace -#line 23 "arch/zxnext/nef16.bas" +#line 24 "arch/zxnext/nef16.bas" END diff --git a/tests/functional/arch/zxnext/nei16.asm b/tests/functional/arch/zxnext/nei16.asm index 5a8db79f6..e4d62f530 100644 --- a/tests/functional/arch/zxnext/nei16.asm +++ b/tests/functional/arch/zxnext/nei16.asm @@ -25,6 +25,9 @@ _t: sbc hl, de ld a, h or l + sub 1 + sbc a, a + inc a ld (0), a ld hl, 0 ld b, h diff --git a/tests/functional/arch/zxnext/nei32.asm b/tests/functional/arch/zxnext/nei32.asm index aa77d53c6..1b5c36f1c 100644 --- a/tests/functional/arch/zxnext/nei32.asm +++ b/tests/functional/arch/zxnext/nei32.asm @@ -28,6 +28,7 @@ _t: call .core.__EQ32 sub 1 sbc a, a + neg ld (0), a ld hl, 0 ld b, h @@ -65,5 +66,5 @@ __EQ32: ; Test if 32bit value HLDE equals top of the stack xor a ret pop namespace -#line 23 "arch/zxnext/nei32.bas" +#line 24 "arch/zxnext/nei32.bas" END diff --git a/tests/functional/arch/zxnext/nei8.asm b/tests/functional/arch/zxnext/nei8.asm index 022116094..1d2ca4656 100644 --- a/tests/functional/arch/zxnext/nei8.asm +++ b/tests/functional/arch/zxnext/nei8.asm @@ -20,6 +20,9 @@ _t: .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: ld a, (_t) + sub 1 + sbc a, a + inc a ld (0), a ld hl, 0 ld b, h diff --git a/tests/functional/arch/zxnext/neu16.asm b/tests/functional/arch/zxnext/neu16.asm index 5a8db79f6..e4d62f530 100644 --- a/tests/functional/arch/zxnext/neu16.asm +++ b/tests/functional/arch/zxnext/neu16.asm @@ -25,6 +25,9 @@ _t: sbc hl, de ld a, h or l + sub 1 + sbc a, a + inc a ld (0), a ld hl, 0 ld b, h diff --git a/tests/functional/arch/zxnext/neu32.asm b/tests/functional/arch/zxnext/neu32.asm index 68eedbb96..4b9de524b 100644 --- a/tests/functional/arch/zxnext/neu32.asm +++ b/tests/functional/arch/zxnext/neu32.asm @@ -28,6 +28,7 @@ _t: call .core.__EQ32 sub 1 sbc a, a + neg ld (0), a ld hl, 0 ld b, h @@ -65,5 +66,5 @@ __EQ32: ; Test if 32bit value HLDE equals top of the stack xor a ret pop namespace -#line 23 "arch/zxnext/neu32.bas" +#line 24 "arch/zxnext/neu32.bas" END diff --git a/tests/functional/arch/zxnext/neu8.asm b/tests/functional/arch/zxnext/neu8.asm index 022116094..1d2ca4656 100644 --- a/tests/functional/arch/zxnext/neu8.asm +++ b/tests/functional/arch/zxnext/neu8.asm @@ -20,6 +20,9 @@ _t: .core.ZXBASIC_USER_DATA_END: .core.__MAIN_PROGRAM__: ld a, (_t) + sub 1 + sbc a, a + inc a ld (0), a ld hl, 0 ld b, h diff --git a/tests/functional/cmdline/test_cmdline.txt b/tests/functional/cmdline/test_cmdline.txt index 15fb86fcd..3933a993d 100644 --- a/tests/functional/cmdline/test_cmdline.txt +++ b/tests/functional/cmdline/test_cmdline.txt @@ -3,9 +3,9 @@ >>> os.environ['COLUMNS'] = '80' >>> process_file('arch/zx48k/arrbase1.bas', ['-q', '-S', '-O --mmap arrbase1.map']) -usage: zxbc.py [-h] [-d] [-O OPTIMIZE] [-o OUTPUT_FILE] [-T] [-t] [-A] [-E] - [--parse-only] [-f {asm,bin,ir,sna,tap,tzx,z80}] [-B] [-a] - [-S ORG] [-e STDERR] [--array-base ARRAY_BASE] +usage: zxbc.py [-h] [-d] [-O OPTIMIZE] [-o OUTPUT_FILE] + [-T | -t | -A | -E | --parse-only | -f {asm,bin,ir,sna,tap,tzx,z80}] + [-B] [-a] [-S ORG] [-e STDERR] [--array-base ARRAY_BASE] [--string-base STRING_BASE] [-Z] [-H HEAP_SIZE] [--heap-address HEAP_ADDRESS] [--debug-memory] [--debug-array] [--strict-bool] [--enable-break] [--explicit] [-D DEFINES] @@ -15,6 +15,7 @@ usage: zxbc.py [-h] [-d] [-O OPTIMIZE] [-o OUTPUT_FILE] [-T] [-t] [-A] [-E] [--arch ARCH] [--expect-warnings EXPECT_WARNINGS] [-W DISABLE_WARNING] [+W ENABLE_WARNING] [--hide-warning-codes] [-F CONFIG_FILE] [--save-config SAVE_CONFIG] + [--opt-strategy {size,speed,auto}] PROGRAM zxbc.py: error: Option --asm and --mmap cannot be used together diff --git a/tests/functional/cmdline/test_read_data.txt b/tests/functional/cmdline/test_read_data.txt index 1950e3b3c..1ff56de74 100644 --- a/tests/functional/cmdline/test_read_data.txt +++ b/tests/functional/cmdline/test_read_data.txt @@ -10,3 +10,5 @@ read3.bas:9: error: 'x' is neither an array nor a function. read6.bas:12: error: Syntax error. Can only read a variable or an array element >>> process_file('arch/zx48k/data0.bas') data0.bas:2: error: 'b' is neither an array nor a function. +>>> process_file('arch/zx48k/readbug.bas') +readbug.bas:2: error: No DATA defined diff --git a/tests/functional/test_.py b/tests/functional/test_.py old mode 100755 new mode 100644 index 9ccb8ebc1..ea879fa57 --- a/tests/functional/test_.py +++ b/tests/functional/test_.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python3 # vim:ts=4:et:ai import os diff --git a/tests/functional/test_asm.py b/tests/functional/test_asm.py old mode 100755 new mode 100644 index a5977f8b1..af6eb8a14 --- a/tests/functional/test_asm.py +++ b/tests/functional/test_asm.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import os import sys diff --git a/tests/functional/test_basic.py b/tests/functional/test_basic.py old mode 100755 new mode 100644 index 516f7caa4..0a8029817 --- a/tests/functional/test_basic.py +++ b/tests/functional/test_basic.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import glob import os import sys diff --git a/tests/functional/test_prepro.py b/tests/functional/test_prepro.py old mode 100755 new mode 100644 index 93e028f67..c5e2f06eb --- a/tests/functional/test_prepro.py +++ b/tests/functional/test_prepro.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import os import sys diff --git a/tests/functional/arch/zx48k/memcpytest.bas b/tests/runtime/cases/memcpytest.bas similarity index 55% rename from tests/functional/arch/zx48k/memcpytest.bas rename to tests/runtime/cases/memcpytest.bas index f33c40455..2948c836e 100644 --- a/tests/functional/arch/zx48k/memcpytest.bas +++ b/tests/runtime/cases/memcpytest.bas @@ -1,12 +1,17 @@ +#include +#include "lib/tst_framework.bas" + +INIT("Testing memcopy to screen") -CLS FOR i = 1 to 10 PRINT "TEST "; NEXT -#include memcopy(16384, 40000, 6912) cls -pause 0 +pause 50 memcopy(40000, 16384, 6912) + +PRINT AT 20,0; +REPORT_OK diff --git a/tests/functional/arch/zx48k/read5.bas b/tests/runtime/cases/read_float_expr.bas similarity index 52% rename from tests/functional/arch/zx48k/read5.bas rename to tests/runtime/cases/read_float_expr.bas index 1bff2914d..8494ebfca 100644 --- a/tests/functional/arch/zx48k/read5.bas +++ b/tests/runtime/cases/read_float_expr.bas @@ -1,4 +1,4 @@ -REM Error x is an array, not an scalar +#include "lib/tst_framework.bas" DIM v as Float = 1.5 @@ -7,8 +7,14 @@ RESTORE DATA 10, 25 * v, SIN(v) * tan(v)^2, PI * v +INIT("Test READ float expressions") + + DIM c, d as Float + FOR i = 1 TO 4: -READ c, d -PRINT c, d + READ c, d + PRINT c, d NEXT i + +REPORT_OK diff --git a/tests/functional/arch/zx48k/read13.bas b/tests/runtime/cases/read_float_expr_into_fixed.bas similarity index 56% rename from tests/functional/arch/zx48k/read13.bas rename to tests/runtime/cases/read_float_expr_into_fixed.bas index 4c0427c59..5757bbb8f 100644 --- a/tests/functional/arch/zx48k/read13.bas +++ b/tests/runtime/cases/read_float_expr_into_fixed.bas @@ -1,16 +1,21 @@ -REM Error x is an array, not an scalar +#include "lib/tst_framework.bas" DIM v as Fixed = 1.5 RESTORE -DATA 10, 25 * v, SIN(v) * tan(v)^2, PI * v +INIT("Test read FP into Fixed") -DIM i as UByte +DATA 10, 25 * v, SIN(v) * tan(v)^2, PI * v + +DIM i as UByte DIM c(3) as Fixed + FOR i = 0 TO 3: -READ c(i) -PRINT c(i) + READ c(i) + PRINT c(i) NEXT i + +REPORT_OK diff --git a/tests/functional/arch/zx48k/read10.bas b/tests/runtime/cases/read_float_func.bas similarity index 66% rename from tests/functional/arch/zx48k/read10.bas rename to tests/runtime/cases/read_float_func.bas index 1462adcc1..2108c3478 100644 --- a/tests/functional/arch/zx48k/read10.bas +++ b/tests/runtime/cases/read_float_func.bas @@ -1,4 +1,4 @@ -REM Error x is an array, not an scalar +#include "lib/tst_framework.bas" DIM v as Float = 1.5 @@ -6,6 +6,7 @@ RESTORE DATA 10, 25 * v, SIN(v) * tan(v)^2, PI * v +INIT("Test reading FP from\#013function body") function p() DIM c as Float @@ -15,3 +16,5 @@ function p() NEXT i end function p() + +REPORT_OK diff --git a/tests/runtime/check_test.py b/tests/runtime/check_test.py index 77bc9ae92..0c4a92402 100755 --- a/tests/runtime/check_test.py +++ b/tests/runtime/check_test.py @@ -3,7 +3,7 @@ import signal import sys -import zx +import zx # type: ignore[import-untyped] def signal_handler(sig, frame): diff --git a/tests/runtime/expected/memcpytest.tzx.scr b/tests/runtime/expected/memcpytest.tzx.scr new file mode 100644 index 000000000..922524a1b Binary files /dev/null and b/tests/runtime/expected/memcpytest.tzx.scr differ diff --git a/tests/runtime/expected/read_float_expr.tzx.scr b/tests/runtime/expected/read_float_expr.tzx.scr new file mode 100644 index 000000000..db2fbcb50 Binary files /dev/null and b/tests/runtime/expected/read_float_expr.tzx.scr differ diff --git a/tests/runtime/expected/read_float_expr_into_fixed.tzx.scr b/tests/runtime/expected/read_float_expr_into_fixed.tzx.scr new file mode 100644 index 000000000..18fa8f23e Binary files /dev/null and b/tests/runtime/expected/read_float_expr_into_fixed.tzx.scr differ diff --git a/tests/runtime/expected/read_float_func.tzx.scr b/tests/runtime/expected/read_float_func.tzx.scr new file mode 100644 index 000000000..5453267cf Binary files /dev/null and b/tests/runtime/expected/read_float_func.tzx.scr differ diff --git a/tests/runtime/update_test.py b/tests/runtime/update_test.py index 2a9957f85..d05f01252 100755 --- a/tests/runtime/update_test.py +++ b/tests/runtime/update_test.py @@ -5,7 +5,7 @@ import sys -import zx +import zx # type: ignore[import-untyped] class Stop(Exception): @@ -46,6 +46,7 @@ def run_test(self, filename): def main(): with TakeSnapshot() as t: t.run_test(sys.argv[1]) + print("OK") diff --git a/tests/symbols/__init__.py b/tests/symbols/__init__.py index 4dad801e0..a8507a547 100644 --- a/tests/symbols/__init__.py +++ b/tests/symbols/__init__.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import os import sys diff --git a/tests/symbols/test_symbolARGLIST.py b/tests/symbols/test_symbolARGLIST.py index f660fb024..fb39c0ecf 100644 --- a/tests/symbols/test_symbolARGLIST.py +++ b/tests/symbols/test_symbolARGLIST.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python3 - -import unittest from unittest import TestCase from src.symbols import sym @@ -46,7 +43,3 @@ def test_make_node_single2(self): def test_make_node_fails(self): self.assertRaises(AssertionError, sym.ARGLIST.make_node, "blah") - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/symbols/test_symbolARRAYACCESS.py b/tests/symbols/test_symbolARRAYACCESS.py index ed37df8a2..aed45bacb 100644 --- a/tests/symbols/test_symbolARRAYACCESS.py +++ b/tests/symbols/test_symbolARRAYACCESS.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - from io import StringIO from unittest import TestCase diff --git a/tests/symbols/test_symbolBASICTYPE.py b/tests/symbols/test_symbolBASICTYPE.py index a2fc7f9ea..827868262 100644 --- a/tests/symbols/test_symbolBASICTYPE.py +++ b/tests/symbols/test_symbolBASICTYPE.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python3 - -import unittest from unittest import TestCase from src.api.constants import TYPE @@ -48,8 +45,9 @@ def test__ne__(self): def test_to_signed(self): for type_ in TYPE.types: - if type_ is TYPE.unknown or type_ == TYPE.string: + if type_ in {TYPE.unknown, TYPE.string, TYPE.boolean}: continue + t = SymbolBASICTYPE(type_) q = t.to_signed() self.assertTrue(q.is_signed) @@ -61,7 +59,3 @@ def test_bool(self): self.assertFalse(t) else: self.assertTrue(t) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/symbols/test_symbolBINARY.py b/tests/symbols/test_symbolBINARY.py index 661a9d8b2..de299c314 100644 --- a/tests/symbols/test_symbolBINARY.py +++ b/tests/symbols/test_symbolBINARY.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - from io import StringIO from unittest import TestCase diff --git a/tests/symbols/test_symbolBLOCK.py b/tests/symbols/test_symbolBLOCK.py index b2a29cdc3..073c492ce 100644 --- a/tests/symbols/test_symbolBLOCK.py +++ b/tests/symbols/test_symbolBLOCK.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - from unittest import TestCase from src.symbols.sym import BLOCK, NUMBER diff --git a/tests/symbols/test_symbolBOUND.py b/tests/symbols/test_symbolBOUND.py index b8f6653af..fe1751952 100644 --- a/tests/symbols/test_symbolBOUND.py +++ b/tests/symbols/test_symbolBOUND.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python3 - -import unittest from io import StringIO from unittest import TestCase @@ -60,7 +57,3 @@ def clearOutput(self): @property def stderr(self): return OPTIONS.stderr.getvalue() - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/symbols/test_symbolBOUNDLIST.py b/tests/symbols/test_symbolBOUNDLIST.py index 3ba7c4b3e..8313e7dc1 100644 --- a/tests/symbols/test_symbolBOUNDLIST.py +++ b/tests/symbols/test_symbolBOUNDLIST.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python3 - -import unittest from unittest import TestCase from src.symbols import sym @@ -35,7 +32,3 @@ def test__len__(self): c = sym.BOUND(l3, l4) a = sym.BOUNDLIST(b, c) self.assertEqual(len(a), 2) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/symbols/test_symbolFUNCDECL.py b/tests/symbols/test_symbolFUNCDECL.py index bfe79ec6c..e826b0360 100644 --- a/tests/symbols/test_symbolFUNCDECL.py +++ b/tests/symbols/test_symbolFUNCDECL.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python3 - -import unittest from unittest import TestCase import src.api.global_ as gl @@ -54,7 +51,3 @@ def test_mangled_(self): def test_make_node(self): f = FUNCDECL.make_node("f", 1, class_=CLASS.function) self.assertIsNotNone(f) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/symbols/test_symbolFUNCTION.py b/tests/symbols/test_symbolFUNCTION.py index 5ea693f09..6573666ff 100644 --- a/tests/symbols/test_symbolFUNCTION.py +++ b/tests/symbols/test_symbolFUNCTION.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python3 - -import unittest from unittest import TestCase from src.api.constants import CLASS @@ -45,7 +42,3 @@ def test_body_setter(self): self.f.ref.body = body self.assertEqual(len(self.f.body), len(body)) self.assertEqual(self.f.body, body) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/symbols/test_symbolNOP.py b/tests/symbols/test_symbolNOP.py index fc6483df8..d8afe0573 100644 --- a/tests/symbols/test_symbolNOP.py +++ b/tests/symbols/test_symbolNOP.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - from unittest import TestCase from src.symbols.sym import NOP diff --git a/tests/symbols/test_symbolNUMBER.py b/tests/symbols/test_symbolNUMBER.py index b23592ce5..f2c01a791 100644 --- a/tests/symbols/test_symbolNUMBER.py +++ b/tests/symbols/test_symbolNUMBER.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python3 - -import unittest from unittest import TestCase from src.api.constants import TYPE @@ -194,7 +191,3 @@ def test__ge__num_num(self): a = NUMBER(4, 0) b = NUMBER(3, 0) self.assertGreaterEqual(a, b) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/symbols/test_symbolSENTENCE.py b/tests/symbols/test_symbolSENTENCE.py index fee7c024e..a14fd8820 100644 --- a/tests/symbols/test_symbolSENTENCE.py +++ b/tests/symbols/test_symbolSENTENCE.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - from unittest import TestCase from src.symbols import sym diff --git a/tests/symbols/test_symbolSTRING.py b/tests/symbols/test_symbolSTRING.py index 2ff3e9634..6ec0d6a4a 100644 --- a/tests/symbols/test_symbolSTRING.py +++ b/tests/symbols/test_symbolSTRING.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python3 - -import unittest from unittest import TestCase from src.symbols import sym @@ -30,7 +27,3 @@ def test__init__(self): self.assertEqual(s.t, _ZXBASIC) self.assertRaises(AssertionError, sym.STRING.t.fset, s, 0) self.assertEqual(s.value, _zxbasic) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/symbols/test_symbolSTRSLICE.py b/tests/symbols/test_symbolSTRSLICE.py index f1203aeae..a383cc657 100644 --- a/tests/symbols/test_symbolSTRSLICE.py +++ b/tests/symbols/test_symbolSTRSLICE.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python3 - -import unittest from unittest import TestCase import src.api.global_ as gl @@ -58,7 +55,3 @@ def test_make_node_wrong(self): bad_index = sym.ID("a", 0, type_=gl.SYMBOL_TABLE.basic_types[gl.TYPE.string]).to_var() s = sym.STRSLICE.make_node(1, self.str_, bad_index, bad_index) self.assertIsNone(s) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/symbols/test_symbolTYPE.py b/tests/symbols/test_symbolTYPE.py index f3e4ca07b..b526a567a 100644 --- a/tests/symbols/test_symbolTYPE.py +++ b/tests/symbols/test_symbolTYPE.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python3 - -import unittest from unittest import TestCase from src.api.constants import TYPE @@ -53,7 +50,3 @@ def test_cmp_types(self): tr = SymbolTYPEREF(Type.unknown, 0) self.assertTrue(tr == Type.unknown) self.assertRaises(AssertionError, tr.__eq__, TYPE.unknown) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/symbols/test_symbolTYPEALIAS.py b/tests/symbols/test_symbolTYPEALIAS.py index 867bee0cd..fc36245d2 100644 --- a/tests/symbols/test_symbolTYPEALIAS.py +++ b/tests/symbols/test_symbolTYPEALIAS.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python3 - -import unittest from unittest import TestCase from src.api.constants import TYPE @@ -24,7 +21,3 @@ def test_is_alias(self): self.assertTrue(ta.is_alias) self.assertTrue(ta.is_basic) self.assertFalse(t.is_alias) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/symbols/test_symbolTYPECAST.py b/tests/symbols/test_symbolTYPECAST.py index 3ac3f21f4..681aaa396 100644 --- a/tests/symbols/test_symbolTYPECAST.py +++ b/tests/symbols/test_symbolTYPECAST.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - from io import StringIO from unittest import TestCase diff --git a/tests/symbols/test_symbolVAR.py b/tests/symbols/test_symbolVAR.py index 6b160c609..d2335f5a2 100644 --- a/tests/symbols/test_symbolVAR.py +++ b/tests/symbols/test_symbolVAR.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python3 - -import unittest from unittest import TestCase from src.api.constants import SCOPE @@ -44,7 +41,3 @@ def test_type_(self): def test_type_fail(self): self.assertRaises(AssertionError, sym.ID.type_.fset, self.v, "blah") - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/symbols/test_symbolVARARRAY.py b/tests/symbols/test_symbolVARARRAY.py index d72db6847..caa273488 100644 --- a/tests/symbols/test_symbolVARARRAY.py +++ b/tests/symbols/test_symbolVARARRAY.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import functools from unittest import TestCase diff --git a/tools/fixed.py b/tools/fixed.py index 76ce2d070..35738452c 100644 --- a/tools/fixed.py +++ b/tools/fixed.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - # A program that displays fixed point numbers in hexa import sys