Skip to content

EDIABAS VM Opcode Handlers - Complete Pseudocode Reference

Reverse-engineered opcode handlers from ebas32.dll decompilation.

VM State Variables

CPU Flags

AddressNameDescription
DAT_100d1740Zero Flag (ZF)Set when result is zero
_DAT_100d1742Carry Flag (CF)Set on unsigned overflow/borrow
DAT_100d1744Sign Flag (SF)Set when result is negative
DAT_100d1746Overflow Flag (OF)Set on signed overflow

Operand Pointers

AddressNameDescription
DAT_100d1760operand0_ptrDestination operand pointer
DAT_100d1764operand0_len_ptrPointer to operand0 length
DAT_100d1770operand0_typeOperand type (1=byte, 2=word, 4=long)
DAT_100d1774operand1_ptrSource operand pointer
DAT_100d178cindexed_offsetOffset for indexed operations
DAT_100d1790operation_sizeSize of operation in bytes

Stack & Execution

AddressNameDescription
DAT_100d1794stack_pointerReturn/data stack pointer (max 0x800)
DAT_100d17a0stack[]Combined stack (2048 bytes)
DAT_100d1748nesting_levelSubroutine nesting depth
DAT_100d226cresult_bufferResult output buffer

Arithmetic Operations

COMP - Compare (FUN_10023fc9)

Compare two operands by subtraction without storing result.

c
void COMP() {
    src_sign = get_sign(operand1, size);
    dst_sign = get_sign(operand0, size);
    
    CF = 0;
    for (i = 0; i < size; i++) {
        diff = operand0[i] - operand1[i] - CF;
        CF = (diff < 0) ? 1 : 0;
        result[i] = diff & 0xFF;
    }
    
    ZF = is_zero(result, size);
    SF = get_sign(result, size);
    
    // Overflow detection
    if (dst_sign > 0 && src_sign == 0 && SF == 0) OF = 1;
    if (dst_sign == 0 && src_sign > 0 && SF > 0) OF = 1;
}

Flags: ZF, CF, SF, OF


SUB - Subtract (FUN_100240f6)

c
void SUB() {
    src_sign = get_sign(operand1, size);
    dst_sign = get_sign(operand0, size);
    
    CF = 0;
    for (i = 0; i < size; i++) {
        diff = operand0[i] - operand1[i] - CF;
        CF = (diff < 0) ? 1 : 0;
        operand0[i] = diff & 0xFF;  // Store result
    }
    
    update_flags(operand0, size);
    // Overflow: pos - neg = neg, or neg - pos = pos
}

SUBC - Subtract with Carry (FUN_10024229)

c
void SUBC() {
    // Same as SUB but CF is NOT cleared first
    // Uses borrow from previous operation
    for (i = 0; i < size; i++) {
        diff = operand0[i] - operand1[i] - CF;
        CF = (diff < 0) ? 1 : 0;
        operand0[i] = diff & 0xFF;
    }
}

ADD - Add (FUN_10024353)

c
void ADD() {
    src_sign = get_sign(operand1, size);
    dst_sign = get_sign(operand0, size);
    
    for (i = 0; i < size; i++) {
        sum = operand0[i] + operand1[i] + CF;
        CF = (sum > 0xFF) ? 1 : 0;
        operand0[i] = sum & 0xFF;
    }
    
    result_sign = get_sign(operand0, size);
    update_flags(operand0, size);
    
    // Overflow: pos + pos = neg, or neg + neg = pos
    if (dst_sign == 0 && src_sign == 0 && result_sign > 0) OF = 1;
    if (dst_sign > 0 && src_sign > 0 && result_sign == 0) OF = 1;
}

ADDC - Add with Carry (FUN_10024481)

c
void ADDC() {
    CF = 0;  // Clear carry first (different from ADD!)
    for (i = 0; i < size; i++) {
        sum = operand0[i] + operand1[i] + CF;
        CF = (sum > 0xFF) ? 1 : 0;
        operand0[i] = sum & 0xFF;
    }
}

Control Flow

JMP - Unconditional Jump (FUN_10024a17)

c
void JMP() {
    set_pc(*operand0);  // Relative jump
}

JTSR - Jump to Subroutine (FUN_10024a30)

c
void JTSR() {
    return_addr = get_current_pc();
    
    if (stack_pointer + 4 > 0x800) {
        error(STACK_OVERFLOW);
    }
    
    memcpy(&stack[stack_pointer], &return_addr, 4);
    stack_pointer += 4;
    
    set_pc(*operand0);
    nesting_level++;
}

RET - Return (FUN_10024aac)

c
void RET() {
    stack_pointer -= 4;
    
    if (stack_pointer < 0) {
        error(STACK_UNDERFLOW);
    }
    
    memcpy(&return_addr, &stack[stack_pointer], 4);
    base = get_current_pc();
    set_pc(return_addr - base);
    
    nesting_level--;
}

Conditional Jumps

JC - Jump if Carry (FUN_10024b1e)

c
void JC() { if (CF != 0) set_pc(*operand0); }

JNC - Jump if No Carry (FUN_10024b43)

c
void JNC() { if (CF == 0) set_pc(*operand0); }

JZ - Jump if Zero (FUN_10024b68)

c
void JZ() { if (ZF != 0) set_pc(*operand0); }

JNZ - Jump if Not Zero (FUN_10024b8d)

c
void JNZ() { if (ZF == 0) set_pc(*operand0); }

