[recovery mode] TI-84+

c8737809dc6fa095a8556a740fae0f9f.gifОбнаружив в моей очередной контрольной энное количество вычислительных ошибок, учитель физики сказал несколько максимально вежливых фраз, которые в вольном переводе на живой великорусский язык звучали бы так: Чтоб в следующий раз был нормальный графический калькулятор!

В результате набега на ближайший книжный магазин (никаких более релевантных в округе не было) был приобретен TI-84 Plus. После того как все контрольные были написаны, возник вопрос: а что, собственно говоря, этот зверь умеет? Путем гугления выяснилось, что TI-84 Plus — это не только ценный извлекатель квадратных корней но и:Легендарный Zilog Z80, 24 Кб RAM и 480 Кб Flash доступной пользователю, Куча полезных (и не очень) программ, написанных энтузиастами. Под катом — небольшой обзор калькулятора и довольно-таки корявая игра «роботы» моего написания. Заранее прошу прощения у любителей обнаженки — разобрать калькулятор я не смог, да и побоялся.TI-84+ — программируемый графический калькулятор с черно-белым экраном 96x64. «Говорит и понимает» © математическую нотацию (дроби вида а над бе, квадратные корни с аргументом под чертой и так далее):e506ca6fc60f4137b7db09ba82ee836c.gifУмеет кучу полезных математических штук, но интереснее с точки зрения Хабра его программируемость.Программирование Программировать TI-84+ «из коробки» можно либо на TI BASIC, либо в машинных кодах. TI BASIC — диалект BASICa. Это «структурный», а не «макаронный» диалект. Вместо ключевых слов — токены (по-моему что-то такое было в Спекртумах). Оптимизирован для математических операций, для игр и других приложений подходит так себе, хотя конечно, умеючи можно написать что угодно. Из минусов очень медленный, так как вдобавок к интерпретации, вся математика с плавающей точкой. Из плюсов — программы занимают очень мало места.

Другая возможность — машинные коды. Как правило, собранные ассемблером на компьютере. Соответственно, программы получаются на несколько порядков быстрее и раза в два больше чем соответствующая программа на бейсике. Еще они могут убить калькулятор.

Энтузиастами созданы и другие способы программировать TI-84+. Наиболее значимый, пожалуй, — AXE. Это аналог Си для калькуляторов: язык с Basic-подобным синтаксисом, транслирующийся в машинные коды. Не требует компьютера для написания и компиляции программы (хотя, писать большую программу на калькуляторе — удовольствие на любителя). Использует шестнадцатибитную арифметику, что конечно медленнее нативной восьмибитной.

Программы для TI-84+ Вот здесь есть архив с кучей программ — как полезных, ятак и игровых. Также, на оффициальном сайте TI есть много полезных программ. На калькуляторе из коробки память забита под завязку, но большая часть программ в стандартной поставке бесполезны, их можно смело удалить.

Пару слов об организации памяти: в калькуляторе есть RAM и FLASH (Archive в терминологии TI). И то и другое организованно в некое подобие файловой системы. Программы и данные можно хранить как в RAM, так и во FLASH. FLASH медленнее, но ее больше. Кроме «программ» и данных во FLASH хранятся «приложения» — от «программ» они отличаются, тем, что распределены по страницам FLASH-памяти и могут занимать больше памяти, чем процессор в состоянии адресовать.

Полезная вещь, которую стоит иметь на калькуляторе — это оболочка, приложение содержащее библиотеки, загрузчик бинарных программ, и графический интерфейс. Лично я пользуюсь Doors CS. Ее плюс в том, что она содержит библиотеки всех популярных оболочек, а минус — в большом размере. Создатели Doors CS попытались сделать интерфейс похожим на Windows, для чего TI-84+ подходит, на мой взгляд, плохо. Впрочем, использовать GUI Door CS необязательно, она автоматический интегрируется в ОС.

Некоторые интересные программы для TI-84+:

«Роботы» на AXE Погоняв птичку и попрыгав через порталы, я решил сам что-нибудь написать. В качестве языка я выбрал AXE, а в качестве задачи — BSDшных роботов. Получилось коряво: большую часть памяти занимают массивы. Но как сделать компактнее, я так и не придумал.

Программа состоит из пяти «частей»: инициализации, отрисовки, создания нового уровня, «интеллекта» роботов и главного цикла. Отличия от оригинала: игровое поле 23x15 (каждый спрайт 4x4 + бордюр), меньше роботов из-за уменьшения игрового поля, нет подсчета очков.

Инициализация Скрытый текст .ROBOTS

.IMAGES .EMPTY .ROBOT .JUNK .PLAYER .STONE .STONE [000000000000000020702000000000007070700000000000702070000000000020707000000000002070700000000000]->Pic1

.FIELD Buff(23*15)->Str1 Buff(23*15)->Str2 Buff(23*15)->Str3 1->L Здесь все просто. Сначала идет заголовок с именем программы, потом шестнадцатиричная строка со спрайтами. AXE поддерживает спрайты 8x8, а у меня — 4x4, так что большая часть этогй стоки — нули. Также, я использовал «пустой» спрайт и повторил спрайт с могилой два раза для упрощения отрисовки.

Дальше инициализируются массивы с игровым полем. Str1 — главное игровое поле, Str2 — вспомогательное, Str3 — копия старого игрового поля для предотвращения ошибок игрока. Переменная L — уровень.

Обратите внимание на особенность синтаксиса AXE (и TI-BASICа): присваивание происходит справа налево.

Создание нового уровня Скрытый текст Lbl NEWLVL Fill(Str1,15*23,0) L*5->R For(R) rand^15->I rand^23->J I*23+J+Str1->P 1->{P} End rand^23->X rand^15->Y 3->{Y*23+X+Str1} Return Сперва игровое поле обнуляется, затем на нем размещаются роботы (спрайт за номером 1). В оригинале на каждом уровне появлялось по десять роботов, у меня игровое поле меньше, поэтому я выбрал пять. Роботов может быть меньше, чем L*5 из-за наложения, я решил считать это фитчей. Затем выбирается позиция игрока (спрайт номер 3), опять же: в отличии от оригинала, где помереть можно на нулевом ходу, у меня игрок «убивает» робота, если приземлится на него в начале игры.

Отрисовка Скрытый текст Lbl DRAW ClrDraw VLine(0,0,62) VLine(94,0,62) HLine(0,0,94) HLine(62,0,94) For(I,0,22) For(J,0,14) Pt-On(I*4+1,J*4+2,{J*23+I+Str1}*8+Pic1) End:End DispGraph Return Здесь, опять же, все просто. Пожалуй, стоит сказать, что двоеточие — разделитель операторов, а Pt-On — отрисовка спрайта. Lbl — метка, от LaBeL. Фигурные скобки в AXE — значение байта по заданному адресу.

Передвижение роботов Скрытый текст Lbl STEP 0->R Fill(Str2,23*15,0) For(I,0,22):For(J,0,14) J*23+I->A {A+Str1}->B If B=2 2->{A+Str2}:End If B=1: R+1->R (J+SIGN(J,Y))*23+I+SIGN(I,X)+Str2->A {A}+({A}<2)->{A} End End:End Copy(Str2,Str1,23*15) Y*23+X+Str1->A {A}+3->{A} Return

Lbl SIGN ([r1]<[r2])-([r1]>[r2]) Return Здесь начинаются грязные хаки. Программа сканирует игровое поле, ища роботов, и передвигает их в сторону игрока. Операции сравнения в AXE возвращают единицу, поэтому {A}+({A}<2)->{A} инкременирует A если и только если А меньше двух. Затем отмечается позиция игрока.

Главный цикл Скрытый текст While 1 0->G NEWLVL() DRAW() While R>0 X->M:Y->N Copy(Str1,Str3,23*15) If G<200 getKey^^r->G ReturnIf G=9 G^100->K End

