Автор Тема: [NES] Код эмулятора и код игры в одно целое.  (Прочитано 6712 раз)

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

Оффлайн teremochek

  • Пользователь
  • Сообщений: 92
    • Просмотр профиля
   Такая мысль. Хорошо-бы иметь исходный код игры с эмулятором, которые вместе компилируются в игру. К тому-же код игры сделать с  заметой "BNE, BEQ и т.д." на If операторы. Как это сделал "Movax12". Затем модифицировать игру(ы), добавив в нее мультиплеер с большим количеством человек.(8-32). В иделе нужно иметь несколько популярных игр(аркад). Начать лучше с марио, т.к. в нем все разобрано..

   Пока что я начал портировать HalfNes на BlitzMax. И Увяз, не получается.
Не знаю может есть какой-нибудь хороший, простой эмулятор с открытым исходным код, который будет удобнее использовать. Пока, из тех эмулей, которые я смотрел... Каждый эмулятор, как загадка. Если бы вы только представляли, на сколько в них разный код и синтаксис и все остальное. Капитально возится с каждым придется, что-бы разобраться, как и где что работает.



Добавлено позже:

disassembly_pc = PC

if PC>=8000 and PC<=8024
    '... some code
else
    current_inst:Byte = ReadRomByte()
    Opcodes( current_inst )
endif


Вот таким вот примерно образом, перевести ассемблер рома в просто код. Частями, проверяя каждую.
В идеале можно избавиться от счетчика команд и регистров. Таким образом можно будет добавлять любое количество кода, в любое место*.
« Последнее редактирование: 22 Февраль 2014, 16:44:04 от teremochek »

Оффлайн Mr2

  • Пользователь
  • Сообщений: 1592
  • Пол: Мужской
  • Free roaming sorcerer
    • Facebook
    • Просмотр профиля

Оффлайн JAM

  • Пользователь
  • Сообщений: 425
    • Просмотр профиля
Re: [NES] Код эмулятора и код игры в одно целое.
« Ответ #2 : 23 Февраль 2014, 06:55:51 »
:facepalm:
Пока ты всё это время пытаешься перевести ASM на NES в понятный код, я уже успел его более-менее выучить :lol:

Оффлайн yur

  • Пользователь
  • Сообщений: 306
  • Пол: Мужской
  • следи за метлой
    • Просмотр профиля
Re: [NES] Код эмулятора и код игры в одно целое.
« Ответ #3 : 24 Февраль 2014, 11:59:14 »
teremochek, как твои успехи в изучении 6502 - может поделишья полезной инфой, а то на этом форуме принято у многих балаболить и мешать другим, мало того что мешают так ещё и обещают обнародовать доки с подробной инфой

Оффлайн teremochek

  • Пользователь
  • Сообщений: 92
    • Просмотр профиля
teremochek, как твои успехи в изучении 6502 - может поделишья полезной инфой, а то на этом форуме принято у многих балаболить и мешать другим, мало того что мешают так ещё и обещают обнародовать доки с подробной инфой
Извиняюсь что не ответил сразу, но успехов нет. Портировать эмулятор я не осилил.
Почитал книгу. "Игровые Приставки" Выпуск 21. Королев А.Г.
Очень доволен. Всем советую, кто искал полезную информацию о устройстве NES,GB,SMD,PS. Хочется сказать что это как библия эмуляторщика)

Что хочу сказать. Я понял почему сложно сделать более простой и понятный код из ассемблера.
Дело в том CPU связан с PPU и APU. То есть несколько процессоров, которые должны быть синхронизированы. Нельзя сделать долгий или бесконечный цикл в CPU. Нужно иногда проверять что происходит в PPU  и APU. В итоге получается рваный код.

Вот приведу пример. Я Начал встраивать Ассемблер в CPU класс эмулятора (HalfNes).


