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>
This commit is contained in:
Executable
+217
@@ -0,0 +1,217 @@
|
||||
intLibrary
|
||||
assert intLibrary >= #8000
|
||||
|
||||
INT_TABLE_HI equ #be
|
||||
INT_TABLE equ 256 * INT_TABLE_HI
|
||||
|
||||
; useLib: keybLibrary, memLibrary
|
||||
; useRam: INT_TABLE_HI
|
||||
|
||||
; export var:
|
||||
; intMode
|
||||
; intFlagPlayAyMus
|
||||
; intFlagPlayAyMusPageAdr
|
||||
|
||||
; export fn:
|
||||
; intLibInit
|
||||
; intSetGameInterrupt
|
||||
; intRestoreDefaultInterrupt
|
||||
; intWaitVsync
|
||||
|
||||
|
||||
; Векторы прерываний:
|
||||
; клавиатура - #ff
|
||||
; кадровое - #ff
|
||||
; CovoxBlaster - #ff (признак — порт #fe.bit7 = 1 и оно висит до захвата прерывания процом)
|
||||
; CTC - #06 (LSB) (висит до захвата прерывания процом)
|
||||
; возможно есть и другие - надо изучить
|
||||
|
||||
; СТС имеет 4 счётчика.
|
||||
; идея в том, что:
|
||||
; - счётчик №2 тактируется по знакоместам (1 тик = 1 знакоместо) с частотой 875 Кгц,
|
||||
; - счётчик №3 тактируется от №2.
|
||||
; эти два счётчика всегда работают в связке
|
||||
; если один счётчик заставить отсчитать 2 пиксельных линии экрана (112 знакомест),
|
||||
; а другой счётчик отсчитать 160 раз от первого, то получим одно срабатывание на 320 пиксельных линий — это полностью идентично кадровому прерыванию.
|
||||
|
||||
|
||||
; Режимы прерываний
|
||||
INT_MODE_SYS equ 0
|
||||
INT_MODE_GAME equ 1
|
||||
INT_MODE_VSYNC_HOOK equ 2
|
||||
|
||||
|
||||
; Здесь храним текущий режим прерываний
|
||||
intMode db INT_MODE_SYS
|
||||
|
||||
; Инициализация библиотеки
|
||||
; запоминаем текущее состояние регистра i
|
||||
; use: af
|
||||
intLibInit
|
||||
ld a,i
|
||||
ld (_intDefaultRegI),a
|
||||
ret
|
||||
|
||||
|
||||
; Установка прерываний игры
|
||||
; use: hl,af,i
|
||||
intSetGameInterrupt
|
||||
; Перед установкой CTC нам необходимо поймать кадровое прерывание
|
||||
; (это важно т.к. у нас некоторые циклы работают с одним экраном до прихода луча развертки)
|
||||
; Просто ei:halt не подойдет т.к. общий вектор для кадрового и клавиатурного прерываний
|
||||
; и если в данный момент будут нажаты кнопки мы поймаем прерывание от них и окажемся в случайном месте кадра
|
||||
; Делаем в несколько шагов:
|
||||
; 1. Отключаем системные прерывания чтобы не мешались
|
||||
; (т.к. они в том числе обрабатывают прерывания от клавиатуры и читают из неё данные)
|
||||
; и устанавливаем пустой обработчик прерываний
|
||||
; также сразу устанавливаем адрес обработки CTC
|
||||
di
|
||||
ld hl,_intHandlerCtc
|
||||
ld (INT_TABLE + #06),hl
|
||||
ld hl,_intHandlerNull
|
||||
ld (INT_TABLE + #ff),hl
|
||||
ld a,INT_TABLE_HI
|
||||
ld i,a
|
||||
im 2
|
||||
ld a,INT_MODE_VSYNC_HOOK
|
||||
ld (intMode),a
|
||||
; 2. Далее ждем прерываний - если есть данные от клавиатуры, то это не кадровое
|
||||
; если одновременно будет и кадровое и клавиатура - пропустим кадровое но тут нам это не страшно (дождемся следующего)
|
||||
_vSyncHookLoop
|
||||
ei
|
||||
halt
|
||||
di
|
||||
in a,(COM_A)
|
||||
bit 0,a ; проверить наличие данных от клавиатуры
|
||||
jr z,_vSyncHookSuccess ; если нет данных значит поймали кадровое
|
||||
in a,(DAT_A) ; считать байт
|
||||
jr _vSyncHookLoop
|
||||
; 3. Поймали кадровое прерывание
|
||||
; Настраиваем CTC и устанавливаем прерывания игры
|
||||
; Почему именно такие значения - надо читать доку по z84c15
|
||||
_vSyncHookSuccess
|
||||
ld a,#57 : out (CTC.Ch_2),a
|
||||
ld a,112 : out (CTC.Ch_2),a
|
||||
ld a,#d7 : out (CTC.Ch_3),a
|
||||
ld a,160 : out (CTC.Ch_3),a
|
||||
ld a,0 : out (CTC.Ch_0),a
|
||||
ld hl,_intHandlerKeybOrFrame
|
||||
ld (INT_TABLE + #ff),hl
|
||||
ld a,INT_MODE_GAME
|
||||
ld (intMode),a
|
||||
;-------
|
||||
; инициализируем CovoxBlaster
|
||||
jp soundDeviceCovoxBlasterLib.init
|
||||
|
||||
; Пустой обработчик прерываний - нужен для определения от кого прерывание (см. intSetGameInterrupt)
|
||||
; use: -
|
||||
_intHandlerNull
|
||||
di
|
||||
call _intReti
|
||||
ei: ret
|
||||
|
||||
_intReti
|
||||
ei
|
||||
reti
|
||||
|
||||
|
||||
; Восстановление прерываний
|
||||
; (обязательно делать перед использованием функций дос и биос)
|
||||
; use: af, i
|
||||
intRestoreDefaultInterrupt
|
||||
di
|
||||
ld a,1
|
||||
out (CTC.Ch_3),a
|
||||
ld a,INT_MODE_SYS
|
||||
ld (intMode),a
|
||||
ld a,#00
|
||||
_intDefaultRegI equ $-1
|
||||
ld i,a
|
||||
im 1
|
||||
ret
|
||||
|
||||
|
||||
; Обработчик "кадровых" прерываний от CTC
|
||||
; на выходе нужно именно reti если заменить на ret то прерывание от CTC больше не придет
|
||||
; use: save & restore all used regs to stack
|
||||
_intHandlerCtc
|
||||
di
|
||||
push hl,de,bc,af
|
||||
ex af,af
|
||||
push af
|
||||
;-
|
||||
ld a,1
|
||||
ld (_vsyncFlag),a ; Устанавливаем флаг что пришло кадровое прерывание
|
||||
;-
|
||||
in a,(EmmWin.P1)
|
||||
ld (_intEmmWinP1),a
|
||||
call soundLib.intHandler
|
||||
ld a,0
|
||||
_intEmmWinP1 equ $-1
|
||||
out (EmmWin.P1),a
|
||||
;---
|
||||
pop af
|
||||
ex af,af
|
||||
pop af,bc,de,hl
|
||||
call _intReti
|
||||
ei: ret
|
||||
|
||||
|
||||
; Обработчик прерываний от клавиатуры и кадровых
|
||||
; тут делаем только обработку прерываний от клавиатуры
|
||||
; use: save & restore all used regs to stack
|
||||
_intHandlerKeybOrFrame
|
||||
di
|
||||
push hl,de,bc,af
|
||||
;---
|
||||
call keybIntHandler
|
||||
;di
|
||||
;---
|
||||
call soundDeviceCovoxBlasterLib.intHandler
|
||||
;---
|
||||
pop af,bc,de,hl
|
||||
call _intReti
|
||||
ei: ret
|
||||
|
||||
; Ожидаем начало фрейма (прерывание от СТС)
|
||||
; Для этого сбрасываем (_vsyncFlag), делаем ei:halt и проверяем что дождались (_vsyncFlag)=1 - кадровое
|
||||
; use: af
|
||||
intWaitVsync
|
||||
ld a,(intMode)
|
||||
cp INT_MODE_SYS
|
||||
jr z,_intWaitVsyncSys
|
||||
;-
|
||||
xor a
|
||||
ld (_vsyncFlag),a
|
||||
;-
|
||||
if DEBUG_BORDER = 1
|
||||
xor a: out(#fe),a
|
||||
endif
|
||||
;-
|
||||
_intWaitVsyncLoop
|
||||
ei
|
||||
halt
|
||||
;-
|
||||
ld a,0
|
||||
_vsyncFlag equ $-1
|
||||
and a
|
||||
jr z,_intWaitVsyncLoop
|
||||
;-
|
||||
if DEBUG_BORDER = 1
|
||||
ld a,2: out(#fe),a
|
||||
endif
|
||||
;-
|
||||
ret
|
||||
; Ожидаем начало фрейма в режиме системных прерываний (ei:halt)
|
||||
; можем поймать прерывание от клавиатуры вместо кадрового
|
||||
; Наверное надо бы запретить вызывать intWaitVsync при системных прерываниях, например так:
|
||||
; if DEBUG_IS_ON = 1
|
||||
; ld hl,txtErrorIntWaitVsync
|
||||
; jp debugShowError
|
||||
; endif
|
||||
; txtErrorIntWaitVsync db "ERROR: Call IntWaitVsync with system int", #00
|
||||
_intWaitVsyncSys
|
||||
call memCacheOffTemporary ;временно выключаем fastRam
|
||||
ei
|
||||
halt
|
||||
jp memCacheRestoryState ;восстанавливаем состояние подключения fastRam
|
||||
Reference in New Issue
Block a user