Автор Тема: [NES] Ассемблер перевести в понятный код  (Прочитано 17592 раз)

0 Пользователей и 2 Гостей просматривают эту тему.

Оффлайн JAM

  • Пользователь
  • Сообщений: 425
    • Просмотр профиля
Re: [NES] Ассемблер перевести в понятный код
« Ответ #30 : 23 Март 2013, 03:12:02 »
Даю реально дельный совет.
Вбей в Google фразу типа "6502 opcode list" или "NES ASM opcodes". Наверняка ты найдёшь или голый список команд, или гид с описанием комманд, что тоже хорошо. Скорее всего, на английском. Команд всего 256, но есть много похожих команд, которые можно сгуппировать, например: LDA, LDA,X, LDA,Y или PHA, PHX, PHY и т.п. Всего групп около 30, это не так много. Не обязательно учить команды, достаточно их понимать. Без понимания команд даже код, который ты привёл, даже с комментариями -- как перевод с японского на китайский. Научись понимать команды, и ты будешь знать китайский =)

Но даже зная команды, придётся попотеть, чтобы понять, какой смысл в определённой команде. Например, ты будешь понимать, что одна команда считывает значение из памяти по определённому адресу в аккумулятор. Другая команда сравнивает значение с определённым байтом в коде. Третья команда выполняет прыжок при определённом условии, четвёртая команда модифицирует значение в аккумуляторе, а пятая команда сохраняет значение аккумулятора обратно в память по тому же адресу. Вот только, не зная, что находится в RAM памяти по адресу $0123, так и не поймёшь, зачем всё это. Благо, Марио игра изученная, и для неё наверняка есть ROMMap и RAMMap. Для неизученных игр придётся самому отслежить с помощью Debugger'а, что же такое по адресу $0123 и когда оно меняется.

Не нужно бояться ASM, как огня. Уж поверь мне. Лет 8 назад я скачал одну дизассемблированную процедуру, долго в неё втыкал, но так ничего и не понял. Прям, как ты сейчас. 4 года назад я стал изучать ассемблер в одиночку, по списку команд. 3 года назад я всё-таки осилил ту процедуру. Даже зная все команды, я месяц втыкал в 27kb текста, пока до меня не начало доходить, что к чему, путём проб и ошибок. С тех пор научился патчи делать для некоторых игр, понимать код в целом, и даже видеть его в HEX-редакторе. Сейчас я как Сайфер из Матрицы, только блондинок и брюнеток не различаю. =) Смотрю на ROM в Hex-редакторе, и вижу где код, где таблицы, где спрайтовая графика, а где всё остальное...

Но это только для одной системы. Ассемблер для Сеги для меня до сих пор -- тёмный лес, хотя там есть некоторые успехи. Для одного хака, например, чтобы изменить 20 байт в разных частях ROM'а, мне лично потребовалось 15 часов, а ты хочешь, чтобы всё и сразу одним нажатием кнопки =) И хотя та игра сильно изученная и даже дизассемблирвоанная, в хаке какие-то данные изменены, где-то удлиннены или укорочены массивы и т.п. В итоге, часть данных перенесена, какие-то данные сдвинуты на X байт, какие-то на Y байт, а все остальные -- на Й байт.

Оффлайн teremochek

  • Пользователь
  • Сообщений: 93
    • Просмотр профиля
Re: [NES] Ассемблер перевести в понятный код
« Ответ #31 : 23 Март 2013, 19:15:58 »
Спасибо. Хороший совет.

Оффлайн teremochek

  • Пользователь
  • Сообщений: 93
    • Просмотр профиля
Re: [NES] Ассемблер перевести в понятный код
« Ответ #32 : 28 Март 2013, 20:22:50 »
Давайте оставим x816, т.к. он сложнее, и посмотрим простой дизассемблер.
Вот еще один пример. На этот раз - "Galaxian".
ProcessPlayerBullet:
LDA spr_buf(32,ycoo)
BEQ skp021
CMP #200
BEQ skp022
tail05: LDA spr_buf(32,ycoo)
SEC
SBC #4
STA spr_buf(32,ycoo)
BCS ret06
skp021: LDA #200
STA spr_buf(32,ycoo)
skp022: LDA PlayerDiedThisVsync
BEQ PinBulletToPlayer
LDA #CHR_Blank
STA spr_buf(32,tile)
ret06: RTS

