Результаты поиска по запросу

Дополнительные фильтры
Теги:
новый тег
Автор поста
Рейтинг поста:
-∞050100200300400+
Найдено: 61
Сортировка:

История видеоигр, часть 32: Air-Sea Battle (1977)

ata ni 7600 VIDEO GAME
ATARI aVW cartridge
ÄIR-SEA BATTLE,старые игры,Atari 2600
Могу себе представить радость маленького милитариста из семидесятых, когда родители вручали ему картридж с Air-Sea Battle для новенькой Атари VCS. Бомбардировщики, зенитки, истребители, вертолёты, дирижабли, линкоры и картонные уточки из тира -- всё это умещалось в одной маленькой коробочке, рассортированное на 27 игр.
,старые игры,Atari 2600
Которые, в свою очередь, были организованы в шесть тематических групп. В первой игрок или игроки отстреливали воздушные цели из стационарных орудий. Во второй -- управляли подвижными субмаринами, которые атаковали торпедами проплывающие корабли. Как обычно в случае с ранними аркадами, единственная цель в любом варианте Air-Sea Battle -- набрать счёт больше, чем у соперника.
,старые игры,Atari 2600
Дирижабли (или воздушные шары) с литерой А стоят 0 очков и
только мешают стрельбе.

Далее по списку игрокам представлялась возможность поуправлять ружьём в тире, кораблём и бомбардировщиком. Некоторые поздние вариации игры были устроены в виде дуэли, где игрокам приходилось выбивать очки друг из друга.
,старые игры,Atari 2600
Тир. Кролики, уточки и клоунские рожицы.
Журнал Video назвал Air-Sea Battle ультимативной игрой для любителей взрывать всё подряд, прочая игровая пресса тоже не скупилась на оценки. Конечно, старушке не тягаться с играми на современных платформах, но держится она достаточно бодро. И бонусный факт: Air-Sea Battle была первой игрой от Ларри Каплана, одного из сооснователей Activision.

Уроки ОСдева №3: блок параметров BIOS

В прошлый раз мы разобрались с физической геометрией дискеты и расположением данных. Кроме того, мы узнали, как записать программу-загрузчик в нулевой сектор носителя. Если кто-то из вас действительно пытался повторить мои действия и потом использовать дискету как загрузочную, то наверняка обнаружил два неприятных момента:

1. При попытке открыть образ дискеты Wndows говорит, что она не отформатирована.
2. BIOS не воспринимает дискету как загрузочную и пишет что-нибудь вроде "no bootable device found".
Давайте разбираться. Если помните, в конце прошлого поста наша будущая программа-загрузчик выглядела так:
.386p
CSEG segment use16
ASSUME cs:CSEG, ds:CSEG, es:CSEG, fs:CSEG, gs:CSEG, ss:CSEG
begin:                    cli
                             hlt
CSEG ends
end begin

По сути это просто заглушка, которая при запуске должна останавливать процессор. Причина ругани Виндоус в том, что в нулевом секторе на отформатированном носителе хранится важная структура данных - блок параметров BIOS (BPB). Записав туда же нашу программу, мы его пот+ёрли. Для того, чтобы этого избежать, нам придётся воссоздать BPB в тексте программы. Для этого нужно знать геометрию носителя. К счастью, в наше время сохранился только один тип дискет.

Непроверенный метод: возможно, если с помощью утилиты debug записать программу не в начало сектора, а со смещением, достаточным, чтобы пропустить оригинальный BPB, то он не пострадает, но я не проверял. По-моему, debug всё равно забьёт остатки сектора каким-то мусором.

Во-первых, измените программу вот так:

.386p
CSEG segment use16
ASSUME cs:CSEG, ds:CSEG, es:CSEG, fs:CSEG, gs:CSEG, ss:CSEG
begin:                     jmp short execute
                             nop
execute:                 cli
                             hlt
CSEG ends
end begin

У нас появились две новые инструкции: jmp short и nop. Последняя - просто пустой оператор. Процессор пропускает его, не выполняя никаких действий. Занимает 1 байт. jmp - инструкция перехода. jmp short - переход в пределах 127 байт от текущего положения. Исполняется гораздо быстрее jmp, так что везде где возможно - используйте его. Занимает 2 байта. execute - название метки, на которую указывает инструкция jmp short.

Зачем всё это и зачем nop? BPB должен располагаться строго в трёх байтах от начала нулевого сектора. Эти три байта и занимают инструкции jmp short execute и nop. Таким образом, когда программа начнёт исполняться, первой инструкцией, которую выполнит процессор, будет пропустить BPB. В противном случае он бы попытался исполнить его как код, что привело бы к катастрофе.
Теперь давайте вставим сам блок параметров BIOS между nop и меткой execute.

.386p
CSEG segment use16
ASSUME cs:CSEG, ds:CSEG, es:CSEG, fs:CSEG, gs:CSEG, ss:CSEG
begin:                     jmp short execute
                             nop

                BPB_OEMname          db    'BOOTDISK'
                BPB_bytespersec       dw    512
                BPB_secperclust        db     1
                BPB_reserved            dw    1
                BPB_numFATs           db     2
                BPB_RDentries          dw    224
                BPB_sectotal             dw    2880
                BPB_mediatype         db     0F0h
                BPB_FATsize             dw     9
                BPB_secpertrack        dw     18
                BPB_numheads         dw     2
                BPB_hiddensec          dd     0
                BPB_sectotal32          dd     0
                EBPB_drivenum         db     0
                EBPB_NTflags            db     0
                EBPB_extsign            db     29h
                EBPB_volID               dd     0
                EBPB_vollabel            db     'BOOTLOADER '
                EBPB_filesys              db     'FAT12   '

