PlayStation 아키텍처
(copetti.org)- PlayStation 아키텍처는 3D 하드웨어 개발 복잡도를 줄이기 위해 단순하고 실용적인 구성을 택했지만, 그래픽 정렬·텍스처 보정·정밀도에서 개발자 부담과 시각적 한계를 남김
- Sony CXD8530BQ는 LSI Logic의 CoreWare 기반 MIPS R3000A 호환 코어와 CP0, GTE, MDEC를 통합한 SoC이며, 33.87MHz로 동작하고 2MB RAM·1KB Scratchpad·DMA를 중심으로 데이터 이동을 구성함
- 그래픽은 GTE가 3D 투영·조명·클리핑을 맡고 GPU가 명령 기반으로 선·사각형·삼각형을 렌더링하는 구조이며, Z-buffer 없이 ordering table을 사용해 CPU가 폴리곤 순서를 정해야 하는 방식임
- GPU는 affine texture mapping, nearest neighbour, 정수 좌표, 서브픽셀 해상도 부재 때문에 흔들림·겹침·texture warping이 생기며, tessellation·단색 대체·pre-rendered 배경 같은 우회가 활용됨
- CD-ROM 기반 설계는 620MB 저장공간, 44.1kHz ADPCM 오디오 스트리밍, BIOS 기반 실행 환경, Wobble Groove 복제 방지와 지역 잠금을 결합해 게임 개발과 배포 방식을 바꿈
기본 설계와 CPU
- PlayStation은 3D 하드웨어가 개발하기 복잡해질 수 있다는 전제에서 단순하고 실용적인 설계를 지향했으며, 그 대가로 일부 한계를 감수하는 구조임
- 메인 칩인 Sony CXD8530BQ는 오늘날 표현으로 SoC에 해당하며, MIPS R3000A 계열과 바이너리 호환되는 LSI Logic의 CoreWare 기반 CPU 코어를 사용함
- CPU 코어는 33.87MHz, MIPS I ISA, 32비트 워드, 32개 범용 레지스터, 32비트 데이터 버스, 32비트 주소 버스, 5단계 파이프라인, 4KB 명령 캐시를 갖춤
- 데이터 캐시는 없고, 원래 데이터 캐시에 해당하는 1KB 메모리는 고정 주소에 매핑된 Scratchpad로 제공되어 빠른 SRAM처럼 사용됨
- 시스템은 범용 작업용 2MB EDO RAM을 제공하며, EDO RAM은 일반 DRAM보다 약간 효율적이고 낮은 지연시간을 얻는 칩으로 설명됨
버스와 보조 프로세서
- 데이터 버스는 32비트 Main Bus와 16/8비트 Sub Bus로 나뉘며, Main Bus는 MDEC와 GPU를 연결하고 Sub Bus는 나머지 구성요소와 I/O를 연결함
- CD-ROM controller, MDEC, GPU, SPU, parallel port는 DMA controller에 접근할 수 있으며, DMA는 CPU를 거치지 않고 메인 버스를 장악해 높은 처리량으로 데이터를 전송함
- DMA가 동작하는 동안 CPU는 메인 버스에 접근할 수 없으며, Scratchpad에 처리할 작업이 없으면 대기 상태가 되는 구조임
- CP0인 System Control Coprocessor는 캐시 구현, Scratchpad 직접 접근, 명령 캐시 격리, 인터럽트, 예외, breakpoint를 관리함
- CP2인 Geometry Transformation Engine은 고정소수점 기반 벡터·행렬 계산을 가속하며, 3D 투영, 조명, 클리핑 등 그래픽 파이프라인 초기 단계를 담당함
- MDEC는 JPEG와 유사하게 인코딩된 macroblock을 GPU가 이해할 수 있는 형식으로 압축 해제하며, 8×8픽셀 24bpp 비트맵을 초당 9,000 macroblock 처리해 320×240px FMV를 30fps로 스트리밍할 수 있음
- CP1에 해당하는 FPU는 제공되지 않으며, 소수 계산은 소프트웨어 부동소수점이나 고정소수점으로 처리할 수 있지만 속도나 정밀도에서 제약이 생김
파이프라인과 지연 슬롯
- MIPS I 파이프라인은 control hazard와 data hazard에 취약하며, branch·jump 다음 명령이 무조건 실행되는 branch delay slot 동작을 가짐
- load 명령은 가져온 데이터가 준비될 때까지 파이프라인을 멈추지 않으므로, 바로 다음 명령이 이전 load 결과에 의존하면 올바른 피연산자를 얻기 위해 filler가 필요함
- 일부 delay slot은 의미 있는 명령으로 채워질 수 있어 항상 낭비 사이클이 되는 것은 아님
- MIPS는 고품질 컴파일러와 어셈블러가 명령 재배치나 filler 삽입을 처리한다는 RISC 철학을 기반으로, CPU 파이프라인을 개발자와 툴체인에 노출하는 설계를 택함
- 이런 설계는 뒤이은 CPU 세대에서 새로운 마이크로아키텍처가 등장할수록 하위 호환성을 어렵게 만드는 단점도 가짐
그래픽 파이프라인
- 그래픽 파이프라인의 상당 부분은 GTE가 처리하며, 결과 데이터는 Sony의 독자 GPU로 전달되어 렌더링됨
- 시스템은 1MB VRAM에 frame buffer, texture, 기타 렌더링 자원을 저장하며, CPU는 DMA로 이 영역을 채울 수 있음
- 초기 모델의 VRAM은 dual-ported 구조로 두 개의 16비트 버스를 사용해 CPU, DMA, GPU, video encoder가 동시에 접근할 수 있음
- 이후 모델은 단일 32비트 데이터 버스를 사용하는 SGRAM으로 바뀌었으며, 타이밍 차이 때문에 Jet Moto 3 같은 후속 게임이 VRAM 기반 시스템에서 그래픽 깨짐을 보일 수 있음
- CPU는 GPU의 64바이트 FIFO buffer에 최대 3개의 명령을 채워 지오메트리 데이터를 보내며, 명령은 렌더링, 설정 변경, VRAM 조작을 요청함
- GPU는 선, 사각형, 삼각형을 개별적으로 그릴 수 있으며, 삼각형은 풍부한 3D 모델을 구성하는 기본 요소로 사용됨
- GPU 좌표계는 각 좌표가 픽셀 중심의 sampling point에 대응하는 정수 좌표 모델이며, fractional coordinate를 사용하지 않음
가시성, 래스터화, 텍스처
- PlayStation GPU는 hardware visibility 해결 기능을 제공하지 않으며, ordering table을 통해 depth 값별로 GPU command 주소를 관리함
- CPU는 폴리곤을 먼저 정렬하고 table의 적절한 항목에 참조를 넣은 뒤, DMA로 table을 GPU에 보내 올바른 순서로 렌더링하게 함
- GPU는 단일 frame buffer만 필요하며, rasteriser가 vertex를 선·삼각형·사각형과 픽셀로 변환함
- 삼각형은 texture와 shading을 지원하는 가장 복잡하고 범용적인 primitive이며, 선은 빠르지만 texture 표면에 적합하지 않고, 사각형은 최대 256×256픽셀 sprite에 제한되고 shading이나 affine 변환 효과를 제공하지 않음
- 조명 효과는 flat shading과 Gouraud shading 두 가지가 있으며, flat shading은 Gouraud shading보다 초당 약 2.5배 많은 폴리곤을 채울 수 있음
- texture는 rasterised pixel마다 texture map의 texel을 찾는 inverse texture mapping으로 적용됨
- PlayStation GPU의 Affine Texture Mapping은 X/Y 2D 좌표만 사용하고 depth를 버리므로 perspective correction을 하지 않음
- texture filtering은 구현되지 않았고, scale 보정에는 nearest neighbour를 사용해 빠르고 저렴하지만 texture 모델이 blocky하게 보이는 원인이 됨
- GPU는 삼각형에 semi-transparency와 dithering 효과를 지원하며, PlayStation은 이 효과들에서 뛰어난 편으로 묘사됨
VRAM 운용과 시각적 한계
- 1MB VRAM 전체를 frame buffer에 크게 쓰는 구상은 TV 표준 형식으로 재조정이 필요하고 texture·colour table 공간을 줄이며, GPU 자체도 최대 640×480픽셀 16비트 색상 frame buffer만 렌더링할 수 있음
- 640×480 16비트 buffer는 424KB VRAM을 재료용으로 남기지만, 당시 가정용 TV에서는 높은 해상도 이점이 특히 두드러지지 않는다는 문제가 있음
- adjustable frame-buffer는 체감이 작은 해상도에 VRAM을 낭비하지 않고 frame buffer 크기를 줄여 texture와 colour lookup table 공간을 늘리는 방식임
- Halkun의 Gears Episode 2 데모는 640×480 frame buffer를 두 개의 320×480 buffer로 나누고 page flipping을 사용해 한 장면을 표시하는 동안 다른 장면을 렌더링하는 구성을 보임
- 이 layout은 600KB VRAM만 소비하고, 나머지 424KB를 colour lookup table과 texture에 사용할 수 있으며, 2KB texture cache와 함께 효율적인 구성이 됨
- VRAM은 여러 colour depth를 동시에 매핑할 수 있어 16bpp frame buffer 옆에 FMV frame에 흔히 쓰이는 24bpp bitmap을 배치할 수 있음
- rasteriser는 픽셀 단위만 처리하고 triangle이 pixel fraction을 얼마나 차지했는지 추적하지 않기 때문에, 모델 외곽선 점프와 triangle 교차부 flicker·overlap이 생길 수 있음
- ordering table은 어느 geometry가 앞에 있는지 결정하는 부담을 개발자나 프로그램에 맡기며, 성능을 위해 근사 계산이 많으면 flickering이나 가려진 표면 문제가 생길 수 있음
- affine transformation은 depth 감각이 없어 카메라가 모델에 가깝고 시선에 수직일 때 texture warping을 만들 수 있으며, 일부 게임은 tessellation이나 solid colour 대체로 왜곡을 줄임
- pre-rendered 배경은 실시간 GPU 표현보다 사실적인 장면이 필요할 때 MDEC로 스트리밍한 영상을 두 개의 삼각형에 얹는 방식으로 활용됨
오디오와 CD 기반 게임
- SPU는 44.1kHz Audio CD 품질의 16비트 ADPCM sample 24채널을 지원함
- SPU는 pitch modulation, frequency modulation, ADSR envelope, looping, digital reverb 기능을 제공함
- 오디오 버퍼인 Sound RAM은 512KB DRAM이며, 게임은 sample 저장용으로 508KB만 사용할 수 있고 reverb를 켜면 사용 가능 용량이 더 줄어듦
- CD controller는 오디오 버퍼나 CPU 개입 없이 sample을 audio mixer로 직접 보낼 수 있으며, XA encoding으로 압축된 sample은 SPU가 실시간으로 디코딩할 수 있음
- CD-ROM 매체는 PS1 게임에 620MB 저장공간, 풍부한 오디오 품질, 2x drive의 비교적 빠른 읽기 속도를 제공함
- 1997년까지 출시된 PS1 revision은 결함 있는 CD drive laser로 FMV와 Audio CD skip이 잦은 것으로 알려졌으며, 이후 모델은 laser unit과 housing을 개선해 문제를 완화함
I/O, BIOS, 개발 환경
- 초기 PlayStation에는 add-on용 Serial과 Parallel I/O 포트가 있었지만, 낮은 채택률과 copy protection 우회 우려로 이후 revision에서 제거됨
- CD subsystem은 motor·laser·RF 신호를 제어하는 DSP, Motorola 68HC05 microcontroller와 512B RAM·16KB ROM으로 구성된 Sub-CPU, main CPU와 CD subsystem 사이를 중계하는 CD Controller, 32KB SRAM buffer로 구성됨
- Sub-CPU의 ROM 프로그램은 copy-protection 절차를 구현하며, main CPU 의사와 관계없이 이를 강제함
- 전면에는 controller 2개와 Memory Card 2개를 위한 소켓 4개가 있으며, 네 slot은 전기적으로 동일하고 주소가 하드코딩되어 있음
- 시스템은 512KB ROM에 BIOS를 저장하며, BIOS는 startup, user shell, I/O routine을 제공함
- BIOS ROM 접근은 8비트 데이터 버스 때문에 매우 느리므로, API는 boot 중 main RAM으로 복사되는 Kernel 형태로 제공되며 64KB main RAM이 PlayStation OS용으로 예약됨
- boot 과정은 BIOS ROM 실행, PlayStation OS 로드, splash 표시, CD 진위 확인,
SYSTEM.CNF확인과 실행 또는 shell 표시 순서로 진행됨 - shell은 Memory Card save 복사·삭제와 Audio CD 재생을 제공하는 단순한 그래픽 인터페이스임
- Sony SDK는 C compiler와 library를 포함했고, library는 hardware access를 위해 BIOS routine에 연결됨
- studio용 DTL-H2000은 PS1 내부와 I/O, debugging 회로를 담은 dual-slot ISA card이며, Windows 3.1 또는 95가 설치된 PC에서 동작하는 소프트웨어를 요구함
- hobbyist용 Net Yaroze는 toolkit, manual, 검은색 PS1 console을 제공했으며, CD drive 접근이 없어 homebrew software가 main RAM 안에 모두 들어가야 하는 제약을 가짐
복제 방지와 지역 잠금
- Sony의 copy protection은 CD의 Table of Contents가 특정 주파수로 새겨진 Wobble Groove를 가지는지 Sub-CPU가 확인하는 방식임
- Wobble Groove는 mastering 과정에서 도입되며 일반 CD burner로 복제할 수 없고, TOC는 CD의 Lead-In 영역에 있으며 fault tolerance를 위해 여러 번 반복됨
- game TOC에는 SCEA, SCEE, SCEI 문자열 중 하나가 들어가며, 이 방식은 region-locking에도 사용됨
- 검사는 시작 시 한 번만 수행되므로 인증 직후 disc를 수동으로 바꾸는 swap trick으로 우회할 수 있지만, drive 손상 위험이 있음
- 일부 game은 gameplay 중 drive를 다시 초기화해 검사를 반복함으로써 swap trick을 막으려 했음
- Modchip은 Wobble Groove 신호를 흉내 내도록 프로그래밍된 작은 보드이며, console에 납땜해 사용됐고 법적으로 논쟁적이지만 매우 인기를 얻음
- 이후 game들은 modchip, CD burner, emulator 확산에 대응해 checksum 중심의 자체 보호 수단을 추가함
- Sony의 Libcrypt는 특정 sector checksum을 disc sub-channel에 저장하는 hardware 측 접근과, game 곳곳에 checksum을 가져와 다른 값과 섞어 검증하는 software 측 routine을 결합함
댓글과 토론
Hacker News 의견들
-
같은 물리 메모리에 매핑되는 메모리 영역들이 있음 — https://psx-spx.consoledev.net/memorymap/
PSX에서 PC로 Metal Gear Solid 포팅을 했는데, Konami 프로그래머들이 C4 폭탄이 벽에 설치됐는지 바닥에 설치됐는지를 저장하려고 꽤 과격한 트릭을 썼음
본질적으로 포인터는 같은 물리 메모리 주소를 가리키지만, 벽이나 바닥에 설치된 경우80000000h와 OR 하거나A0000000h를 쓰는 식이었던 것 같음. 오래전이라 정확히 뭘 했는지는 이제 잘 기억나지 않지만 PC로 포팅하는 과정은 재미있었음- 메모리 카드 부트로더도 같은 식으로 동작함
BIOS 코드에 결함 있는 배열 반복자가 있어서 기준 포인터보다 메모리 맵 상위 위치로 임의 데이터를 복사할 수 있음. 보통은 기준 포인터가 매우 높은 곳에 있어서 실행 코드 덮어쓰기가 안 되지만, 메모리 별칭 때문에 값을 잘 맞추면 쓰기가 “돌아 들어가서” BIOS를 덮어쓸 수 있음
그래서 사실상 메모리 카드 화면에 들어가는 것만으로 커스텀 BIOS를 부팅할 수 있고, 거기서 mechacon 검사를 거치지 않고 PSX.EXE를 실행해 복사 방지를 우회할 수 있음
MGS 포팅에 대해서도 더 알고 싶음. 기억나는 게 있는지 궁금함. 대다수 스크립팅에 TCL을 쓴 것으로 기억하고, MGS 1~4가 같은 계보의 스크립트 언어를 쓴 것 같음
최근 MGS2 소스 코드가 유출됐지만, 아마 완전 재작성에 가까워서 PSX 코드베이스와 공유한 부분은 거의 없었을 것 같음 - 요즘 이런 트릭은 보통 포인터의 하위 유효 비트를 쓰고 역참조할 때 마스킹으로 제거하는 방식으로 처리함. 대신 더 높은 정렬을 요구하게 되고, 예를 들어 4비트를 쓰면 16바이트 정렬이 필요해짐
PS1도 RAM 전체 디코딩 창을 덮을 만큼 RAM이 충분하지 않아서 RAM 별칭이 생김. 자세한 원리는 모르지만, PS1 실행 파일이 스택 포인터를 개발 키트의 8MiB RAM 끝으로 설정해도 리테일 기기에서는 결국 2MiB RAM 끝으로 떨어져서 정상 동작하는 걸 본 적 있음. 이론적으로는 거기에도 비트를 넣을 수 있고, 캐시 동작이 다른 메모리 영역을 건드리지 않아도 됨 - 흥미로움. 디컴파일된 코드에서 그 부분을 찾으려니 쉽지 않음. 아직 발견해서 문서화하지 못한 것인지도 궁금함
https://github.com/FoxdieTeam/mgs_reversing/blob/master/sour... - 초기 Mac은 32비트 포인터의 상위 바이트를 다른 데이터에 사용했음
https://en.wikipedia.org/wiki/Classic_Mac_OS_memory_manageme...
그 결과 일부 모델에는 PC의 A20 게이트와 크게 다르지 않은 하위 호환 모드가 생겼지만, 그 기간은 짧았음 - 요즘은 이런 기능이 하드웨어 확장으로 표준화되어 있음
Arm Top Byte Ignore(TBI), Intel Linear-Address Masking(LAM)과 수정판인 Linear Address Space Separation(LASS), AMD Upper Address Ignore(UAI)가 있고, UAI는 아직 SLAM 공격에 안전하지 않음. 그 위에 ARM Memory Tagging Extension(MTE) 같은 보안 확장도 있음
- 메모리 카드 부트로더도 같은 식으로 동작함
-
훌륭한 글이지만 원래는 2019년에 공개된 것임. 예전 논의는 2020년 https://news.ycombinator.com/item?id=22932134와 2021년 https://news.ycombinator.com/item?id=27576902에 각각 댓글 114개씩 있음
- 그 이후로 여러 번 업데이트됐음
- 그래도 5~7년 전 일임. 처음 보는 글이라 다시 올라온 게 반가움
-
정말 아름답게 설계된 웹사이트임. 모든 것이 사려 깊게 배치되어 있고, 잘 큐레이션된 디지털 정원의 좋은 예시처럼 보임. 잘 관리되고 사람이 직접 만든 느낌이 강함
-
지금 PS1 관련 프로젝트를 작업 중이고 곧 공개하고 싶어서 이 글을 올렸음
PS1 웹/JS/WASM 에뮬레이터 추천이 있는지 궁금함. 데스크톱에서는 PCSX-Redux [0]와 DuckStation [1]이 좋았음
JS/emscripten 기반 시도들을 몇 개 찾긴 했지만, 추천이 있으면 고마울 것 같음
[0] https://github.com/grumpycoders/pcsx-redux/
[1] https://duckstation.org/ -
PS1은 RISC, 또는 더 정확히는 로드-스토어 아키텍처를 좋아하게 만든 구조였고, x86 쪽에서 내가 잘못 생각하고 있었다는 걸 깨닫게 해준 아키텍처였음
-
PS1 아키텍처는 매력적임. PS1 게임들이 왜 지금도 재현하려는 독특하고 알아보기 쉬운 스타일을 갖게 됐는지도 보여줌
-
Copetti 글을 좋아함. 다루는 모든 내용을 잘 아는 편은 아니지만, 글과 다이어그램을 훑어보는 것만으로도 즐거움
특히 5세대와 6세대 콘솔 같은 기계 내부에서 무슨 일이 일어나는지 이해해 보려는 과정이 재미있음- Copetti를 좋아한다면 Fabien Sanglard의 작업도 전부 볼 만함. Wolfenstein과 Doom Black Books, Another World 포팅 분석, 그 밖에 공개한 수십 개의 코드 리뷰가 있음
https://fabiensanglard.net/ - 1994년이라는 시점도 늘 놀라움. 이런 기기들은 더 90년대 후반 물건처럼 느껴짐
- Copetti를 좋아한다면 Fabien Sanglard의 작업도 전부 볼 만함. Wolfenstein과 Doom Black Books, Another World 포팅 분석, 그 밖에 공개한 수십 개의 코드 리뷰가 있음
-
Claude 이전에 나온 글이라 더 좋음
-
점프 뒤의 명령어를 실행한다는 건 처음엔 정신 나간 것 같았지만, 며칠 지나니 자연스러워졌음. N64에도 비슷한 문제가 있어서 곱셈 두 개 사이에 넣을 명령어를 찾아야 했음
첫 번째 곱셈이 0을 곱하거나 해서 두 사이클 만에 끝나면, 다음 명령어도 곱셈일 때 CPU가 멈췄음- 또 다른 이상한 구석은 COP2, 즉 GTE 명령어가 프로그램 카운터 기준 위치보다 한 명령어 일찍 실행을 시작한다는 점임
그래서 예외가 발생하면 커널 인터럽트 핸들러가 다음 명령어가 COP2인지 확인하고, 두 번 실행하지 않도록 프로그램 카운터에 4를 더해야 함
또한 COP2 명령어는 분기 지연 슬롯에 넣을 수 없었는데, 아마 비슷한 이유였을 것임. 그런데 일부 게임, 기억으로는 Tekken 3가 실제로 그렇게 했음. 여러 에뮬레이터가 이 부분에서 문제를 겪거나 특별 처리가 필요했기 때문에, 몰래 넣은 에뮬레이션 방지였는지 늘 궁금했음
- 또 다른 이상한 구석은 COP2, 즉 GTE 명령어가 프로그램 카운터 기준 위치보다 한 명령어 일찍 실행을 시작한다는 점임
-
이 시리즈 글들은 항상 훌륭함
PS1 게임들은 지금 기준으로는 그리 잘 버티지 못하지만, PS2 게임을 1440p~4K로 업스케일하면 거의 완벽하다고 봄- PS1 게임도 원래 의도된 방식대로, 가능하면 CRT에서 하거나 불가능하면 에뮬레이터의 CRT 필터로 플레이하면 꽤 잘 버팀. 선명한 LCD에서 매우 높은 해상도로 플레이하는 건 최악의 방식이라고 봄
- “PS1 게임은 지금 보기 어렵다”는 건 각자 다르게 느낄 수 있음. PS1은 가정용 콘솔에서 3D 시대의 시작을 알렸고, 특유의 PS1 “흔들림”이 있는 저폴리곤 3D 모델을 좋아하는 사람들도 많음
향수 때문인 부분도 크겠지만 분명한 매력이 있고, PS1의 독특한 하드웨어 제약을 알고 나서는 시간이 갈수록 더 좋아졌음. 소셜 미디어 피드만 봐도 “PS1 그래픽”은 약간의 부활기를 맞고 있고, 그 느낌을 재현하려는 사람이 많음 - 사양을 보면, 개발자들이 거기서 뽑아낸 결과물이 정말 놀라움
- 그래픽 면에서는 CRT나 CRT 필터로 하거나, 높은 렌더링 해상도에서 정점 떨림을 없애는 PGXP 지오메트리 보정을 지원하는 에뮬레이터를 쓰면 됨
게임플레이로 보면 이 콘솔은 상업적으로 출시된 게임만 수천 개에 달하는 거대한 라이브러리를 갖고 있고, 숨은 명작도 많음. 그 목록에서 취향에 맞는 게임을 하나도 못 찾는 게이머가 있다면 오히려 놀랄 것 같음 - 2D 게임들은 지금도 잘 버팀. 예를 들면 Symphony of the Night 같은 작품들임