• 이용안내
  • 이상한 모자
  • 야채인간
  • 김민하 공화국
  • 신간 안내
혁명은 언제나 시기상조

에뮬레이터

안드로이드 에뮬 게임기에서 ES-DE와 Standalone 에뮬레이터 연결 문제

2025년 12월 15일 by 이상한 모자

최근 이 문제를 깊이, AI 친구들과 함께 고민하였다.

증상은 ES-DE를 프론트엔드로 쓰고 있을 때 Retroarch로 구동하는 게임은 문제가 없지만, 외부의 에뮬레이터를 사용해야 하는 경우에는 제대로 작동하지 않고 에뮬레이터의 메인 화면 등으로 연결되는 문제이다. 내 경우에는 Duckstation(PS1), PPSSPP(PSP), Redream(Dreamcast), NetherSX2(PS2)가 말썽이었다.

핵심은 ES-DE가 ROM의 주소(위치)를 개별 에뮬레이터에 넘겨 줄 때, 어떤 형식으로 넘겨줄 것인가의 문제이다. 크게 보면 ES-DE는 3가지 변수를 사용할 수 있다.

1) ROMSAF

일괄 디폴트로 잡혀 있는 변수다. content://com.android.externalstorage.documents/… 와 같은 형태로 주소를 넘겨준다.

2) ROMPROVIDER

ES-DE가 생성하는 변수로 content://org.es_de.frontend.files/…의 형태이다.

3) ROMRAW

/storage/xxxx-xxxx/Games/ps2/xxx.iso와 같이 파일 문자열을 그대로 보낸다.

문제는 에뮬레이터에 따라서 1)로 해결되는 경우, 2)만 먹히는 경우, 3)만 먹히는 경우가 제각각이라는 것이다. 즉, 1)로 주소 전달이 실패하는 경우 2)나 3)으로 시도해봐야 한다는 것이다. 그러면 이 변수는 어디서 어떻게 바꿔줄 수 있는가? es_systems.xml에서 규정해야 한다. 이 파일은 바꾸고 싶은 부분만 발췌한 후 파일로 만든 다음에 ES-DE/custom_systems(처음 ES-DE 구동할 때에 어디에 폴더를 만들 것인지 설정했을 것이다. 바로 그 폴더이다…) 폴더에 저장하면 된다. 가령 기본 설정에 어떻게 반영되는지를 찾아보면 플레이스테이션 2의 경우는 다음과 같은 내용이다.

<system>
   <name>ps2</name>
   <fullname>Sony PlayStation 2</fullname>
   <path>%ROMPATH%/ps2</path>
   <extension>.bin .BIN .chd .CHD .ciso .CISO .cso .CSO .dump .DUMP .elf .ELF .gz .GZ .m3u .M3U .mdf .MDF .img .IMG .iso .ISO .isz .ISZ .ngr .NRG</extension>
   <command label="AetherSX2 (Standalone)">%EMULATOR_AETHERSX2% %ACTIVITY_CLEAR_TASK% %ACTIVITY_CLEAR_TOP% %ACTION%=android.intent.action.MAIN %EXTRA_bootPath%=%ROMSAF%</command>
   <command label="Play! (Standalone)">%EMULATOR_PLAY!% %ACTION%=android.intent.action.VIEW %DATA%=%ROMSAF%</command>
   <platform>ps2</platform>
   <theme>ps2</theme>
</system>

이대로 실행하면 NetherSX2는 파일 이름이 필요하다든지 못 찾겠다고 하면서 아무런 일도 하지 않는다. %EXTRA_bootPath%=%ROMSAF% 부분에서 ‘content://com.android.externalstorage.documents/… ‘을 해석해 ROM 파일 위치를 추출하는 게 아니라, 그냥 문자열 그대로를 파일 이름으로 받아서 ROM 위치를 못 찾는 것이다. 따라서 해당 변수를 ROMRAW로 바꿔 파일명 그대로를 전달해야 한다. 이를 적용하면 es_system.xml은 이렇게 만들어야 할 것이다.