JO - Jump if Overflow (FUN_10024bb2)

c
void JO() { if (OF != 0) set_pc(*operand0); }

JNO - Jump if No Overflow (FUN_10024bd7)

c
void JNO() { if (OF == 0) set_pc(*operand0); }

JS - Jump if Sign (FUN_10024bfc)

c
void JS() { if (SF != 0) set_pc(*operand0); }

JNS - Jump if No Sign (FUN_10024c21)

c
void JNS() { if (SF == 0) set_pc(*operand0); }

Stack Operations

PUSH - Push to Stack (FUN_10024ff5)

c
void PUSH() {
    if (stack_pointer + size > 0x800) {
        error(STACK_OVERFLOW);
    }
    
    memcpy(&stack[stack_pointer], operand0, size);
    stack_pointer += size;
    update_flags(operand0, size);
}

POP - Pop from Stack (FUN_10025068)

c
void POP() {
    stack_pointer -= size;
    
    if (stack_pointer < 0) {
        error(STACK_UNDERFLOW);
    }
    
    memcpy(operand0, &stack[stack_pointer], size);
    update_flags(operand0, size);
}

PEEK - Read from Stack (FUN_10025da7)

c
void PEEK() {
    offset = stack_pointer - indexed_offset;
    
    if (offset < 0) {
        error(STACK_UNDERFLOW);
    }
    
    memcpy(operand0, &stack[offset], size);
}

POKE - Write to Stack (FUN_10025df7)

c
void POKE() {
    offset = stack_pointer - indexed_offset;
    
    if (offset < 0) {
        error(STACK_UNDERFLOW);
    }
    
    memcpy(&stack[offset], operand0, size);
}

PUSHF - Push Flags (FUN_1002658c)

c
void PUSHF() {
    // Push all 14 bytes of flag state
    if (stack_pointer + 14 > 0x800) {
        error(STACK_OVERFLOW);
    }
    memcpy(&stack[stack_pointer], &flags_block, 14);
    stack_pointer += 14;
}

POPF - Pop Flags (FUN_100265df)

c
void POPF() {
    stack_pointer -= 14;
    if (stack_pointer < 0) {
        error(STACK_UNDERFLOW);
    }
    memcpy(&flags_block, &stack[stack_pointer], 14);
}

String Operations

SCMP - String Compare (FUN_100250d2)

c
void SCMP() {
    ZF = 0;
    CF = (*operand0_len < size) ? 1 : 0;
    
    if (*operand0_len == size) {
        for (i = 0; i < size; i++) {
            if (operand0[i] < operand1[i]) CF = 1;
            if (operand0[i] != operand1[i]) {
                ZF = 0;
                return;
            }
        }
        ZF = 1;  // Strings equal
    }
}

SCAT - String Concatenate (FUN_1002517c)

c
void SCAT() {
    overflow = (max_len < *operand0_len + size);
    if (overflow) {
        size = max_len - *operand0_len;
    }
    CF = overflow ? 1 : 0;
    
    memcpy(&operand0[*operand0_len], operand1, size);
    *operand0_len += size;
    update_flags(operand0, size);
}

SCPY - String Copy (FUN_1002520d)

c
void SCPY() {
    overflow = (max_len < *operand0_len + size);
    if (overflow) {
        operand1[max_len - *operand0_len - 1] = '\0';
    }
    CF = overflow ? 1 : 0;
    
    strcat(operand0, operand1);
    *operand0_len = strlen(operand0) + 1;
    update_flags(operand0, size);
}

SCUT - String Cut (FUN_10025299)

c
void SCUT() {
    *operand0_len -= cut_count;
    if (*operand0_len < 0) *operand0_len = 0;
    
    ZF = (*operand0_len == 0) ? 1 : 0;
    if (*operand0_len > 0) {
        operand0[*operand0_len - 1] = '\0';
    }
}

Conversion Operations

ATOI - ASCII to Integer (FUN_10025c50)

c
void ATOI() {
    ptr = operand1;
    
    if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X')) {
        // Hexadecimal: 0x...
        value = strtol(ptr + 2, NULL, 16);
    }
    else if (ptr[0] == '0' && (ptr[1] == 'y' || ptr[1] == 'Y')) {
        // Binary: 0y...
        value = strtol(ptr + 2, NULL, 2);
    }
    else if (ptr[0] == '-') {
        // Negative decimal
        value = strtol(ptr, NULL, 10);
    }
    else {
        // Unsigned decimal
        value = strtoul(ptr, NULL, 10);
    }
    
    // Store based on operand type
    switch (operand0_type) {
        case 1:  // Byte
            *operand0 = (uint8_t)value;
            if (value > 0xFF) CF = 1;
            break;
        case 2:  // Word
            *(uint16_t*)operand0 = (uint16_t)value;
            if (value > 0xFFFF) CF = 1;
            break;
        case 4:  // Long
            *(uint32_t*)operand0 = value;
            break;
    }
}

ITOA - Integer to ASCII (FUN_10025b14)

c
void ITOA() {
    value = read_integer(operand1, operand1_type);
    
    if (format == HEX) {
        sprintf(operand0, "0x%X", value);
    } else if (format == BINARY) {
        sprintf(operand0, "0y%b", value);
    } else {
        sprintf(operand0, "%d", value);
    }
    
    *operand0_len = strlen(operand0) + 1;
}

Floating Point Operations

FADD - Float Add (FUN_1002762f)

