Разработка и ромхакинг > Ромхакинг
[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.
Еще мечтаю, как увеличить кол-во спрайтов.
Беларус:
Я так и не понял - что ты хочешь от игры? На какую игру какой мультиплеер?
И дай ссыль на то, что сделал 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:
Теремочек, лучше римейк гардиан легенд сделай. С графоном и плюшками
Навигация
Перейти к полной версии