<systemList>
   <system>
    <name>ps2</name>
    <fullname>Sony PlayStation 2</fullname>
    <path>%ROMPATH%/ps2</path>
    <extension>.bin .BIN .chd .CHD .ciso .CISO .cso .CSO .dump .DUMP .elf .ELF .gz .GZ .m3u .M3U .mdf .MDF .img .IMG .iso .ISO .isz .ISZ .ngr .NRG</extension>
    <command label="NetherSX2(AetherSX2) (Standalone)">%EMULATOR_AETHERSX2% %ACTIVITY_CLEAR_TASK% %ACTIVITY_CLEAR_TOP% %ACTION%=android.intent.action.MAIN %EXTRA_bootPath%=%ROMRAW%</command>
    <command label="Play! (Standalone)">%EMULATOR_PLAY!% %ACTION%=android.intent.action.VIEW %DATA%=%ROMSAF%</command>
    <platform>ps2</platform>
    <theme>ps2</theme>
  </system>
</systemList>

나머지도 마찬가지 원리에 따라서 진행하면 된다.

PPSSPP는 ROMPROVIDER, Redream도 ROMPROVIDER, DuckStation은 ROMRAW 변수가 먹혔다. 이를 다 적용하려면 아래와 같은 내용으로 es_system.xml 파일을 작성하면 된다.

<systemList>
<system>
<name>ps2</name>
<fullname>Sony PlayStation 2</fullname>
<path>%ROMPATH%/ps2</path>
<extension>.bin .BIN .chd .CHD .ciso .CISO .cso .CSO .dump .DUMP .elf .ELF .gz .GZ .m3u .M3U .mdf .MDF .img .IMG .iso .ISO .isz .ISZ .ngr .NRG</extension>
<command label="NetherSX2(AetherSX2) (Standalone)">%EMULATOR_AETHERSX2% %ACTIVITY_CLEAR_TASK% %ACTIVITY_CLEAR_TOP% %ACTION%=android.intent.action.MAIN %EXTRA_bootPath%=%ROMRAW%</command>
<command label="Play! (Standalone)">%EMULATOR_PLAY!% %ACTION%=android.intent.action.VIEW %DATA%=%ROMSAF%</command>
<platform>ps2</platform>
<theme>ps2</theme>
</system>
<system>
<name>psx</name>
<fullname>Sony PlayStation</fullname>
<path>%ROMPATH%/psx</path> <extension>.bin .BIN .cbn .CBN .ccd .CCD .chd .CHD .cue .CUE .ecm .ECM .exe .EXE .img .IMG .iso .ISO .m3u .M3U .mdf .MDF .mds .MDS .minipsf .MINIPSF .pbp .PBP .psexe .PSEXE .psf .PSF .toc .TOC .z .Z .znx .ZNX .7z .7Z .zip .ZIP</extension>
<command label="Beetle PSX">%EMULATOR_RETROARCH% %EXTRA_CONFIGFILE%=/storage/emulated/0/Android/data/%ANDROIDPACKAGE%/files/retroarch.cfg %EXTRA_LIBRETRO%=mednafen_psx_libretro_android.so %EXTRA_ROM%=%ROM%</command>
<command label="Beetle PSX HW">%EMULATOR_RETROARCH% %EXTRA_CONFIGFILE%=/storage/emulated/0/Android/data/%ANDROIDPACKAGE%/files/retroarch.cfg %EXTRA_LIBRETRO%=mednafen_psx_hw_libretro_android.so %EXTRA_ROM%=%ROM%</command>
<command label="PCSX ReARMed">%EMULATOR_RETROARCH% %EXTRA_CONFIGFILE%=/storage/emulated/0/Android/data/%ANDROIDPACKAGE%/files/retroarch.cfg %EXTRA_LIBRETRO%=pcsx_rearmed_libretro_android.so %EXTRA_ROM%=%ROM%</command>
<command label="SwanStation">%EMULATOR_RETROARCH% %EXTRA_CONFIGFILE%=/storage/emulated/0/Android/data/%ANDROIDPACKAGE%/files/retroarch.cfg %EXTRA_LIBRETRO%=swanstation_libretro_android.so %EXTRA_ROM%=%ROM%</command>
<command label="DuckStation (Standalone)">%EMULATOR_DUCKSTATION% %ACTIVITY_CLEAR_TASK% %ACTIVITY_CLEAR_TOP% %EXTRABOOL_resumeState%=false %EXTRA_bootPath%=%ROMRAW%</command>
<command label="ePSXe (Standalone)">%EMULATOR_EPSXE% %ACTION%=android.intent.action.MAIN %EXTRA_com.epsxe.ePSXe.isoName%=%ROMSAF%</command>
<command label="FPseNG (Standalone)">%EMULATOR_FPSE-NG% %ACTION%=android.intent.action.VIEW %DATA%=%ROMPROVIDER%</command>
<command label="FPse (Standalone)">%EMULATOR_FPSE% %ACTION%=android.intent.action.VIEW %DATA%=%ROMPROVIDER%</command>
<platform>psx</platform>
<theme>psx</theme>
</system>
<system>
<name>psp</name>
<fullname>Sony PlayStation Portable</fullname>
<path>%ROMPATH%/psp</path>
<extension>.chd .CHD .cso .CSO .elf .ELF .iso .ISO .pbp .PBP .prx .PRX .7z .7Z .zip .ZIP</extension>
<command label="PPSSPP">%EMULATOR_RETROARCH% %EXTRA_CONFIGFILE%=/storage/emulated/0/Android/data/%ANDROIDPACKAGE%/files/retroarch.cfg %EXTRA_LIBRETRO%=ppsspp_libretro_android.so %EXTRA_ROM%=%ROM%</command>
<command label="PPSSPP (Standalone)">%EMULATOR_PPSSPP% %ACTION%=android.intent.action.VIEW %CATEGORY%=android.intent.category.DEFAULT %DATA%=%ROMPROVIDER%</command>
<platform>psp</platform>
<theme>psp</theme>
</system>
<system>
<name>dreamcast</name>
<fullname>Sega Dreamcast</fullname>
<path>%ROMPATH%/dreamcast</path>
<extension>.cdi .CDI .chd .CHD .cue .CUE .dat .DAT .elf .ELF .gdi .GDI .iso .ISO .lst .LST .m3u .M3U .7z .7Z .zip .ZIP</extension>
<command label="Flycast">%EMULATOR_RETROARCH% %EXTRA_CONFIGFILE%=/storage/emulated/0/Android/data/%ANDROIDPACKAGE%/files/retroarch.cfg %EXTRA_LIBRETRO%=flycast_libretro_android.so %EXTRA_ROM%=%ROM%</command>
<command label="Flycast (Standalone)">%EMULATOR_FLYCAST% %ACTION%=android.intent.action.VIEW %DATA%=%ROM%</command>
<command label="Redream (Standalone)">%EMULATOR_REDREAM% %ACTION%=android.intent.action.VIEW %DATA%=%ROMPROVIDER%</command>
<platform>dreamcast</platform>
<theme>dreamcast</theme>
</system>
</systemList>