Подпрограмма - "ProcessPlayerBullet:". В конце стоит "RTS". Т.е. возврат. Похоже на Функцию, как во многих языках.
Можно записать так:
Function ProcessPlayerBullet()За место "RTS" - End Function
LDA spr_buf(32,ycoo)
Загрузить память в аккамулятор. Это не самый лучший пример, потому что "spr_buf(32,ycoo)" это массив.
Очевидно это координата Y "спрайта" - пули игрока.
записываем просто:
a = spr_buf(32,ycoo)следующая
BEQ skp021Я понимаю так. Что-то в роде IF ... GOTO ...
Поскольку Compare команды не видно. Наверноо сравниваем с нулем "0"
If a == 0 Then Goto skp021дальше
CMP #200
BEQ skp022
Сравниваем a и 200
If a==200 Then Goto skp022Далее Лабель tail05: Записываются везде по разному. У меня так.
#tail05

LDA spr_buf(32,ycoo)
a = spr_buf(32,ycoo)
SEC
I=1
SBC #4  'Вычитание с займом ?
a = a - 4  ?

STA spr_buf(32,ycoo)  'Сохраняем А в память.
spr_buf(32,ycoo) = a
BCS ret06   'Условный переход, если перенос. Не понимаю.

Пока хватит...

Оффлайн vladikcomper

  • Пользователь
  • Сообщений: 57
  • Пол: Мужской
    • Просмотр профиля
Re: [NES] Ассемблер перевести в понятный код
« Ответ #33 : 29 Март 2013, 01:38:27 »
SEC
SBC #4
STA spr_buf(32,ycoo)
BCS ret06

SEC - Задать Carry флаг.

SBC отнимает из аккумулятора (А) значение 4 и инвертированное значение Carry-флага. Т.е., если Carry=1, ничего не отнимается, если Carry=0, дополнительно отнимается 1. В процессоре 6502 не предусмотрено отнимание без учета Carry-флага, поэтому флаг Carry специально задается инструкцией SEC, чтобы гарантировать, что SBC отнимает именно 4.

SBC очищает флаг Carry, если при выполнении вычитая случилось заимствование (borrow), т.е. результат пересек границу 00-FF. Например, если отнять из 01 число 04, получится FD, тогда флаг Carry будет очищен. Таким образом...

BCS - Branch if carry set - переходит, если заимствования не произошло (Carry=1).

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

Оффлайн JAM

  • Пользователь
  • Сообщений: 425
    • Просмотр профиля
Re: [NES] Ассемблер перевести в понятный код
« Ответ #34 : 29 Март 2013, 12:05:52 »
Я понимаю так. Что-то в роде IF ... GOTO ...
Поскольку Compare команды не видно. Наверноо сравниваем с нулем "0"
Да, это короткий вариант сравнения. Если нужно сравнить с нулём, то просто
LDA $1234
BEQ Метка

Если нужно сравнить с чем-то ещё:
LDA $1234
CMP #$56
BEQ Метка

Оффлайн teremochek

  • Пользователь
  • Сообщений: 93
    • Просмотр профиля
Re: [NES] Ассемблер перевести в понятный код
« Ответ #35 : 01 Апрель 2013, 16:08:36 »
vladikcomper, JAM, Спасибо за полезную информацию.

Итак, в целом  получилась такая функция.
Function ProcessPlayerBullet()
    a = spr_buf(32,ycoo)
    If a == 0 Then Goto skp021
    If a == 200 Then Goto skp022
#tail05
    a = spr_buf(32,ycoo)
C_FLAG = 1
a = a - 4
spr_buf(32,ycoo) = a
#skp021
a = 200
spr_buf(32,ycoo) = a
#skp022
a = PlayerDiedThisVsync
If a == 0 Then Goto PinBulletToPlayer
a = CHR_Blank
spr_buf(32,tile) = a
#ret06
End Function 'RTS

