Files
snark13 c71e249a4e Add full compiler toolchain, libc, examples and reference docs
First substantive commit: the entire Sprinter C compiler tree on top of
the bare README+gitignore initial commit.

What's in here:
  bin/sprinter-cc        — driver script invoking SDCC + linker + mkexe
  libc/                  — Sprinter-specific libc layer over ESTEX/BIOS
                           (conio, gfx, io, mem, stdio + headers)
  runtime/               — crt0 variants (default/small/banked/minimal)
                           + heap + bank trampolines
  toolchain/             — mkexe (SprintEXE packer, C + tests)
  examples/              — 30 demo programs (gfx, file I/O, env, time, …)
  lib/Makefile           — builds the libc archive (sprinter.lib)
  docs/                  — converted Sprinter manuals + asm reference samples
  third_party/           — solid-c reference compiler dump + sdcc setup script
  release_docs/          — packaging / release notes

gitignore overhaul:
  • Drop dangerous blanket patterns: *.asm (would hide docs/samples/*.asm)
    and *.exe (case-insensitive match was hiding third_party/solid-c/*.EXE
    on macOS APFS).  Replaced with examples/*/*.{asm,exe,…} and lib/*.lib.
  • Restore tracking of toolchain/mkexe/tests/{one,big}.bin — those are
    INPUT fixtures, not build outputs.
  • Collapse the duplicated SDCC/C/Sdcc sections into one section per
    concern (build outputs / vendored / OS-junk).
  • Add .sprinter-cc-*/, build/ (catches lib/build/ too), .claude/.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 16:13:21 +03:00

309 lines
7.0 KiB
NASM
Executable File

PAGE_0: equ 82h ; порт 0 окна = addr 0000h
PAGE_1: equ 0A2h ; порт 1 окна = 4000h
PAGE_2: equ 0C2h ; порт 2 окна = 8000h
PAGE_3: equ 0E2h ; порт 3 окна = 0c000h
SIO_CONTROL_A: EQU 19h
SIO_DATA_REG_A: EQU 18h
SIO_CONTROL_B: EQU 1Bh
SIO_DATA_REG_B: EQU 1Ah
CTC_CH0: equ 10h
CTC_CH1: equ 11h
CTC_CH2: equ 12h
CTC_CH3: equ 13h
RGMOD equ 0c9h
; ....
; Запомним текущий видео-режим
LD C, DSS.GetVMod
RST 10h
LD HL, GetVMod_Error_Message
;JR C, PutError
LD C, A
LD (.Current_VMod), BC
; Запрос памяти
; сохраним текущие значения страниц
IN A, (PAGE_1)
LD (SavePage1), A
IN A, (PAGE_3)
LD (SavePage3), A
; Настройка прерываний CTC и SIO
LD HL, IM2_Empty : LD (0FDFFh), HL
LD (0FD10h), hl
LD (0FD12h), hl
LD (0FD14h), hl
LD (0FD16h), hl
LD (0FD18h), hl
LD (0FD1Ah), hl
LD (0FD1Ch), hl
LD (0FD1Eh), hl
LD HL, IM2_VShandler : LD (0FD06h), HL
LD A, I
LD (.SaveInterrupt), A
LD A, 0FDh
DI
LD I, A
IM 2
.Sync:
EI
HALT
DI
IN A, (SIO_CONTROL_A)
BIT 0, A ; 0-bit, байт пришел ?
JR Z, .EndSync ; да, это прерывание от клавиатуры
CALL Keyboard.PS2_Scan
JR .Sync
.EndSync:
LD B, 5
.loopSync:
DJNZ .loopSync
; Настройка CTC
LD A, 057h : OUT (CTC_CH2), A
LD A, 112 : OUT (CTC_CH2), A
LD A, 0d7h : OUT (CTC_CH3), A
LD A, 160 : OUT (CTC_CH3), A
LD A, 0 : OUT (CTC_CH0), A
; Настройка SIO
LD A, 1 : OUT (SIO_CONTROL_A), A
LD A, 18h : OUT (SIO_CONTROL_A), A
LD A, 2 : OUT (SIO_CONTROL_B), A
LD A, 10h : OUT (SIO_CONTROL_B), A
LD HL, IM2_Keyhandler
LD (0FDFFh), HL
LD (0FD10h), hl
LD (0FD12h), hl
LD (0FD14h), hl
LD (0FD16h), hl
LD (0FD18h), hl
LD (0FD1Ah), hl
LD (0FD1Ch), hl
LD (0FD1Eh), hl
Loop:
; основаной цикл
; ................
LD A, (Keyboard.KeyFlags)
BIT 7, A
JR NZ, .Key_ESC
JP Loop
.Key_ESC: ; Выход
DI
; Восстановим прерывания и CTC
LD A, 057h : OUT (CTC_CH3), A
LD A, 160 : OUT (CTC_CH3), A
; Восстановим SIO
LD A, 1 : OUT (SIO_CONTROL_A), A
LD A, 0 : OUT (SIO_CONTROL_A), A
LD A, 2 : OUT (SIO_CONTROL_B), A
LD A, 10h : OUT (SIO_CONTROL_B), A
.SaveInterrupt+*: LD A, 0
LD I, A
IM 1
EI
CALL Keyboard.PS2_Clear_Buf
; Восстанавливаем страницы памяти
LD A,(SavePage1)
OUT (PAGE_1), A
LD A,(SavePage3)
OUT (PAGE_3), A
; Освободим память запрошенную память
; возвращаем текстовый режим
.Current_VMod+*: LD BC, 0
LD A, C
LD C, DSS.SetVMod
RST 10h
.Exit:
.ExitCode+*: LD B, 0
LD C, DSS.Exit
RST 10h
JR $
UpdateMechanics:
LD A, (Keyboard.KeyFlags)
OR A
RET Z
BIT 3, A
JR NZ, .Key_UP
BIT 2, A
JR NZ, .Key_DOWN
RET
.Key_DOWN:
; ...
.Key_UP:
; ...
RET
IM2_Empty:
EI
RETI
IM2_Keyhandler:
PUSH AF, BC, DE, HL
EXX
EX AF, AF
PUSH AF, BC, DE, HL, IX, IY
IN A, (SIO_CONTROL_A)
BIT 0, A ; 0-bit, байт пришел ?
CALL NZ, Keyboard.PS2_Scan ; да, это прерывание от клавиатуры
.SkipClearKeyFlags:
POP IY, IX, HL, DE, BC, AF
EX AF, AF
EXX
POP HL, DE, BC, AF
EI
RETI
IM2_VShandler:
PUSH AF, BC, DE, HL
EXX
EX AF, AF
PUSH AF, BC, DE, HL, IX, IY
.NeedChangePage+*: LD A, 0 ; 1 - нужно переключить экран
OR A
JR Z, .skip
.NumberScreen+*: LD B, 0 ; 0/1 - номер экрана, который в данный момент выводится
; Переключаем экран
IN A, (RGMOD)
AND 0feh
OR B
XOR 1
OUT (RGMOD), A
AND 1
LD (.NumberScreen), A
XOR A
LD (.NeedChangePage), A
.skip:
CALL UpdateMechanics ; Возможно нужно перенести из прерывания
; Расчет FPS
; ..........
POP IY, IX, HL, DE, BC, AF
EX AF, AF
EXX
POP HL, DE, BC, AF
EI
RETI
; очистка буфера клавиатуры
; Портит регистры AF
Keyboard.PS2_Clear_Buf:
IN a, (SIO_CONTROL_A)
BIT 0, a
RET Z
IN A, (SIO_DATA_REG_A)
JR PS2_Clear_Buf
; Из PS/2 возвращает в Keyboard.KeyFlags нажатые клавиши:
; бит кнопка
; 0 - RIGHT
; 1 - LEFT
; 2 - DOWN
; 3 - UP
; 4 - SPACE
; 5 - none
; 6 - ENTER
; 7 - ESC
; Портит регистры AF, BC, DE, HL
Keyboard.PS2_Scan:
LD HL, .KeyStatus
LD DE, 0c686h ; D - код команды SET 0, (HL) / E - код команды RES 0, (HL)
.Loop
IN a, (SIO_CONTROL_A)
BIT 0, a
RET Z
IN A, (SIO_DATA_REG_A)
CP 0E0h
JR NZ, .kh1
SET 7, (HL) ; // двойной сканкод
JR .Loop
.kh1:
CP 0F0h
JR NZ, .kh2
SET 6, (HL) ; // отпускание клавиши
JR .Loop
.kh2:
BIT 7, A ; автоповтор?
JR Z, .kh3
LD (HL), 0
JR .Loop
.kh3:
LD B, 8
BIT 6, (HL)
LD C, D ; С - код команды SET 0, (HL)
JR Z, .KeyPress
.KeyRelease:
LD C, E ; С - код команды RES 0, (HL)
.KeyPress:
LD (HL), 0
PUSH HL
INC HL
.KeyPressLoop:
CP (HL)
JR Z, .SetKey
INC HL
DJNZ .KeyPressLoop
POP HL
JR .Loop
.SetKey:
LD A, B
DEC A
CPL
RLA
RLA
RLA
AND 00111000b
OR C
LD (.CodeSet + 1), A ; Изменяем команду по .CodeSet
POP HL
DEC HL
.CodeSet: SET 0, (HL)
INC HL
JR .Loop
.KeyFlags: DB 0
.KeyStatus: DB 0
.KeysArray: DB 74h, 6bh, 72h, 75h, 29h, 00h, 5ah, 76h
Keyboard.KeyFlags: EQU .KeyFlags
SavePage1: DB 0
SavePage3: DB 0