버블슈터 jsf 스프라이트 뷰어 제작

이미지
내가 초등학교 저학년 쯤 즐겨했던 온라인 게임 버블슈터. 이 게임의 추억에 잠겨, 약 4~5일간 초집중해서 버블슈터의 jsf 스프라이트 이미지를 분석하여 출력하는 작은 프로젝트를 진행했다. #pragma pack ( push , 1 ) struct JSFFileHeader {   int8_t Version [ 32 ];   int8_t Description [ 18 ];   int8_t FileName [ 200 ];   uint32_t InfoCount ; }; #pragma pack ( pop ) #pragma pack ( push , 1 ) struct JSFInfoHeader {   uint32_t Unknown11 ;   uint32_t Unknown12 ;   uint32_t Unknown13 ;   uint32_t Unknown14 ;   uint16_t Unknown15 ;   uint32_t Unknown16 ;   uint32_t Unknown17 ;   uint32_t WordCount ;   uint16_t Width ;   uint16_t Height ; }; #pragma pack ( pop ) JSF 파일의 헤더를 완전 분석하진 못했지만, 필요한 정보들은 모두 충족했기 때문에 추출하는 데는 문제가 없었다. [과정 간략 설명] 1. DXWnd 프로그램으로 클라이언트를 창모드로 실행 2. 치트엔진 실행, 메모리 스캔 및 어셈블리 레벨 디버깅 3. HxD 프로그램 실행 시 클라이언트가 종료되므로, 대신 ImHex 프로그램을 이용하여 jsf 파일 바이너리를 분석 4. C++ 헤더 작성 및 jsf를 읽어서 단일의 스프라이트 파일로 변환 5. Gosu + ruby를 사용하여 변환된 파일을 읽어들인 후, RGB565 -> RGB888 색상 변환하고 한 픽셀씩 점을 찍음  ...

gosu 엔진을 사용하기로 결정했다