Теперь можно еще упростить, убрав загрузку в регистры и сохранение из регистров.
Function ProcessPlayerBullet() 
    If spr_buf(32,ycoo) == 0 Then Goto skp021
    If spr_buf(32,ycoo) == 200 Then Goto skp022
#tail05
spr_buf(32,ycoo) = spr_buf(32,ycoo) - 4
if spr_buf(32,ycoo) > 0 Then Goto #ret06
#skp021
spr_buf(32,ycoo) = 200
#skp022
If PlayerDiedThisVsync == 0 Then Goto PinBulletToPlayer
spr_buf(32,tile) = CHR_Blank
#ret06
End Function
Возможно хорошая идея, избавиться от Меток ? (label).

Получилось вот так.
Function ProcessPlayerBullet()
    If spr_buf(32,ycoo) == 0 or spr_buf(32,ycoo) == 200
    spr_buf(32,ycoo) = 200
    If PlayerDiedThisVsync == 0 Then Goto PinBulletToPlayer
    spr_buf(32,tile) = CHR_Blank
    Return
Endif
#tail05
spr_buf(32,ycoo) = spr_buf(32,ycoo) - 4
if spr_buf(32,ycoo) > 0 Then Return
spr_buf(32,ycoo) = 200
If PlayerDiedThisVsync == 0 Then Goto PinBulletToPlayer
spr_buf(32,tile) = CHR_Blank
End Function

Метка "#tail05" осталась, т.к. ссылка на нее находится вне.
Как оказалось, нужно добавить еще одну часть кода, для ясности картины.
Вот эту

PinBulletToPlayer:
   LDA player_x_pos   
   CLC
   ADC #124
   STA spr_buf(32,xcoo)   
   LDX #0
   JSR FireHoldoff      
   JSR StartPlayerShootSound
   JMP tail05      


Упрощаем:

     #PinBulletToPlayer
     spr_buf(32,xcoo) = player_x_pos +124
     FireHoldoff()      
     StartPlayerShootSound()
     GOTO tail05   


Теперь смотрим, что получается вместе:

Function ProcessPlayerBullet() 
    If spr_buf(32,ycoo) == 0 or spr_buf(32,ycoo) == 200
     spr_buf(32,ycoo) = 200
    If PlayerDiedThisVsync == 0
        spr_buf(32,xcoo) = player_x_pos +124 ; PinBulletToPlayer
                FireHoldoff()
        StartPlayerShootSound()
                GOTO tail05
    endif
      spr_buf(32,tile) = CHR_Blank
      Return
    Endif
#tail05
spr_buf(32,ycoo) = spr_buf(32,ycoo) - 4
if spr_buf(32,ycoo) > 0 Then Return
spr_buf(32,ycoo) = 200
If PlayerDiedThisVsync == 0
   spr_buf(32,xcoo) = player_x_pos +124   ; PinBulletToPlayer
           FireHoldoff()
   StartPlayerShootSound()
           GOTO tail05
endif
spr_buf(32,tile) = CHR_Blank
End Function

Наверняка можно записать еще проще, пока не знаю...
Код без меток получился больше по объему, чем Код с метками. И к тому-же Код с метками воспринимается лучше.

Оффлайн teremochek

  • Пользователь
  • Сообщений: 93
    • Просмотр профиля
Re: [NES] Ассемблер перевести в понятный код
« Ответ #36 : 02 Апрель 2013, 16:34:27 »
Вот. Код без меток получился такой.

Function ProcessPlayerBullet() 
    If spr_buf(32,ycoo) == 0 or spr_buf(32,ycoo) == 200
     spr_buf(32,ycoo) = 200
    If PlayerDiedThisVsync == 0
spr_buf(32,xcoo) = player_x_pos +124
                FireHoldoff()
        StartPlayerShootSound() 
    else
        spr_buf(32,tile) = CHR_Blank
Return
            endif
    Endif