if (PC >= 0x8000 && PC <= 0x8009) {// reset
          delayInterrupt(); interruptsDisabled = true; cycles += 2;//SEI 78
          decimalModeFlag = false; cycles += 2;                    //CLD D8
          PC=0x8002; lda(imm()); cycles += 2;                      //LDA A9 10
          PC=0x8004; sta(abs()); cycles += 4;                      //STA 8D 00 20
          PC=0x8007; ldx(imm()); cycles += 2;                      //LDX A2 FF
          S = X; cycles += 2;                                      //TXS 9A
          PC=0x8009;//////////// PC++; //ram.read(PC++);
      } else if (PC >= 0x800A && PC <= 0x800E) {// VBlank1
                     lda(abs()); cycles += 4;                      // 00:800A:AD 02 20  LDA $2002 = #$50
          PC=0x800D; isc(abs(Y, dummy.ALWAYS)); cycles += 7;       // 00:800D:10 FB     BPL _DO_WHILE_0001
      } else if (PC >= 0x800F && PC <= 0x8013) {// VBlank2
                     lda(abs()); cycles += 4;                      // 00:800F:AD 02 20  LDA $2002 = #$50
          PC=0x8013; isc(abs(Y, dummy.ALWAYS)); cycles += 7;       // 00:8012:10 FB     BPL _DO_WHILE_0002 _DO_EXIT___LOOP_
      } else if (PC >= 0x8014 && PC <= 0x8017) {
          PC=0x8015; ldy(imm()); cycles += 2;                      // 00:8014:A0 FE     LDY #$FE
          PC=0x8017; ldx(imm()); cycles += 2;                      // 00:8016:A2 05     LDX #$05
      } else if (PC >= 0x8018 && PC <= 0x801E) {// WBootCheck
         //WBootCheck
                     lda(abs(X, dummy.ONCARRY)); cycles += 4 + pb; // 00:8018:BD D7 07  LDA DisplayDigits TopScoreDisplay,X @ $07DC = #$00
          PC=0x801C; cmp(A, imm()); cycles += 2;                   // 00:801B:C9 0A     CMP #$0A
          PC=0x801E; branch(carryFlag); cycles += 2 + pb;          // 00:801D:B0 0C     BCS _END_IF_0002 coldboot
      } else if (PC >= 0x801F && PC <= 0x8021) { //IF_CODE_BLOCK_START_LABEL_0001:
          X--; X &= 0xFF; setflags(X); cycles += 2;                // 00:801F:CA        DEX
          PC=0x8021; isc(abs(Y, dummy.ALWAYS)); cycles += 7;       // 00:8020:10 F6     BPL WBootCheck
      } else if (PC >= 0x8022 && PC <= 0x8028) {// _DO_EXIT___LOOP_CONTINUE_0003:
                     lda(abs()); cycles += 4;                      // 00:8022:AD FF 07  LDA WarmBootValidation = #$A5
          PC=0x8026; cmp(A, imm()); cycles += 2;                   // 00:8025:C9 A5     CMP #$A5
          PC=0x8028; branch(!zeroFlag); cycles += 2 + pb;          // 00:8027:D0 02     BNE _END_IF_0002 coldboot
          //IF_CODE_BLOCK_START_LABEL_0002:
          PC=0x802A; ldy(imm()); cycles += 2;                      // 00:8029:A0 D6     LDY #$D6
          //coldboot:


Пока вот такая каша. Надеюсь получится что-то поинтереснее)

Оффлайн spiiin

  • Модератор
  • Сообщений: 760
    • Просмотр профиля
teremochek
ты так задолбаешься переписывать по порядку код. лучше на луа переписывать произвольные части кода игры, которые тебе интересно подменять, есть примеры модификаций игр, марио того же, с новыми фишками:
https://www.youtube.com/watch?v=-jbFjhBYCjg

Оффлайн Inspector_Popabol

  • Пользователь
  • Сообщений: 1946
  • Пол: Женский
  • ▲Олдфаг, гроза рачья ▲▲
    • Просмотр профиля
А я могу пользуясь случаем спросить про римейк The Guardian Legend? Будь няшей!

Оффлайн teremochek

  • Пользователь
  • Сообщений: 92
    • Просмотр профиля
teremochek
ты так задолбаешься переписывать по порядку код. лучше на луа переписывать произвольные части кода игры, которые тебе интересно подменять, есть примеры модификаций игр, марио того же, с новыми фишками:
https://www.youtube.com/watch?v=-jbFjhBYCjg
Верно, но в моем случае есть плюс. Есть код эмулятора, который можно изменять(Ну память к примеру увеличить.)
К тому-же не обязательно все по порядку переписывать. Разумеется частями. Просто в идеале хотелось бы иметь код полностью оторванный от рома.