execute:                 cli
                             hlt

CSEG ends
end begin

BPB - это блок данных, и здесь мы впервые объявляем переменные. В TASM это выглядит так: BPB_OEMname (имя) -пробел- db, dw, dd или dq -пробел- 'BOOTDISK' (значение). Имени может и не быть, но тогда к переменной нужно будет обращаться по смещению, это не очень удобно. DB, DW, DD и DQ - сокращение от define byte (word, double word или quad word) - обозначают размер переменной. Соответственно, 1, 2, 4 или 8 байт. Инстркция этого типа позволяют объявлять целые серии значений через запятую: myvalue dw 2, 5, 165, 776. С помощью инструкции db можно объявлять строки: mytext db 'Allo, Yoba!' Обратите внимание, что в плоском бинарнике переменные при компиляции не выносятся в какую-то специальную область данных. В исполняемом файле они будут именно там, где вы их объявили в тексте программы. Ещё важный момент: имена переменных только для вашего личного пользования, в исполняемый файл они не попадут, так что вы не обязаны копировать названия у меня. Теперь давайте посмотрим, что за информация хранится в BPB.

BPB_OEMname - 8 байт: по идее здесь должно быть название производителя, но по факту вы можете писать что угодно, никто на это значение не смотрит.
BPB_bytespersec - 2 байта: размер сектора в байтах, для дискет как правило 512.
BPB_secperclust - 1 байт: число секторов в кластере. Про кластеры мы поговорим позже, но в случае с дискетами секторы и кластеры соответствуют друг другу.
BPB_reserved - 2 байта: число зарезервированных секторов, недоступных файловой системе. В нашем случае такой один, это наш загрузочный сектор.
BPB_numFATs - 1 байт: количество FAT (file allocation table), таблиц распределения файлов. Так как носители информации (особенно дискеты) подвержены порче, а FAT - очень важная часть файловой системы, для неё часто делается резервная копия.
BPB_RDentries - 2 байта: количество записей в корневой директории (Root Directory). Про корневую директорию тоже будем говорить в другой раз, но пока можете представить её как список файлов с указанием их физического расположения на носителе.
BPB_sectotal - 2 байта: число секторов на диске, если их не больше 65535. Если больше, здесь должен быть 0.
BPB_mediatype - 1 байт: тип носителя. F0 - код для 3,5-дюймовой дискеты с 18 секторами в дорожке.
BPB_FATsize - 2 байта: размер одной FAT в секторах.
BPB_secpertrack - 2 байта: число секторов в дорожке.
BPB_numheads - 2 байта: число головок.
BPB_hiddensec - 4 байта: количество скрытых секторов перед загрузочным, в нашем случае 0.
BPB_sectotal32 - 4 байта: число секторов, если их больше 65535. Если меньше, здесь должен быть 0.

Здесь стандартный BIOS Parameter Block заканчивается и начинается расширенный, который появился в поздних версиях DOS.

EBPB_drivenum - 1 байт: бесполезная переменная, хранящая номер привода, в который был вставлен носитель при форматировании.
EBPB_NTflags - 1 байт: флаги Вин НТ. Если установлен бит 0, необходимо проверить носитель на битые секторы. Значения других флагов не знаю.
EBPB_extsign - 1 байт: признак расширенного BPB. Для нашей версии должно быть 29h.
EBPB_volID - 4 байта: случайный номер, который присваивается при форматировании. В общем бесполезен.
EBPB_vollabel - 11 байт: имя носителя.
EBPB_filesys - 8 байт: имя файловой системы.

Если вы теперь заново скомпилируете программу и запишите на дискету, то она отлично откроется в Windows. Первая проблема решена, но осталась вторая: дискета всё ещё не опознаётся как загрузочная. Вспоминаем: для этого последние 2 байта загрузочного сектора должны иметь значения AAh и 55h. Добавим ещё две строчки в нашу программу:

.386p
CSEG segment use16
ASSUME cs:CSEG, ds:CSEG, es:CSEG, fs:CSEG, gs:CSEG, ss:CSEG
begin:                     jmp short execute
                             nop

                BPB_OEMname          db    'BOOTDISK'
                BPB_bytespersec       dw    512
                BPB_secperclust        db     1
                BPB_reserved            dw    1
                BPB_numFATs           db     2
                BPB_RDentries          dw    224
                BPB_sectotal             dw    2880
                BPB_mediatype         db     0F0h
                BPB_FATsize             dw     9
                BPB_secpertrack        dw     18
                BPB_numheads         dw     2
                BPB_hiddensec          dd     0
                BPB_sectotal32          dd     0

                EBPB_drivenum         db     0
                EBPB_NTflags            db     0
                EBPB_extsign            db     29h
                EBPB_volID               dd     0
                EBPB_vollabel            db     'BOOTLOADER '
                EBPB_filesys              db     'FAT12   '