do While PlayerDiedThisVsync == 0
spr_buf(32,ycoo) = spr_buf(32,ycoo) - 4
if spr_buf(32,ycoo) > 0 Then Return
spr_buf(32,ycoo) = 200
If PlayerDiedThisVsync == 0
     spr_buf(32,xcoo) = player_x_pos +124   
             FireHoldoff()
     StartPlayerShootSound() 
endif
Loop

spr_buf(32,tile) = CHR_Blank
End Function

Вот такой возник вопрос.
...
CMP #5      
BCC skp019

...

Потом, в конце Функции встречается
...
DEC l_cur_bullet
BNE NextEnemyBullet


BCC работает без CMP т.е.
If a<0 Then Goto skp019

,а BNE ,будет работать с тем CMP, что написан вначале?


Еще, кажется я понял, как записать такое выражение.. Но это только в конкретном случае..
LDA spr_buf(33,xcoo),x
------------------------------
a = spr_buf(33 + x, xcoo)
Где   33 + x   это номер спрайта..

Оффлайн MetalliC

  • Технический консультант
  • Сообщений: 9390
  • Пол: Мужской
  • Demul team / MAME developer
    • Просмотр профиля
Re: [NES] Ассемблер перевести в понятный код
« Ответ #37 : 02 Апрель 2013, 16:54:56 »
Цитата: teremochek
а BNE ,будет работать с тем CMP, что написан вначале?

BNE пляшет от флага Z, который изменяют почти все команды разве что кроме перехода/возврата, а не только CMP
DEC l_cur_bullet --- читаем в http://www.6502.org/tutorials/6502opcodes.html про комманду DEC - Affects Flags: S Z, т.е. после декремента в зависимости от результата взводятся/сбрасываются флаги Zero и Sign
BNE NextEnemyBullet
итого это можно записать как
l_cur_bullet = l_cur_bullet -1;
if (l_cur_bullet != 0) goto NextEnemyBullet;


ты почему-то думаешь что типа только CMP меняет флаги, но как я уже сказал это делают почти все комманды, даже например LDA - после записи числа в аккумулятор будут изменены флаги S и Z, грубо говоря CMP делается как бы автоматом после почти всех операций

Оффлайн teremochek

  • Пользователь
  • Сообщений: 93
    • Просмотр профиля
Re: [NES] Ассемблер перевести в понятный код
« Ответ #38 : 04 Апрель 2013, 11:36:02 »
Если я правильно понял, то CMP перед BCC, BCS стоят не просто так.
И по видимому записать такую последовательность:

CMP #5
BCC skp019
CMP #17
BCS DoneWithThisBullet


можно так:

if a - 5 < 0 Then Goto skp019
if a - 17 >= 0 Then Goto DoneWithThisBullet

Оффлайн GManiac

  • Пользователь
  • Сообщений: 1284
    • Просмотр профиля
Re: [NES] Ассемблер перевести в понятный код
« Ответ #39 : 04 Апрель 2013, 15:11:08 »
Конечно, не просто так, CMP - это явное сравнение. Сравнение - это простановка флагов. После многих арифметических и не только команд происходит неявное сравнение результата с нулём, и это может использоваться в следующих командах - обычно, бранчах, но иногда и в других командах и даже в последовательности команд. Что может привести к не совсем очевидной логике для неопытного чтеца.
А если нужно сравнить произвольный операнд с произвольным числом, тут CMP и помогает.

Это самое неявное сравнение, точнее, простановка флагов (причём не всех всегда - некоторые команды проставляют не все флаги), делает асм более гибким, чем ЯВУ, но может усложнить понимание. В сях есть что-то похожее, когда можно и операцию произвести, и сравнение сразу, вроде
if (--a > 0) {...};

Две последние строки можно упростить:
if a < 5 then ...
if a >= 17 then ...
Добавлено позже:
Насчёт "не всех флагов": для M6502 могу ошибаться, но для M68k есть такое.
« Последнее редактирование: 04 Апрель 2013, 15:21:44 от GManiac »

Оффлайн Ti_

  • Пользователь
  • Сообщений: 3265
  • Пол: Мужской
    • ВКонтакте
    • Youtube
    • Просмотр профиля
