



ASSEMBLY WITH COMPILED STRUCRURED EXTENDED BASIC
================================================

When using SXB you can embed assembler subroutines in your SXB program just like SUB..ENDSUB:

ASM AROUT(P1,P2,P3)
       B @RTN comment     
ASMEND

The line “ASM AROUT(P1,P2,P3)” will be translated by TiCodEd to the assembly line

AROUT    BL @GET3       Get parameter: AROUT(A,B,C)

Up to four parameters are automatically loaded into R6 and below, see section "Parameter Passing".

By utilizing the `ASM...ASMEND` block, you can write inline assembly and completely avoid the cumbersome process of writing, compiling, and converting standalone assembly files. A TMS9900 Assembly reference card will follow these general instruction.

# Using Embedded Assembly in SXB

SXB allows you to embed assembler subroutines directly into your BASIC source code, functioning similarly to a standard `SUB..ENDSUB` structure

# Basic Syntax
To declare an inline assembly block, use the `ASM` directive followed by your routine name and parameters, and close it with `ASMEND`. 

ASM MYROUT(P1,P2,P3)
* Your TMS9900 assembly code goes here   
ASMEND

When TiCodEd processes the `ASM` line, it automatically generates the required assembly instruction to retrieve your parameters (e.g., `MYROUT BL @GET3`), the ASMEND  becomes a "B @RTN" to return to the compiler.


### Parameter Passing
TiCodEd SXB automatically handles up to four parameters, loading them into the lower workspace registers[cite: 1]. The registers are populated sequentially ending at R6:
* One parameter: Loaded into R6.
* Two parameters: Loaded into R5 and R6.
* Three parameters: Loaded into R4, R5, and R6.
* Four parameters: Loaded into R3, R4, R5, and R6.

If your routine requires more than four parameters, you can load additional ones using the `BL @GETx` function.

---

### Handling Data Types

The way you interact with the registers depends on whether the BASIC variables passed are numeric or strings.

#### 1. Numeric Parameters
For numeric parameters, the populated registers will point directly to the number. 
* Reading: If `R6` points to your number, you can simply use `MOV *R6` to transfer it to another register for calculations.
* Writing: To pass a numeric result back to BASIC, move the computed value directly back into the memory location pointed to by the register (e.g., MOV R3,*R6).

#### 2. String Parameters
String parameters require an extra step because the registers point to a *pointer* to the string, not the string itself.
* Reading: If the pointer is in `R6`, execute `MOV *R6,R6` so that `R6` updates to point directly to the length byte at the beginning of the string. This will be inserted automatically for the initial 4 parameters.
* Processing: You can move the string to `GPBUFF` to process it.`GPBUFF` is a general-purpose buffer that is >0118 bytes long.
* Writing: To assign a string back to BASIC, use `BLWP @STRSTR` (Store String), which is the compiler's equivalent of `STRASG`. 
    * Set `R0` to point to the length byte of your new string (typically located in `GPBUFF`).
    * Set `R1` to point to the original string address provided by the `GETx` routine.
    * This may be automated for one string by using ASMEND B$(GPBUFF) to return B$.

#### 3. Checking Variable Types Dynamically
If you need to determine whether a parameter is a string or a numeric value at runtime:
* Use `BL @ASTRNG`.
* This routine checks the value in `R6`—you **must** use `R6` for this test.
* It returns an `EQ` status if `R6` points to a string, and an `NE` status if `R6` points to a number.

---

### Exiting the Subroutine
When your assembly routine is finished running, you must return control to the compiler properly:
* Always use `B @RTN` to return to the compiler from your subroutine.
* Ensure that your workspace pointer is set to `>8300` before returning[cite: 38]. [cite_start]The workspace `>8300` is the main workspace used by the compiler
* ASMEND will generate `B @RTN` for you.





TMS9900 MICROPROCESSOR ASSEMBLY REFERENCE CARD
===============================================