위의 파일은 오타가 있을 수 있으니 신중하게 고려하시기 바라고, 아무튼 이렇게 작성한 파일을 아까 파일이 있어야 할 경로로 넣으면 대체로 될 것이다. 다른 에뮬레이터의 경우, 뭐가 되고 뭐가 안 되는지는 맨땅에 헤딩하기로 찾아야 한다.

Posted in: 신변잡기, 잡감 Tagged: Duckstation, ES-DE, NetherSX2, PPSSPP, Redream, 안드로이드, 에뮬레이터

아이폰의 올인원 게임 콘솔 에뮬레이터

2024년 5월 1일 by 이상한 모자

애플이 영미 사법부의 여러 결정에 따라 그동안 안 해주던 여러가지를 해주고 있는 가운데, 고전 게임 애호가로서 가장 흥미롭게 여기는 대목은 고전 콘솔 게임기의 에뮬레이터의 앱스토어 등록이 허용되었다는 거다. 이로써 아이폰을 갖고 다니면서 SFC게임을 돌리는 일을 할 수가 있게 되었다. 안드로이드에서는 이미 되는 일이긴 했겠지만…

그리하여 Delta라는 나름 올인원 에뮬레이터 앱이 이미 등장을 하였는데 패미컴, 슈퍼패미컴, 게임보이어드밴스, 닌텐도64, 닌텐도DS 등을 지원한다고 돼있다. 닌텐도DS는 melonDS 코어라는 거 같다. 아무튼 이걸로 패미컴, 슈퍼패미컴 게임을 돌려봤는데 슈퍼마리오 같은 플랫포머 게임은 아무래도 터치스크린으로 버튼을 연타하는 것 등에 대한 불편함 때문에 한계가 있다. 8bitdo 등에서 나온 포켓컨트롤러라고 하는 작은 패드를 휴대해갖고 다니면 카페 등에서 아이패드와 함께 즐길 수도 있겠습니다만… 그렇게까진 좀 오버인 거 같고. 다만 타이밍이 중요하지 않은 롤플레잉, 텍스트 어드벤처, 턴 기반 전략시뮬레이션 등은 충분히 할 수 있을 거 같았다. 패미컴탐정구락부 파트2를 돌려보았는데 느낌이 좋다. 다만 슈퍼패미컴은 아직 사운드가 가끔씩 튀는 거 같다.