Re: [NES] Ассемблер перевести в понятный код
« Ответ #40 : 04 Апрель 2013, 20:21:30 »
LDA не влияет на carry, поэтому иногда в коде CMP может и раньше быть - через строчку или даже несколько.

Вот примеры использования:
BANK0:8C22                 LDA     Objects_X_speed,X
BANK0:8C25                 CMP     #$FF
BANK0:8C27                 LDA     #$18
BANK0:8C29                 BCS     loc_0_8C57


BANK0:8951                 LDA     Level_ID
BANK0:8953                 CMP     #4
BANK0:8955                 LDA     bike_frames_ids - $38,Y
BANK0:8958                 BCC     loc_0_895D
BANK0:895A                 LDA     bike_frames_ids2 - $38,Y
BANK0:895D
BANK0:895D loc_0_895D
BANK0:895D                 STA     Obj_anim_frame,X
BANK0:8960                 RTS



Оффлайн teremochek

  • Пользователь
  • Сообщений: 93
    • Просмотр профиля
Re: [NES] Ассемблер перевести в понятный код
« Ответ #41 : 05 Апрель 2013, 17:04:46 »
Посмотрел что есть в верху кода. Где все переменные.
В основном встречаются  3 типа:

1. numplayers .byt 0
Просто байтовая переменная, в конце которой стоит "0". Не знаю что он обозначает.

2. chrdest .word 0
Строковая переменная. Тоже вконце стоит "0".

3. velocity_bullet_x .dsb 24,0
dsb - Data Storage of Bytes, очевидно массив. Из 24 Байт. И опять "0".

numplayers : BYTE
chrdest : STRING
velocity_bullet_x : BYTE [ 24 ]



Попробовал перевести еще одну функцию.

Код.

l_player_width = local5
l_player_left_edge = local6
l_cur_bullet = local7

ProcessAllBullets:
JSR ProcessPlayerBullet
LDA #7
STA l_cur_bullet
LDY #0
LDX #0
NextEnemyBullet:
CLC ; loop 7 times
LDA velocity_bullet_x,y
ADC spr_buf(33,xcoo),x
STA spr_buf(33,xcoo),x ; sprite33..sprite39 (enemy bullets)
CLC
LDA spr_buf(33,ycoo),x ; if Y coordinate of bullet is 0
BNE skp018
STA spr_buf(33,xcoo),x ; reset X coordinate
BEQ DoneWithThisBullet
skp018: ADC #2
STA spr_buf(33,ycoo),x ; move enemy bullets down at 2pixels/vsync
INC PlayerDiedThisVsync
DEC PlayerDiedThisVsync ; test PlayerDiedThisVsync without modifying A
BNE DoneWithThisBullet
SEC
SBC #202 ; bulletY-202
CMP #5 ; bulletY-202 <=> 5?
BCC skp019
CMP #17 ; bulletY-202 <=> 17?
BCS DoneWithThisBullet

LDA player_x_pos
ADC #119
STA l_player_left_edge ; player_x_pos + 119 = left edge
LDA #11
STA l_player_width ; 11 = width
JMP skp020

skp019: LDA player_x_pos
ADC #122
STA l_player_left_edge ; player_x_pos + 122 = left edge
LDA #5
STA l_player_width ; 5 = width

skp020: SEC
LDA spr_buf(33,xcoo),x
SBC l_player_left_edge ; did it collide with the ship?
CMP l_player_width
BCS DoneWithThisBullet
LDA #1
STA PlayerDiedThisVsync
JSR StartPlayerDiedSound
LDA #0
STA spr_buf(33,ycoo),x
DoneWithThisBullet:
INY
INX
INX
INX
INX
DEC l_cur_bullet
BNE NextEnemyBullet
RTS

Избавляемся от загрузки, сохранения регистров.
l_player_width = local5
l_player_left_edge = local6
l_cur_bullet = local7

Function  ProcessAllBullets()
ProcessPlayerBullet()
l_cur_bullet = 7
y = 0
x = 0

# NextEnemyBullet  ; loop 7 times

