전문 정보
롤러코스터 타이쿤과 관련된 전문적인 정보에 대해 수록하였습니다.
RCT 관련 사이트나 프로그램 제작 등에 참고하면 좋은 것도 있습니다. ☞ 목록으로 돌아가기

반복 길이 부호화(RLE; Run-Length Encoding)
RCT의 TD4나 세이브 게임 파일은 모두 '반복 길이 부호화(Run Length Encoding; RLE)' 기술로 압축되어 있습니다.
압축되지 않은 RCT 관련 파일은 파일의 내용이 달라져도 크기가 변하지 않고, 그 내용에는 "00"이라는 문자열을 많이 포함하고 있습니다. 크리스 소이어가 RLE를 사용한 것은 바로 이 많은 0을 처리하기 위한 것으로 보입니다. 이 압축 기술은 우리가 흔히 사용하는 데이터는 잘 압축되지 않는다는 단점이 있지만, 압축이 빠르고 프로그래밍하기 간단하다는 장점이 있습니다.
파일의 마지막 4개 바이트는 검사합(checksum)으로 되어 있습니다. 여러분이 파일을 복호화하게 되면 이 마지막 4개의 바이트는 제외한 뒤에 사용하시기 바랍니다. 반대로 파일을 암호화할 때에는, 검사합(checksum)을 계산해서 파일의 맨 끝에 4개의 바이트로 추가하십시오.

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

* 복호화 예제:
예를 들어 다음과 같은 데이터가 있다고 하겠습니다. (마지막 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"입니다.(결과물) = 47
  • 그 다음 바이트인 FF는 8 bit로 바꿔보면(*) 1111 1111 인데, MSB = 1입니다.
    따라서 다음 바이트인 "6F"를 (257 - FF) = (257 - 255) = (2)회 반복합니다.(결과물) = 47 6F 6F
  • 그 다음 바이트인 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


복호화한 데이터 "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 바이트로 제한하셔야 합니다.

(*) Windows 계산기에서 [보기]-[공학용 계산기]를 눌러 공학용 계산기를 켠 뒤 다음 과정을 따라해보세요:
Hex에 체크(16진수) → FF 입력 → Bin(2진수)에 체크 → 결과 확인
* 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); ?>

↑TOP