c
void FADD() {
    clear_fp_exceptions();
    *(double*)operand0 = *(double*)operand0 + *(double*)operand1;
    
    if (check_fp_exceptions() & 0x1E) {  // Any FP error
        error(FP_ERROR);
    }
}

FSUB - Float Subtract (FUN_10027670)

c
void FSUB() {
    clear_fp_exceptions();
    *(double*)operand0 = *(double*)operand0 - *(double*)operand1;
    
    if (check_fp_exceptions() & 0x1E) {
        error(FP_ERROR);
    }
}

FMUL - Float Multiply (FUN_100276b1)

c
void FMUL() {
    clear_fp_exceptions();
    *(double*)operand0 = *(double*)operand0 * *(double*)operand1;
    
    if (check_fp_exceptions() & 0x1E) {
        error(FP_ERROR);
    }
}

FDIV - Float Divide (FUN_100276f2)

c
void FDIV() {
    divisor = *(double*)operand1;
    clear_fp_exceptions();
    *(double*)operand0 = *(double*)operand0 / divisor;
    
    if (check_fp_exceptions() & 0x1E) {
        error(FP_ERROR);
    }
}

Result Output (ERG*)

ERGB - Output Unsigned Byte (FUN_10025503)

c
void ERGB() {
    if (nesting_level == 0) {  // Only at top level
        strncpy(result_buffer.name, operand0, 256);
        result_buffer.type = UNSIGNED_BYTE;  // 1
        result_buffer.value = read_byte(operand1);
        result_buffer.count = result_count++;
        result_buffer.valid = 1;
    }
}

ERGS - Output Signed Byte (FUN_1002558a)

c
void ERGS() {
    if (nesting_level == 0) {
        strncpy(result_buffer.name, operand0, 256);
        result_buffer.type = SIGNED_BYTE;  // 0
        result_buffer.value = read_byte(operand1);
        result_buffer.count = result_count++;
        result_buffer.valid = 1;
    }
}

ERGW - Output Unsigned Word (FUN_10025611)

c
void ERGW() {
    if (nesting_level == 0) {
        strncpy(result_buffer.name, operand0, 256);
        result_buffer.type = UNSIGNED_WORD;  // 3
        result_buffer.value = read_word(operand1);
        result_buffer.count = result_count++;
        result_buffer.valid = 1;
    }
}

ERGI - Output Signed Word (FUN_10025699)

c
void ERGI() {
    if (nesting_level == 0) {
        strncpy(result_buffer.name, operand0, 256);
        result_buffer.type = SIGNED_WORD;  // 2
        result_buffer.value = read_word(operand1);
        result_buffer.count = result_count++;
        result_buffer.valid = 1;
    }
}

Logical Operations

AND - Bitwise AND (FUN_1002489d)

c
void AND() {
    for (i = 0; i < size; i++) {
        result[i] = operand0[i] & operand1[i];
    }
    update_flags(result, size);
    // Result NOT stored
}

ANDS - AND and Store (FUN_1002483d)

c
void ANDS() {
    for (i = 0; i < size; i++) {
        operand0[i] = operand0[i] & operand1[i];
    }
    update_flags(operand0, size);
}

OR - Bitwise OR (FUN_100248fe)

c
void OR() {
    for (i = 0; i < size; i++) {
        operand0[i] = operand0[i] | operand1[i];
    }
    update_flags(operand0, size);
}

XOR - Bitwise XOR (FUN_1002495e)

c
void XOR() {
    for (i = 0; i < size; i++) {
        operand0[i] = operand0[i] ^ operand1[i];
    }
    update_flags(operand0, size);
}

NOT - Bitwise NOT (FUN_100249be)

c
void NOT() {
    for (i = 0; i < size; i++) {
        operand0[i] = ~operand0[i];
    }
    update_flags(operand0, size);
}

Shift Operations

ASR - Arithmetic Shift Right (FUN_10024da2)

c
void ASR() {
    sign_bit = operand0[size-1] & 0x80;
    CF = operand0[0] & 1;
    
    for (i = 0; i < size - 1; i++) {
        operand0[i] = (operand0[i] >> 1) | ((operand0[i+1] & 1) << 7);
    }
    operand0[size-1] = (operand0[size-1] >> 1) | sign_bit;
    
    update_flags(operand0, size);
}

LSR - Logical Shift Right (FUN_10024e78)

c
void LSR() {
    CF = operand0[0] & 1;
    
    for (i = 0; i < size - 1; i++) {
        operand0[i] = (operand0[i] >> 1) | ((operand0[i+1] & 1) << 7);
    }
    operand0[size-1] = operand0[size-1] >> 1;  // Zero fill
    
    update_flags(operand0, size);
}

ASL/LSL - Shift Left (FUN_10024f38)

c
void ASL() {
    CF = (operand0[size-1] & 0x80) ? 1 : 0;
    
    for (i = size - 1; i > 0; i--) {
        operand0[i] = (operand0[i] << 1) | ((operand0[i-1] & 0x80) >> 7);
    }
    operand0[0] = operand0[0] << 1;  // Zero fill LSB
    
    update_flags(operand0, size);
}

Data Movement

MOVE - Copy Data (FUN_10023f01)

c
void MOVE() {
    memcpy(operand0, operand1, size);
    update_flags(operand0, size);
}

CLEAR - Zero Memory (FUN_10023f76)

c
void CLEAR() {
    memset(operand0, 0, size);
    *operand0_len = 0;
    ZF = 1;
}