아무튼 이런 시대인데, 눈이 좋지 않다. 근시성 노안이라 안경을 벗으면 얼마든지 가까운 것도 볼 수 있지만 문제는 그러면 다시 안경을 썼을 때 적응이 잘 안 된다. 초점이 잘 안 맞는다. 소위 조절능력의 저하다. 심각하다. 그래서 되도록이면 안경을 안 벗으려고 하는데 물론 잘 안 된다. 어떻게 해야 하나…

역시 핸드폰 화면을 큰 걸 사야 하나? 지금까지는 무게 때문에 프로 맥스 라인을 고려하지 않아 왔는데… 언제가 될진 모르지만 다음 번에는 프로 맥스로… 그러고보니 애플워치도 울트라를 갖고 싶고… 아이패드는 12.9인치로… 이런 걸 다 사서 갖추려면 도대체 무슨 직업을 가져야 할까. 노안과 허세와 퇴행과 욕망의 환장의 콜라보… 그러나 현실은… 역시 소금빵으로는 부족한 거 같다. 삼각김밥이나 사러 가든지 해야겠다.

Posted in: 신변잡기, 잡감 Tagged: delta, 에뮬레이터

최고의 에뮬머신 닌텐도 스위치 2

2022년 12월 10일 by 이상한 모자

안 되냐? 니넨 축구 얘기 하잖아. 난 대신 게임 얘기 한다니까? 알겠냐? 아무튼, 전에 쓴 글에 이어서… 자 그렇다면 이러한 꿈의 에뮬머신은 어떻게 완성되는가! 일단 개념 정리 전에, 나는 닌텐도 스위치 온라인 서비스 가입자이다. 내돈내산 스위치와 내부 프로그램을 변조하는 것은 닌텐도와의 규약 위반은 될지 모르나 남에게 피해를 안 준다면 큰 문제 없다고 알고 있다. 이 점을 분명히 하면서…

개념을 정리해보자. 닌텐도가 제공하는 에뮬레이터도 결국은 어떤 프로그램이다. 그리고 스위치의 커스텀펌인 atmosphere는 layeredFS 기능을 제공한다. 가령 설치된 프로그램이 A, B, C, D라는 파일로 구성돼있다고 할 때 프로그램을 직접 변조하지 않더라도 D를 변조한 D’에 해당하는 파일을 atmosphere의 contents/타이틀id 폴더에 넣어두기만 하면 프로그램이 A, B, C, D’를 읽어오도록 할 수 있다는 거다. 이 D’에다가 한글패치된 파일을 집어 넣는 게 그동안 스위치 비공식 한글패치의 적용 방식이었다.

그렇다면, 닌텐도가 제공하는 에뮬레이터에 대해서도 롬파일 등의 정보를 담고 있는 부분을 마치 한글패치를 적용하는 것처럼 다른 롬파일 등으로 대체할 수 있다면, 임의로 별개의 게임롬을 구동하는 것이 가능할 것이다! 바로 이 점을 활용하는 것이다. 핵심은 롬파일, 타이틀 목록과 실제 롬 파일의 매칭 정보가 들어있는 파일, 각 타이틀의 구체적 메타 정보를 담고 있는 파일을 내가 커스터마이징한 파일로 대체하는 것이다. 에뮬레이터를 뜯어보면 수정이 매우 용이하게 작성돼있다. 그냥 줄줄이 쓰면 되게 돼있어. 눈이 좀 아프지만… 다만 커버이미지 등은 XTX.Z 확장자를 달고 있는데 Z확장자는 Zip 에서 사용하는 zlib을 적용했다는 거고 XTX는 얘들이 쓰는 그래픽 포맷이다. 추출 프로그램 등으로 불러올 수 있다. 이걸 바꾸면 나만의 커버 아트를 넣을 수 있는 거지. 완벽해.

근데 이 모든 과정이 귀찮잖아… 게임 하나 넣자고 이 삽질을 다 해야? 덕중덕은 양덕이다 라는 말이 있지. 이걸 대충 알아서 해주는 프로그램을 어떤 양덕이 개발하였다 이것이다. DarkAkuma라는, 이름만 딱 봐도… 아무튼 이 양반이 CaVE Database Manager라는 프로그램을 자기 블로그에 공개해놨다. 이걸 이용하면 앞서의 복잡한 과정을 좀 부실하긴 하지만 GUI를 활용해 좀 더 편하게 할 수 있다.

