TL;DR
- DOOM 엔진은 게임플레이 중
malloc()없이 자체 메모리 할당기와 캐시 축출을 사용하고, 제한된 1993년 하드웨어에서의 성능을 위해 고정소수점 연산·룩업 테이블·직접 화면 버퍼·공간 인덱스를 채택한 구조임 z_zone.c의 메모리 할당기는 시작 시 확보한 하나의 큰 아레나를 블록으로 나누고, 새 메모리 할당 과정에서 재생성 가능한 캐시 블록을 자동 회수함tables.c는 사인·탄젠트·아크탄젠트 값을 컴파일 시점에 미리 계산해 렌더러 전체에서 부동소수점 연산 없이 고정소수점 정수 연산을 수행하게 함- 화면은 320×200 크기의 1바이트 픽셀 배열이며, 3D 월드·HUD·몬스터·무기 스프라이트가 동일한 픽셀 블리팅 방식으로 그려짐
p_maputl.c의 블록맵은 충돌 검사를 인접한 지오메트리로 제한하는 자체 공간 인덱스이며, 모든 설계가 과도한 엔지니어링이 아니라 당시 하드웨어 제약에 대한 대응임
메모리 할당과 캐시 축출
- 게임플레이 중
malloc()을 사용하지 않으며, id가 자체 메모리 할당기를 작성함. - 프로그램 시작 시 하나의 큰 메모리 아레나를 한 번 확보하고, 이를 중요도 태그가 붙은 블록으로 분할함.
PU_STATICPU_LEVELPU_CACHE- 새 메모리를 할당할 때 할당기가 지나가는 기존 캐시 블록을 조용히 축출할 수 있음.
free()를 호출하는 대신, 할당기가 캐시된 텍스처를 재생성 비용이 낮은 데이터로 판단해 즉시 공간을 회수함.- 캐시 축출 정책이 메모리 할당 경로 자체에 내장된 구조이며, 오늘날의
malloc()과free()로는 동일한 동작을 수행할 수 없음.
부동소수점 없는 렌더링
- 렌더러 어디에서도 부동소수점 연산을 사용하지 않음.
tables.c는 2,000줄이 넘는 파일이며, 엔진이 필요로 하는 사인·탄젠트·아크탄젠트 값을 거의 전부 담은 룩업 테이블로 구성됨.- 해당 값은 컴파일 시점에 미리 계산되며, 이동·각도·렌더링은 이 테이블을 이용한 고정소수점 정수 연산으로 처리됨.
- 1993년의 모든 기기에 부동소수점 연산 장치(FPU)가 탑재된 것은 아니었고, FPU가 있는 경우에도 테이블 조회가 실시간 삼각함수 계산보다 빠름.
화면 버퍼와 UI의 부재
- 전체 화면이 바이트 배열이며, UI는 별도의 시스템이 아니라 화면을 공유한 결과임.
screens[0]은 픽셀당 1바이트를 사용하는 평면형 320×200 버퍼임.- 3D 월드는 이 버퍼에 열 단위로 그려짐.
- 이후 HUD가 몬스터 스프라이트와 무기 스프라이트를 그릴 때 사용하는 것과 정확히 같은 픽셀 블리팅 함수로 화면 위에 찍힘.
- UI 툴킷이나 위젯 트리가 없으며, 게임이 디스플레이 전체를 직접 소유하므로 그 위에 별도 UI 계층을 구축할 기반 자체가 없음.
- 체력 숫자와 악마 스프라이트가 동일한 종류의 그리기 호출로 처리됨.
블록맵 기반 충돌 검사
- 충돌 감지는 별도로 직접 구현한 공간 인덱스를 사용함.
p_maputl.c는 맵을 블록맵이라는 격자로 나눔.- 피격 검사는 레벨의 모든 벽을 순회하지 않고 인접한 지오메트리만 확인함.
- 이 구조는 널리 논의되기 전부터 자체적으로 구현한 공간 해시임.
하드웨어 제약에 맞춘 설계
- 이러한 시스템은 과도한 엔지니어링이 아님.
- 각 시스템은 표준적인 대안이 대상 하드웨어에 존재하지 않았거나 너무 느렸기 때문에 도입됨.
malloc- 부동소수점 연산
- GUI 라이브러리
- 무차별 대입 방식의 충돌 검사
- Benzi를 통해 메모리에 의존해 추측하는 대신 코드베이스를 직접 읽으며 DOOM 엔진의 구조를 탐색함.
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요