Сейчас есть следующие конфигурации с двумя окнами проецирования 0000 и c000:
1. LEC Memory Extension (1987)
2. MB02 (1992)
3. ATM2/2+ (1992/1993)
4. Схема fk0 для KAY, Pentagon, Scorpion (ZX-MMU) (2000)
5. Тестовая прошивка KOE для Pentagon 1024SL2.x (нижнее окно переключается по #fe) (2007)
6. ATM3 (2010)
[7. Тестовая прошивка LVD для NeoGS - для оси внутри NeoGS]

под что их лучше занять?
а) много данных задачи и много кода задачи (переключать задачи именно так) (как выводить на экран? через резидент или через функции оси?) (гонять данные из страницы в страницу тоже можно через резидент или функции оси)
б) много данных задачи и экран (большие программы делить на задачи, с общей памятью, придётся свопить код в нижней памяти)
в) много кода/данных задачи и экран (будет неудобно делать программы с плавающим числом страниц данных - доступ только через резидент или извратно - через куски кода в каждой странице данных)
г) много кода/данных задачи и отключаемая ось


Ос микрокерналь:
работает на 48к
нет устройств
нет фс
разметка нижней памяти учитывает дырку 16к в нужном месте
шедулер юзает хук доступа к записям (меняет драйвер страничной памяти)

драйвер пускать из-под шедулера? Неоткуда грузить (надо через снапшот).
И как переразметить нижнюю память? Только низ, без кучи?




На неАТМ можно выделять память блоками в нижнем ОЗУ (перемещаемый код и данные) и свопить эти блоки с верхней
памятью, если не хватает нижней. Если процесс хотя бы частично в свопе, при переходе на него надо его
восстанавливать.
Так можно до (48K минус размер ядра) нижней памяти на процесс, но переключение между большими процессами
более 1 фрейма (а между большим и маленьким - пропорционально размеру маленького).
Своп должен быть частью ядра, но выполняться в контексте процесса, иначе как предусмотреть 3-фреймовый своп, чтобы во время него периодически выполнялся пт плеер?
Этот метод назовём "СНДП" (своп нижней динамической памяти (НДП)) в отличие от "ПСО" (полностью страничная организация).
У СНДП, казалось бы, экономия страниц (многим программам не нужны страницы), но и в ПСО можно класть много процессов в одну страницу!
Ещё, если процесс обещает не использовать верхнюю память, то можно не щёлкать страницами при переключении на него, но вряд ли это экономия.

Ещё может быть метод "фрагментирование нижней динамической памяти" (ФНДП):
блоки внизу настолько маленькие (по одной процедуре), что при реальных сценариях нижняя память никогда не переполнится.
В нижней памяти при ФНДП только:
- функции работы с динамической памятью (их надо особо помечать в исходнике и проверять! pointer!=dynpointer!)
- стек (без проверки переполнения!)
- глобальные переменные
- системные буфера по 256 байт на файл/пайп
Thunk'и лучше не делать - нижней памяти не хватит. Поэтому вызовы между страницами - через функции оси.
Система без свопа, с ограниченной нижней памятью, превращающейся в решето при
закрытии программ, в принципе, может выполнять свои функции. Ошибка "недостаточно
нижней памяти" возникает только при запуске приложения, но может неожиданно
выскочить при выполнении шелл-скрипта!!!



Поскольку нижней памяти мало, то было решено разбивать программы на
модули, часть из которых предназначена для размещения в верхней
памяти, а оставшиеся в нижней и свопятся отдельно друг от друга
(а вот сегмент стека всегда присутствует в нижней памяти, если процесс
активен). Вызов
функции одного модуля из другого модуля - через специальную функцию
системы (с точки зрения программиста это может быть макрос FARCALL
name_of_function, который транслируется в вызов системы с передачей
2 параметров: номер модуля, номер/адрес функции).
Данные другого модуля использовать запрещается. Передача
информации от модуля к модулю - а) через регистры, б) через физические
страницы, в) через очереди (ld (de),a:inc e:call z,os_queue_put на передающей стороне и ld
a,(hl):inc l:call z,os_queue_get на принимающей).