Table Operations

TABSEEK - Search in Table (FUN_10025a56)

Search for value in table column, jump if not found.

c
void TABSEEK() {
    // Copy table data to work buffer
    strcpy(work_buffer, table_data);
    
    // Tokenize by separator (e.g., ";")
    token = strtok(work_buffer, TABLE_SEP);
    found = (token == NULL);
    
    while (token != NULL && !found) {
        // Compare token with search value
        if (strncmp(token, operand1, size) == 0) {
            found = true;
        }
        token = strtok(NULL, TABLE_SEP);
    }
    
    if (!found) {
        set_pc(immediate);  // Jump to target
    }
}

TABSET - Set Table Parameters (FUN_1002662a)

Set search separator and column index for table operations.

c
void TABSET() {
    operand0[size] = '\0';  // Null terminate
    strncpy(table_separator, operand0, 16);
    table_column = indexed_offset;
}

TABGET - Get Table Value (FUN_100266e4)

Get value from table at current column position.

c
void TABGET() {
    column_index = 0;
    
    // Copy source to work buffer
    strcpy(work_buffer, operand1);
    
    // Tokenize by configured separator
    token = strtok(work_buffer, table_separator);
    
    while (token != NULL) {
        column_index++;
        
        if (column_index == table_column) {
            // Found target column - copy to dest
            strcpy(operand0, token);
            *operand0_len = strlen(operand0) + 1;
            table_column++;  // Advance for next call
            break;
        }
        
        token = strtok(NULL, table_separator);
    }
    
    if (token == NULL) {
        ZF = 1;  // End of table
    }
    
    work_buffer[0] = '\0';  // Clear buffer
}

REVERSE - Reverse Byte Order (FUN_10026663)

Reverse bytes in operand (endian swap).

c
void REVERSE() {
    left = 0;
    right = size - 1;
    
    while (left < right) {
        temp = operand0[left];
        operand0[left] = operand0[right];
        operand0[right] = temp;
        left++;
        right--;
    }
    
    *operand0_len = offset + size;
}

SWAP - Swap Nibbles/Bytes (FUN_100267a6)

Swap nibbles (byte) or bytes (word/long).

c
void SWAP() {
    switch (operand_type) {
        case 1:  // Byte - swap nibbles
            immediate = ((immediate & 0x0F) << 4) | ((immediate >> 4) & 0x0F);
            *operand0 = immediate;
            break;
            
        case 2:  // Word
        case 4:  // Long - reverse bytes
            for (i = 0; i < size / 2; i++) {
                temp = operand0[i];
                operand0[i] = operand0[size - 1 - i];
                operand0[size - 1 - i] = temp;
            }
            break;
            
        case 8:  // Double - reverse all bytes
            left = 0;
            right = size - 1;
            while (left < right) {
                temp = operand0[left];
                operand0[left] = operand0[right];
                operand0[right] = temp;
                left++;
                right--;
            }
            break;
    }
}

TABLINE - Get Table Line (FUN_10027141)

Find and position to specific line in table.

c
void TABLINE() {
    table_size = get_table_size();
    set_position(table_size);
    read_table_info(&table_info, 4);
    
    line_index = 0;
    while (line_index < table_info.line_count) {
        read_table_info(&line_data, 0x50);
        
        if (compare(operand0, line_data) == 0) {
            return;  // Found
        }
        line_index++;
    }
    
    error(TABLE_ERROR, 0xFFFF);
}

TABCOL - Iterate Table Columns (FUN_100271cb)

Iterate through table columns for matching value.

c
void TABCOL(int mode) {
    if (mode == 1) {
        // Initialize iteration
        column_pos = 0;
        found_column = -1;
        cached_rows = table_rows;
        cached_cols = table_cols;
        ZF = 0;
        
        set_position(table_start);
        
        for (i = 0; i < table_rows; i++) {
            read_cell(cell_buffer);
            if (compare(operand0, cell_buffer) == 0) {
                found_column = i;
            }
        }
        
        if (found_column == -1) {
            error(TABLE_ERROR, 0xFFFF);
        }
    }
    
    // Continue iteration
    while (column_pos < cached_rows * cached_cols) {
        if (column_pos % cached_rows == 0) {
            save_position();
        }
        
        read_cell(cell_buffer);
        
        if (column_pos % cached_rows == found_column) {
            if (compare(operand1, cell_buffer) == 0) {
                return;  // Match found
            }
        }
        
        column_pos++;
        
        // Yield periodically
        if (column_pos % YIELD_INTERVAL == 0) {
            return YIELD;
        }
    }
    
    ZF = 1;  // End of iteration
}

TABROW - Iterate Table Rows (FUN_1002733a)

Iterate through table rows starting at specific row.

c
void TABROW(int mode) {
    if (mode == 1) {
        // Get start row from operand
        switch (operand_type) {
            case 1: start_row = read_byte(operand0); break;
            case 2: start_row = read_word(operand0); break;
            case 4: start_row = read_long(operand0); break;
        }
        
        row_offset = start_row * table_cols;
        row_pos = 0;
        total_cells = table_rows * table_cols;
        ZF = 0;
        
        set_position(table_start);
        
        // Skip to start row
        for (i = 0; i < table_cols; i++) {
            read_cell(cell_buffer);
        }
    }
    
    // Continue iteration
    while (row_pos < total_cells) {
        if (row_pos % table_cols == 0) {
            save_position();
            if (row_pos == row_offset) {
                return;  // At target row
            }
        }
        
        read_cell(cell_buffer);
        row_pos++;
        
        // Yield periodically
        if (row_pos % YIELD_INTERVAL == 0) {
            return YIELD;
        }
    }
    
    ZF = 1;  // End of table
}

