libc: сплит «1 функция = 1 модуль» — вся библиотека, wildcard-сборка
- bios/conio/env/errno/gfx/io/mem/mouse/stdio/stdlib/string/sys/time/ video разложены по модулям: общие статики и helpers — в internal _-модулях (_conio.h/_mouse.h/_gfx.h/_palette.h/_atexit.h/_time.h) - lib/Makefile: LIBC_C = wildcard libc/*/*.c — гранулярность файлов = гранулярность DCE линкера - эффект _CODE: gfx_text 6986→2568 Б, gfx_mous −1745, gfx_demo/d16 −542; ранее timedir −3270, ls −3098, stattest −2995 - комментарии оставшихся модулей переведены на русский; puts: убран мёртвый pchars; videomode_raw разложен на get/set - docs/libc-split-asm-cases.md — правила asm-связок между модулями; docs/libc-roadmap.md — план этапа - восстановлен examples/mdview/SAMPLE.MD (нужен make floppy) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* _mouse.h — внутренние скретчи и хелперы мышиного драйвера (RST 30h).
|
||||
* НЕ публичный заголовок; данные в _mouse_scratch.c, хелпер в _ms_query.c.
|
||||
*/
|
||||
#ifndef _MOUSE_INTERNAL_H
|
||||
#define _MOUSE_INTERNAL_H
|
||||
|
||||
#include <mouse.h>
|
||||
|
||||
/* Скретч курсора для IX-конвенции LOAD/RETURN CURSOR ($09/$0B):
|
||||
* RST 30h берёт указатель на битмап в IX, поля передаём через память. */
|
||||
extern uint16_t _mc_image;
|
||||
extern uint8_t _mc_width;
|
||||
extern uint8_t _mc_height;
|
||||
extern uint8_t _mc_hot_x;
|
||||
extern uint8_t _mc_hot_y;
|
||||
|
||||
/* GET SENSITIVITY ($0E): возвращает (vert<<8)|horz. */
|
||||
int _ms_query(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* _mouse_scratch — скретч-поля курсора, общие для mouse_load_cursor и
|
||||
* mouse_get_cursor (обмен с asm по известным именам, т.к. RST 30h
|
||||
* использует IX и портит регистры). Модуль только с данными.
|
||||
*/
|
||||
|
||||
#include "_mouse.h"
|
||||
|
||||
uint16_t _mc_image;
|
||||
uint8_t _mc_width;
|
||||
uint8_t _mc_height;
|
||||
uint8_t _mc_hot_x;
|
||||
uint8_t _mc_hot_y;
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* _ms_query — GET SENSITIVITY (RST 30h, fn $0E): H=верт, L=гориз;
|
||||
* возвращаем (vert<<8)|horz в DE. Общий хелпер для
|
||||
* mouse_get_sensitivity_x/y.
|
||||
*/
|
||||
|
||||
#include "_mouse.h"
|
||||
|
||||
int _ms_query(void) __naked
|
||||
{
|
||||
__asm
|
||||
push ix
|
||||
ld c, #0x0E ; GET SENSITIVITY
|
||||
rst #0x30 ; MOUSE
|
||||
ld d, h
|
||||
ld e, l
|
||||
pop ix
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
@@ -1,305 +0,0 @@
|
||||
/*
|
||||
* mouse.c — Sprinter mouse driver wrappers (RST 30h).
|
||||
*
|
||||
* All calls use the same pattern as ESTEX (push/pop IX around the RST)
|
||||
* since the driver doesn't promise to preserve registers either.
|
||||
*/
|
||||
|
||||
#include <mouse.h>
|
||||
|
||||
/* Scratch for READ_STATE — RST 30h clobbers HL/DE/A so we can't keep the
|
||||
* state pointer in HL across the call. Explicit `= 0` so SDCC reserves
|
||||
* real BSS storage — see memory/sdcc_static_storage_gotcha.md. */
|
||||
static uint16_t mb_x = 0, mb_y = 0;
|
||||
static uint8_t mb_buttons = 0;
|
||||
|
||||
int mouse_init(void) __naked
|
||||
{
|
||||
__asm
|
||||
push ix
|
||||
ld c, #0x00 ; INITIALIZATION
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
jr c, _mi_err
|
||||
ld de, #0
|
||||
ret
|
||||
_mi_err:
|
||||
ld de, #-1
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
|
||||
void mouse_show(void) __naked
|
||||
{
|
||||
__asm
|
||||
push ix
|
||||
ld c, #0x01 ; SHOW MOUSE CURSOR
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
|
||||
void mouse_hide(void) __naked
|
||||
{
|
||||
__asm
|
||||
push ix
|
||||
ld c, #0x02 ; HIDE MOUSE CURSOR
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
|
||||
void mouse_refresh(void) __naked
|
||||
{
|
||||
__asm
|
||||
push ix
|
||||
ld c, #0x83 ; MOUSE REFRESH
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
|
||||
void mouse_read(mouse_state_t *st) __naked
|
||||
{
|
||||
(void)st;
|
||||
__asm
|
||||
;; HL = state ptr on entry.
|
||||
push ix
|
||||
push hl ; stash ptr across RST
|
||||
ld c, #0x03 ; READ MOUSE STATE
|
||||
rst #0x30 ; MOUSE
|
||||
;; Returns: A=buttons, HL=x, DE=y (CF=err but we ignore here)
|
||||
ld (_mb_x), hl
|
||||
ld (_mb_y), de
|
||||
ld (_mb_buttons), a
|
||||
pop hl ; restore state ptr
|
||||
pop ix
|
||||
|
||||
;; Copy scratch → *st. Struct layout: x(2), y(2), buttons(1).
|
||||
ld de, (_mb_x)
|
||||
ld (hl), e
|
||||
inc hl
|
||||
ld (hl), d
|
||||
inc hl
|
||||
ld de, (_mb_y)
|
||||
ld (hl), e
|
||||
inc hl
|
||||
ld (hl), d
|
||||
inc hl
|
||||
ld a, (_mb_buttons)
|
||||
ld (hl), a
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
|
||||
void mouse_goto(int x, int y) __naked
|
||||
{
|
||||
(void)x; (void)y;
|
||||
__asm
|
||||
;; HL = x, DE = y.
|
||||
push ix
|
||||
ld c, #0x04 ; GOTO MOUSE CURSOR
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
|
||||
void mouse_bounds_x(int xmin, int xmax) __naked
|
||||
{
|
||||
(void)xmin; (void)xmax;
|
||||
__asm
|
||||
;; HL = xmin, DE = xmax.
|
||||
push ix
|
||||
ld c, #0x08 ; HORZ BOUNDS
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
|
||||
void mouse_bounds_y(int ymin, int ymax) __naked
|
||||
{
|
||||
(void)ymin; (void)ymax;
|
||||
__asm
|
||||
;; HL = ymin, DE = ymax.
|
||||
push ix
|
||||
ld c, #0x07 ; VERT BOUNDS
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
|
||||
/* ---- $09 LOAD CURSOR + $0B RETURN CURSOR ---------------------- */
|
||||
/* Scratch for the IX-passing convention — RST 30h takes the bitmap
|
||||
* pointer in IX, so we have to set it up explicitly.
|
||||
*
|
||||
* Initialised to 0 so SDCC reserves real BSS storage — uninitialised
|
||||
* `static uint8_t` declarations can coalesce to a single address and
|
||||
* stomp on each other. See memory/sdcc_static_storage_gotcha.md. */
|
||||
static uint16_t mc_image = 0;
|
||||
static uint8_t mc_width = 0;
|
||||
static uint8_t mc_height = 0;
|
||||
static uint8_t mc_hot_x = 0;
|
||||
static uint8_t mc_hot_y = 0;
|
||||
/* Saved struct pointer for mouse_get_cursor. SDCC __sdcccall(1) passes
|
||||
* `c` in HL, then stashes it in DE around the inline asm. Our asm
|
||||
* clobbers DE (driver returns hot_y/hot_x in D/E) so the post-asm
|
||||
* `c->width = ...` writes would otherwise land at a garbage address.
|
||||
* We park the pointer in BSS instead so SDCC re-fetches it from
|
||||
* memory after the asm. */
|
||||
static mouse_cursor_t *mc_dest = 0;
|
||||
|
||||
void mouse_load_cursor(const mouse_cursor_t *c)
|
||||
{
|
||||
/* Copy fields out of the C struct into our scratch globals so the
|
||||
* asm side has well-known names. */
|
||||
mc_image = (uint16_t)(uintptr_t)c->image;
|
||||
mc_width = c->width;
|
||||
mc_height = c->height;
|
||||
mc_hot_x = c->hot_x;
|
||||
mc_hot_y = c->hot_y;
|
||||
__asm
|
||||
push ix
|
||||
ld ix, (_mc_image)
|
||||
ld a, (_mc_height)
|
||||
ld h, a
|
||||
ld a, (_mc_width)
|
||||
ld l, a
|
||||
ld a, (_mc_hot_y)
|
||||
ld d, a
|
||||
ld a, (_mc_hot_x)
|
||||
ld e, a
|
||||
ld b, #0
|
||||
ld c, #0x09 ; LOAD MOUSE CURSOR
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
__endasm;
|
||||
}
|
||||
|
||||
void mouse_get_cursor(mouse_cursor_t *c)
|
||||
{
|
||||
mc_dest = c; /* park ptr in BSS */
|
||||
mc_image = (uint16_t)(uintptr_t)c->image;
|
||||
__asm
|
||||
push ix
|
||||
ld ix, (_mc_image) ; IX = bitmap buffer from caller
|
||||
ld c, #0x0B ; RETURN CURSOR
|
||||
rst #0x30 ; mouse driver, NOT ESTEX
|
||||
;; Returns: H=height, L=width, D=hot_y, E=hot_x.
|
||||
ld a, h
|
||||
ld (_mc_height), a
|
||||
ld a, l
|
||||
ld (_mc_width), a
|
||||
ld a, d
|
||||
ld (_mc_hot_y), a
|
||||
ld a, e
|
||||
ld (_mc_hot_x), a
|
||||
pop ix
|
||||
__endasm;
|
||||
/* Re-fetch the struct pointer from BSS — `c` (kept in DE by SDCC
|
||||
* around the inline asm) was clobbered by the RST 30h above. */
|
||||
mouse_cursor_t *p = mc_dest;
|
||||
p->width = mc_width;
|
||||
p->height = mc_height;
|
||||
p->hot_x = mc_hot_x;
|
||||
p->hot_y = mc_hot_y;
|
||||
}
|
||||
|
||||
/* ---- $0E / $0F SENSITIVITY ------------------------------------ */
|
||||
/* GET returns H=vert, L=horz in HL. We expose the two halves as
|
||||
* separate getters so the simple "uint8_t" return ABI works cleanly. */
|
||||
|
||||
static int ms_query(void) __naked
|
||||
{
|
||||
__asm
|
||||
push ix
|
||||
ld c, #0x0E ; GET SENSITIVITY
|
||||
rst #0x30 ; MOUSE
|
||||
ld d, h
|
||||
ld e, l
|
||||
pop ix
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
|
||||
uint8_t mouse_get_sensitivity_x(void)
|
||||
{
|
||||
return (uint8_t)(ms_query() & 0xFF); /* E = horz */
|
||||
}
|
||||
|
||||
uint8_t mouse_get_sensitivity_y(void)
|
||||
{
|
||||
return (uint8_t)(ms_query() >> 8); /* D = vert */
|
||||
}
|
||||
|
||||
void mouse_set_sensitivity(uint8_t horz, uint8_t vert) __naked
|
||||
{
|
||||
(void)horz; (void)vert;
|
||||
/* Pack into HL: H=vert, L=horz. */
|
||||
__asm
|
||||
push ix
|
||||
ld h, l
|
||||
ld l, a
|
||||
ld c, #0x0F ; SET SENSITIVITY
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
__endasm;
|
||||
}
|
||||
|
||||
/* ---- $81 CHANGE VIDEO MODE ------------------------------------ */
|
||||
/* SDCC __sdcccall(1): single uint8_t arg arrives in A. */
|
||||
void mouse_video_mode_changed(uint8_t mode) __naked
|
||||
{
|
||||
(void)mode;
|
||||
__asm
|
||||
push ix
|
||||
;; A already holds the mode byte (from SDCC ABI).
|
||||
ld c, #0x81 ; CHANGE VIDEO MODE
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
|
||||
/* CURSOR_TEXT_MODES ($0A):
|
||||
* B = 0
|
||||
* H = AND symbol mask L = XOR symbol mask
|
||||
* D = AND attribute mask E = XOR attribute mask
|
||||
*
|
||||
* SDCC __sdcccall(1) gives us:
|
||||
* sym_and in L (low byte of HL arg)
|
||||
* sym_xor in E (low byte of DE arg)
|
||||
* attr_and at [SP+2]
|
||||
* attr_xor at [SP+3]
|
||||
*/
|
||||
void mouse_text_cursor(uint8_t sym_and, uint8_t sym_xor,
|
||||
uint8_t attr_and, uint8_t attr_xor) __naked
|
||||
{
|
||||
(void)sym_and; (void)sym_xor; (void)attr_and; (void)attr_xor;
|
||||
__asm
|
||||
;; SDCC __sdcccall(1) for 4×uint8_t args:
|
||||
;; arg1 sym_and → A
|
||||
;; arg2 sym_xor → L
|
||||
;; arg3 attr_and → stack low byte (packed into HL.L on caller, push HL)
|
||||
;; arg4 attr_xor → stack high byte (HL.H pushed by caller)
|
||||
pop iy ; return address
|
||||
pop bc ; C = attr_and (low), B = attr_xor (high)
|
||||
|
||||
push ix
|
||||
;; Target: H=sym_and, L=sym_xor, D=attr_and, E=attr_xor, B=0
|
||||
ld h, a ; H = sym_and (from A)
|
||||
; L already holds sym_xor
|
||||
ld d, c ; D = attr_and
|
||||
ld e, b ; E = attr_xor
|
||||
ld b, #0
|
||||
ld c, #0x0A ; CURSOR TEXT MODE
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
jp (iy)
|
||||
__endasm;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* mouse_bounds_x — ограничить движение курсора по горизонтали
|
||||
* [xmin..xmax] (RST 30h, fn $08).
|
||||
*/
|
||||
|
||||
#include <mouse.h>
|
||||
|
||||
void mouse_bounds_x(int xmin, int xmax) __naked
|
||||
{
|
||||
(void)xmin; (void)xmax;
|
||||
__asm
|
||||
;; HL = xmin, DE = xmax.
|
||||
push ix
|
||||
ld c, #0x08 ; HORZ BOUNDS
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* mouse_bounds_y — ограничить движение курсора по вертикали
|
||||
* [ymin..ymax] (RST 30h, fn $07).
|
||||
*/
|
||||
|
||||
#include <mouse.h>
|
||||
|
||||
void mouse_bounds_y(int ymin, int ymax) __naked
|
||||
{
|
||||
(void)ymin; (void)ymax;
|
||||
__asm
|
||||
;; HL = ymin, DE = ymax.
|
||||
push ix
|
||||
ld c, #0x07 ; VERT BOUNDS
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* mouse_get_cursor — прочитать текущую форму курсора в *c (RST 30h,
|
||||
* fn $0B RETURN CURSOR). Битмап пишется по c->image (указатель уходит
|
||||
* в IX), поля возвращаются в H/L/D/E и идут в структуру через общий
|
||||
* скретч (_mouse.h).
|
||||
*/
|
||||
|
||||
#include "_mouse.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* Припаркованный указатель структуры: SDCC держит `c` в DE вокруг
|
||||
* inline asm, а RST 30h портит DE (драйвер возвращает hot_y/hot_x в
|
||||
* D/E) — без парковки записи полей ушли бы по мусорному адресу. */
|
||||
static mouse_cursor_t *mc_dest;
|
||||
|
||||
void mouse_get_cursor(mouse_cursor_t *c)
|
||||
{
|
||||
mc_dest = c; /* припарковать в BSS */
|
||||
_mc_image = (uint16_t)(uintptr_t)c->image;
|
||||
__asm
|
||||
push ix
|
||||
ld ix, (__mc_image) ; IX = буфер битмапа вызывающего
|
||||
ld c, #0x0B ; RETURN CURSOR
|
||||
rst #0x30 ; мышиный драйвер, НЕ ESTEX
|
||||
;; Возврат: H=height, L=width, D=hot_y, E=hot_x.
|
||||
ld a, h
|
||||
ld (__mc_height), a
|
||||
ld a, l
|
||||
ld (__mc_width), a
|
||||
ld a, d
|
||||
ld (__mc_hot_y), a
|
||||
ld a, e
|
||||
ld (__mc_hot_x), a
|
||||
pop ix
|
||||
__endasm;
|
||||
/* Перечитать указатель из BSS — DE с `c` испорчен RST'ом выше. */
|
||||
mouse_cursor_t *p = mc_dest;
|
||||
p->width = _mc_width;
|
||||
p->height = _mc_height;
|
||||
p->hot_x = _mc_hot_x;
|
||||
p->hot_y = _mc_hot_y;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* mouse_get_sensitivity_x — горизонтальная чувствительность (делитель:
|
||||
* меньше = быстрее; документация утверждает обратное — неверно).
|
||||
*/
|
||||
|
||||
#include "_mouse.h"
|
||||
|
||||
uint8_t mouse_get_sensitivity_x(void)
|
||||
{
|
||||
return (uint8_t)(_ms_query() & 0xFF); /* E = horz */
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* mouse_get_sensitivity_y — вертикальная чувствительность (делитель:
|
||||
* меньше = быстрее).
|
||||
*/
|
||||
|
||||
#include "_mouse.h"
|
||||
|
||||
uint8_t mouse_get_sensitivity_y(void)
|
||||
{
|
||||
return (uint8_t)(_ms_query() >> 8); /* D = vert */
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* mouse_goto — переставить курсор мыши в (x, y) (RST 30h, fn $04).
|
||||
*/
|
||||
|
||||
#include <mouse.h>
|
||||
|
||||
void mouse_goto(int x, int y) __naked
|
||||
{
|
||||
(void)x; (void)y;
|
||||
__asm
|
||||
;; HL = x, DE = y.
|
||||
push ix
|
||||
ld c, #0x04 ; GOTO MOUSE CURSOR
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* mouse_hide — спрятать курсор мыши (RST 30h, fn $02).
|
||||
*/
|
||||
|
||||
#include <mouse.h>
|
||||
|
||||
void mouse_hide(void) __naked
|
||||
{
|
||||
__asm
|
||||
push ix
|
||||
ld c, #0x02 ; HIDE MOUSE CURSOR
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* mouse_init — инициализация мышиного драйвера (RST 30h, fn $00).
|
||||
* Возвращает 0 или -1, если драйвер недоступен (CF=1).
|
||||
* Все вызовы RST 30h — с push/pop IX: драйвер регистры не бережёт.
|
||||
*/
|
||||
|
||||
#include <mouse.h>
|
||||
|
||||
int mouse_init(void) __naked
|
||||
{
|
||||
__asm
|
||||
push ix
|
||||
ld c, #0x00 ; INITIALIZATION
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
jr c, _mi_err
|
||||
ld de, #0
|
||||
ret
|
||||
_mi_err:
|
||||
ld de, #-1
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* mouse_load_cursor — загрузить форму курсора из *c (RST 30h, fn $09
|
||||
* LOAD MOUSE CURSOR). Драйвер берёт указатель битмапа в IX, поля —
|
||||
* в H/L/D/E; переносим их из структуры через общий скретч (_mouse.h),
|
||||
* чтобы у asm были известные имена.
|
||||
*/
|
||||
|
||||
#include "_mouse.h"
|
||||
#include <stdint.h>
|
||||
|
||||
void mouse_load_cursor(const mouse_cursor_t *c)
|
||||
{
|
||||
/* Разложить поля структуры по скретч-переменным для asm. */
|
||||
_mc_image = (uint16_t)(uintptr_t)c->image;
|
||||
_mc_width = c->width;
|
||||
_mc_height = c->height;
|
||||
_mc_hot_x = c->hot_x;
|
||||
_mc_hot_y = c->hot_y;
|
||||
__asm
|
||||
push ix
|
||||
ld ix, (__mc_image)
|
||||
ld a, (__mc_height)
|
||||
ld h, a
|
||||
ld a, (__mc_width)
|
||||
ld l, a
|
||||
ld a, (__mc_hot_y)
|
||||
ld d, a
|
||||
ld a, (__mc_hot_x)
|
||||
ld e, a
|
||||
ld b, #0
|
||||
ld c, #0x09 ; LOAD MOUSE CURSOR
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
__endasm;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* mouse_read — снять состояние мыши в *st (RST 30h, fn $03).
|
||||
* Возвращает: A=кнопки, HL=x, DE=y — RST портит HL/DE/A, поэтому
|
||||
* указатель на структуру не удержать в регистрах: результат идёт через
|
||||
* приватный скретч в BSS, потом копируется в *st.
|
||||
* Раскладка mouse_state_t: x(2), y(2), buttons(1).
|
||||
*/
|
||||
|
||||
#include <mouse.h>
|
||||
|
||||
/* Скретч только для mouse_read. */
|
||||
static uint16_t mb_x, mb_y;
|
||||
static uint8_t mb_buttons;
|
||||
|
||||
void mouse_read(mouse_state_t *st) __naked
|
||||
{
|
||||
(void)st;
|
||||
__asm
|
||||
;; HL = указатель на структуру на входе.
|
||||
push ix
|
||||
push hl ; спрятать указатель через RST
|
||||
ld c, #0x03 ; READ MOUSE STATE
|
||||
rst #0x30 ; MOUSE
|
||||
;; Возврат: A=кнопки, HL=x, DE=y (CF=err — здесь игнорируем)
|
||||
ld (_mb_x), hl
|
||||
ld (_mb_y), de
|
||||
ld (_mb_buttons), a
|
||||
pop hl ; вернуть указатель
|
||||
pop ix
|
||||
|
||||
;; Скопировать скретч → *st. Раскладка: x(2), y(2), buttons(1).
|
||||
ld de, (_mb_x)
|
||||
ld (hl), e
|
||||
inc hl
|
||||
ld (hl), d
|
||||
inc hl
|
||||
ld de, (_mb_y)
|
||||
ld (hl), e
|
||||
inc hl
|
||||
ld (hl), d
|
||||
inc hl
|
||||
ld a, (_mb_buttons)
|
||||
ld (hl), a
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* mouse_refresh — перерисовать курсор мыши (RST 30h, fn $83) — после
|
||||
* того как приложение изменило экран под ним.
|
||||
*/
|
||||
|
||||
#include <mouse.h>
|
||||
|
||||
void mouse_refresh(void) __naked
|
||||
{
|
||||
__asm
|
||||
push ix
|
||||
ld c, #0x83 ; MOUSE REFRESH
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* mouse_set_sensitivity — установить чувствительность (RST 30h, fn $0F):
|
||||
* H=верт, L=гориз. Значения — делители: меньше = быстрее.
|
||||
*/
|
||||
|
||||
#include <mouse.h>
|
||||
|
||||
void mouse_set_sensitivity(uint8_t horz, uint8_t vert) __naked
|
||||
{
|
||||
(void)horz; (void)vert;
|
||||
/* Упаковать в HL: H=vert, L=horz. */
|
||||
__asm
|
||||
push ix
|
||||
ld h, l
|
||||
ld l, a
|
||||
ld c, #0x0F ; SET SENSITIVITY
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
__endasm;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* mouse_show — показать курсор мыши (RST 30h, fn $01).
|
||||
*/
|
||||
|
||||
#include <mouse.h>
|
||||
|
||||
void mouse_show(void) __naked
|
||||
{
|
||||
__asm
|
||||
push ix
|
||||
ld c, #0x01 ; SHOW MOUSE CURSOR
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* mouse_text_cursor — форма курсора в текстовых режимах (RST 30h,
|
||||
* fn $0A CURSOR_TEXT_MODES):
|
||||
* B = 0
|
||||
* H = AND-маска символа L = XOR-маска символа
|
||||
* D = AND-маска атрибута E = XOR-маска атрибута
|
||||
*
|
||||
* SDCC __sdcccall(1) для 4×uint8_t даёт:
|
||||
* sym_and в A, sym_xor в L, attr_and/attr_xor парой на стеке.
|
||||
*/
|
||||
|
||||
#include <mouse.h>
|
||||
|
||||
void mouse_text_cursor(uint8_t sym_and, uint8_t sym_xor,
|
||||
uint8_t attr_and, uint8_t attr_xor) __naked
|
||||
{
|
||||
(void)sym_and; (void)sym_xor; (void)attr_and; (void)attr_xor;
|
||||
__asm
|
||||
;; SDCC __sdcccall(1) для 4×uint8_t:
|
||||
;; arg1 sym_and → A
|
||||
;; arg2 sym_xor → L
|
||||
;; arg3 attr_and → младший байт пары на стеке
|
||||
;; arg4 attr_xor → старший байт пары
|
||||
pop iy ; адрес возврата
|
||||
pop bc ; C = attr_and (low), B = attr_xor (high)
|
||||
|
||||
push ix
|
||||
;; Цель: H=sym_and, L=sym_xor, D=attr_and, E=attr_xor, B=0
|
||||
ld h, a ; H = sym_and (из A)
|
||||
; L уже держит sym_xor
|
||||
ld d, c ; D = attr_and
|
||||
ld e, b ; E = attr_xor
|
||||
ld b, #0
|
||||
ld c, #0x0A ; CURSOR TEXT MODE
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
jp (iy)
|
||||
__endasm;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* mouse_video_mode_changed — сообщить драйверу мыши о смене видеорежима
|
||||
* (RST 30h, fn $81), чтобы он пересчитал отрисовку курсора. Звать
|
||||
* после settextmode()/gfx_init().
|
||||
*/
|
||||
|
||||
#include <mouse.h>
|
||||
|
||||
void mouse_video_mode_changed(uint8_t mode) __naked
|
||||
{
|
||||
(void)mode;
|
||||
__asm
|
||||
push ix
|
||||
;; A уже держит байт режима (SDCC __sdcccall(1)).
|
||||
ld c, #0x81 ; CHANGE VIDEO MODE
|
||||
rst #0x30 ; MOUSE
|
||||
pop ix
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
Reference in New Issue
Block a user