velocity_bullet_x[ y ] += spr_buf(33+x,xcoo)
spr_buf(33+x,xcoo) = velocity_bullet_x[ y ]
if spr_buf(33+x,xcoo) <> 0 Then GoTo skp018
spr_buf(33+x,xcoo) = 0
if spr_buf(33+x,xcoo) == 0 Then Goto DoneWithThisBullet

# skp018:
    spr_buf(33+x,ycoo)  +=2
If PlayerDiedThisVsync <> 0 Then Goto DoneWithThisBullet
spr_buf(33+x,ycoo) -= 202
If spr_buf(33+x,ycoo) - 5 < 0 Then Goto skp019  ;BCC
If spr_buf(33+x,ycoo) - 17 >= 0 Then Goto DoneWithThisBullet  ;BCS


l_player_left_edge = player_x_pos + 119
l_player_width = 11
Goto skp020 

# skp019
l_player_left_edge = player_x_pos + 122
l_player_width = 5

# skp020
spr_buf(33+x,xcoo) -= l_player_left_edge
if spr_buf(33+x,xcoo) - l_player_width >= 0 Then Goto DoneWithThisBullet

PlayerDiedThisVsync = 1
StartPlayerDiedSound()
spr_buf(33+x,ycoo) = 0

# DoneWithThisBullet
y +=1
x +=4
l_cur_bullet -=1
If l_cur_bullet <> 0 Then GoTo NextEnemyBullet
End Function

Избавляемся от меток.
Function  ProcessAllBullets()
ProcessPlayerBullet()
l_cur_bullet = 7
y = 0
x = 0

Do
velocity_bullet_x[ y ] += spr_buf(33+x,xcoo)
spr_buf(33+x,xcoo) = velocity_bullet_x[ y ]
if spr_buf(33+x,xcoo) <> 0
else
   spr_buf(33+x,xcoo) = 0
   if spr_buf(33+x,xcoo) == 0
      y +=1
      x +=4
      l_cur_bullet -=1
      If l_cur_bullet <> 0 Then Continue
   endif
endif

    spr_buf(33+x,ycoo)  +=2
If PlayerDiedThisVsync <> 0
else
   spr_buf(33+x,ycoo) -= 202
   If spr_buf(33+x,ycoo) - 5 < 0
      l_player_left_edge = player_x_pos + 122
      l_player_width = 5

      spr_buf(33+x,xcoo) -= l_player_left_edge
      if spr_buf(33+x,xcoo) - l_player_width >= 0
          else
        PlayerDiedThisVsync = 1
        StartPlayerDiedSound()
        spr_buf(33+x,ycoo) = 0
      endif
        y +=1
        x +=4
        l_cur_bullet -=1
        If l_cur_bullet <> 0 Then Continue
   endif
   
   If spr_buf(33+x,ycoo) - 17 >= 0 
       else
     l_player_left_edge = player_x_pos + 119
     l_player_width = 11

      spr_buf(33+x,xcoo) -= l_player_left_edge
      if spr_buf(33+x,xcoo) - l_player_width >= 0
          else
        PlayerDiedThisVsync = 1
        StartPlayerDiedSound()
        spr_buf(33+x,ycoo) = 0
      endif
   endif
endif

y +=1
x +=4
l_cur_bullet -=1
If l_cur_bullet <> 0 Then Continue
break
loop
End Function

Надо-бы подумать, как можно проверить работоспособность этих функции..

Оффлайн JAM

  • Пользователь
  • Сообщений: 425
    • Просмотр профиля
Re: [NES] Ассемблер перевести в понятный код
« Ответ #42 : 06 Апрель 2013, 00:04:13 »
А вот как ты их проверишь-то?
Массивы xcoo и ycoo, ты, допустим задал. А их адреса в роме?

STA l_cur_bullet

Это даже без перевода на C работать не будет. В исходном коде был адрес, заменённый на переменную l_cur_bullet где-то в самом начале кода. Не указав его, куда прикажешь сохранять? Нельзя просто так выдрать из рома кусок кода с переменными, не расшифровав их. Вернее можно, но работать код не будет =)

Оффлайн teremochek

  • Пользователь
  • Сообщений: 93
    • Просмотр профиля