execute:                 cli
                             hlt

               org 510
                dw 0AA55h

CSEG ends
end begin

Команда org 510 заполнит нулями место от текущей позиции до 510 байта, а в последние два мы поместили метку загрузочного сектора. Вуаля, проблема 2 решена.

Выражалось мнение, что всё это ебучее легаси и современные пацаны предпочитают UEFI, но UEFI не даст вам того интимного, я бы сказал, понимания железа, на котором работает ваша ось, так что основная серия будет продолжена по старинке.

Нужны ли туторы по UEFI?
Да
88(69,29%)
Нет
8(6,3%)
Я не знаю, заебал свою гиковскую xуйню сюда постить, вали на гитxаб!
31(24,41%)

История видеоигр, часть 37: Human Cannonball (1978)

Сегодня, дорогие читатели, мы поднимем животрепещущую тему игрового насилия. Задолго до Doom и Mortal Kombat была игра, которая заставила задуматься: не примеряем ли мы корону бога? Не слишком ли большую ответственность мы берём на себя, оказывая влияние на хрупкую психику игрока? Игра эта называлась Human Cannonball и была разработана Оуэном Рубином для игровых автоматов. Концепция её была проста: есть пушка, есть стена с отверстием. Регулируя наклон пушки и мощность выстрела, игрок должен был сделать так, чтобы заряженный в пушку человек попал в отверстие. Если игрок ошибался, человек-ядро со смачным шлепком разбивался о стену. Однако начальству Рубина идея показалось дикой и слишком жестокой, и проект свернули. Лишь через два года, когда нравы в мире пришли в достаточный упадок, Atari решилась выпустить Human Cannonball на домашней консоли Atari 2600.
gome program'"
HUMAN CANNONBALL
Use with Joystick Controllers,Игры,старые игры,atari,Atari 2600
Просто вглядитесь в эту полную боли фальшивую улыбку.
Human Cannonball предлагает вам попробовать себя в роли циркового трюкача, стреляющего собой из пушки. Судя по всему, авторы оставили за кадром выступление и овации, показав вместо этого суровую процедуру пристрелки орудия.
,Игры,старые игры,atari,Atari 2600
Телесного цвета штука на шестах - сеть или корзина.
Попадание в цель зависит от трёх факторов: скорости полёта, угла наклона и положения пушки. Как водится на Atari 2600, в Human Cannonball есть куча вариантов игры. В одних игрок может регулировать скорость полёта, в других угол, в третьих -- двигать саму пушку. Остальные параметры или фиксированы или меняются случайным образом от выстрела к выстрелу. На поздних этапах на радость маленьким и взрослым садистам между пушкой и целью появляется стена с отверстием, которое ездит туда-сюда.
,Игры,старые игры,atari,Atari 2600
Недолёт.
На всё про всё игроку даётся 7 попыток. Каждое попадание в корзину приносит одно очко, а цель игры, разумеется, набрать максимальный счёт и похвастаться друзьям.

Управление в игре чрезвычайно простое, но авторы как-то ухитрились напортачить. При удержании джойстика в одном направлении значения угла и скорости проматываются слишком медленно, а на одиночные нажатия игра иногда вообще не реагирует.
,Игры,старые игры,atari,Atari 2600

Оценивать звук в играх для Atari 2600 бессмысленно, а вот графически игра выделяется. Это не шедевр, но, поймите правильно, когда на этой платформе спрайт человечка похож на человечка, а пушки на пушку -- это уже успех! Как это ни удивительно, но Human Cannonball не сгинула в безвестности. С 2010 года игра доступна на Windows и Xbox в составе Microsoft Game Room. А что касается Оуэна Рубина, то он позже отметился ещё одним человеконенавистническим хитом про экстремальный спорт.
,Игры,старые игры,atari,Atari 2600

История видеоигр, часть 18: Night Driver (1976)

,Игры,старые игры,игровой автомат,обзор

Night Driver - игра о безответственном водителе, мчащемся тёмной ночью по извилистой трассе с явной целью совершить [роскомнадзор]. Кроме того, это одна из первых гоночных игр с видом от первого лица. Оригинальный аркадный автомат с рулём, педалями и рукояткой переключения передач был разработан в 1976 году фирмой Micronetics. Позже игра была портирована на Atari 2600 (1980) и Commodore 64 (1982).

HIGH	SCORE	OOO	TOP	SPEED	0 0 0
				ATARI	
YOUR	SCORE	1 31	TOP	SPEED	21 1
		i ,J	,,		
		1	1		
		1	1		
I	I,Игры,старые игры,игровой автомат,обзор

Сегодня поиграть в первую версию Night Driver можно, например, с помощью эмулятора MAME, хотя экспириенс будет странным: на экран игрового автомата клеился пластиковый капот машины, что позволяло почувствовать её габариты. В эмулированной версии его, конечно, нет, и ощущения от управления невидимым авто -- необычные.

YOUR SCORE	074	TOP	T IME SPEED	033 1 59
i l	- '■	1 1 1		
	1	1		
1		1		
I,Игры,старые игры,игровой автомат,обзор