TABFIND - Find in Table (FUN_100274be)

Find value in table column and return corresponding value.

c
void TABFIND() {
    found_index = -1;
    
    set_position(table_start);
    
    // Search in first column
    for (i = 0; i < table_cols; i++) {
        read_cell(work_buffer);
        if (compare(operand1, work_buffer) == 0) {
            found_index = i;
        }
    }
    
    if (found_index == -1) {
        error(TABLE_ERROR, 0xFFFF);
    }
    
    // Position to found row
    set_position(saved_position);
    for (i = 0; i <= found_index; i++) {
        read_cell(operand0);
    }
    
    *operand0_len = strlen(operand0) + 1;
}

Additional Result Output (ERG*)

ERGL - Output Unsigned Long (FUN_10025721)

Output 32-bit unsigned integer result.

c
void ERGL() {
    if (nesting_level == 0) {
        strncpy(result_buffer.name, operand0, 256);
        result_buffer.type = UNSIGNED_LONG;  // 5
        result_buffer.value = read_long(operand1);
        result_buffer.count = result_count++;
        result_buffer.valid = 1;
    }
}

ERGI - Output Signed Long (FUN_100257a8)

Output 32-bit signed integer result.

c
void ERGI_LONG() {
    if (nesting_level == 0) {
        strncpy(result_buffer.name, operand0, 256);
        result_buffer.type = SIGNED_LONG;  // 4
        result_buffer.value = read_long(operand1);
        result_buffer.count = result_count++;
        result_buffer.valid = 1;
    }
}

ERGR - Output Real/Double (FUN_1002582f)

Output 64-bit floating point result.

c
void ERGR() {
    if (nesting_level == 0) {
        strncpy(result_buffer.name, operand0, 256);
        result_buffer.type = REAL;  // 8
        
        // Copy 8 bytes (double)
        result_buffer.value_lo = operand1[0];
        result_buffer.value_hi = operand1[1];
        
        result_buffer.count = result_count++;
        result_buffer.valid = 1;
    }
}

ERGS_STR - Output String (FUN_100258b8)

Output string result with optional character set conversion.

c
void ERGS_STR() {
    if (nesting_level == 0) {
        strncpy(result_buffer.name, operand0, 256);
        result_buffer.type = STRING;  // 6
        
        strncpy(result_buffer.string_value, operand1, size);
        result_buffer.string_value[size] = '\0';
        
        // Apply character set conversion if enabled
        if (charset_conversion_enabled) {
            ptr = result_buffer.string_value;
            while (*ptr != '\0') {
                *ptr = charset_table[*ptr];
                ptr++;
            }
        }
        
        result_buffer.count = result_count++;
        result_buffer.valid = 1;
    }
}

ERGY - Output Binary (FUN_1002599f)

Output raw binary data result.

c
void ERGY() {
    if (nesting_level == 0) {
        strncpy(result_buffer.name, operand0, 256);
        result_buffer.type = BINARY;  // 7
        
        // Copy binary data
        memcpy(result_buffer.binary_data, operand1, size);
        result_buffer.binary_len = size;
        
        result_buffer.count = result_count++;
        result_buffer.valid = 1;
    }
}

Additional String Operations

SINS - String Insert (FUN_10025370)

Insert string at position.

c
void SINS() {
    insert_pos = *operand0_len - offset;
    
    if (insert_pos < 1) {
        return;  // Invalid position
    }
    
    // Check if insert would exceed max
    overflow = (max_len < *operand0_len + size);
    if (overflow) {
        size = max_len - *operand0_len;
    }
    CF = overflow ? 1 : 0;
    
    // Check tail length
    tail_len = *operand0_len - offset - size;
    if (max_len < *operand0_len + size + tail_len) {
        tail_len = max_len - (*operand0_len + size);
        CF = 1;
    }
    
    // Move tail to make room
    memmove(&operand0[size], operand0, tail_len);
    
    // Insert new content
    memmove(operand0, operand1, size);
    
    *operand0_len += size;
    update_flags(operand0, size);
}

SDEL - String Delete (FUN_10025477)

Delete characters from string.

c
void SDEL() {
    available = *operand0_len - offset;
    
    if (available < 1) {
        return;  // Nothing to delete
    }
    
    // Calculate remaining after delete
    remaining = available - indexed_offset;
    if (remaining < 1) {
        remaining = 0;
    }
    
    *operand0_len = offset + remaining;
    
    // Move remaining content
    memmove(operand0, &operand0[indexed_offset], remaining);
    
    // Zero out deleted area
    memset(&operand0[remaining], 0, indexed_offset);
}

STRCMP - String Compare (FUN_10027cbc)

Compare two null-terminated strings.

c
void STRCMP() {
    ZF = 0;
    CF = 0;
    i = 0;
    
    while (operand1[i] != '\0' && 
           operand1[i] == operand0[i] && 
           i < max_len - 1) {
        i++;
    }
    
    if (i >= max_len - 1) {
        error(STRING_OVERFLOW);
    }
    
    if (operand0[i] != operand1[i]) {
        ZF = 1;  // Strings differ
        if (operand0[i] < operand1[i]) {
            CF = 1;  // operand0 < operand1
        }
    }
}