FORMAT
------
Labels start in column 1, start with a letter and may have up to five following letters or numbers. Labels don't have 
a line on their own, they are always followed by an Op-Code. There is no colon after an assembly label. 
Assembly Op-Codes start on the 8th column, followed by a space and the parameters. There are no spaces between parameters. 
Everything after the next space is a comment. Comment-lines have an asterisk in column 1. 

REGISTER OVERVIEW
-----------------
Registers: R0 - R15 (16-bit Workspace Registers)
PC: Program Counter
ST: Status Register (L>, A>, EQ, C, OV, OP, X, INT mask)
WP: Workspace Pointer

ADDRESSING MODES
----------------
Workspace Register:         Rn      (e.g., R5)
Workspace Reg Indirect:     *Rn     (e.g., *R5)
Indirect Auto-increment:    *Rn+    (e.g., *R5+)
Symbolic (Direct):          @LABEL
Indexed:                    @LABEL(Rn)

INSTRUCTION SET REFERENCE
-------------------------

I. DATA TRANSFER
MOV  src, dst  - Move Word: Copies 16-bit word from source to destination.
MOVB src, dst  - Move Byte: Copies 8-bit byte. Affects Status bits based on byte value.
LI   Rn, val   - Load Immediate: Loads 16-bit immediate value into Workspace Register Rn.
LWPI val       - Load WP Immediate: Loads immediate value into Workspace Pointer.
STWP Rn        - Store WP: Stores current Workspace Pointer into Register Rn.
STST Rn        - Store Status: Stores current Status Register into Register Rn.
SWPB Rn        - Swap Bytes: Swaps high and low bytes of the specified register.

II. ARITHMETIC
A    src, dst  - Add Word: Adds source to destination (dst = dst + src).
AB   src, dst  - Add Byte: Adds source byte to destination byte.
S    src, dst  - Subtract Word: Subtracts source from destination (dst = dst - src).
SB   src, dst  - Subtract Byte: Subtracts source byte from destination byte.
INC  Rn        - Increment: Adds 1 to Rn.
INCT Rn        - Increment Two: Adds 2 to Rn (useful for stepping through word arrays).
DEC  Rn        - Decrement: Subtracts 1 from Rn.
DECT Rn        - Decrement Two: Subtracts 2 from Rn.
MPY  src, Rn   - Multiply: Multiplies src (unsigned) by Rn. Result (32-bit) in Rn (MSW) and Rn+1 (LSW).
DIV  src, Rn   - Divide: Divides Rn:Rn+1 (32-bit) by src. Quotient in Rn, Remainder in Rn+1.
NEG  Rn        - Negate: Replaces Rn with its two's complement (Rn = -Rn).
ABS  Rn        - Absolute Value: Replaces Rn with its absolute value.

III. LOGICAL
ANDI Rn, val   - AND Immediate: Logical AND of Rn and 16-bit immediate value.
ORI  Rn, val   - OR Immediate: Logical OR of Rn and 16-bit immediate value.
XOR  src, Rn   - Exclusive OR: Logical XOR of src with Rn. Result in Rn.
INV  Rn        - Invert: One's complement (bitwise NOT) of Rn.
CLR  dst       - Clear: Sets destination word to 0.
SETO dst       - Set to One: Sets destination word to all ones (>FFFF).

IV. COMPARISON
C    src, dst  - Compare Word: Compares src and dst (algebraically). Sets ST bits.
CB   src, dst  - Compare Byte: Compares src byte and dst byte (algebraically).
CI   Rn, val   - Compare Immediate: Compares Rn with immediate value.
COC  src, Rn   - Check if Ones Correspond: Tests if all 1-bits in src are also 1 in Rn.
CZC  src, Rn   - Check if Zeros Correspond: Tests if all 1-bits in src are 0 in Rn.

V. SHIFT
SLA  Rn, count - Shift Left Arithmetic: Shift Rn left. LSB filled with 0.
SRA  Rn, count - Shift Right Arithmetic: Shift Rn right. MSB sign-extended.
SRC  Rn, count - Shift Right Circular: Shift Rn right. Bits shifted out of LSB enter MSB.
SRL  Rn, count - Shift Right Logical: Shift Rn right. MSB filled with 0.