Night Driver предлагает на выбор три трассы, различающихся крутизной и частотой поворотов. Цель игрока - набрать как можно больше очков за отведённый промежуток времени. Чем быстрее едет игрок - тем быстрее растёт счёт. Столкновение с ограждением не заканчивает гонку, а просто останавливает машину. После набора 350 очков игрок получает дополнительное время. После 1000 счёт обнуляется, так что умелый гонщик может продлевать заезд не один раз. Как видно на скриншотах, оформление игры более чем аскетично. Это не неудачные кадры, вы действительно не увидите ничего, кроме столбиков ограждения. Нет соперников, нет окружения, только дорога, игрок и тикающий таймер. Звуковое сопровождение под стать: монотонный гул мотора, который через минуту начинаешь воспринимать как абсолютную тишину, изредка нарушает только визг покрышек при особенно крутом повороте. Хотя в вышедшем 4 года спустя порте для Atari 2600 уже были элементы окружения и даже другие авто, от которых надо было уклоняться.

YOUR SCORE 125
T IME TOP SPEED
01 2 21 1
I
I
I
■,Игры,старые игры,игровой автомат,обзор

При всей минималистичности оформления игра оставляет приятное впечатление. Трасса движется плавно, а белые прямоугольники при наличии воображения действительно напоминают подсвеченные фарами светоотражающие столбики ограждения.

Оригинал: https://silicondarwin.blogspot.com/2017/03/night-driver-1976.html

История видеоигр, часть 33: Indy 500 (1977)

game program'"
INDV 500
Use with Driving Controllers,старые игры,Atari 2600
Недавно я писал про Street Racer, которая, как и Indy 500, была одной из стартовых игр для Atari 2600. В конце статьи я сделал игре скидку из-за новизны системы и отсутствия у автора опыта работы с ней. Это было до того, как я увидел Indy 500. Теперь я беру свои слова обратно -- на Atari 2600 уже тогда можно было реализовать динамичную и графически привлекательную гоночную игру, просто приняв правильные дизайнерские решения.
,старые игры,Atari 2600
Ларри Каплан жаловался, что не смог сделать плавный скроллинг трассы в Street Racer -- в Indy 500 вся трасса умещается на одном экране и скроллинг не нужен.
В Street Racer нет ощущения скорости -- в Indy 500 машина ускоряется, тормозит и дрифтует так, что через несколько минут игры начинаешь чувствовать её массу и инерцию.
В Street Racer машина управляется как пушка из Space Invaders -- Indy 500 поддерживает аналоговый контроллер и плавное вращение спрайтов.
,старые игры,Atari 2600
В Indy 500 почти в два раза меньше вариантов игры, чем в Street Racer, но это тот случай, когда качество победило количество.
,старые игры,Atari 2600
Эта трасса называется Devil's Elbow, Локоть Дьявола.
Я не смог проехать ни одного круга без десятка-другого
вылетов на обочину.

Эд Риддл при создании игры вдохновлялся гоночным событием под названием Indianapolis 500, знакомому многим любителям заездов на скорость. В отличие от прототипа, Indy 500 не ограничивается нарезанием кругов наперегонки. Кроме традиционных гонок тут  есть состязание по сбиванию призовых коробок, "автосалочки" и гонки на льду со "скользкой" физикой.
,старые игры,Atari 2600
Здесь моя задача -- протаранить как можно больше голубых коробок,
пока не истекло время. Каждый раз, когда я наезжаю на цель, мне
засчитывается очко, а цель появляется в другом месте.

В каждую из представленных игр можно сыграть как с другом, так и одному, наперегонки с таймером. Единственная обязательно парная игра -- салочки, но и тут соперника может заменить компьютер.
,старые игры,Atari 2600
Моя машина (жёлтая) сейчас мигает, поэтому её не видно на скриншоте.
Это значит, что я должен убегать, а игрок в синей машине -- пытаться
меня догнать.

,старые игры,Atari 2600
Эта ледяная трасса выглядит проще остальных, но на деле игроку,
не освоившему управляемых заносов, здесь придётся туго.

Indy 500 можно со спокойной совестью рекомендовать всем любителям ретрогейминга. Она не пытается прыгнуть выше головы и не ломает представления о возможностях системы. Это просто качественная и разнообразная для своего времени игра. И в отличие от Street Racer, где было всё что угодно кроме стритрейсинга, Indy 500 -- действительно про гонку Индианаполис 500.

История видеоигр, часть 17: Blockade (1976)

by ôrcmlrn,Игры,старые игры,обзор,игровой автомат

У кого из вас, читатели, был телефон Nokia 3310 или что-то из той же эпохи? Помните игру "змейка"? Вот откуда она произошла:

,Игры,старые игры,обзор,игровой автомат
В игре использовался чёрно-белый дисплей, зелёным
картинку делала наклеенная поверх плёнка-фильтр

Компания Gremlin, которая до того занималась механическими аркадными автоматами, в 1976 году решила выйти на рынок видеоигр. Дебютным проектом стала игра Blockade для двоих игроков. При помощи четырёх направляющих кнопок каждый управлял стрелкой, оставляющей за собой кирпичную стену. Как и в "змейке", стрелки всегда находились в движении, игрок мог только менять его направление. В отличие от "змейки", хвост каждого игрока всегда оставался в стартовой точке, т.е. стена просто закрашивала пройденный игроком путь. Первый игрок, столкнувшийся со стеной (своей или чужой), проигрывал. Партия продолжалась 6 раундов.

