Разработка и ромхакинг > Ромхакинг и программирование
[NES] Код эмулятора и код игры в одно целое.
(1/1)
teremochek:
   Такая мысль. Хорошо-бы иметь исходный код игры с эмулятором, которые вместе компилируются в игру. К тому-же код игры сделать с  заметой "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


Вот таким вот примерно образом, перевести ассемблер рома в просто код. Частями, проверяя каждую.
В идеале можно избавиться от счетчика команд и регистров. Таким образом можно будет добавлять любое количество кода, в любое место*.
Mr2:
teremochek,  не живётся тебе спокойно... :lol:
JAM:
:facepalm:
Пока ты всё это время пытаешься перевести ASM на NES в понятный код, я уже успел его более-менее выучить :lol:
yur:
teremochek, как твои успехи в изучении 6502 - может поделишья полезной инфой, а то на этом форуме принято у многих балаболить и мешать другим, мало того что мешают так ещё и обещают обнародовать доки с подробной инфой
teremochek:

--- Цитата: yur от 24 Февраль 2014, 11:59:14 ---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:
teremochek
ты так задолбаешься переписывать по порядку код. лучше на луа переписывать произвольные части кода игры, которые тебе интересно подменять, есть примеры модификаций игр, марио того же, с новыми фишками:
https://www.youtube.com/watch?v=-jbFjhBYCjg
Inspector_Popabol:
А я могу пользуясь случаем спросить про римейк The Guardian Legend? Будь няшей!
teremochek:

--- Цитата: spiiin от 04 Май 2014, 21:47:00 ---teremochek
ты так задолбаешься переписывать по порядку код. лучше на луа переписывать произвольные части кода игры, которые тебе интересно подменять, есть примеры модификаций игр, марио того же, с новыми фишками:
https://www.youtube.com/watch?v=-jbFjhBYCjg

--- Конец цитаты ---
Верно, но в моем случае есть плюс. Есть код эмулятора, который можно изменять(Ну память к примеру увеличить.)
К тому-же не обязательно все по порядку переписывать. Разумеется частями. Просто в идеале хотелось бы иметь код полностью оторванный от рома.
Segaman:
Вот смотрю я на вас и понимаю: хватит с меня интернета на сегодня :)
teremochek:
Задача не очень простая. Делаю маленькую ошибку, и все глючит конкретно. Т.е. нужно каждую частичку тестировать. В марио, если на глас мерить, то порядка где-то 400 Методов. А главное что все уже дизассемблировано и в высокий уровень переведено. Остается анализировать, писать и тестировать.

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

--- Цитата: Segaman от 05 Май 2014, 22:47:19 ---Вот смотрю я на вас и понимаю: хватит с меня интернета на сегодня :)

--- Конец цитаты ---
Вот такие замечания мне нравятся :)
JAM:
Жду через 50 лет супер-пупер крутой хак на Марио, где можно будет играть ввосьмером на доработаном эмуле =)
teremochek:
Два дня ковырялся, разобраться не мог, почему все так глючит.
Оказалось в дебаггере был один ром, а в ява эмуляторе другой.(Адреса не совпадают.)


--- Цитата: JAM от 06 Май 2014, 23:48:31 ---... можно будет играть ввосьмером ...

--- Конец цитаты ---
Мыслишь в интересном направлении :)
teremochek:
Вот покажу один рабочий метод.

--- Код: ---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:
Покажу, как я пишу метод.

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

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

{
PC=0xB6CD + 1; jsr(0xbfd7);   JSR()
....
PC=0xB6CD + 3; rts();               RTS()
}
После этого пишу тело  метода. Проверяю, если все работает нормально, то операторы JSR  и RTS можно убрать.
Пока хочу как можно больше избавиться от привязанности к счетчику команд PC.
Еще мечтаю, как увеличить кол-во спрайтов.
perfect_genius:
Я так и не понял - что ты хочешь от игры? На какую игру какой мультиплеер?
И дай ссыль на то, что сделал Movax12, пожалуйста.  Я не в курсе.
teremochek:
У меня небольшой успех. Я импортировал в эмулятор HalfNes 40 функций отвечающие за Огненный шар в игре "Super Mario Bros". В коде я избавился от счетчика команд PC. Так-же я заменил branch переходы на IF, DO LOOP.
Честно такой большой минус что - Дебаггера нет. Поэтому приходилось все в ручную тестировать. Устал искать, исправлять ошибки.

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

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

--- Цитата: SUPER_ROBOT от 28 Июнь 2014, 22:49:28 ---Я так и не понял - что ты хочешь от игры? На какую игру какой мультиплеер?
И дай ссыль на то, что сделал 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:
Теремочек, лучше римейк гардиан легенд сделай. С графоном и плюшками
Навигация
Главная страница сообщений

Перейти к полной версии