VI. CONTROL FLOW / JUMPS
B    dst       - Branch: Unconditional branch to destination.
BL   dst       - Branch and Link: Branch to dst, store return address in R11.
BLWP dst       - Branch and Load WP: Context switch. dst points to a 2-word vector (WP, PC).
RTWP           - Return with WP: Restores WP, PC, and ST from the workspace (R13, R14, R15).
X    src       - Execute: Executes the instruction found at the source address.

VII. CONDITIONAL JUMPS (PC Relative +/- 127 words)
JMP  label     - Jump Unconditional
JEQ  label     - Jump if Equal (ST bit 2 = 1)
JNE  label     - Jump if Not Equal (ST bit 2 = 0)
JGT  label     - Jump if Greater Than (ST bit 0 = 1)
JLT  label     - Jump if Less Than (ST bit 1 = 1)
JHE  label     - Jump if Higher or Equal
JLE  label     - Jump if Low or Equal
JOC  label     - Jump on Carry
JNC  label     - Jump on No Carry
JOP  label     - Jump on Odd Parity

VIII. CRU (Communications Register Unit)
LDCR src, cnt  - Load CRU: Output bits from src to CRU.
STCR src, cnt  - Store CRU: Input bits from CRU to src.
SBO  bit       - Set Bit On: Set CRU bit to 1.
SBZ  bit       - Set Bit Zero: Set CRU bit to 0.
TB   bit       - Test Bit: Test CRU bit (result in Equal bit of ST).

IX. MISCELLANEOUS
IDLE           - Idle: CPU pauses until interrupt occurs.
CKON/CKOF      - Clock Control: User defined external clock control signals.
LREX           - Load or Restart Execution: External control signal.

ASSEMBLER DIRECTIVES
--------------------
AORG  - Absolute Origin
BSS   - Block Starting with Symbol (reserve bytes)
DATA  - Define Word Data
BYTE  - Define Byte Data
TEXT  - Define String Data
EQU   - Equate symbol to value
END   - End of source code

TI-99/4a SPECIFICS
==================

1. CPU RAM LAYOUT

>0000 Console Rom;Interrupt vectors, XOP vectors GPL Interpreter, Floating POINT routines, XMLINK vectors,
>1FFF Low-level cassette DSR etc.
>2000 Low Memory Expansion Ram; Varies according to the loader used (Assembly). Generally
>3FFF not used by XBASIC programs.
>4000 DSR ROM; Device service routines. Determined by CRU bit setting 
>5FFF Disk Controller, RS232 etc.
>6000 Cartridge Memory, bankswitched by writing to >6000, >6002, >6004 etc for the first, second and third bank.
>8000 RAM Memory Mapped Devices - VDP,GROM, SOUND, SPEECH.
>8000 Duplication of scratch pad RAM at >8300 - >83FF
>8100 Dup. as above
>8200 again
>8300 Scratch Pad RAM
>8400 Sound Chip
>8800 VDP READ DATA
>8802 VDP STATUS
>8C00 VDP WRITE DATA
>8C02 VDP READ/WRITE ADDRESS
>9000 SPEECH READ
>9400 SPEECH WRITE
>9800 GRON/GRAM READ DATA
>9802 GROM/GRAM READ ADDRESS
>9C00 GROM/GRAM WRITE DATA
>9C02 GROM/GRAM WRITE ADDRESS
>A000 HIGH MEMORY EXP RAM XBASIC high memory usage, Free space end pointed to by CPU RAM PAD address >8366

2. XB256 16K VDP RAM Memory Map

The XB256 library utilizes the 16K of VDP RAM on the TI-99/4A to provide its enhanced graphics and sound features. The layout of this memory is structured differently than standard Extended BASIC to accommodate Screen2 and sound tables. Regular XB uses memory up to >081F and the Value Stack + Disk Buffers.

