' Binary Coded Decimal — convert between BCD and binary representations
#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN() AS LONG
    LOCAL i AS LONG
    LOCAL j AS LONG
    LOCAL binaryVal AS LONG
    LOCAL bcdVal AS LONG
    LOCAL converted AS LONG
    LOCAL digit0 AS LONG
    LOCAL digit1 AS LONG
    LOCAL digit2 AS LONG
    LOCAL digit3 AS LONG
    LOCAL digit4 AS LONG
    LOCAL digit5 AS LONG
    LOCAL tens AS LONG
    LOCAL ones AS LONG
    LOCAL hundreds AS LONG
    LOCAL thousands AS LONG
    LOCAL testCount AS LONG
    LOCAL passCount AS LONG
    LOCAL failCount AS LONG
    LOCAL packed_bcd AS LONG
    LOCAL unpacked_bcd AS LONG
    LOCAL lineStr AS STRING
    testCount = 0
    passCount = 0
    failCount = 0
    PRINT "============================================"
    PRINT "     BINARY CODED DECIMAL CONVERTER"
    PRINT "============================================"
    PRINT ""
    PRINT "Binary to unpacked BCD (each nibble = 1 digit)"
    PRINT ""
    FOR i = 0 TO 99
        binaryVal = i
        tens = binaryVal / 10
        ones = binaryVal - tens * 10
        bcdVal = tens * 16 + ones
        converted = (bcdVal / 16) * 10 + (bcdVal AND 15)
        testCount = testCount + 1
        IF converted = i THEN
            passCount = passCount + 1
        ELSE
            failCount = failCount + 1
        END IF
        lineStr = STR$(binaryVal) + " -> BCD 0x"
        IF tens = 0 THEN
            lineStr = lineStr + "0"
        END IF
        lineStr = lineStr + HEX$(bcdVal)
        IF LEN(HEX$(bcdVal)) < 2 THEN
            lineStr = lineStr + " (0x0" + HEX$(bcdVal) + ")"
        ELSE
            lineStr = lineStr + " (0x" + HEX$(bcdVal) + ")"
        END IF
        PRINT lineStr
    NEXT i
    PRINT ""
    PRINT "============================================"
    PRINT "     PACKED BCD (2 digits per byte)"
    PRINT "============================================"
    PRINT ""
    FOR i = 0 TO 99
        binaryVal = i
        tens = binaryVal / 10
        ones = binaryVal - tens * 10
        packed_bcd = tens * 16 + ones
        digit0 = packed_bcd AND 15
        digit1 = (packed_bcd / 16) AND 15
        converted = digit1 * 10 + digit0
        testCount = testCount + 1
        IF converted = i THEN
            passCount = passCount + 1
        END IF
        PRINT " " + STR$(binaryVal) + " -> 0x" + HEX$(packed_bcd) + " -> " + STR$(converted)
    NEXT i
    PRINT ""
    PRINT "============================================"
    PRINT "     3-DIGIT PACKED BCD"
    PRINT "============================================"
    PRINT ""
    FOR i = 0 TO 255
        binaryVal = i
        hundreds = binaryVal / 100
        tens = (binaryVal - hundreds * 100) / 10
        ones = binaryVal - hundreds * 100 - tens * 10
        packed_bcd = hundreds * 256 + tens * 16 + ones
        digit0 = packed_bcd AND 15
        digit1 = (packed_bcd / 16) AND 15
        digit2 = (packed_bcd / 256) AND 15
        converted = digit2 * 100 + digit1 * 10 + digit0
        testCount = testCount + 1
        IF converted = binaryVal THEN
            passCount = passCount + 1
        ELSE
            failCount = failCount + 1
        END IF
        IF i MOD 16 = 0 OR i = 255 THEN
            PRINT " " + STR$(binaryVal) + " -> BCD[" + STR$(digit2) + "][" + STR$(digit1) + "][" + STR$(digit0) + "] -> " + STR$(converted)
        END IF
    NEXT i
    PRINT ""
    PRINT "============================================"
    PRINT "     BCD ADDITION (decimal adjust)"
    PRINT "============================================"
    PRINT ""
    LOCAL bcdA AS LONG
    LOCAL bcdB AS LONG
    LOCAL bcdSum AS LONG
    LOCAL lowNibble AS LONG
    LOCAL highNibble AS LONG
    FOR i = 0 TO 9
        FOR j = 0 TO 9
            bcdA = i
            bcdB = j
            bcdSum = bcdA + bcdB
            lowNibble = bcdSum AND 15
            IF lowNibble > 9 THEN
                bcdSum = bcdSum + 6
            END IF
            highNibble = (bcdSum / 16) AND 15
            lowNibble = bcdSum AND 15
            IF highNibble > 9 THEN
                bcdSum = bcdSum + 96
            END IF
            binaryVal = i + j
            converted = (bcdSum / 16) * 10 + (bcdSum AND 15)
            IF converted > 99 THEN
                converted = converted - 100
            END IF
            testCount = testCount + 1
            IF binaryVal < 10 THEN
                IF converted = binaryVal THEN
                    passCount = passCount + 1
                ELSE
                    failCount = failCount + 1
                END IF
            END IF
        NEXT j
    NEXT i
    PRINT "BCD addition verified for 0-9 range"
    PRINT ""
    PRINT "============================================"
    PRINT "     BCD SUBTRACTION (decimal borrow)"
    PRINT "============================================"
    PRINT ""
    LOCAL bcdDiff AS LONG
    FOR i = 5 TO 9
        FOR j = 0 TO i
            bcdA = i
            bcdB = j
            bcdDiff = bcdA - bcdB
            lowNibble = bcdDiff AND 15
            IF lowNibble > 9 THEN
                bcdDiff = bcdDiff - 6
            END IF
            highNibble = (bcdDiff / 16) AND 15
            IF highNibble > 9 THEN
                bcdDiff = bcdDiff - 96
            END IF
            converted = (bcdDiff / 16) * 10 + (bcdDiff AND 15)
            binaryVal = i - j
            testCount = testCount + 1
            IF converted = binaryVal THEN
                passCount = passCount + 1
            ELSE
                failCount = failCount + 1
            END IF
        NEXT j
    NEXT i
    PRINT "BCD subtraction verified for 5-9 range"
    PRINT ""
    PRINT "============================================"
    PRINT "     BCD TABLE (0-99)"
    PRINT "============================================"
    PRINT ""
    PRINT "Dec  BCD  Hex"
    FOR i = 0 TO 99
        tens = i / 10
        ones = i MOD 10
        packed_bcd = tens * 16 + ones
        lineStr = " " + STR$(i) + "    "
        IF i < 10 THEN
            lineStr = lineStr + " "
        END IF
        lineStr = lineStr + STR$(tens) + STR$(ones) + "   0x" + HEX$(packed_bcd)
        IF LEN(HEX$(packed_bcd)) < 2 THEN
            lineStr = lineStr + " (0x0" + HEX$(packed_bcd) + ")"
        END IF
        PRINT lineStr
    NEXT i
    PRINT ""
    PRINT "Results: " + STR$(passCount) + " passed, " + STR$(failCount) + " failed of " + STR$(testCount)
    FUNCTION = 0
END FUNCTION