Такие же очереди используются для межпроцессового обмена (например,
очередь событий от клавиатуры).
или лучше от клавиатуры передавать события, т.к. надо выдывать их сразу, не откладывая.
но тогда перенаправить из файла в терминал и наоборот - нетривиально.

через эти очереди можно организовать и файлы произвольного доступа,
они же массивы произвольного размера. Надо реализовать и возможность открытия
такого массива в верхней памяти (чтобы не переносить куски при каждой смене сегмента).
В нижней одновременно можно открыть их много, в верхней только один.
Пример верхнего массива - текст в sword, пример нижнего - таблица смещений для этого текста.
(по сравнению со старым sword'ом надо добавить в цикл вставки один call z, а в цикл удаления
bit:call z)
один и тот же файл/массив нельзя открывать сверху и снизу? а как тогда сделать эмулятор?
(там нижний массив - (PC)). надо п/п перечитывания нижнего буфера после изменения верхнего.
иначе нижний буфер (если в нём установлен флаг writeable) при выходе из него запишется
поверх (flush).

если открывать только снизу, то при произвольном доступе потеря времени 5000t на копию 256 байт + столько же при записи изменённого вверх (flush)
но нельзя открыть снизу дважды один файл (или придётся делать flush при изменении каждого байта)
sword лучше делать на двух файлах (разрезано по курсору), второй из файлов задом наперёд (если файловая система не позволяет уменьшать файл, то просто увеличиваем и игнорируем пустой хвост)
а эмулятор?



os_farcall_fromlow
;de,bc (или de,bc,ix,hl для мат.функций с long) = параметры вызываемой процедуры, на выходе в них результат
;hl(iy?) = calladdr
;a=callpg (нельзя свопить!)
call os_set_pg_a ;использует bc
jp (hl) ;iy?

_farcall_fromfarpg1
;de,bc (или de,bc,ix,hl для мат.функций с long) = параметры вызываемой процедуры, на выходе в них результат
;hl(iy?) = calladdr
;a=callpg (нельзя свопить!)
call os_farcall_fromlow
ld a,retpg1
jp os_set_pg_a ;использует bc
;это thunk, но их нужно немного (по одному на каждую страницу кода)





У PT player самый большой модуль лежит в странице и включает в себя массив размером 13-14K.

Часть модулей самого ядра со структурами - тоже страничные?

чего даст возможность передавать данные от задачи к задаче и от модуля к модулю через буфера в нижней памяти?
1. на 21 такт/байт ускорится вывод спрайтов
2. на 65 тактов/байт ускорится передача строки в процедуру другого модуля (и освободится 256 байт под буфер очереди)
 какие проблемы это вызовет?
1. как узнать, какие области не свопить? вызов с передачей буфера - через системную функцию?
2. как быть, если вызываемый модуль засвоплен и не поместится в ниж.ОЗУ ни до, ни после указанной области? переместить саму область?

Динамическая память (если она потребуется), реализуется не на уровне
системы, а на уровне программы пользователя?
Это невыгодно, т.к. жирная распределялка должна быть в нижней памяти у каждой программы - места может не хватить.
Система умеет динамически
выделять только целые страницы, а также очереди (очереди состоят из 256-байтных
сегментов, какие используются и для свопа).

Своп на диск возможен только на уровне драйвера страничной памяти.
Он выдаёт 2-байтные номера страниц, и программы работают с ними.
В простейшем случае (если нет свопа) это физический номер страницы, и
все переключения страниц работают максимально быстро.
Драйвер страничной памяти цепляется к нескольким хукам (физическим
адресам) операционной
системы - включение страницы, выдача страницы, освобождение страницы.















простое копирование между буферами произвольного доступа
для каждого сегмента буфера (256 байт) надо хранить его расположение: page, H
каждая таблица сегментов (256 байт) содержит 85 1/3 записей
таблиц сегментов может быть до 85, что даёт массив размером 256*(85 1/3)*85 байт
как быстро перейти к нужному месту буфера? для эмулятора это жизненно важно

