OpenRCT2 매뉴얼/고급/반복 길이 부호화 압축



OpenRCT2 로고 OpenRCT2 매뉴얼
시작하기 전에 시작하기 관리 사전 기타 고급
OpenRCT2 소개
RCT 시리즈 소개
개발 & 역사
설치하는 법
업데이트 하는 법
한국어 패치 방법
기본 인터페이스
기본 단축키
지형 편집
보도·터널·다리 제작
놀이기구 운행 모드
간단한 놀이기구 건설
트랙 놀이기구 건설
멀티플레이
흥미도
격렬도
공원 상
RCT1 놀이기구 목록
RCT1 시나리오 목록
RCT1 테마 목록
RCT2 놀이기구 목록
RCT2 시나리오 목록
이스터 에그 (치트키)
놀이기구 탑승료 계산기
놀이기구 수치 조건표
플러그인
반복 길이 부호화 압축
RCT 파일 검사합
TD4 파일 포맷



1. 반복 길이 부호화(Run Length Encoding)
2. 복호화 방법
3. 복호화 예제
4. 코드 예제
4.1. PHP



1 반복 길이 부호화(Run Length Encoding)

RCT의 TD4나 세이브 게임 파일은 모두 '반복 길이 부호화(Run Length Encoding; RLE)' 기술로 압축되어 있습니다.
RLE는 쉽게 말해서 aaaaabbbc라는 문자열을 a5b3c1으로 압축하는 기술입니다.
압축되지 않은 RCT 관련 파일은 특정 위치에 특정 정보가 기록되기 때문 내용이 달라져도 크기가 변하지 않고, 그 내용에는 "00"이라는 문자열을 많이 포함하고 있습니다.
크리스 소이어가 RLE를 사용한 것은 바로 이 많은 0을 처리하기 위한 것으로 보입니다.
이 압축 기술은 우리가 흔히 사용하는 데이터는 잘 압축되지 않는다는 단점이 있지만, 압축이 빠르고 프로그래밍하기 비교적 간단하다는 장점이 있습니다.

파일의 마지막 4개 바이트는 검사합(checksum)으로 되어 있습니다.
여러분이 파일을 복호화하게 되면 이 마지막 4개의 바이트는 제외한 뒤에 사용해야 합니다.
반대로 파일을 암호화할 때에는, 검사합(checksum)을 계산해서 파일의 맨 끝에 4개의 바이트로 추가하십시오.

2 복호화 방법

  1. 파일에서 1byte를 읽어옵니다.
  2. 그 바이트의 최고 비트 값(MSB)를 검사합니다. MSB는 1 byte를 8개의 bit로 바꿨을 때 가장 큰 자릿수의 비트값, 즉 가장 왼쪽에 나오는 비트의 값을 말합니다.
    1. MSB=0 이면, B는 가져올 데이터의 개수를 나타냅니다. 그 다음 (B+1)개의 바이트를 읽어서 결과물에 넣으십시오.
    2. 반면, MSB=1 이면, B는 반복해야 할 데이터(문자)를 나타냅니다. 다음 바이트를 읽어서 (257-B)회 반복하여 결과물에 넣으십시오.
      만약 파일의 끝에 도달하지 못했다면 1단계로 다시 돌아가 그 다음 바이트를 읽으십시오. (단, 검사합으로 사용하는 마지막 4개의 바이트를 무시하는 것을 잊지 마십시오.)

3 복호화 예제

예를 들어 다음과 같은 데이터가 있다고 하겠습니다. (마지막 4개의 검사합 데이터는 제거한 상태)

00 47 FF 6F 05 64 20 6A 6F 62 21

맨 처음의 00을 8 bit로 바꿔보면 0000 0000 인데, 밑줄 친 곳이 MSB(가장 왼쪽 자리)입니다.
MSB가 0이므로, 그 다음 바이트를 (00 + 1) = 1개 읽어옵니다. 00의 다음 1바이트는 47입니다. 이걸 결과물에 추가합니다.

그 다음 바이트인 FF는 8 bit로 바꿔보면[1] 1111 1111 인데, MSB = 1입니다.
따라서 다음 바이트인 "6F"를 (257 - FF) = (257 - 255) = 2회 반복합니다. 이걸 결과물에 추가합니다.

그 다음 바이트인 05는 8 bit로 바꿔보면 0000 0101 인데, MSB = 0입니다.
따라서 그 다음 바이트를 (05 + 1) = 6개 읽어옵니다. 05의 다음 6개 바이트는 64 20 6A 6F 62 21입니다. 이걸 결과물에 추가합니다.

복호화한 데이터 47 6F 6F 64 20 6A 6F 62 21는 아스키(ASCII) 코드로 바꾸면 Good job!이 됩니다.
이 예제는 9 byte의 'Good job!'이라는 문자열이 00 47 FF 6F 05 64 20 6A 6F 62 21라는 11 byte의 문자열로 압축(?)을 했음에도 용량이 오히려 늘어나는 것을 보여줍니다.
앞에서 언급한대로, RLE는 이 예제에서 보듯 일반적인 압축엔 좋지 않지만 "00"이라는 값을 가지는 바이트가 많은 파일에 매우 효과적입니다.

파일을 압축하기 위해서는 위에서 언급한 과정을 거꾸로 하기만 하면 됩니다.
전반적인 RCT 프로그램에서는, 문자의 반복 회수를 125회로 제한하셔야 합니다.

4 코드 예제

4.1 PHP

<?php // RLE 압축 풀기 function RLEdecode($encoded_source, $file_size) { for($l=0; $l<$file_size; $l++) { $indata[$l] = ord(substr($encoded_source, $l, 1)); } $l=0; $j=0; $k=0; while($l < $file_size) { $num = $indata[$l]; // MSB 체크. 128=1000 0000 이므로 127보다 크면 MSB=1, 아니면 MSB=0 if($num > 127) { $num = 257 - $num; // 가져올 다음 문자 개수 for($k=1; $k<=$num; $k++) { $decodedData[$j+$k-1] = $indata[$l+1]; } $l++; $j = $j+$k-1; } else { for($k=1; $k<=$num+1; $k++) { $decodedData[$j+$k-1] = $indata[$l+$k]; } $l = $l+$k-1; $j = $j+$k-1; } $l++; } return $decodedData; } // TD4 파일의 경로 지정 $file_path = './coaster.TD4'; $file_size = filesize($file_path); // 파일 내용 읽기 $fp = fopen($file_path, 'r'); $encoded_source = @fread($fp, $file_size); fclose($fp); // RLE 복호화 $data = RLEdecode($encoded_source, $file_size); /* 흥미도 출력. 흥미도는 16진수로 33번째, 10진수로 51번째에 있다. PHP 배열의 인덱스에는 10진수를 쓰므로 [] 사이에 51 입력. TD4 파일 포맷 문서 참고. */ echo '흥미도는 '.($data[51]/10);
  1. [1] Windows 계산기에서 [보기]-[공학용 계산기]를 눌러 공학용 계산기를 켠 뒤 다음 과정을 따라해보세요: Hex에 체크(16진수) → FF 입력 → Bin(2진수)에 체크 → 결과 확인


TELKwiki에 기여함은 TELKLAND의 이용 약관에 동의함을 뜻합니다.


↑TOP

신고하기 ×

신고 종류
작성자
내용

신고 사유