Войти
ФлеймФорумЖелезо

Блеск и нищета 8/16-битных консолей и ПК (58 стр)

Страницы: 157 58 59 6064 Следующая »
#855
(Правка: 14:44) 14:41, 26 янв. 2020

innuendo
> помню в 95-96 был такой форт в protected mode
Smal32?
Автор, правда, забил на проект и сайт, и не открыл исходники даже в историческом интересе (и по почте недоступен). :)

P.S.  http://www.forth.ru/smal32.html
http://www.forth.org.ru/~cactus/smal32.htm


#856
15:30, 26 янв. 2020

KPG
> innuendo
> > помню в 95-96 был такой форт в protected mode
> Smal32?
> Автор, правда, забил на проект и сайт, и не открыл исходники даже в
> историческом интересе (и по почте недоступен). :)

Скорее всего опечатка: не форт, а форк (fork).  Нет, в Чикаге (Win95, Win98) ДОС-программам никаким способом нельзя в 32 бита кроме DPMI.  Flat Unreal Mode работал только в чистом ДОС'е.

#857
15:50, 26 янв. 2020

Попробовал поискать другие реализации многопоточности на ZX Spectrum и первая же ссылка вывела на забавную тему где человек вспоминает как делал это в детстве: https://www.linux.org.ru/forum/talks/12579983
И меня привлекло вот что:

Вплоть до того, что я запускал 3 программы: одна играла музыку, воторая гоняла по экрану точку, которая отпрыгивала от занятых пикселей и от краёв экрана, а третьей была сама среда программирования бейсик встроенная в ZX. Забавно было наблюдать, как точка отпрыгивала от набираемого мной текста на бейсике.

Оппа, подумал тут уже я. А ведь это интересная идея - что если основной поток выполнения отдать обратно бейсику?
Сказано - сделано!
Во первых - диспетчер потоков по прерыванию уже реально сохраняет теневые регистры, ибо уже без этого тут никак. Для краткости серии push и pop всех регистров распиханы по макросам, т.к. неоднократно используются.
Во вторых - раз мы отняли изначально прерывание у бейсика тут уже нужно ему опять его возвращать. Но только если мы в основном потоке. Поэтому диспетчер потоков проверяет не находится ли он в последнем (основном) потоке по счёту и если да, то не выходит из прерывания сразу, а прыгает на обработчик прерывания в ПЗУ бейсика ($0038).
Ну и для красоты сделал потоки такими:
1) первый инкрементирует как можно быстрее слово в начале пикселей памяти - они просто мельтешат, т.к. это очень быстро
2) второй увеличивает цвета всех знакомест на 1 в цикле но увеличив их все засыпает (т.е. отдаёт квант времени следующему потоку)
3) третий и основной - просто возвращает управление в бейсик
+ полный исходный код

Получилось настолько забавно, что записал видео с процессом:

На видео может быть не так заметно, но скорость работы бейсика реально снижена более чем в 2 раза, т.к. время как минимум полноценно делится с первым потоком, да и обновление цветовых атрибутов хоть и отдаёт квант времени, но сколько-то времени у него отнимает тоже.
Поэтому та же отзывчивость нажатия кнопок тоже серьёзно снижена.
Радуга идёт волнами просто из-за коллизий между фоновым потоком (он обновляет экран весь за раз) и перетиранием атрибутов бейсиком.

#858
10:02, 27 янв. 2020

Gradius
> Скорее всего опечатка: не форт, а форк (fork).

именно форт https://subscribe.ru/archive/comp.soft.prog.forth/200512/09151433.html

#859
7:37, 28 янв. 2020

К вопросу об оптимизациях.
Если посмотреть на код который я парой сообщений выше запостил, то в нём исповедуется такой подход: в буфер задач context_table добавляются контексты новых потоков начиная с нулевого индекса, а в конце последним добавляется (проще всего, но всё же тоже добавлением в таблицу) текущий основной поток. Он же в примере этом возвращается в бейсик и поэтому проверка в диспетчере задач не является ли текущий поток потоком бейсика чтобы вернуть управление в конце на обработку прерывания бейсика довольно громоздка.
Это заставило задуматься - а почему бы собственно основной поток не поместить в самое начало таблицы контекстов, ведь на начало проверить проще.
И это размотало прям несколько оптимизаций.
Там где было:

                org $8000