Оффлайн Segaman

  • Пользователь
  • Сообщений: 3240
  • Пол: Мужской
  • Blast Processing!
    • Youtube
    • Просмотр профиля
Вот смотрю я на вас и понимаю: хватит с меня интернета на сегодня :)

Оффлайн teremochek

  • Пользователь
  • Сообщений: 92
    • Просмотр профиля
Задача не очень простая. Делаю маленькую ошибку, и все глючит конкретно. Т.е. нужно каждую частичку тестировать. В марио, если на глас мерить, то порядка где-то 400 Методов. А главное что все уже дизассемблировано и в высокий уровень переведено. Остается анализировать, писать и тестировать.

Добавлено позже:
Вот смотрю я на вас и понимаю: хватит с меня интернета на сегодня :)
Вот такие замечания мне нравятся :)

Оффлайн JAM

  • Пользователь
  • Сообщений: 425
    • Просмотр профиля
Жду через 50 лет супер-пупер крутой хак на Марио, где можно будет играть ввосьмером на доработаном эмуле =)

Оффлайн teremochek

  • Пользователь
  • Сообщений: 92
    • Просмотр профиля
Два дня ковырялся, разобраться не мог, почему все так глючит.
Оказалось в дебаггере был один ром, а в ява эмуляторе другой.(Адреса не совпадают.)

... можно будет играть ввосьмером ...
Мыслишь в интересном направлении :)

Оффлайн teremochek

  • Пользователь
  • Сообщений: 92
    • Просмотр профиля
Вот покажу один рабочий метод.
public void _DrawFireball() {
    if (PC < 0xECEA){                                                         
        Y = ram.wram[FBall_SprDataOffset + X];                                                     
        ram.wram[Sprite_Y_Position + Y] = ram.wram[Fireball_Rel_YPos];           
        ram.wram[Sprite_X_Position + Y] = ram.wram[Fireball_Rel_XPos]; cycles += 22 + pb;
    }
    //DrawFirebar:
    A = ram.wram[FrameCounter];             
    lsrA();                                 
    lsrA();                                 
    ram.read(0xECF1+1 + 1); push(A);         
    A &= 0x01;                               
    A ^= 0x64; A &= 0xff;                   
    ram.wram[0x0201 + Y] = A;               
    ram.read(0xECF9+1 + 1); A = pop();       
    lsrA();                                 
    lsrA();                                 
    A = 0x02;                               
                                             
    if (carryFlag){
        A |= ram.wram[0xC0]; A &= 0xff; cycles += 2;
    }
    ram.wram[0x0202 + Y] = A;               
    PC=0xED06; rts(); cycles += 37;         
}

Получается примерно тоже что и дизассемблер "Movax13".
Только в данном случае плюс - быстрая компиляция.

Пока еще много вопросов и задач предстоит решить.
Такой минус еще есть. Java в полно экранном режиме подлагивает.
Проверю потом Экзешник. Может в нем лучше будет.

Оффлайн teremochek

  • Пользователь
  • Сообщений: 92
    • Просмотр профиля
Re: [NES] Код эмулятора и код игры в одно целое.
« Ответ #13 : 26 Июнь 2014, 19:51:37 »
Покажу, как я пишу метод.

JSR ImposeGravity вызов субрутины заменяем на метод _ImposeGravity()

public void _ImposeGravity() {
}

Затем нужно добавить две детали. Оператор JSR()  и выход из рутины RTS() 

{
PC=0xB6CD + 1; jsr(0xbfd7);   JSR()
....
PC=0xB6CD + 3; rts();               RTS()
}

После этого пишу тело  метода. Проверяю, если все работает нормально, то операторы JSR  и RTS можно убрать.
Пока хочу как можно больше избавиться от привязанности к счетчику команд PC.
Еще мечтаю, как увеличить кол-во спрайтов.

Оффлайн perfect_genius

  • Пользователь
  • Сообщений: 1145
    • ВКонтакте
    • Steam
    • Просмотр профиля
Re: [NES] Код эмулятора и код игры в одно целое.
« Ответ #14 : 28 Июнь 2014, 22:49:28 »
Я так и не понял - что ты хочешь от игры? На какую игру какой мультиплеер?
И дай ссыль на то, что сделал Movax12, пожалуйста.  Я не в курсе.

Оффлайн teremochek

  • Пользователь
  • Сообщений: 92
    • Просмотр профиля