♦
GAME
OUER
•fr,Игры,старые игры,обзор,игровой автомат

Интересно, что в Blockade не было "змеиной" тематики, хотя многие из появившихся позже подражателей ею прониклись. Возможно, дело в странном выборе цветофильтра: зелёная накладка действительно делала кирпичные стены в игре похожими на чешуйчатых змей.

,Игры,старые игры,обзор,игровой автомат

Урок ОСдева №7: первичный загрузчик, финал.

В прошлый раз мы написали процедуру загрузки данных и использовали ее для того, чтобы 
поместить корневую директорию нашей дискеты в оперативную память сразу после собственно
программы-загрузчика по адресу 07C0h:0200h. План действий на сегодня:

-Найти в КД номер первого кластера файла.
-Загрузить первый кластер.
-Следуя по цепочке записей в FAT, загрузить остальные кластеры.

Перед тем, как кодить дальше, давайте  разберёмся, что такое КД и как её использовать для
поиска файлов*.

По сути корневая директория в FAT12 - это таблица, в которой каждому файлу или
поддиректории соответствует одна 32-байтная запись. Давайте посмотрим, что в ней есть.

Байты 0-10: имя файла в формате 8:3. Этот формат подразумевает, что имя файла занимает
ровно 8 байтов, а расширение - 3. Если имя файла меньше 8 символов, оно дополняется
пробелами: так, файл 'loader.bin' в КД будет проходить под именем 'LOADER  BIN'.

Байт 11: атрибуты записи. Набор флагов, позволяющий придать записи особые свойства.
          00000001b = только для чтения
          00000010b = скрытый
          00000100b = системный
          00001000b = метка раздела
          00010000b = директория
          00100000b = архив
          00001111b = LFN (long file name), запись имеет особый формат, поддерживающий длинные
                              имена файлов.

Байт 12: зарезервирован для Windows NT.

Байт 13: время создания в десятых секунды (почему-то 0-199 согласно OSDev Wiki).

Байты 14-15: время, когда был создан файл. Младшие 5 бит - секунды/2 (то есть при интерпретации
значения, например, для вывода на экран, эту часть надо умножать на 2). Следующие 6 - минуты.
Последние 5 бит - часы.

Байты 16-17: дата создания файла. Примерно та же история. День(0-4), месяц(5-8), год(9-15).

Байты 18-19: дата последнего доступа в том же формате, что и дата создания.

Байты 20-21: старшие 16 бит номера первого кластера файла. В FAT12 и FAT16 не используется.

Байты 22-23: время последнего изменения в том же формате, что и время, когда был создан файл.

Байты 24-25: дата последнего изменения в том же формате, что и дата создания.

Байты 26-27: младшие 16 бит номера первого кластера файла.

Байты 28-31: размер файла в байтах.
Довольно много информации, но нас интересуют только два поля: имя записи и младшая часть номера
стартового кластера (старшая половина в FAT12 не используется). Вырисовывается в общих чертах
алгоритм поиска файла? Если нет, я помогу:

1. Переходим к началу КД
2. Считываем имя записи
3. Сравниваем имя записи с именем искомого файла
4. Если имена совпали, файл найден, SUCCESS!
5. Записи кончились?
6. Если кончились - файла нет, аварийно завершаемся
7. Переходим к следующей записи
8. goto 2
Вот таким нехитрым способом мы сможем найти на диске начало файла или, если его нет, уведомить
об этом пользователя и свернуть выполнение загрузчика. Я решил, начиная с этого поста, не
перепечатывать весь листинг из предыдущих уроков. Вместо этого я приложу ссылку на файл в
конце. Это позволит вместить в пост больше полезной информации, не растягивая его до
нечитабельных размеров. А теперь давайте выполним наш поисковый алгоритм в коде. После
call read_sectors пишите:

                   mov cx,BPB_RDentries
                   mov di,0200h
                   mov si,offset fname
                   mov bp,si

next_entry:   mov ax,cx
                   mov bx,di
                   mov cx,11
                   rep cmpsb
                   mov si,bp
                   mov di,bx
                   mov cx,ax
                   je load_FAT
                   add di,32
                   loop next_entry

                   mov ah,3
                   xor bh,bh
                   int 10h

                   mov ax,1300h
                   mov bx,0007h
                   mov cx,22
                   mov bp,offset fname
                   int 10h

                   cli
                   hlt
Что всё это значит? В строчке mov cx,BPB_RDentries мы устанавливаем счётчик основного
цикла. Напоминаю, что в переменной BPB_RDentries у нас хранится число записей корневой
директории. 0200h - смещение загруженной в RAM КД. В SI мы помещаем смещение строки с
именем искомого файла. Кстати, впишите в переменные fname db 'LOADER  BIN'. После этого
мы сохраняем это же смещение в регистре BP. Это может быть пока неочевидно, но позже вы
поймёте, зачем.