이미지
며칠간 Ruby로 어떤 클라 게임 엔진을 사용할지 선택의 기로에 놓여있었다. 후보는 mkxp-z와 gosu인데, 후자를 사용하는 것으로 결정내렸다. mkxp-z vs gosu mkxp-z gosu 1. IDE 디버깅 여부 X O 2. 한글 IME 지원 O X 3. ruby 설치 선택 필수 4. 프로젝트 규모 무거움 가벼움 5. RGSS 호환성 높음 낮음 6. 라이센스 GNU Free 7. 클라이언트 변조 쉬움 (mkxp.json, rxdata 수정) 모름 (ocra 빌드로 rb 스크립트를 캡슐화 할 수 있을 것으로 기대) 1. IDE 디버깅 여부 내가 gosu를 사용하려는 결정적인 요인이다. 이걸 지원하지 않으면 아무리 좋은 엔진이라도 사용하기가 꺼려진다. 대부분에 디버깅에 많은 시간을 써야 할텐데, 예전에 했던 p/print/콘솔 출력 등을 이용하는 디버깅은 더 이상 하고 싶지 않다. mkxp-z: 제한적인 OS 에서만 IDE 디버깅을 할 수 있다. Windows에서는 IDE 디버깅을 할 방법이 없어 보인다. ruby_jard 는 Windows 에서 지원하지 않는다. ( https://rubyjard.org/docs/ ) ruby-debug-ide  로 Game.exe 내의 루비 스크립트를 IDE 디버깅 할 방법을 찾지 못했다.( https://github.com/ruby-debug/ruby-debug-ide ) 참고:  https://github.com/Ancurio/mkxp/issues/198 gosu: IDE 디버깅이 가능하다. 2. 한글 IME 지원 mkxp-z: 한글 입력을 지원하는데, gosu에서는 영어만 지원한다. gosu: 한글 입력이 가능하도록 소스코드를 변경할 수 있을지는 알 수 없다. 3. ruby 설치 mkxp-z: 미리 만들어진 dll의 루비 라이브러리를 사용할 수 있기 때문에 루비 설치가 필요 없다. gosu: 개발 시에는 반드시 설치해야 한다. 4. 프로젝트 규모 / 5. RGSS 호환성 mkxp-z: 프로젝트를 ...

Ruby TCP Socket 생성 및 논블록 send/recv

이미지
ruby 클라이언트 소켓 생성 및 connect require 'socket' tcp_socket = Socket . new ( Socket :: AF_INET , Socket :: SOCK_STREAM , 0 ) tcp_socket. setsockopt ( Socket :: IPPROTO_TCP , Socket :: TCP_NODELAY , true ) sockaddr_server = Socket . sockaddr_in ( 9000 , "127.0.0.1" ) begin     tcp_socket. connect (sockaddr_server) end 윈도우 mkxp-z 3.1.3 버전에서  Socket#connect_nonblock  을 쓰려고 시도했으나, 지원하지 않는 메서드라고 에러를 띄웠다. 이러면 connect 시에는 블록되는 상황을 마주할 수밖에 없다. 매우 아쉬운 부분이다.  ruby 논블록 send begin     tcp_socket. write_nonblock ( "안녕 client #{ $ count } " ) rescue IO :: WaitReadable => e # the socket is marked as nonblocking and the connection cannot be completed immediately     print ( "WaitReadable" ) end 1. plain (15 bytes) tcp_socket. write_nonblock ( "안녕 client #{ $ count } " ) 0000   98 83 89 7b 5f 29 34 7d f6 a0 02 d0 08 00 45 00   ...{_)4}......E. 0010   00 37 aa a3 40 00 80 06 18 5d c0 a8 db 01 c0 a8   .7..@....]...... ...

방화벽 인바운드 규칙

이미지
인바운드 규칙 TCP 8000번 포트를 개방했어도, 8000번 포트를 bind하는 서버 프로그램이 Block 되어 있다면 상대측에서 connect가 되지 않는다. 코드를 오랫동안 보고 있다가 방화벽 설정 문제임을 깨닫고 반성의 의미로 글을 쓴다. 최초로 서버 프로그램 구동 시 경고 메세지가 나오는데 취소를 누르면서 block 처리가 된 것으로 보인다. 위 사진처럼 block 표시가 있다면 직접 찾아서 지워야 한다. 그렇게 해서 해결됐다.

레드-블랙 트리 시각화 프로그램

이미지
  Red-black Tree Visualizer 프로그램 시연 영상

RGSS Color 직렬구조 메모

이미지
https://github.com/zh99998/OpenRGSS/blob/master/lib/openrgss/color.rb#L60 Color 클래스는 Animations.rxdata 에서 사용하고 있었다. 그리고 예상과 달리  놀랍게도 R, G, B, A는 각각 1바이트 unsigned 정수가 아니라 IEEE754 표준  64비트 부동소수점 이었다. 0x000001A81BA40093  3a 0a 43 6f 6c 6f 72 25   :.Color % 0x000001A81BA4009B  00 00 00 00 00 e0 6f 40   .....?o@ 0x000001A81BA400A3  00 00 00 00 00 e0 6f 40   .....?o@ 0x000001A81BA400AB  00 00 00 00 00 e0 6f 40   .....?o@ 0x000001A81BA400B3  00 00 00 00 00 e0 6f 40   .....?o@ 0x25 = 37 - 5(\x5) = 총 32 바이트 00 00 00 00 00 e0 6f 40  -> Red:    0x 40 6f e0 00 00 00 00 00 00 00 00 00 00 e0 6f 40   -> Green: 0x 40 6f e0 00 00 00 00 00 00 00 00 00 00 e0 6f 40   -> Blue:   0x 40 6f e0 00 00 00 00 00 00 00 00 00 00 e0 6f 40   -> Alpha: 0x 40 6f e0 00 00 00 00 00 0x 40 6f e0 00 00 00 00 00를 10진수로  변환하면 255가 나온다.

2024 다녀온 곳

이미지
2024년 5월 제주도