STRLEN - Get String Length (FUN_10027d8d)

Get length of null-terminated string.

c
void STRLEN() {
    len = 0;
    
    while (operand1[len] != '\0' && len < max_len - 1) {
        len++;
    }
    
    if (len >= max_len - 1) {
        error(STRING_OVERFLOW);
    }
    
    // Store based on operand type
    switch (operand_type) {
        case 2:  // Word
            store_word(operand0, len);
            update_flags(operand0, 2);
            break;
        case 4:  // Long
            store_long(operand0, len);
            update_flags(operand0, 4);
            break;
    }
}

Conversion Operations (Extended)

HTOB - Hex String to Bytes (FUN_10027b53)

Convert hex string to binary bytes.

c
void HTOB() {
    src = operand1;
    dest_pos = 0;
    CF = 0;
    
    // Check output buffer size
    if (max_len - 2 < size / 2) {
        error(STRING_OVERFLOW);
    }
    
    while (*src != '\0') {
        // Validate high nibble
        if (!is_hex_char(*src)) {
            CF = 1;  // Invalid character
            break;
        }
        
        high = *src;
        src++;
        
        if (*src == '\0') break;
        
        // Validate low nibble
        if (!is_hex_char(*src)) {
            CF = 1;
            break;
        }
        
        low = *src;
        src++;
        
        // Convert hex pair to byte
        operand0[dest_pos] = hex_to_byte(high, low);
        dest_pos++;
    }
    
    *operand0_len = dest_pos;
}

bool is_hex_char(char c) {
    return (c >= '0' && c <= '9') ||
           (c >= 'A' && c <= 'F') ||
           (c >= 'a' && c <= 'f');
}

BTOH - Bytes to Hex String (FUN_10027e4c)

Convert binary bytes to hex string (digits only, 0-9).

c
void BTOH() {
    src = operand1;
    dest_pos = 0;
    
    // Check sizes
    if (size == 0 || (size * 2 > max_len - 2)) {
        error(STRING_OVERFLOW);
    }
    
    for (i = 0; i < size; i++) {
        high_nibble = (src[i] >> 4) & 0x0F;
        low_nibble = src[i] & 0x0F;
        
        // Convert to ASCII (0-9 only, * for A-F)
        operand0[dest_pos] = (high_nibble < 10) ? 
                             ('0' + high_nibble) : '*';
        operand0[dest_pos + 1] = (low_nibble < 10) ? 
                                 ('0' + low_nibble) : '*';
        
        dest_pos += 2;
    }
    
    operand0[dest_pos] = '\0';
    *operand0_len = dest_pos + 1;
}

BTOHEX - Bytes to Hex String Full (FUN_10027f71)

Convert binary bytes to full hex string (0-9, A-F).

c
void BTOHEX() {
    src = operand1;
    dest_pos = 0;
    
    if (size == 0 || (size * 2 > max_len - 2)) {
        error(STRING_OVERFLOW);
    }
    
    for (i = 0; i < size; i++) {
        high_nibble = (src[i] >> 4) & 0x0F;
        low_nibble = src[i] & 0x0F;
        
        // Convert to ASCII (0-9, A-F)
        operand0[dest_pos] = (high_nibble < 10) ? 
                             ('0' + high_nibble) : 
                             ('A' + high_nibble - 10);
        operand0[dest_pos + 1] = (low_nibble < 10) ? 
                                 ('0' + low_nibble) : 
                                 ('A' + low_nibble - 10);
        
        dest_pos += 2;
    }
    
    operand0[dest_pos] = '\0';
    *operand0_len = dest_pos + 1;
}

ITOF - Integer to Float (FUN_10027598)

Convert integer to double.

c
void ITOF() {
    *(double*)operand0 = (double)indexed_offset;
}

File I/O Operations

FOPEN - Open File (FUN_10025e89)

c
void FOPEN() {
    handle = indexed_offset;  // 0-5
    
    if (handle > 5) {
        error(FILE_ERROR);
    }
    
    file_handles[handle] = fopen(operand0, mode);
    
    if (file_handles[handle] == NULL) {
        CF = 1;  // Failed
    }
}

FCLOSE - Close File (FUN_10025f57)

c
void FCLOSE() {
    handle = indexed_offset;
    
    if (handle > 5) {
        error(FILE_ERROR);
    }
    
    if (file_handles[handle] != NULL) {
        fclose(file_handles[handle]);
        file_handles[handle] = NULL;
    }
}

FREAD - Read from File (FUN_10025fbd)

c
void FREAD() {
    handle = indexed_offset;
    
    if (handle > 5 || file_handles[handle] == NULL) {
        error(FILE_ERROR);
    }
    
    bytes_read = fread(operand0, 1, size, file_handles[handle]);
    *operand0_len = bytes_read;
    
    if (bytes_read < size) {
        CF = 1;  // EOF or error
    }
}

FRDLN - Read Line (FUN_1002606b)

c
void FRDLN() {
    handle = indexed_offset;
    CF = 0;
    
    if (handle > 5) {
        error(FILE_ERROR);
    }
    
    if (file_handles[handle] == NULL) {
        error(FILE_ERROR);
    }
    
    *operand0_len = 0;
    pos = 0;
    
    while (!CF) {
        bytes = fread(&operand0[pos], 1, 1, file_handles[handle]);
        
        if (bytes <= 0) {
            CF = 1;  // EOF
        }
        
        if (operand0[pos] == '\n') {
            return;  // End of line
        }
        
        if (pos > 0x3FF) {
            CF = 1;  // Line too long
        }
        
        (*operand0_len)++;
        pos++;
    }
}