Следующий блок кода, начинающийся с метки next_entry, - это собственно цикл просмотра
записей КД и сравнения имён. Первым делом мы сохраняем счётчик цикла и смещение текущей
записи. Счётчик сохраняем потому, что будет вложенный цикл, а смещение - потому, что
строковые инструкции вроде cmpsb изменяют значения регистров SI и DI. Кстати, теперь вам
должно быть понятно, зачем мы сохраняли указатель на строку с именем в BP.

mov cx,11 - установка счётчика вложенного цикла. Имена в FAT12 хранятся в формате 8:3,
значит, нам нужно сравнить две строки по 11 символов. Надеюсь, тут вопросов нет?
Инструкция cmpsb сравнивает значения двух байтов (в нашем случае символов), находящихся
в DS:SI и ES:DI. Префикс rep повторяет инструкцию, пока не обнулится счётчик в CX.
Далее мы восстанавливаем счётчик основного цикла в CX, смещение текущей записи в DI и
смещение строки с именем файла в SI. В старых версиях здесь у меня были пары инструкций
push/pop, но потом я подумал, что трансфер из регистра в регистр быстрее, чем обращение
к стеку, и поменял. Никогда не вредно сэкономить пару циклов.

Если в результате rep cmpsb все символы совпали, в регистре флагов будет установлен бит
ZF. Команда je load_FAT выполняет переход к метке load_FAT если флаг ZF установлен.
В случае если строки не совпали, мы переводим DI к следующей записи в КД и продолжаем
цикл командой loop next_entry. Тут бы можно было и закончить, но нужно обработать
отсутствие файла. С этим набором инструкций мы уже знакомы по предыдущему посту.
Первый блок возвращает положение курсора в DH,DL, а второй выводит от этой позиции
сообщение. Отличается только само сообщение. Вместо 'Disk read error.' мы выводим строку
с именем файла. Внимание, тут небольшой хак. Идея в том, чтобы вывести следующий текст:
'{filename} not found!'. Вызвать вывод строки два раза, но зачем? Если поместить в
разделе переменных текст ' not found!' сразу после переменной fname, а при вызове int 10h
указать в CX не 11 символов, а 22, то выведется сначала имя файла, а потом ' not found!'
Конечно же, этот текст обязательно должен быть сразу после fname. Добавьте строчкой ниже
db ' not found!' После этого останавливаем процессор парой команд cli и hlt. Не так-то
сложно, да? Впрочем, файл ещё нужно загрузить.

Для этого нам нужно будет загрузить в память FAT и разобраться, как ею пользоваться.
Давайте начнём с первой задачи, она чисто техническая и не требует умственного напряжения.
После hlt набирайте:

Load_FAT:          mov ax,[di+26]
                         mov cluster,ax
                         mov ax,BPB_reserved
                         mov cx,total_FATs_size
                         mov bx,BPB_RDentries
                         shl bx,5
                         add bx,0200h
                         mov FAT_offset,bx
                         call read_sectors
В строчке mov ax,[di+26] мы считываем из записи КД номер первого кластера файла, а затем
сохраняем его в переменной cluster. Далее, мы помним, что FAT у нас идут сразу после
зарезервированных секторов, поэтому в AX помещаем BPB_reserved. В CX у нас будет число
секторов, которое надо загрузить, то есть total_FATs_size. Загружать FAT будем сразу после
КД, то есть в 07С0h:0200h+размер КД. Размер КД = число записей КД*размер записи (32 байта).
Помещаем в BX число записей (BPB_RDentries), умножаем на 32 (shl bx,5 эквивалентно умножению
на 32, но выполняется быстрее) и добавляем 0200h. Готово! Сохраняем на будущее в переменной
FAT_offset (кстати, объявите её рядом с прочими) и вызываем read_sectors.

А теперь время вернуться к теории. Что такое FAT? Не поверите, но это тоже таблица, и её
структура ещё проще, чем у КД. Каждая запись в FAT соответствует кластеру на диске. FAT
можно назвать оглавлением диска (украл с OSDev Wiki). Кластер может быть свободен, занят
частью файла, зарезервирован ОС или испорчен. Если кластер хранит часть файла, то его
запись в FAT будет содержать номер следующего кластера файла. Понятно? Зная номер первого
кластера файла, мы можем загрузить его в память, потом заглянуть в FAT, найти нужную запись
и считать номер следующего кластера. Повторять до конца файла. Звучит просто, но, как
всегда, есть большое "НО"! Размер записи в FAT12 - 12 бит. Мы не можем оперировать
12-битными ячейками. Мы можем считать 8 или 16. То есть, если мы загрузим в AX начало FAT,
то в регистре окажется первая запись и часть второй. А если сдвинемся на один байт, то
получим конец первой записи и всю вторую. Давайте попробую проиллюстрировать для
наглядности. В верхней строчке будет часть FAT, разделённая на записи, а в нижней она же,
но поделенная на 8-битные куски.

0 0 0 1 0 1 1 1 0 0 1 0|0 1 1 1 0 0 1 0 1 0 0 0|0 0 1 0 0 1 0 0 0 1 1 1          3 Записи.
0 0 0 1 0 1 1 1|0 0 1 0 0 1 1 1|0 0 1 0 1 0 0 0|0 0 1 0 0 1 0 0|0 1 1 1         4,5 байта.

Решение в том, чтобы, считывая каждый нечётный кластер, сдвигать значение на 4 бита вправо, а
у чётного - обнулять 4 старших бита. Зная всё это, давайте писать код:

                             push 0050h
                             pop es
                             xor bx,bx