irq_table       block 257, $81  ; таблица векторов прерываний (адрес $8181)
active_context  dw 0            ; указатель на текущий контекст
context_end_low db low context_table    ; нижний байт конца таблицы контекстов
contexts_tmp    dw 0                    ; пока времянка для старого sp для add_task
context_table                           ; таблица контекстов (чуть меньше $80 байт)
стало
                org $8000
irq_table       block 257, $81      ; таблица векторов прерываний (адрес $8181)
active_context  dw context_table    ; указатель на текущий контекст
context_end_low db low context_table + 2    ; нижний байт конца таблицы контекстов
contexts_tmp    dw 0            ; пока времянка для старого sp для add_task
context_table                   ; таблица контекстов (чуть меньше $80 байт)
Т.е. мы сразу в active_context ложим указатель на нулевой элемент context_table и, соответственно, конец массива увеличиваем на 2 байта. Это нам ничего не стоит в плане операций - просто в переменные сразу положили нужные значения, которые раньше инициализировала (и по другому) процедура start_tasks.
Из-за того что контекст основного потока перекочевал в самое начало таблицы сперва упростился код находимся ли мы в нём в irq_handler, было:
                ld a, (active_context)
                add a, 2
                ld b, a
                ld a, (context_end_low)
                cp b
                jp z, .ret_to_basic
стало:
                ld a, (active_context)
                cp low context_table
                jp z, .ret_to_basic
Логично. Но теперь еще когда мы доходим до процедуры start_tasks, то оказывается что таблица уже заполнена как надо, поэтому было:
start_tasks     di                      ; отключим прерывания
                push hl                 ; сохраним hl
                ld a, (context_end_low)
                ld h, high context_table
                ld l, a                 ; hl = указатель на новый контекст
                add a, 2
                ld (context_end_low), a ; context_end_low += 2
                ld (active_context), hl ; делаем активным контекст текущего потока
                pop hl                  ; восстанавливаем hl чтобы не портить
                ld a, high irq_table
                ld i, a                 ; загружаем в i адрес таблицы векторов прерываний
                im 2                    ; активируем режим прерываний 2
                ei                      ; включим прерывания
                ret
стало:
start_tasks     di                      ; отключим прерывания
                ld a, high irq_table
                ld i, a                 ; загружаем в i адрес таблицы векторов прерываний
                im 2                    ; активируем режим прерываний 2
                ei                      ; включим прерывания
                ret
Как раз полностью ликвидирован код обновляющий таблицу между push/pop hl включительно, ибо всё уже заполнено как надо.
Вот так бывает от перестановки пары байт программа резко упрощается. :)

#860
10:25, 28 янв. 2020

Нуууу... тоже, можно сказать, что про 8-bit

+ Показать
#861
11:50, 28 янв. 2020

0iStalker

Кое как понял как он должен защёлкиваться.

#862
13:28, 28 янв. 2020

Всё, решено, в следующее свободное для себя время поделаю что-нибудь на Famicom/NES/Денди.
Оказывается есть среда программирования Nesicide, где почти всё что нужно для разработки включено сразу - и CC65 (вместе с ассемблером CA65), и FamiTracker и эмулятор не понял на базе чего и среда разработки с подсветкой асма и даже при создании нового проекта рабочий "Hello, world!" сразу готов, так что прям остаётся только сесть и поковыряться.
А это я люблю. :D

#863
(Правка: 0:40) 0:28, 29 янв. 2020

=A=L=X=
> так что прям остаётся только сесть и поковыряться.
> А это я люблю. :D
:)
Не "ковырялся" ли процессор Saturn применяемый в программируемых калькуляторах линейки HP?
  Первый раз он был установлен в "калькулятор" HP-71B (84год) и лишь годами позже был заменён на ARM и эмуляцию данного процессора при сохранении базы ПО калькуляторов от HP.
(зверёк должен быть достаточно интересен по архитектурным решениям)