VDP Address Hex Address	Description
>0000 – >02FF	Screen Image Table: Address for a specific row and column is calculated as (Row-1)*32 + Column-1.
>0300 – >036F	Sprite Attribute Table: Room for 28 sprites. Each sprite uses 4 bytes: vertical position-1, horizontal position, character code+96, and color-1 (with +128 added for the early clock).
>03F0 – >077F	Pattern Descriptor Table (Screen1): 8 bytes per character. Character 30 starts at address 1008.
>0780 – >07EF	Sprite Motion Table: 4 bytes per sprite: vertical velocity, horizontal velocity, and 2 bytes for system use (usually 0).
>0800 – >081F	Color Table (Screen1): 1 byte per character set. The value is (foreground-1)*16 + background-1.
>0980 – >0BFF	Sound Tables / Free Space: 640 bytes reserved for sound tables and other temporary data.
>0C00 – >0FFF	Inactive Screen Buffer: Used to store the contents of the screen that is not currently being displayed when switching between Screen1 and Screen2.
>1000 – >17FF	Pattern Descriptor Table (Screen2): 8 bytes per character for all 256 characters. Specifically, character 160 starts at 4096, character 0 at 4864, and character 32 at 5120.
>1800 – >181F	Color Table (Screen2): 1 byte per character set for the 256 characters of Screen2.
>1820 – >37D7	Value Stack: Used by Extended BASIC for strings and internal operations. The size is reduced if you reserve VDP RAM for sound lists via CALL LINK("XB256", n).
>37D8 – >3FFF	Disk Buffering Area: Reserved for file operations (standard for CALL FILES(3)).

Key Details and Constraints
    • Sprite Patterns: Note that sprite patterns always use the character definitions from Screen1, even when Screen2 is active.
    • Stack Space: The standard stack space is reduced from 11,840 bytes in normal XB to 8,056 bytes in XB256 (with 3 disk files) to make room for these extra graphics tables.
    • Memory Reservation: Using CALL LINK("XB256", n) allows you to reserve up to 6,000 bytes starting at address 6176 for sound tables, which further decreases the available stack space for strings.



3. CONSOLE ROM UTILITIES (BLWP ACCESS)

Use these via BLWP @<Name> for standard, safe access.
    • VSBW (Write Byte): Writes MSB of R1 to VRAM address in R0. 
    • VSBR (Read Byte): Reads VRAM address in R0 into MSB of R1. 
    • VMBW (Write Block): Writes R2 bytes from CPU RAM (R1) to VRAM (R0). 
    • VMBR (Read Block): Reads R2 bytes from VRAM (R0) into CPU RAM (R1). 
    • VWTR (Write Register): Writes LSB of R0 to VDP Register in MSB of R0. 
    • KSCAN (Scan Keys): Checks keyboard/joysticks based on address >8374. 

4. DIRECT HARDWARE ACCESS (BL ACCESS)

For high-speed code, write to the ports directly. Disable interrupts (LIMI 0) during this process.

Set VRAM Address for Writing
    1. Take 14-bit VRAM address.
    2. Set bit 14 high (OR with >4000) to signify "Write."
    3. Send Low Byte to >8C02.
    4. Send High Byte to >8C02.
    5. Send/Receive Data at >8C00.
Set VDP Register
    1. Set bits 14 and 15 high (OR with >8000).
    2. Send Data Byte to >8C02.
    3. Send Register Number to >8C02.

5.

* VDP Memory Map
*
VDPRD  EQU  >8800             * VDP read data
VDPSTA EQU  >8802             * VDP status
VDPWD  EQU  >8C00             * VDP write data
VDPWA  EQU  >8C02             * VDP set read
VSBW   EQU  >2020		Write 1 char to VRAM				
VMBW   EQU  >2024		Write multi char to VRAM				
VWTR   EQU  >2030		Write 1 byte to VDP Reg.				