read_cluster:           mov ax,cluster
                             sub ax,2
                             movzx cx,BPB_secperclust
                             mul cx
                             add ax,datasector
                             call read_sectors
                             mov ax,cluster
                             mov si,ax
                             shr ax,1
                             add si,ax
                             add si,FAT_offset
                             mov dx,[si]
                             mov ax,cluster
                             test ax,1
                             jnz odd_cluster
                             and dx,0000111111111111b
                             jmp short done
odd_cluster:           shr dx,4
done:                     mov cluster,dx
                             cmp dx,0FF7h
                             jb read_cluster
Финальный рывок. Первое, что мы делаем - устанавливаем сегмент для загрузки файла. Так как
BIOS нам больше не указ, выбирать можно самостоятельно. Я бы с удовольствием отправил его
в 0000h:0000h, но первые 1280 байт заняты важными вещами, о которых поговорим позже.
Ближайший свободный участок RAM - 0050h:0000h (или 0000h:0500h, это тот же самый адрес
если вы вдруг забыли правила адресации сегмент:смещение). Обнуляем BX, так чтобы пара
ES:BX указывала на 0050h:0000h. Считываем в AX номер первого кластера файла. Дальше мы
вычитаем 2 из этого номера. Зачем? Затем, что значения 0 и 1 в FAT зарезервированы и не
используются в качестве номеров, а номер, указанный в таблицах, на 2 больше, чем правильное
значение. Да, это идиотизм.

Загружать будем не сектор, а кластер (что в нашем случае одно и то же, но всё-таки),
поэтому в качестве числа секторов помещаем в CX переменную BPB_secperclust и на неё же
умножаем номер кластера. AX*CX в данном случае дадут нам номер первого сектора нужного
кластера. А так как кластеры в FAT начинают считаться от начала области данных,то для
абсолютного значения добавляем к AX datasector. Готово. Вызываем read_sectors и загружаем
первый кластер файла в RAM.

Дальше будет немножко математической магии, объяснять которую я не буду. Если интересно -
разберётесь самостоятельно, там не так сложно. Остальным предлагаю просто поверить, что
смещение записи кластера внутри FAT = 3/2 номера кластера. Значит, берём в AX номер
кластера, его же помещаем в SI, делим AX на 2 и прибавляем к SI. Вуаля, смещение
записи от начала FAT найдено. Добавляем к нему смещение FAT_offset и считываем в DX
значение записи.

Теперь надо проверить, чётная ли запись. Для этого опять берём в AX номер кластера и
делаем сравнение с 1. Если флаг ZF не установлен (то есть 0 бит значения равен 1),
значит, номер записи - нечётный, переходим к odd_cluster и сдвигаем значение вправо на
4 позиции. Если чётный - делаем логическое "И" с маской 0000111111111111b и обнуляем
тем самым 4 старших бита. Теперь у нас есть содержимое нужной записи без всяких
посторонних хвостов, то есть номер следующего кластера. Сохраняем его в переменной
cluster. Дальше у нас идёт сравнение с номера с числом 0FF7h. Дело в том, что,
начиная от этого значения в FAT идут специальные коды, которые могут означать конец
файла, испорченный сектор и т.д. Для нас это значит, что если в качестве номера
кластера мы получили 0FF7h или больше, продолжать загрузку не имеет смысла. Поэтому
продолжаем цикл только если DX меньше 0FF7h. Я умышленно оставляю здесь дыру и
предлагаю всем заинтересованным попытаться самостоятельно сделать обработку ошибки,
связанной с битым кластером (код 0FF7h). Код конца файла, кстати, 0FF8h. Вся необходимая
для этой задачи информация и примеры кода уже есть в этом посте.

А мне остаётся только добавить в конце три строчки:

                    push 0050h
                    push 0000h
                    retf
Этот набор команд мы уже помним из старых постов. Помещаем в стек сегмент, потом
смещение, и передаём управление загруженному файлу командой retf. Поздравим себя!
Первичный загрузчик готов. Да, он умеет немного, но и задача у него всего одна:
найти загрузчик второго уровня, поместить его в RAM и отдать штурвал. Если вы
скомпилируете файл без инструкций org 1FEh и dw 0AA55h, то увидите, что программа
занимает всего 447 байт. Значит, у нас есть в запасе ещё 63. Как раз должно
хватить на проверку успешного считывания кластеров. У меня вместе с ней вышло 497
байт. Можете подсмотреть в приложенном файле, хоть это и неспортивно. Если вы
поместили загрузчик на дискету и получили в bochs (или на реальной машине) вот такой
экран, то всё работает как надо!

Plex86/Bochs UGABios (PCI) current-cvs 08 Jul 2014 This UGA/UBE Bios is released under the GNU LGPL
Please visit :
. http://bochs.sourceforge.net . http ://www.nongnu.org/vgab ios
Bochs UBE Display Adapter enabled
Bochs BIOS - build: 07/10/14
$Revis ion: 12412 $ $Date: 2014-07-10 09:28:59

Чистая дискета:
https://drive.google.com/file/d/1Bold4ds8oEruHQ7fJZKHglVo7A2Vc5MR/view?usp=sharing