...
copyloop
ld a,(hl)
inc l
call z,user_queue_get_lowmem
ld (de),a
inc e
call z,user_queue_put_lowmem
dec bc
ld a,b
or c
jnz copyloop
...

user_queue_get_lowmem
;должно менять только hl
ld (user_queue_get_lowmem_a),a
ld (user_queue_get_lowmem_bc),bc
exd
ld (user_queue_get_lowmem_de),hl
ld hl,(os_cur_pg)
ld (user_queue_get_lowmem_pg),hl
call os_queue_get_lowmem
user_queue_get_lowmem_pg=$+1
ld hl,0
call os_set_pg ;как было
user_queue_get_lowmem_de=$+1
ld hl,0
exd
user_queue_get_lowmem_bc=$+1
ld bc,0
user_queue_get_lowmem_a=$+1
ld a,0
ret

os_queue_get_lowmem
;de'=указатель на таблицу сегментов (надо бы её в верхнюю память)
;hl'=указатель на таблицу размещения таблиц сегментов (надо бы её в верхнюю память)
;а где хранить такие указатели для put-буфера???
exx
ld a,(de) ;pgL
inc e:call z,os_queue_get_lowmem_block
exx
ld l,a
exx
ld a,(de) ;pgH
inc e:call z,os_queue_get_lowmem_block
exx
ld h,a
exx
ld a,(de) ;H
inc e:call z,os_queue_get_lowmem_block
exx
call os_set_pg ;hl ;не раньше, т.к. os_queue_get_block мог включить другую страницу
ld h,a:ld l,e ;=0
ld bc,256
ldir
dec d ;начало буфера
ret

os_queue_get_lowmem_block
push de ;указатель на таблицу сегментов
ld e,(hl) ;pgL
inc l
ld d,(hl) ;pgH
inc l
exd
call os_set_pg ;hl
exd
pop de ;указатель на таблицу сегментов
push hl ;указатель на таблицу размещения таблиц сегментов
ld h,(hl) ;H
ld l,e ;=0
ld bc,256
ldir
dec d ;начало таблицы сегментов
pop hl ;указатель на таблицу размещения таблиц сегментов
inc l
ret



os_set_pg
;портит только bc
;никаких push нельзя!!!
;(можно push bc, если это 100% число:
;уровень стека, начиная с которого не релоцируем, записать в переменную,
;а при переключении процессов эту переменную класть в описатель процесса)
ld (os_cur_pg),hl
ld bc,memport1
out (c),h
ld bc,memport2
out (c),l
ret