FSEEK - Seek in File (FUN_1002618e)

c
void FSEEK() {
    handle = immediate;
    
    if (handle > 5) {
        error(FILE_ERROR);
    }
    
    if (file_handles[handle] == NULL) {
        error(FILE_ERROR);
    }
    
    result = fseek(file_handles[handle], indexed_offset, SEEK_SET);
    
    if (result == -1) {
        error(FILE_ERROR);
    }
}

FSLINE - Seek to Line (FUN_1002621e)

c
void FSLINE() {
    handle = immediate;
    target_line = indexed_offset;
    CF = 0;
    
    if (handle > 5 || file_handles[handle] == NULL) {
        error(FILE_ERROR);
    }
    
    // Rewind to start
    fseek(file_handles[handle], 0, SEEK_SET);
    
    current_line = 0;
    while (current_line < target_line && !CF) {
        ch = fgetc(file_handles[handle]);
        if (ch == EOF) {
            CF = 1;
        }
        if (ch == '\n') {
            current_line++;
        }
    }
}

FSIZE - Get File Size (FUN_10026394)

c
void FSIZE() {
    handle = indexed_offset;
    
    if (handle > 5 || file_handles[handle] == NULL) {
        error(FILE_ERROR);
    }
    
    // Save current position
    current = ftell(file_handles[handle]);
    
    // Seek to end
    fseek(file_handles[handle], 0, SEEK_END);
    size = ftell(file_handles[handle]);
    
    // Restore position
    fseek(file_handles[handle], current, SEEK_SET);
    
    store_integer(operand0, size, operand_type);
}

FLINES - Count Lines (FUN_10026415)

c
void FLINES() {
    handle = indexed_offset;
    
    if (handle > 5 || file_handles[handle] == NULL) {
        error(FILE_ERROR);
    }
    
    // Save position
    current = ftell(file_handles[handle]);
    fseek(file_handles[handle], 0, SEEK_SET);
    
    line_count = 0;
    while ((ch = fgetc(file_handles[handle])) != EOF) {
        if (ch == '\n') {
            line_count++;
        }
    }
    
    // Restore position
    fseek(file_handles[handle], current, SEEK_SET);
    
    store_integer(operand0, line_count, operand_type);
}

IFH (Interface Handler) Operations

Communication with ECU hardware through the IFH layer.

ifhBreak (FUN_10021111)

Break/interrupt current communication.

c
void ifhBreak() {
    log("ifhBreak...");
    
    channel = get_active_channel();
    ifh_error = IFH_Break(channel);
    
    if (ifh_error != 0) {
        error(IFH_ERROR, ifh_error);
    }
    
    busy_flag = 0;
}

ifhEnd (FUN_1002116a)

End IFH session.

c
void ifhEnd() {
    clear_state(0, 1);
    log("ifhEnd...");
    
    ifh_error = IFH_End();
    
    if (ifh_error != 0) {
        error(IFH_ERROR, ifh_error);
    }
    
    busy_flag = 0;
}

ifhConnect (FUN_100211c6)

Connect to ECU.

c
void ifhConnect() {
    clear_state(0, 1);
    log("ifhConnect...");
    
    ifh_error = IFH_Connect(ecu_address);
    
    if (ifh_error != 0) {
        error(IFH_ERROR, ifh_error);
    }
    
    interface_ptr = get_interface(1);
    busy_flag = 0;
}

ifhDisconnect (FUN_1002123a)

Disconnect from ECU.

c
void ifhDisconnect() {
    clear_state(0, 1);
    log("ifhDisconnect...");
    
    ifh_error = IFH_Disconnect();
    
    if (ifh_error != 0) {
        error(IFH_ERROR, ifh_error);
    }
    
    busy_flag = 0;
}

ifhSysInfo (FUN_10021296)

Get system information from interface.

c
void ifhSysInfo() {
    if (debug_enabled) {
        log("ifhSysInfo...");
        log_hex(operand1, size);
    }
    
    channel = get_active_channel();
    ifh_error = IFH_SysInfo(channel, size, operand1);
    
    if (ifh_error != 0) {
        error(IFH_ERROR, ifh_error);
    }
    
    busy_flag = 1;
}

ifhSetParameter (FUN_1002132c)

Set communication parameter.

c
void ifhSetParameter() {
    if (debug_enabled) {
        log("ifhSetParameter...");
        log_hex(operand0, size);
    }
    
    channel = get_active_channel();
    ifh_error = IFH_SetParameter(channel, size, operand0);
    
    if (ifh_error != 0) {
        error(IFH_ERROR, ifh_error);
    }
    
    busy_flag = 0;
}

ifhSetTelPreface (FUN_10021452)

Set telegram preface bytes.

c
void ifhSetTelPreface() {
    if (debug_enabled) {
        log("ifhSetTelPreface...");
        log_hex(operand0, size);
    }
    
    channel = get_active_channel();
    ifh_error = IFH_SetTelPreface(channel, size, operand0);
    
    if (ifh_error != 0) {
        error(IFH_ERROR, ifh_error);
    }
    
    busy_flag = 0;
}

ifhSendTelegram (FUN_100214e8)

Send telegram to ECU.