이 프로그램에 대해서 좀 더 설명을 하자면… 닌텐도가 자체 개발한 에뮬레이터에는 그들다운 코드네임이 붙어 있다. SFC에뮬레이터는 Canoe, FC는 KachiKachi이다. 아마 들어본 분도 있을텐데, 슈퍼패미컴 미니, 패미컴 미니에 들어가있는 에뮬레이터를 좀 고친 거다. 여튼. CaVE Database Manager는 여기에 닌텐도64 에뮬레이터인 hovercraft, MD/제네시스 에뮬레이터에 더해 공개되지 않은 게임보이 에뮬레이터인 hiyoko, GBA 에뮬레이터인 sloop의 관리/적용을 할 수 있도록 한다. 그래서 이 프로그램을 활용해 각 에뮬레이터의 대체파일들을 만들고, 앞서 atmosphere의 기능을 이용해서 적용한다면 나만의 콜렉션을 만들 수 있게 되는 것이다!

다만 Canoe와 KachiKachi의 경우 자기들이 제공한 롬을 돌리는 것만이 목적이므로, 호환성의 폭은 상대적으로 좁다. 그 중에서도 Canoe가 좀 그런데, 롬을 그냥 넣으면 안되고 DarkAkuma가 제공하는 툴로 컨버팅을 한 후에 넣어야 한다. 심지어 슈패미니용과 스위치용을 구분돼있다. 그러나 이걸로도 안 돌아가는 게임이 있다. 가령 테일즈 오브 판타지아는 안 돌아간다. 원본 카트리지가 Canoe가 지원하지 않는 영역의 마스크롬-메모리맵을 사용하기 때문으로 추측. 근데 덕중덕은 뭐다? 양덕이다… 특정롬에 영문패치를 한 경우 양덕들이 만들어 놓은 패치를 추가 적용하면 테일즈 오브 판타지아도 스위치의 Canoe에서 돌릴 수 있다. 다만 한글패치롬으로는 안 된다. 특히 이 게임의 한글패치는 임의로 롬확장을 한 거여서 안 된다. 성검전설3의 경우는 원본롬은 돌아가지만 한글패치 적용 롬은 글자가 깨진다. 이런 게임들은 어쩔 수 없이 레트로아크에서 돌리는 걸로 만족해야 한다.

KachiKachi도 아쉬움이 있는데 가령 일본판 캐슬바니아3인 악마성전설이다. 악마성전설 카트리지에는 보다 화려한 음향효과를 제공하려는 목적으로 특수칩이 들어가있다. 근데 캐슬바니아3에는 이 특수칩이 없다. 그래서 음악 딱 들으면 차이가 느껴진다. 악마성전설은 채널이 8개고 캐슬바니아3는 원래 패미컴사양인 5개다. 관심있으면 함 들어봐라.

이게 악마성전설의 Beginning (36분55초)
https://youtu.be/KqyoTvZ5cOE?t=2215

이게 캐슬바니아3의 Beginning
https://youtu.be/78706bv98S8

그런데 KachiKachi는 이 특수칩을 에뮬레이션 할 마음은 없는지, 악마성전설을 돌리면 뻗어버린다. 캐슬바니아3는 돌아간다. 레트로아크로 돌리시고… 몇 가지 안 되는 경우를 써놨지만 대부분은 작동한다. 그리고 SFC복각 패드는 스위치용 KachiKachi에서도 Canoe와 동일하게 인식한다. 최고다!

그담에 나머지 떠들만한 게… sloop 포함 나머지 에뮬레이터와, 여기엔 해당 안 되지만 CaVE Database Manager가 제공하는 Zebra엔진을 적용한 새턴 게임 에뮬레이션인데… 이건 나중에 또 얘기해보자.

Posted in: 신변잡기, 잡감 Tagged: 고전 게임, 닌텐도, 닌텐도 스위치, 에뮬레이터, 에뮬머신
1 2 다음 »

최근 글

  • 이대남에 대한 이중잣대라는 이중잣대
  • 안드로이드 에뮬 게임기에서 ES-DE와 Standalone 에뮬레이터 연결 문제
  • 내란 1년
  • 심야노동을 할 거냐 말 거냐
  • 하이퍼 능력주의와 공정 담론

분류

누적 카운터

  • 1,523,426 hits

블로그 구독

Flickr 사진

추가 사진

____________

  • 로그인
  • 입력 내용 피드
  • 댓글 피드
  • WordPress.org

Copyright © 2025 혁명은 언제나 시기상조.

Omega WordPress Theme by ThemeHall