17.12.2007
18:57        LordVader        ага и будет это виндофс виста для зх спецтрум        
LordVader        если свопить        
18:59        alone_co        иначе жестокие ограничения на число процессов        
alone_co        своп-то в озу        
19:00        alone_co        так что то не тормоз, а медленный газ        
LordVader        забей на неатм        
19:01        alone_co        какие процессы по-любому будут запущены: гуй, клава, шелл, редактор, клипборд        
LordVader        даже атм для мультитаскинга с трудом подходит        
LordVader        гуй - не будет!         
alone_co        на неатм не забьу низачто        
LordVader        редактор и клипборд тоже        
LordVader        тада "ты живёшь в своей голове"        
alone_co        гуй - это тупая вещь, просто переключающая задачи по шифт-ентер и раздающая фокус, клаву и сообщения прорисовки        
LordVader        http://www.6502asm.com/        
19:02        alone_co        а редактор - это то, ради чего всё начиналось        
alone_co        без гуя ничего работать не будет        
19:03        LordVader        точно в своей голове        
LordVader        для редактора придумывать хуйню аж со свопом (лдир туда лдир сюда)        
alone_co        у тебя другие идеи?        
19:04        LordVader        забить на своп        
LordVader        всем задачам дать память 4000-бффф а задачи в пагах        
alone_co        тогда память кончится быстро        
alone_co        один редактор жрёт кил 10        
19:05        alone_co        в минимальной комплектации        
LordVader        побей его на задачи!        
LordVader        на РАЗНЫЕ        
LordVader        с минимумом обмена        
alone_co        и чо это даст, если нет свопа        
19:06        LordVader        раскидать их по памяти это даст        
LordVader        по верхней        
alone_co        при ПСО требуется атм и памяти минимум по 16к на задачу        
LordVader        тебе 16кб не хватает - и 48кб тоже не хватит        
LordVader        даже со свопом        
LordVader        так что раскидывай на задачи        
19:08        alone_co        на задачи по-любому раскину        
alone_co        особенно при СНДП        
LordVader        редактору СРАЗУ вся память с техтом НЕ НУЖНА        
19:09        LordVader        потому ему рабочей памяти хватит 32к        
LordVader        а редактор сам по кускам на 16к разбить        
LordVader        и всё        
alone_co        память с текстом нужна БОЛЬШЕЙ части редактора        
LordVader        вся сразу? неверю        
alone_co        ибо там до фига функций        
LordVader        например        
19:10        alone_co        обработчики текста (в том числе поиск-замена), дисковые операции        
alone_co        навигация по тексту        
alone_co        вывод текста        
alone_co        печать        
alone_co        конверторы        
LordVader        это всё построчно работает        
19:11        alone_co        нет        
LordVader        потому без страниц с текстом обойдётся        
alone_co        это в ацедит построчно        
alone_co        а в сворде нет        
alone_co        иначе опять ограничение на длину строки        
alone_co        кстати, и в ацедит не всё построчно        
alone_co        поиск-замена и конверторы - не построчно        
alone_co        и форматирование тоже        
19:12        alone_co        то, что текст должен быть в страничной памяти - очевидно        
alone_co        а к нему будут стучаться разные процессы        
19:13        LordVader        ага а их лдирить будут туда-сюда        
LordVader        для 1 байта текста 10кб лдира        
alone_co        ну, лдирение сетупа, например, ничего страшного        
alone_co        и вообще лдирение менюшек        
alone_co        а уж конверторы и без того не только лдирятся, но и депачатся в ацедите        
alone_co        плеер пт вот желательно не лдирить        
19:15        alone_co        либо в верхнюю его, либо защитить от свопа как-то        
alone_co        гуй тоже надо защитить от свопа как-то        
alone_co        проблема, что выделять НДП требуется нефрагментируемыми кусками        
alone_co        защищённые от свопа растут снизу, а незащищённые - сверху        
LordVader        вот тебе критерий оценки. придумал кучу фич.а теперь пощитай СКОРОСТЬ РАБОТЫ        
LordVader        и сравни с другим вариантом.        
alone_co        с ПСО?        
19:20        alone_co        а как под него программы писать?        
alone_co        всё ли можно там реализовать?        
alone_co        в редакторе скорость одинаковая        
alone_co        а вот на ПСО невозможно больше 61 процесса        
alone_co        одновременно запустить        
19:23        alone_co        ибо страниц всего 64        
LordVader        а ПСО это что?        
19:25        alone_co        полностью страничная организация        
alone_co        то есть нижняя память тоже выделяется страничкой        
alone_co        это реально только на атм


работу с текстом лучше сделать через файлы в памяти (с 256-байтным системным буфером внизу)





а)
ld hl, ;сегмент*2
ld a, ;смещение
jp longjump
...
longjump
;hl=смещение в массиве
;pg=*hl++
;h=*hl
ld l,a
;десвопить pghl
jp (hl)


*hl из массива, начинающегося с произвольного сегмента:
;карта - сегмент, адресует 64К-блоки
;64К-блок - сегмент, адресует сегменты массива
;сегмент массива - если пропускать проход по карте, то надо буферизировать в нижней памяти!!! лучше не пропускать, ибо доступ произвольный!!! для последовательного доступа есть пайпы