P.S. Забавно, что вместе с прошитым Бейсиком для данного калькулятора был сделан штатно и Форт для загрузки с модуля и сопряжённого с Бейсиком по взаимодействию.
Сейчас для последних калькуляторов пилят и "новый" язык программирования - New RPL с полной реализацией фирмваре на С для ARM железа.  https://sourceforge.net/projects/newrpl/

 
 

#864
4:54, 29 янв. 2020

KPG
> Не "ковырялся" ли процессор Saturn применяемый в программируемых калькуляторах
> линейки HP?

Нет, такого не доводилось. В основном я иду по игровым консолям и домашним компьютерам и в темах "блеск и нищета..." тут на форуме большую часть из того что наковырял интересного можно прочитать.

#865
(Правка: 16:26) 6:17, 29 янв. 2020

Игры на калькуляторе HP-48G(X) :) (с исходниками и видосиками)
http://jadegame.com/games/hp48

P.S. Процессор Saturn при разрядности основных регистров 64-е бит команды 4/8 битные.

#866
(Правка: 19:31) 19:29, 29 янв. 2020

Чуток освоился на Famicom/NES/Денди в среде программирования Nesicide.
Прикольно. На самом деле всё не так сложно как я раньше думал.
Помнится меня сильно отталкивали две вещи:
1. описание того как делается прокрутка экрана в очень старом и известном мануале прям напрягало - говорилось что делать это надо обязательно через регистр PPU "PPUADDR" - адрес байта в VRAM куда CPU может записать байт через порты ввода-вывода, но оказалось это миф развенчанный на http://nesdev.com. На самом деле всё просто - есть логичный порт PPUSCROLL и через него всё делается легко. PPUADDR на самом деле во время активной фазы работы PPU по построению кадра, как я понял активно юзается как некий текущий адрес строящегося изображения и поэтому возможно к нему надо будет вернуться в этом плане в сложных случаях HBlank-отсечения, но для простых штук такие сложности излишни.
2. архитектура процессора 6502 никогда мне не нравилась - прям отвращала. всего 3 регистра, убогий стек, всё насквозь 8-битное. по сравнению со знакомым с детства Z80 это всё казалось каким то убожеством и представлялось, что программировать в этом будет еще тем геморроем.
но на деле нужно было просто перестроить себя по архитектуру машин 60/70-х годов: архитектура часто описываемая как аккумулятор-память.
надо подавить в себе желание как можно больше всего хранить в многочисленных регистрах как у Z80 - нет их тут и всё тут - а аккумулятор воспринимать только как место хранения промежуточного результата между памятью и памятью, причём хранимого лишь миг. сразу мозги вправляются и становится понятно как на этом программировать - берешь и программируешь. нюансы и неудобства конечно есть, но после главного перелома сознания они уже непринципиальны. можно тут программировать, можно.

Опять зреет чувство что захочется подробно описать как в этом всё быстро и просто напрограммировать что-то описывая свой опыт... На деле есть конечно подводные камни и непросто найти вменяемый курс даже на английском.

#867
9:48, 30 янв. 2020

Мда, Nesicide всё-таки далека от совершенства.
Уже обнаружил критические недоработки.
Как ни бился - кириллицу не поддерживает, комментарии на русском исключены. Для меня критично.
Стоит только разбрасывать код по нескольким файлам - отладчик начинает чудить и на каждый запуск открывать по нескольку окон одного и того же исходника куда пытается спозиционироваться, но не получается каменный цветок. Печально. Это сводит многое тоже на нет. В одном файле программировать ненапряжно только совсем уж маленькие примеры.
В общем походу надо будет переползать на ручную инвокацию ca65 по другим примерам. Хм. Посмотрим...

#868
(Правка: 10:15) 10:13, 30 янв. 2020

=A=L=X=
> ca65

https://github.com/camsaul/nesasm
www.magicengine.com/mkit/

#869
10:20, 30 янв. 2020

0iStalker
> www.magicengine.com/mkit/

Что-то совсем уж старое, 2000 года последнее обновление и архив для DOS (!).
Не, проще уж взять просто cc65 и из него заюзать все утилиты как это делает Nesicide и многие другие примеры в инете которые можно найти.

Страницы: 157 58 59 6064 Следующая »
ФлеймФорумЖелезо