Листинг:
https://drive.google.com/file/d/1Q5EtKX5kyF4MWcBeD8a6Jz5cPtqZja9C/view?usp=sharing

Bochs:
https://drive.google.com/file/d/16k2Gpr7oPSekq4rAhmtBV0IPnIteDLlE/view?usp=sharing

* FAT поддерживает вложенные директории, и они ничем принципиально не отличаются
от корневой, так что всё нижеизложенное касается и их. 


С Новым Годом, пацандрэ. Несколько лет назад взял за правило встречать 1 января без поxмелья, чего и всем советую.

История видеоигр, часть 3: Nimrod (1951)


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

Разумеется, как всякая уважающая себя древняя игра, ним имеет множество вариаций и наборов правил. Всех желающих приглашаю ознакомиться со статьёй в Википедии. Нас же интересует созданный в 1951 году компьютер Nimrod, с которым любой желающий мог помериться силами в означенной игре.

Машина размером 3,65 на 2,74 на 1,52 метров была собрана специально для этой задачи и представлена на Фестивале Британии. Как и другие игровые аппараты этой эпохи, Nimrod был создан для демонстрация технических возможностей или инноваций компании-производителя. Реализацией проекта занимались служащие Ferranti австралиец Джон Беннетт и британец Реймонд Стюарт-Виллиамс. Первый был ответственен за разработку концепции и схемы устройства, второй - за практическое исполнение.

,geek,Прикольные гаджеты. Научный, инженерный и  айтишный юмор,старые игры,обзор,Игры

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

Несмотря на произведённый на выставке ажиотаж, Nimrod был разобран, а компания Ferranti продолжила делать компьютеры общего назначения. Оба автора в становлении игровой индустрии тоже никак не участвовали.




9 ¡0 H ** ? • fl	r-rr^L ‘:*T T J «j ■ il
	Sl2$y S' - t _>xS«âje,geek,Прикольные гаджеты. Научный, инженерный и  айтишный юмор,старые игры,обзор,Игры

Хотя реальная машина существовала в единственном экземпляре, сегодня любой желающий может сыграть в браузерную версию здесь.

История видеоигр, часть 2: Bertie the Brain


Всего через три года после Cathode-ray tube amusment device на свет появился второй кандидат на звание первой в мире видеоигры. Как мы увидим позже, Bertie the Brain также не удовлетворяет всем критериям определения "видеоигры", так что вопрос о первенстве остаётся открытым.

Автор, Джозеф Кейтс (Кац), родился в 1921 году в Вене в семье австрийских евреев Баруха и Анны Кац. Как вы понимаете, жизнь еврейского юноши в то время оказалась нелёгкой: бегство от нацистов в Италию, а потом в Британию, депортация как потенциально враждебного элемента в Канаду, два года в лагере. После выхода на свободу в 1942 году Джозеф осел в Торонто и устроился на работу в Имперскую Оптическую Компанию, где два года занимался созданием точной оптики для канадского флота. Оттуда перешёл в Rogers Vacuum Tube Company, а затем в вычислительный центр при Университете Торонто. В обоих местах деятельность Кейтса была связана с разработкой радиоламп. Где-то в начале 50-го года Джозеф Кейтс решил, что настало его время двигать прогресс и сконструировал лампу-аддитрон. Одна такая лампа могла выполнять роль полного сумматора, для чего требовался комплект из 10 обычных вакуумных ламп.

Для демонстрации своего изобретения на Национальной выставке в Торонто Кейтс и собрал устройство, которое назвал Bertie the Brain. По сути это компьютер для игры в крестики-нолики. Внушительное устройство состояло из 4-метрового корпуса, панели с девятью кнопками, организованными в поле 3 на 3, и дисплея для отображения хода игры. Справа от дисплея располагались индикаторы, которые показывали, чей сейчас ход.


В отличие от полностью аналогового CRTAD, в Bertie the Brain использовался цифровой компьютер, что ставит его ближе к нынешним электронным развлечениям, и даже имелось три уровня сложности ИИ. Однако дисплей представлял собой просто массив из цветных ламп за стеклянным экраном, неспособный к выводу каких-то иных изображений.

Как и CRTADBertie the Brain остался просто малоизвестным историческим курьёзом, и даже его основная задача - продвижение лампы-аддитрона - оказалась проваленной: ещё до того, как Кейтс уладил все дела с патентом, вакуумные лампы были вытеснены транзисторами. Это не нанесло непоправимого вреда карьере Джозефа Кейтса, который позже стал основателем своей собственной компании, не имеющей, однако, никакого отношения к игровой индустрии и поэтому для нас малоинтересной. После выставки Bertie the Brain был разобран и навсегда забыт.

Раз уж мы здесь, почему бы не взглянуть одним глазом на историю игры, ставшей основой для Betie the Brain? У нас она известна под именем "крестики-нолики" или ранее как "херики-оники". Считается, что происходит от древней китайской игры "вэй-чи" или "гомоку" по-японски, где два игрока по очереди выкладывали на расчерченную клетками доску белые и чёрные камешки, пытаясь выложить линию нужной длины и не дать сделать того же своему противнику.

Здесь мы собираем самые интересные картинки, арты, комиксы, мемасики по теме (+61 постов - )