goodboy,нада смотреть на какой машине было сделано раньше.Цитата:
ZX Spectrum, Amstrad CPC, Commodore 64
Вид для печати
goodboy,нада смотреть на какой машине было сделано раньше.Цитата:
ZX Spectrum, Amstrad CPC, Commodore 64
Там есть вот такое место:
И сравни, например, с анимацией птицы:Код:; Data block at 77BE
anim_ball_resize:
DEFW spr_ball_normal
DEFW spr_empty_1
DEFW spr_empty_2
DEFW spr_empty_3
DEFW spr_empty_4
DEFW spr_empty_5
DEFW spr_empty_6
DEFW spr_empty_7
DEFW spr_big_ball
Я думаю, что мы сейчас делаем двойную работу. Многое из того, что вы написали с ivagor, мне уже было известно из кода. Давайте я закончу с дизассемблированием, выложу то, что получилось и мы потом вместе приступим к анализу кода. Это будет гораздо удобнее и быстрее. Я сейчас по ходу разбора переименовываю некоторые безликие цифровые метки, присваивая им осмысленные названия. И уже дальше, опираясь на эти названия, из контекста становится примерно понятно что значат соседние процедуры. Например:Код:; Анимация птицы
anim_bird:
DEFW spr_bird_1
DEFW spr_bird_2
DEFW spr_bird_3
DEFW spr_bird_4
DEFW spr_bird_3
DEFW spr_bird_2
DEFW spr_bird_1
DEFW spr_bird_5
DEFW spr_bird_1
DEFW spr_bird_2
DEFW spr_bird_3
Код:; Used by the routines at L927F and LB9E8.
L93F8:
LD HL,$0000
LD (L938A),HL
CALL draw_frame
LD HL,$BF00 ; Координаты окна (весь экран нижняя строка)
LD DE,win_full_screen_purple_ink
CALL fill_attrib
LD HL,$B708 ; Координаты окна
LD DE,win_1e_16_white_ink
CALL fill_attrib
LD HL,$4718 ; Адрес на экране
LD DE,spr_press_a
CALL print_sprite ; Press A
LD HL,$47C8 ; Адрес на экране
LD DE,spr_press_b
CALL print_sprite ; Press B
LD HL,hi_score_1up
LD DE,txt_score_1up+4
CALL copy_score
LD HL,hi_score_2up
LD DE,txt_score_2up+4
CALL copy_score
LD DE,txt_main_menu
LD B,$0F ; Количество строк в сообщении
CALL print_message
LD HL,(coord_ctrl_1up)
LD DE,spr_pointer_1
CALL print_sprite
LD HL,(coord_ctrl_2up)
LD DE,spr_pointer_2
CALL print_sprite
Код:; Data block at 9614
L9614:
DEFW txt_1_player
DEFW txt_controls
Ну что ж, теперь все компилируется и играет по адресу отличному от стандартного. Пробовал компилировать на 100 байт больше и на 100 байт меньше. Если на 100 байт меньше, то в таблице когда ввожу имя портится верхняя часть экрана. Скорее всего какой-то нижний буфер перехлестнул кодом. Потому что такого эффекта нет, если скомпилировать на +100 байт от стандартного адреса. Глубоко не тестировал - может там ещё что есть. Но сейчас анализировать код уже стало гораздо проще, так как я могу что-то менять, закомментировать какие-то участки кода, добавить своё и т.д.
Нашёл в игре неиспользуемый цветной спрайт. Кусок левой боковины. Мне показалось, что это дверь, как а Арканойде, для перехода на следующий раунд. Скорее всего это должно было выглядеть вот так:
https://pic.maxiol.com/thumbs2/15922....battydoor.png
Причём сейчас я эту "дверь" поместил не в графическом редакторе, а путём добавления нескольких строчек кода к исходнику :) Отладка в действии!
Да, правильная мысль! Сдвинул на 257 байт и эффект проявился в обоих сторонах. Не думаю, что это серьёзная проблема, равно или поздно найду в чём проблема, потому что сейчас в игре практически не осталось белых пятен :)
По мере разбора кода наталкиваюсь на интересные вещи. Например, игровое поле окружено бордюром. И бордюр шириной не 8 пикселей, а 9! Вначале рисуются спрайты толщиной 8 пикселей, а потом ещё отдельно по внутреннему краю дорисовывается несплошная линия толщиной в пиксель. Вот автор заморочился, чтобы всё было идеально!
Нашёл причину порчи таблицы! Почему-то я этот абсолютный адрес в тексте программы пропустил, хотя смотрел её вдоль и поперёк многократно.
Прикладываю версию Batty, скомпилированную по другом адресу (+257 байт от стандартного). Кому не лень потестируйте, пожалуйста, чтобы убедиться, что ничего не сломалось.
Нашёл в игре очень интересный звук, который автор в итоге так и не использовал нигде.
Сделал специальный снепшот, чтобы можно было его услышать. Для воспроизведения этого таинственного звука, в главном меню нужно нажать кнопку В - выбор управления для второго игрока. И вместо стандартного звука (как на кнопке А) вы услышите нечто другое :)
Ничего себе проект!!! Очень интересно. А какая конечная цель? Портирование на другой комп?
На всякий случай сообщаю, что дизассемблирование не бросил, а продолжаю копаться в программе. То, чтобы было сходу понятно давно уже разобрал. Сейчас работа замедлилась, потому что теперь в силу неочевидности и моего малого опыта работы с чужим кодом, приходится подолгу сидеть над каждой новой процедурой и переменной. Но дело потихоньку движется!
Ну, и так, для затравки могу немного рассказать про какие-то части игры.
То, что я в самом начале принял за декодирование и распаковку кода на самом деле оказалось подготовкой графики. Во-первых, в конце памяти строится таблица сдвигов. К этой таблице обращается процедура печати спрайтов для их вывода со сдвигом по горизонтали. Это относится к перемещению врагов, искр от взорвавшейся каретки, выпадающей цифры 400 и т.д. После этого идёт создание некоторых готовых спрайтов со сдвигом. В игре, сразу после её загрузки, есть пустые спрайты и эта процедура заполняет эти пустые спрайты сдвинутыми. Прежде всего это касается шарика - к стандартному спрайту добавляется ещё 7 сдвинутых спрайтов. И также ещё по одному сдвинутому спрайту добавляется к спрайтам каретки: стандартной, расширенной и к каретке с пулемётом. То есть подготавливаются самые используемые спрайты, а остальные сдвигаются по таблице в процессе их вывода на экран. И на последнем этапе подготовки графики часть спрайтов инвертируется. После этого управление передаётся игре по адресу #B9B1.
Странно автор подошёл к формированию уровней. Все свойства уровней раскиданы по коду, а некоторые свойства выбираются программно.
1. Кирпичи: их расположение и прочность практически единственная вещь, которую можно редактировать. Собственно, это и было обнаружено хакерами, которые выпускали Batty 2, Batty 3 и т.д. При этом в этих "продолжениях" всё остальное оставалось от оригинальной игры.
2. Магниты: их наличие на уровне, количество и расположение также можно редактировать. Однако без доступа к коду сделать это не очень просто и к тому же есть ограничения. Дело в том, что под описание магнитов на уровнях отведено разное место. В описании вначале идёт байт, указывающий сколько магнитов есть на уровне, и далее, если в первом байте не ноль, по два байта координат каждого магнита. Таким образом для описания магнитов первого уровня используется только один один байт (#00), а для второго уже три (#01, #XX, #YY). На уровнях 9, 13 и 14 используется по 4 магнита и, соответственно описание для каждого из них занимает по 9 байт. И так как описание каждого уровня имеет разный размер, в игре есть таблица расположения этих описаний. Как видите, не так-то просто это отредактировать по живому коду, особенно если захочется поместить магнитов больше, чем есть в игре..
3. Текстуры: всего есть 4 вида текстур и они последовательно чередуются по кругу от уровня к уровню. Таким образом назначить какую-то определённую текстуру уровню не представляется возможным. Причём, что интересно, текстура первого уровня находится в одном месте программы, а текстуры трёх других совсем в другом месте.Код:; Data block at 8E06
; Таблица магнитов для уровней
magnets:
DEFW magnet_level_03 ; Данные для первого уровня берутся из 3-го
DEFW magnet_level_02
DEFW magnet_level_03
DEFW magnet_level_04
DEFW magnet_level_05
DEFW magnet_level_06
DEFW magnet_level_07
DEFW magnet_level_08
DEFW magnet_level_09
DEFW magnet_level_10
DEFW magnet_level_11
DEFW magnet_level_12
DEFW magnet_level_13
DEFW magnet_level_14
DEFW magnet_level_15
DEFW magnet_level_15 ; Для чего-то продублирован 15-й уровень
; Data block at 8E26
; Первый байт - количество магнитов на уровне, далее по два байта их координаты
magnet_level_15:
DEFB $02,$4C,$82,$9C,$82
magnet_level_14:
DEFB $04,$8C,$24,$C4,$24,$8C,$64,$C4,$64
magnet_level_13:
DEFB $04,$10,$20,$D8,$20,$18,$6C,$D0,$6C
magnet_level_12:
DEFB $03,$74,$08,$20,$44,$C8,$44
magnet_level_11:
DEFB $02,$5C,$84,$8C,$84
magnet_level_10:
DEFB $01,$74,$44
magnet_level_09:
DEFB $04,$40,$3C,$A8,$3C,$54,$6C,$94,$6C
magnet_level_08:
DEFB $03,$74,$18,$4C,$74,$9C,$74
magnet_level_07:
DEFB $02,$30,$5C,$D8,$5C
magnet_level_06:
DEFB $03,$74,$10,$48,$73,$A0,$73
magnet_level_05:
DEFB $00
magnet_level_04:
DEFB $01,$74,$7C
magnet_level_03:
DEFB $00
magnet_level_02:
DEFB $01,$74,$2C
4. Враги: всего есть два вида врагов и они, также как и текстуры, просто чередуются от уровня к уровню.Код:; Routine at BE8B
;
; Used by the routine at LB9E8.
; Рисуем полный игровой экран со всеми элементами в буфере
game_screen_draw_to_buffer:
LD HL,spr_level_textures
LD A,(current_level_number_1up)
AND $03
ADD A,A
CALL hl_add_a
LD E,(HL)
INC HL
LD D,(HL)
LD (current_texture+1),DE ; Помещаем указатель на текстуру уровня
Всё ещё не бросил разбор Batty, как может показаться из-за отсутствия активности в этой теме. Но это процесс небыстрый, на который я сейчас трачу львиную долю своего свободного времени. Всё, чтобы было очевидного я давно разобрал. Теперь разбираю то, во что необходимо вникать подольше. Бывает, что за весь вечер после работы удаётся разобрать только одну небольшую процедуру. Но с каждым разом белых пятен становится всё меньше и меньше. Листинг приобретает читабельный вид. Например:
Как в судоку, в японских кроссвордах или других подобных головоломках, каждая разобранная процедура, переменная или таблица, помогают понять суть происходящего там, где ещё вчера было ничего не понятно.Код:CALL rnd_update
LD HL,handling_object
CALL call_hl_for_all_obj
CALL fill_briks_data
LD HL,ix_buf_addr_calc
CALL call_hl_for_all_obj
CALL obj_to_buff_transfer
LD HL,print_spr_with_mask_buff
LD A,(object_ball_2)
RLA
CALL NC,call_hl_for_all_obj
CALL play_sounds_queue
LD HL,print_spr_from_buf_to_scr
CALL call_hl_for_all_obj
LD A,(wins_counter)
AND A
CALL NZ,wins_recovery
CALL L987A_0
CALL pause_game
LD A,(object_ball_2)
AND A
JP NZ,LBC10_5
LD B,$03
CALL pause_long
LD A,(lives_1up)
DEC A ; Отнимаем жизнь
LD (lives_1up),A
JR Z,LBC10_6
LD A,(game_mode)
DEC A
CALL Z,current_level_2up_copier
JP LB9E8_1
Вообще ощущаю себя так, как будто я тайком проник на огромный работающий завод, где все работники ушли в отпуск. И я втихаря могу заходить во все кабинеты и помещения, дёргать и крутить все ручки на станках, и наблюдать за происходящим.
Ну и на закуску. Batty могла бы выглядеть примерно так, как на скринштах. В игре постоянно обнаруживаю какие-то ошмётки от экспериментов автора. И это один из них, который автор, видимо, просто забыл удалить из игры.
https://pic.maxiol.com/images2/15956...18.screen1.png https://pic.maxiol.com/images2/15956...18.screen2.png
Я, безусловно, знал, что бонусы в игре выпадают неравномерно. Но оказалось, что автор сделал ещё и разную вероятность для разных раундов.
Вероятность выпадения бонусов на первых 6-ти уровнях:
Увеличение биты: 3
Пулемёт: 2
Размножение шариков: 2
Липучка: 2
Slow: 2
Дополнительная жизнь: 1
Ракета: 1
Smash: 1
5000 очков: 1
Kill Aliens: 1
А вот вероятность выпадения бонусов на остальных уровнях:
Увеличение биты: 4
Пулемёт: 2
Размножение шариков: 3
Липучка: 3
Slow: 0
Дополнительная жизнь: 0
Ракета: 1
Smash: 1
5000 очков: 1
Kill Aliens: 1
Вообще в игре помимо этих двух таблиц вероятностей выпадения призов, есть ещё три, но, как и многое другое, автор решил их не использовать.
При этом на всех уровнях вероятность выпадения ракеты принудительно занижается ещё больше. А если на каком-то раунде была поймана дополнительная жизнь, то больше на этом раунде же можно не ждать такого же приза - его совершенно точно не будет :)
И ещё, врагов на раунде не стоит ждать, если количество невыбитых кирпичей 44 и больше. А также враги вообще не пояалются на 5-м уровне.
Вообще, автор конкретно заморочился с геймдизайном и балансом игры. Это отчётливо видно по коду. Всего 15 раундов, но какая реиграбельность у игры! Видно, что он продумывал каждый раунд и подкручивал баланс, а не просто нарисовал сотню разных раундов и в таком виде выкатил игру. На самом деле памяти хватило бы не на один десяток раундов, но автор ограничился лишь 15-ю...
Batty - чрезвычайно трудная игра. Первые три уровня ещё ничего, с ракетой можно на халяву их посмотреть, а вот дальше идёт тяжело. Много проблем доставляет повышение скорости шарика через время или когда враги начинают наглеть и летать низко. После двух повышений шанс выжить практически нулевой. Наверное, единицы прошли всю игру до конца без "бессмертия".
Вот интересно - влияет ли на повышение скорости шарика столкновение его с врагами?
Мы с другом проходили ;) И не раз! И в одиночной игре, и совместно. При этом своё мастерство оттачивали на игровом автомате, платя по 15 коп. за каждую попытку. Тогда мы даже не догадывались, что это игра с домашнего компьютера - думали, что это просто игровой автомат такой специальный. Денег тогда на Batty было потрачено немерено! Когда мы играли в неё, вокруг нас собиралась толпа зрителей. Вот с тех самых пор для меня Batty является особенной игрой. Именно поэтому я и занялся её ковырянием. Причем это уже который мой подход, но все предыдущие закончились неудачей.
Я такой проверки не встречал. Вот конкретно процедуру сбивания врагов шариком я ещё детально не разбирал, но совершенно точно сбивание врага кареткой на скорость никак не влияет.
А вот POKE, чтобы скорость не увеличивалась: 0xA48C - 0
Скорость шарика можно замедлить ещё на один шаг и тогда она будет минимальной и такой же как у врагов, но играть тогда станет вообще неинтересно. Вообще скорость шарика регулируется переменной со значениями от 2 до 6. В игре стоит ограничение, чтобы скорость не поднималась выше 6-ти. А когда ловим приз Slow, то скорость опускается до 2-х, как и при старте. И ещё, если скорость шарика 2, то приз Slow не выпадет - всё автором продумано :)
я уже `несколько` раз рассказывал что Batty `выросла` из игры WipeOut
https://zx-pk.ru/threads/11127-ranny...iya-batty.html
Только сегодня посмотрел видеопрохождение WipeOut, чтобы сравнить с Batty. Конечно, общие корни видны во всём. Тот самый таинственный звук, найденный в Batty, звучит при старте WipeOut. Также, например, в WipeOut активная надпись в меню мерцает, переливаясь цветами, а в Batty она просто мигает. Но на самом деле в Batty процедура тоже перебирает цвета для перелива из таблице, но в таблице жёстко задан в первой половине белый цвет, а по второй - чёрный. Ну и по другим мелочам видно, что большая часть кода у этих игр одинакова.
@ivagor Не смог найти откуда скачать этот вариант. Не мог бы ты поделиться? Мне удалось только выяснить, что игру адаптировал Сергей Коровкин (Crystal Grafic). Но самой игры нет нигде. Есть только вот такое:
https://www.youtube.com/watch?v=HvzVdQMtcDI
???
ссылка там практически в описании
http://zvzd3d.ru/Orion128/Orion128Main.html
Наверное, я неправильно выразился. Я ищу Batty, адаптированную со Спектрума - её нет нигде. Везде попадается только тот вариант, видео которого я привёл.
Большое спасибо!
Непонятно для чего автору Орионовской конверсии понадобилось вносить "улучшения" в раскраску, если, как я понимаю, была возможность перенести игру 1:1.
https://pic.maxiol.com/images2/16005...attyorion0.png https://pic.maxiol.com/images2/16005...attyorion1.png
Я собирался всё причесать, подправить, окультурить и т.д., но понял, что вряд ли буду этим заниматься в обозримом будущем (если вообще буду), и решил выложить то, что имею на текущий момент:
https://github.com/CityAceE/Batty
Просто запускаете батник и на выходе получите sna с игрой - в комплекте есть всё необходимое.
Игра разобрана полностью. Любые части кода можно переносить куда угодно, менять переменные, компилировать с любого доступного адреса и т.д. - в итоге всё скомпилируется и будет работать, если внесённые изменения адекватны, то есть, например, буферы не налазят друг на друга, или стек не оказывается в области кода. Проверено целенаправленно и многократно, в том числе и адаптацией данной игры на ПК Специалист.
Когда я разбирал игру, я комментировал многие строчки кода и переименовывал процедуры, чтобы в дальнейшем можно было понять, что они делают. И чем больше становилось таких описанных и переименованных процедур, тем проще потом становилось разбираться с остальным кодом. Однако на ранних этапах анализа я мог ошибочно расценить назначение тех или иных вещей. На поздних этапах я почти всё это поправил, но, конечно, что-то да осталось. Так что имейте ввиду, что где-то там могут встретиться какие-то ошибочные описания. Но это не значит, что они там есть!
Буду благодарен, если кто-то разберётся с оставшимися неописанными переменными и процедурами, поправит мои ошибки и сделает pull request.
а 8080 версия? :)
а там много кода используещего стек не по назначению?
пробежался глазами
увидел только одну процедуру
после С300 известно точное расположении всех буферов?
вижу одна дырка 3К вторая 1К
мдо там только 425 JR
плачевная ситуация...
Если вдруг у тебя возникла мысль перевести игру на i8080, то давай я тебе лучше дам исходник для Специалиста. От этого перевода хотя бы прок будет. Но заранее предупреждаю, что в обычной памяти Специалиста места не осталось совсем - всё занято кодом и буферами. Если только использовать место по бокам экрана - а это целых 4 Кб (2+2)!
я думал быстренько сделать порт для zx8080
чтоб хоть что нибудь было
тк ПЗУ-шка задерживается (пойдет адаптироватьсо по второму кругу : )
но я смотрю тут быстренько не получитсо...
еще и рисуется с исползованием стека
я думал пройтись автозаменой и наделать макросов
чтоб особо не думать :)
а в условиях специалиста так вообще
вангую что для него это возможно только если избавиться от экранного буфера и рисовать напрямую в экран со всем миганием...
- - - Добавлено - - -
только оно блоками по 16 байт
в принципе с ADP это не проблема
оно само туда положит если будет вмещатся
но нужно иметь такие блоки (тем более в больших количествах)
или же нарезать малоиспользуемый код на 16 байтные блокии при помощи jp
но такой код станет еще на 19% жирнее и медленее
CityAceE, может немного шлифанешь игру? В том смысле, чтоб из главного меню можно выбрать макс. скорость шарика к-во жизней, типа как в кракаут?
Скорее всего просто код вылез за допустимые пределы. Там же сразу после кода всякие нужные буферы идут, которые будут код затирать, если код попадёт в эту область.
---
Нет. Это процедура print_message валит игру. Если вместо неё поставить заглушку (ret), то игра, как минимум, запустится.
---
Ах, да... Я же совсем забыл! В Batty постоянно используется самомодификация кода. В том числе и переходы по JR вычисляются и подставляются. Просто так слепо JR на JP заменить не удастся.
Круто. Весь топик от начала до конца как детектив прочитал! :)
Уважаемые как удлинить доску и/или замедлить полет шара/мяча.
Кстати, хотел бы заиметь эффект блика на кирпичах в начале каждого раунда. Есть процедурка? Вернее - по каким адресам/меткам искать?
; Routine at AD8F
;
; Used by the routine at all_metal_briks_animation_snd.
Вроде оно?
Я уже, к сожалению, не смогу подсказать, потому что ничего не помню. Но, думаю, что по комментариям и названием процедур эту подпрограмму реально отыскать. Ещё для облегчения поиска можно с исходниками поэкспериментировать - ставить точки останова, закомментировать некоторые процедуры и т.д.