If K=47 rand^23->X rand^15->Y STEP() DRAW() If {A}!=3 getKey^^r:Return End Else (K=51)+(K=48)+(K=45)-(K=49)-(K=46)-(K=43)->I ((K>=43) and (K<=45))-((K>=49) and (K<=51))->J

If ((J+Y)<15) and ((J+Y)>=0) and ((I+X)<23) and ((I+X)>=0) X+I->X:Y+J->Y Else:0->G End

STEP() If {A}!=3 M->X:N->Y Copy(Str3,Str1,23*15) 0->G End End Собственно, можете наблюдать ухудшение качества кода: главный цикл мне пришлось переписывать три раза (заповедь «делай бекапы» для TI-84+ как никогда актуальна), и под конец я устал. В результате получилось то, что получилось.

Пояснения:

R — количество роботов на игровом поле. Если роботов больше не осталось — значит уровень пройден.

getKey^^r ждет нажатия клавиши, затем возвращает скан-код. Реализуя свой преступный замысел, я использовал тот факт, что модификатор 2nd прибавляет к скан-кодам цифровых клавиш сотню. Таким образом, новая клавиша не считывается если 2nd была нажата — таким образом реализуется повторение. Истинный скан-код сохраняется в переменную G, и если G больше 200, новая команда не считывается.

Скан-код 147 — клавиша «5». В игре это команда телепортации. Телепортация — единственный ход, на котором игра может закончится, поэтому он обрабатывается отдельно.

Скан-коды 43…45, 49…51, 46 и 48 — это цифровые клавиши, по ним игрок двигается. Убить игрока во время движения нельзя, так что состояние игры сохраняется до хода и восстанавливается если игрок с кем-то столкнулся. При этом, G обнуляется.

Как это все выглядит в собранном виде: Скрытый текст .ROBOTS

.IMAGES .EMPTY .ROBOT .JUNK .PLAYER .STONE .STONE [000000000000000020702000000000007070700000000000702070000000000020707000000000002070700000000000]->Pic1

.FIELD Buff(23*15)->Str1 Buff(23*15)->Str2 Buff(23*15)->Str3 1->L

While 1 0->G NEWLVL() DRAW() While R>0 X->M:Y->N Copy(Str1,Str3,23*15) If G<200 getKey^^r->G ReturnIf G=9 G^100->K End

If K=47 rand^23->X rand^15->Y STEP() DRAW() If {A}!=3 getKey^^r:Return End Else (K=51)+(K=48)+(K=45)-(K=49)-(K=46)-(K=43)->I ((K>=43) and (K<=45))-((K>=49) and (K<=51))->J

If ((J+Y)<15) and ((J+Y)>=0) and ((I+X)<23) and ((I+X)>=0) X+I->X:Y+J->Y Else:0->G End

STEP() If {A}!=3 M->X:N->Y Copy(Str3,Str1,23*15) 0->G End End

DRAW() End L+1->L End Return

Lbl DRAW ClrDraw VLine(0,0,62) VLine(94,0,62) HLine(0,0,94) HLine(62,0,94) For(I,0,22) For(J,0,14) Pt-On(I*4+1,J*4+2,{J*23+I+Str1}*8+Pic1) End:End DispGraph Return

Lbl NEWLVL Fill(Str1,15*23,0) L*5->R For(R) rand^15->I rand^23->J I*23+J+Str1->P 1->{P} End rand^23->X rand^15->Y 3->{Y*23+X+Str1} Return

Lbl STEP 0->R Fill(Str2,23*15,0) For(I,0,22):For(J,0,14) J*23+I->A {A+Str1}->B If B=2 2->{A+Str2}:End If B=1: R+1->R (J+SIGN(J,Y))*23+I+SIGN(I,X)+Str2->A {A}+({A}<2)->{A} End End:End Copy(Str2,Str1,23*15) Y*23+X+Str1->A {A}+3->{A} Return

Lbl SIGN ([r1]<[r2])-([r1]>[r2]) Return Спасибо за внимание! Ссылки: Специально для тех, кто дочитал: aff0833956dc046a7d2f5879313c282e.png

© Habrahabr.ru