c71e249a4e
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>
309 lines
7.0 KiB
NASM
Executable File
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
|
|
|