c
void ifhSendTelegram() {
    if (debug_enabled) {
        log("ifhSendTelegram...");
        log_hex(operand1, size);
    }
    
    channel = get_active_channel();
    ifh_error = IFH_SendTelegram(channel, size, operand1);
    
    if (ifh_error != 0) {
        error(IFH_ERROR, ifh_error);
    }
    
    busy_flag = 1;
}

ifhSend (FUN_10021614)

Send raw data.

c
void ifhSend() {
    if (debug_enabled) {
        log("ifhSend...");
        log_hex(operand0, size);
    }
    
    channel = get_active_channel();
    ifh_error = IFH_Send(channel, size, operand0);
    
    if (ifh_error != 0) {
        error(IFH_ERROR, ifh_error);
    }
    
    busy_flag = 0;
}

ifhReceive (FUN_100216aa)

Receive data from ECU.

c
void ifhReceive() {
    if (debug_enabled) {
        log("ifhReceive...");
        log_int(indexed_offset);
    }
    
    channel = get_active_channel();
    ifh_error = IFH_Receive(channel, &indexed_offset, operand0, &received_len);
    
    if (ifh_error != 0) {
        error(IFH_ERROR, ifh_error);
    }
    
    *operand0_len = received_len;
    busy_flag = 0;
}

Wait/Timing Operations

WAIT - Wait with Idle (FUN_100268dc)

c
void WAIT() {
    // Call idle handler during wait
    while (wait_time > 0) {
        idle_handler();
        wait_time--;
    }
}

WAITS - Wait Seconds (FUN_1002691a)

c
void WAITS() {
    seconds = read_integer(operand0, operand_type);
    Sleep(seconds * 1000);
}

WAITMS - Wait Milliseconds (FUN_100269e8)

c
void WAITMS() {
    milliseconds = read_integer(operand0, operand_type);
    Sleep(milliseconds);
}

GETTICK - Get Tick Count (FUN_10026a8e)

c
void GETTICK() {
    ticks = GetTickCount();
    store_integer(operand0, ticks, operand_type);
}

Argument Operations

GETARG - Get Argument (FUN_10026d39)

c
void GETARG() {
    arg_index = indexed_offset;
    
    // Parse semicolon-separated arguments
    arg = get_argument(arg_index);
    
    if (arg != NULL) {
        strcpy(operand0, arg);
        *operand0_len = strlen(arg) + 1;
    } else {
        *operand0_len = 0;
        CF = 1;
    }
}

ARGCOUNT - Count Arguments (FUN_10026e6d)

c
void ARGCOUNT() {
    count = 0;
    ptr = argument_string;
    
    while (*ptr != '\0') {
        if (*ptr == ';') {
            count++;
        }
        ptr++;
    }
    count++;  // Last argument
    
    store_integer(operand0, count, operand_type);
}

Miscellaneous

NOP - No Operation (FUN_10024fec)

c
void NOP() {
    // Do nothing
}

BREAK - Break/Trap (FUN_10025e46)

c
void BREAK() {
    error(BREAK_TRAP);
}

CLRO - Clear Overflow (FUN_10025e5f)

c
void CLRO() {
    OF = 0;
}

CHKREG - Check Register (FUN_10025e71)

c
void CHKREG() {
    if (reg_flag != 0) {
        error(REG_ERROR, reg_value);
    }
}

Helper Functions

update_flags (FUN_10028d4d)

c
void update_flags(byte* data, int size) {
    ZF = 1;
    for (i = 0; i < size; i++) {
        if (data[i] != 0) {
            ZF = 0;
            break;
        }
    }
    SF = (data[size-1] & 0x80) ? 1 : 0;
}

set_pc (FUN_10023ca5)

c
void set_pc(int offset) {
    program_counter += offset;
}

get_current_pc (FUN_10023b1c)

c
int get_current_pc() {
    return program_counter;
}

Summary

CategoryCountOpcodes
Arithmetic5COMP, SUB, SUBC, ADD, ADDC
Control Flow3JMP, JTSR, RET
Conditionals8JC, JNC, JZ, JNZ, JO, JNO, JS, JNS
Stack6PUSH, POP, PEEK, POKE, PUSHF, POPF
String8SCMP, SCAT, SCPY, SCUT, SINS, SDEL, STRCMP, STRLEN
Conversion6ATOI, ITOA, HTOB, BTOH, BTOHEX, ITOF
Float4FADD, FSUB, FMUL, FDIV
Result9ERGB, ERGS, ERGW, ERGI, ERGL, ERGI_LONG, ERGR, ERGS_STR, ERGY
Logical5AND, ANDS, OR, XOR, NOT
Shift3ASR, LSR, ASL
Data2MOVE, CLEAR
Table8TABSEEK, TABSET, TABGET, REVERSE, SWAP, TABLINE, TABCOL, TABROW, TABFIND
File I/O8FOPEN, FCLOSE, FREAD, FRDLN, FSEEK, FSLINE, FSIZE, FLINES
IFH10ifhBreak, ifhEnd, ifhConnect, ifhDisconnect, ifhSysInfo, ifhSetParameter, ifhSetTelPreface, ifhSendTelegram, ifhSend, ifhReceive
Wait/Timing4WAIT, WAITS, WAITMS, GETTICK
Arguments2GETARG, ARGCOUNT
Misc3NOP, BREAK, CLRO

Total: 94 opcodes with pseudocode


Generated from ebas32.dll decompilation (Ghidra).