Re: [NES] Код эмулятора и код игры в одно целое.
« Ответ #15 : 19 Ноябрь 2014, 17:35:50 »
У меня небольшой успех. Я импортировал в эмулятор HalfNes 40 функций отвечающие за Огненный шар в игре "Super Mario Bros". В коде я избавился от счетчика команд PC. Так-же я заменил branch переходы на IF, DO LOOP.
Честно такой большой минус что - Дебаггера нет. Поэтому приходилось все в ручную тестировать. Устал искать, исправлять ошибки.

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

Минусы: Эмуляция подлагивает  иногда. (К моему удивлению лагать перестало, кода отключил звук.)

Оффлайн teremochek

  • Пользователь
  • Сообщений: 92
    • Просмотр профиля
Re: [NES] Код эмулятора и код игры в одно целое.
« Ответ #16 : 22 Ноябрь 2014, 18:31:02 »
Я так и не понял - что ты хочешь от игры? На какую игру какой мультиплеер?
И дай ссыль на то, что сделал Movax12, пожалуйста.  Я не в курсе.
Извиняюсь, что не ответил. Мозги от вопросов расплавились..

От игры я хочу мультиплеер. Желательно на много игроков.(Как в CS, Quake и т.д.)
Еще, к примеру, если увеличить число спрайтов, тогда можно сделать хак c двойными боссами"The Guardian Legend".

Для простоты я выбрал "SMB", потому что на него уже сделали исходный код. Вообщем-то я его и преобразую, параллельно заглядывая в дизассемблер fceux. Что-бы не было ошибок. Да, и еще адреса нужны.
Честно я не фанат SMB и не знаю что с ним такого сделать. Вероятно следующим шагом, попробую увеличить число Fireballs(Огненных Шариков).
Не уверен, можно-ли это сделать, без увеличения числа спрайтов. А так по идее, нужно расширить память. И поменять адреса переменных.

Вот ссылки на "Super Mario Brothers High Level Disassembly"
http://www.romhacking.net/documents/635/

Топик на форуме
http://forums.nesdev.com/viewtopic.php?f=2&t=9780

Для сравнения:
Код 1
  ProcFireball_Bubble:
      lda PlayerStatus       
      cmp #$02
      bcc ProcAirBubbles     
      lda A_B_Buttons
      and #B_Button             
      beq ProcFireballs         
      and PreviousA_B_Buttons
      bne ProcFireballs         
      lda FireballCounter       
      and #%00000001           
      tax
      lda Fireball_State,x     
      bne ProcFireballs         
      ldy Player_Y_HighPos     
      dey
      bne ProcFireballs
      lda CrouchingFlag         
      bne ProcFireballs
      lda Player_State           
      cmp #$03
      beq ProcFireballs
      lda #Sfx_Fireball         
      sta Square1SoundQueue
      lda #$02                 
      sta Fireball_State,x
      ldy PlayerAnimTimerSet     
      sty FireballThrowingTimer
      dey
      sty PlayerAnimTimer     
      inc FireballCounter       
      . . .   


Код 2
.proc ProcFireball_Bubble

    if PlayerStatus <> #2         
        if A_B_Buttons & #BUTTON_B && not a & PreviousA_B_Buttons
            mb x := FireballCounter & #%00000001                     
            if !Fireball_State[ x ] && y := Player_Y_HighPos - 1 == zero && !CrouchingFlag && Player_State <> #3
                mb Square1SoundQueue := #SFX_Fireball               
                mb Fireball_State[ x ] := #2       
                mb y, FireballThrowingTimer := PlayerAnimTimerSet   
                mb PlayerAnimTimer := y - 1       
                inc FireballCounter             
if PlayerStatus <> #0
    mb y, FireballThrowingTimer := PlayerAnimTimerSet
mb PlayerAnimTimer := y - 1
mb a := #1
endif
            endif
        endif
        . . .     

                                                                                     P.S. Jumanji Entertaiment System

Оффлайн Smoke

  • Пользователь
  • Сообщений: 3430
  • Пол: Мужской
  • Get Serious!
    • Steam
    • Просмотр профиля
Re: [NES] Код эмулятора и код игры в одно целое.
« Ответ #17 : 25 Ноябрь 2014, 13:37:06 »
Теремочек, лучше римейк гардиан легенд сделай. С графоном и плюшками