MODULE CONSOLE
VAR _INPUT_QUEUE_INDEX: BYTE
VAR _ROW: BYTE
VAR _COL: BYTE
VAR _POS: PAIR
VAR _COLOR_ADDEND: PAIR
VAR _BLINK_SAVE: PAIR
VAR _BLINK: BOOL
VAR CURSOR_VISIBLE: BOOL
VAR BUFFER: BYTE[]
VAR SCROLL_OFF: BOOL
VAR REVERSE: BOOL
VAR MATTE: BOOL
VAR CTRL_KEY: BOOL
FUNC INIT()
NEW BYTE[](10) -> CONSOLE::BUFFER
CONSOLE::BUFFER.RESIZE(10)
IO::INPUT_QUEUE_END_INDEX -> CONSOLE::_INPUT_QUEUE_INDEX
1024 -> CONSOLE::_COLOR_ADDEND
CONSOLE::_PRINT_CHAR(5)
IF ART::FONTS.SIZE > 0
DO ENGINE::TILE_LAYER_A.LOAD_TILESET(ART::FONTS[0])
VAR IO_TILEMAP: IO_TILEMAP
IO::TILEMAP_A -> IO_TILEMAP
64 -> IO_TILEMAP.COL_COUNT
32 -> IO_TILEMAP.ROW_COUNT
TO_ADDRESS(KERNEL::CONSOLE_GRID) -> IO_TILEMAP.TILE_CODES_ADDRESS
END FUNC
FUNC _BLINK_OFF()
IF CONSOLE::_BLINK THEN
FALSE -> CONSOLE::_BLINK
CONSOLE::_BLINK_SAVE -> KERNEL::CONSOLE_GRID[CONSOLE::_POS]
END IF
END FUNC
FUNC _BLINK_RESTORE()
IF CONSOLE::CURSOR_VISIBLE THEN
TRUE -> CONSOLE::_BLINK
VAR C: PAIR
KERNEL::CONSOLE_GRID[CONSOLE::_POS] -> C
C -> CONSOLE::_BLINK_SAVE
TO_PAIR(MATH::BIT_AND(C, $3FF)) -> C
TO_PAIR(C + CONSOLE::_COLOR_ADDEND) -> C
TO_PAIR(MATH::BIT_XOR(C, $4000)) -> C
C -> KERNEL::CONSOLE_GRID[CONSOLE::_POS]
END IF
END FUNC
FUNC SET_COLOR(COLOR: INT)
CONSOLE::_BLINK_OFF()
IF COLOR < 0 OR COLOR > 15
DO KERNEL::FAIL("SET_COLOR() INVALID COLOR")
TO_PAIR(COLOR * 1024) -> CONSOLE::_COLOR_ADDEND
CONSOLE::_BLINK_RESTORE()
END FUNC
FUNC PRINT(TEXT: STRING)
CONSOLE::_BLINK_OFF()
VAR SIZE: INT
TEXT.SIZE -> SIZE
VAR I: INT
0 -> I
LOOP
IF I >= SIZE
DO DROP
VAR C: PAIR
TEXT[I] -> C
CONSOLE::_PRINT_CHAR(C)
I + 1 -> I
END LOOP
CONSOLE::_BLINK_RESTORE()
END FUNC
FUNC PRINT_INT(N: INT)
CONSOLE::_BLINK_OFF()
VAR C: INT
N -> C
IF C < 0 THEN
CONSOLE::_PRINT_CHAR(45)
-C -> C
END IF
VAR I: INT, D: INT
0 -> I
LOOP
C % 10 -> D
TO_BYTE(48+D) -> CONSOLE::BUFFER[I]
IF C < 10
DO DROP
I + 1 -> I
C / 10 -> C
END LOOP
LOOP
CONSOLE::_PRINT_CHAR(CONSOLE::BUFFER[I])
I - 1 -> I
IF I < 0
DO DROP
END LOOP
CONSOLE::_BLINK_RESTORE()
END FUNC
FUNC PRINT_CHAR(C: PAIR)
CONSOLE::_BLINK_OFF()
CONSOLE::_PRINT_CHAR(C)
CONSOLE::_BLINK_RESTORE()
END FUNC
FUNC _PRINT_CHAR(C: PAIR)
VAR COL: BYTE
VAR ROW: BYTE
VAR POS: PAIR
CONSOLE::_COL -> COL
CONSOLE::_ROW -> ROW
CONSOLE::_POS -> POS
IF C < 0
DO TO_PAIR(C + 256) -> C
IF C < 32 THEN
IF C = 1 THEN
FALSE -> CONSOLE::SCROLL_OFF
FALSE -> CONSOLE::REVERSE
FALSE -> CONSOLE::MATTE
ELSIF C = 2 THEN
TRUE -> CONSOLE::SCROLL_OFF
ELSIF C = 3 THEN
CONSOLE::_SCROLL_UP()
ELSIF C = 4 THEN
KERNEL::MEMCPY(
| TO_ADDRESS(KERNEL::CONSOLE_GRID) + 128,
| TO_ADDRESS(KERNEL::CONSOLE_GRID),
| 3456)
KERNEL::MEMSET_PAIR(
| TO_ADDRESS(KERNEL::CONSOLE_GRID),
| 32,
| 40)
ELSIF C = 5 THEN
KERNEL::MEMSET_PAIR(
| TO_ADDRESS(KERNEL::CONSOLE_GRID),
| 32,
| 1792)
0 -> POS
0 -> COL
0 -> ROW
ELSIF C = 6 THEN
TO_PAIR(POS - COL) -> POS
0 -> COL
KERNEL::MEMSET_PAIR(
| TO_ADDRESS(KERNEL::CONSOLE_GRID) + POS * 2,
| 32,
| 40)
ELSIF C = 9 THEN
VAR TAB_AMOUNT: INT
8 - TO_BYTE(MATH::BIT_AND(COL, 7)) -> TAB_AMOUNT
TO_BYTE(COL + TAB_AMOUNT) -> COL
TO_PAIR(POS + TAB_AMOUNT) -> POS
IF COL >= 40 THEN
TO_PAIR(POS - COL + 64) -> POS
0 -> COL
TO_BYTE(ROW + 1) -> ROW
END IF
ELSIF C = 10 THEN
TO_PAIR(POS - COL + 64) -> POS
0 -> COL
TO_BYTE(ROW + 1) -> ROW
ELSIF C = 11 THEN
0 -> POS
0 -> COL
0 -> ROW
ELSIF C = 12 THEN
1728 -> POS
0 -> COL
27 -> ROW
ELSIF C = 13 THEN
TO_PAIR(POS - COL) -> POS
0 -> COL
ELSIF C = 14 THEN
TRUE -> CONSOLE::REVERSE
ELSIF C = 15 THEN
TRUE -> CONSOLE::MATTE
ELSIF C >= 16 AND C <=25 THEN
TO_PAIR((C - 16) * 1024) -> CONSOLE::_COLOR_ADDEND
ELSIF C = 28 THEN
IF ROW > 0 THEN
TO_PAIR(POS - 64) -> POS
TO_BYTE(ROW - 1) -> ROW
END IF
ELSIF C = 29 THEN
TO_PAIR(POS + 64) -> POS
TO_BYTE(ROW + 1) -> ROW
ELSIF C = 30 THEN
IF COL > 0 THEN
TO_PAIR(POS - 1) -> POS
TO_BYTE(COL - 1) -> COL
ELSE
IF ROW > 0 THEN
TO_PAIR(POS - COL - (64 - 39)) -> POS
39 -> COL
TO_BYTE(ROW - 1) -> ROW
END IF
END IF
ELSIF C = 31 THEN
IF COL < 39 THEN
TO_PAIR(POS + 1) -> POS
TO_BYTE(COL + 1) -> COL
ELSE
TO_PAIR(POS - COL + 64) -> POS
0 -> COL
TO_BYTE(ROW + 1) -> ROW
END IF
END IF
ELSE
VAR P: PAIR
TO_PAIR(C + CONSOLE::_COLOR_ADDEND) -> P
IF CONSOLE::REVERSE THEN
TO_PAIR(MATH::BIT_OR(P, $4000)) -> P
END IF
IF CONSOLE::MATTE THEN
TO_PAIR(MATH::BIT_OR(P, $8000)) -> P
END IF
P -> KERNEL::CONSOLE_GRID[POS]
IF COL < 39 THEN
TO_PAIR(POS + 1) -> POS
TO_BYTE(COL + 1) -> COL
ELSE
TO_PAIR(POS - COL + 64) -> POS
0 -> COL
TO_BYTE(ROW + 1) -> ROW
END IF
END IF
IF ROW >= 28 THEN
TO_BYTE(ROW - 1) -> ROW
TO_PAIR(POS - 64) -> POS
IF NOT CONSOLE::SCROLL_OFF THEN
CONSOLE::_SCROLL_UP()
END IF
END IF
COL -> CONSOLE::_COL
ROW -> CONSOLE::_ROW
POS -> CONSOLE::_POS
END FUNC
FUNC _SCROLL_UP()
KERNEL::MEMCPY(
| TO_ADDRESS(KERNEL::CONSOLE_GRID),
| TO_ADDRESS(KERNEL::CONSOLE_GRID) + 128,
| 3456)
KERNEL::MEMSET_PAIR(
| TO_ADDRESS(KERNEL::CONSOLE_GRID) + 3456,
| 32,
| 40)
END FUNC
FUNC READ_KEY(): BYTE
VAR INDEX: BYTE, END_INDEX: BYTE
VAR RESULT: BYTE
IO::INPUT_QUEUE_END_INDEX -> END_INDEX
CONSOLE::_INPUT_QUEUE_INDEX -> INDEX
0 -> RESULT
LOOP
IF INDEX = END_INDEX
DO DROP
VAR EVENT: ^IO_INPUT_EVENT
IO::INPUT_QUEUE[INDEX] -> EVENT
TO_BYTE(INDEX + 1) -> INDEX
IF INDEX >= 16
DO 0 -> INDEX
VAR EVENT_KIND: BYTE, EVENT_KEYID: BYTE
EVENT.KIND -> EVENT_KIND
EVENT.KEYID -> EVENT_KEYID
IF EVENT_KIND = 0 OR EVENT_KIND = 1 THEN
IF EVENT_KEYID = 18 OR EVENT_KEYID = 19 THEN
TRUE -> CONSOLE::CTRL_KEY
ELSIF EVENT.HASCII > 0 AND EVENT.HASCII < 256 THEN
TO_BYTE(EVENT.HASCII) -> RESULT
DROP
END IF
ELSE
IF EVENT_KEYID = 18 OR EVENT_KEYID = 19 THEN
FALSE -> CONSOLE::CTRL_KEY
END IF
END IF
END LOOP
INDEX -> CONSOLE::_INPUT_QUEUE_INDEX
RETURN RESULT
END FUNC
FUNC CHECK_KEY(): BYTE
VAR RESULT: BYTE
IF CONSOLE::_INPUT_QUEUE_INDEX = IO::INPUT_QUEUE_END_INDEX THEN
0 -> RESULT
ELSE
1 -> RESULT
END IF
RETURN RESULT
END FUNC
FUNC GET_BOOKMARK(): PAIR
VAR BOOKMARK: PAIR
CONSOLE::_POS -> BOOKMARK
RETURN BOOKMARK
END FUNC
FUNC GOTO_BOOKMARK(BOOKMARK: PAIR)
IF BOOKMARK >= 3200
DO KERNEL::FAIL("INVALID BOOKMARK")
CONSOLE::_BLINK_OFF()
TO_BYTE(MATH::SHIFT_RIGHT_UNSIGNED(BOOKMARK, 6)) -> CONSOLE::_ROW
TO_BYTE(MATH::BIT_AND(BOOKMARK, 63)) -> CONSOLE::_COL
BOOKMARK -> CONSOLE::_POS
CONSOLE::_BLINK_RESTORE()
END FUNC
FUNC THINK()
VAR BLINK_COUNTER: INT
MATH::BIT_AND(IO::FRAME_COUNTER, 31) -> BLINK_COUNTER
IF NOT CONSOLE::CURSOR_VISIBLE OR BLINK_COUNTER >= 16 THEN
CONSOLE::_BLINK_OFF()
ELSE
IF NOT CONSOLE::_BLINK THEN
TRUE -> CONSOLE::_BLINK
CONSOLE::_BLINK_RESTORE()
END IF
END IF
END FUNC
END MODULE