Re: [NES] Ассемблер перевести в понятный код
« Ответ #43 : 11 Апрель 2013, 10:01:38 »
А вот как ты их проверишь-то?
Массивы xcoo и ycoo, ты, допустим задал. А их адреса в роме?
Не понимаю, зачем нужны их адреса.
За место спрайтов использовал квадраты.
Хочу разобраться, как Графику рома приделать.. (chr).
Вроде там 64 плитки. Вот только как именно они загружаются в память.. подряд, или в опр. порядке.
На худой конец можно скопировать из эмулятора буфер VRAM.

STA l_cur_bullet

Это даже без перевода на C работать не будет. В исходном коде был адрес, заменённый на переменную l_cur_bullet где-то в самом начале кода. Не указав его, куда прикажешь сохранять? Нельзя просто так выдрать из рома кусок кода с переменными, не расшифровав их. Вернее можно, но работать код не будет =)

как написано перед функцией.
l_cur_bullet = local7

Вроде так можно делать, два имени у одной переменной. Если нельзя. То просто заменить все l_cur_bullet на local7.


Перевел еще две простенькие функции.

IsPlayerMoving:
LDA PlayerDiedThisVsync
BNE ret18
JSR IsPlayerGoingLeft
LDA activejoykeys
AND #JOY_RIGHT
BEQ ret19
LDA player_x_pos
CMP #106 ; normalized 234
BEQ ret19
INC player_x_pos
ret19: RTS

;-------------------------------------------------------------------------------
IsPlayerGoingLeft:
LDA activejoykeys
AND #JOY_LEFT
BEQ ret19
LDA player_x_pos
CMP #<-106 ; clip player to no further left than -106 (normalized 22)
BEQ ret20
DEC player_x_pos
ret20: RTS

Перевод:
Function IsPlayerMoving()
IF PlayerDiedThisVsync <> 0 Then Return   ; BNE ret18
IsPlayerGoingLeft()
if activejoykeys AND #JOY_RIGHT == 0 Then Return
if player_x_pos == 106 Then Return  ;BEQ 234 normalized
player_x_pos:+1
end function

;-------------------------------------------------------------------------------
Function IsPlayerGoingLeft()
if activejoykeys AND #JOY_LEFT == 0 Then Return
if player_x_pos == -106 Then Return ;(normalized 22)
player_x_pos:-1
end function

Оффлайн JAM

  • Пользователь
  • Сообщений: 425
    • Просмотр профиля
Re: [NES] Ассемблер перевести в понятный код
« Ответ #44 : 12 Апрель 2013, 21:54:24 »
   if player_x_pos == 106 Then Return  ;BEQ 234 normalized
Тогда уж не 106, а 262. Хотя ХЗ, там Hex в твоём коде или нет

Оффлайн teremochek

  • Пользователь
  • Сообщений: 93
    • Просмотр профиля
Re: [NES] Ассемблер перевести в понятный код
« Ответ #45 : 01 Ноябрь 2014, 19:18:07 »
(оффтоп)
Такая мысль пришла. Легче сделать видео, чем игру. Сначала записать видео на эмуляторе. А потом по верх него положить 3Д модели в Блендере.


Оффлайн s1nka

  • Пользователь
  • Сообщений: 1571
  • Пол: Мужской
    • Steam
    • Просмотр профиля
Re: [NES] Ассемблер перевести в понятный код
« Ответ #46 : 01 Ноябрь 2014, 20:08:45 »
teremochek, выглядит офигенно.

Оффлайн teremochek

  • Пользователь
  • Сообщений: 93
    • Просмотр профиля
Re: [NES] Ассемблер перевести в понятный код
« Ответ #47 : 02 Ноябрь 2014, 11:46:26 »
Сложность в том, что объекты в NES нарисованы в Ортографическом виде.
Но что-бы нам показать трехмерность нужен перспективный вид.

Такая мысли пришла, смоделировать объект в перспективном виде, но что-бы он выглядел так, как в ортографическом.
Это для игр типа Zelda. Где картинка статична, и перемещается лишь при переходе на другой экран.