C64의 국경에 스프라이트를 어떻게 표시합니까?
문제
화면의 테두리 영역에서 스프라이트를 보여주는 멋진 C64 데모를 보았습니다. 가능하지 않아야합니다. 나는 그들이 어떻게 든 그래픽 칩을 속일 수 있다고 생각합니다. 그들은 정확히 어떻게 했습니까?
해결책
예, 어셈블러가 필요합니다. 인터럽트 타이밍 트릭입니다. 빅은 테두리에 스프라이트를 보여줄 수 있지만 프레임이 숨겨져있어 스프라이트가 그 뒤에 미끄러질 수 있습니다. VIC가 표시하는 스캔 라인에 연결되어 있습니다. 하위/위 경계의 경우 매우 간단합니다.
- 교단을 프로그래밍하고, 특정 스캔 라인, 7 픽셀 또는 하단 테두리 앞에서 이와 유사한 것으로 동기화되었습니다.
- 국경을 더 작게 만들도록 Vic에서 레지스터를 설정하십시오. (그렇게 할 수있는 레지스터가 있습니다.)
- Vic은 이제 국경이 이미 시작되었고 페인트 칠을 시작하지 않는다고 생각합니다.
- -> 바닥에 테두리가 없습니다.
- 실제 테두리 후에 또 다른 인터럽트를 프로그래밍하여 원본으로 다시 설정하십시오.
왼쪽/오른쪽 경계의 스프라이트의 경우 모든 스캔 라인에 대해 프로세스가 반복되어야하기 때문에 더 복잡합니다.
- 프로그래밍 특정 스캔 라인에서 시작하도록 동기화 된 인터럽트.
- 그런 다음 오른쪽 테두리 앞에서 7 픽셀이 될 때까지 NOPS를 수행하십시오.
- 국경을 더 작게 만들도록 Vic에서 레지스터를 설정하십시오.
- -> 오른쪽에는 테두리가 없습니다.
- 실제 테두리가있을 때까지 NOPS를 수행하고 레지스터를 원래 값으로 다시 설정하십시오.
- 다시 2 단계까지 NOPS를 수행하십시오.
문제는이 모든 Nops가 바쁘고 기다리는주기를 훔치는 것입니다.
하단 테두리의 스프라이트 스크롤러에서 코드를 찾을 수있었습니다. 코드는 다음과 같습니다. (데모에서 찢어졌습니다.)
C198 78 SEI
C199 20 2E C1 JSR C12E # clear sprite area
C19C 20 48 C1 JSR C148 # init VIC
C19F A9 BF LDA #BF # set up IRQ in C1BF
C1A1 A2 C1 LDX #C1
C1A3 8D 14 03 STA 0314
C1A6 8E 15 03 STX 0315
C1A9 A9 1B LDA #1B
C1AB 8D 11 D0 STA D011
C1AE A9 F7 LDA #F7
C1B0 8D 12 D0 STA D012
C1B3 A9 01 LDA #01
C1B5 8D 1A D0 STA D01A
C1B8 A9 7F LDA #7F
C1BA 8D 0D DC STA DC0D
C1BD 58 CLI
C1BE 60 RTS
----------------------------------
# init VIC
C148 A2 00 LDX #00
C14A BD 88 C1 LDA C188,X
C14D 9D 00 D0 STA D000,X # set first 16 values from table
C150 E8 INX
C151 E0 10 CPX #10
C153 D0 F5 BNE C14A
C155 A9 FF LDA #FF
C157 8D 15 D0 STA D015
C15A A9 00 LDA #00
C15C 8D 1C D0 STA D01C
C15F A9 FF LDA #FF
C161 8D 17 D0 STA D017
C164 8D 1D D0 STA D01D
C167 A9 C0 LDA #C0
C169 8D 10 D0 STA D010
C16C A9 F8 LDA #F8
C16E A2 00 LDX #00
C170 9D F8 07 STA 07F8,X
C173 18 CLC
C174 69 01 ADC #01
C176 E8 INX
C177 E0 08 CPX #08
C179 D0 F5 BNE C170
C17B A9 0E LDA #0E
C17D A2 00 LDX #00
C17F 9D 27 D0 STA D027,X
C182 E8 INX
C183 E0 08 CPX #08
C185 D0 F8 BNE C17F
C187 60 RTS
----------------------------------
# data set into VIC registers
C188 00 F7 30 F7 60 F7 90 F7
C190 C0 F7 F0 F7 20 F7 50 F7
----------------------------------
# main IRQ routine
C1BF A2 08 LDX #08
C1C1 CA DEX
C1C2 D0 FD BNE C1C1
C1C4 A2 28 LDX #28 # 40 or so lines
C1C6 EA NOP # "timing"
C1C7 EA NOP
C1C8 EA NOP
C1C9 EA NOP
C1CA CE 16 D0 DEC D016 # fiddle register
C1CD EE 16 D0 INC D016
C1D0 AC 12 D0 LDY D012
C1D3 88 DEY
C1D4 EA NOP
C1D5 98 TYA
C1D6 29 07 AND #07
C1D8 09 18 ORA #18
C1DA 8D 11 D0 STA D011
C1DD 24 EA BIT EA
C1DF EA NOP
C1E0 EA NOP
C1E1 CA DEX
C1E2 10 E4 BPL C1C8 # repeat next line
C1E4 A9 1B LDA #1B
C1E6 8D 11 D0 STA D011
C1E9 A9 01 LDA #01
C1EB 8D 19 D0 STA D019
C1EE 20 00 C0 JSR C000 # call main code
C1F1 4C 31 EA JMP EA31 # finish IRQ
다른 팁
그것은 모두 타이밍에 의존했습니다. C64는 화면을 그리는 동안 전자 빔의 정확한 수직 위치를 쿼리하는 방법을 가지고있었습니다. 새 라인이 시작되면 몇 사이클을 기다려야했습니다 (NOP 명령을 사용하여 시간을 가질 수 있음). 그런 다음 스크린 모드 (및 테두리 너비)를 설정하는 VideoChip의 하드웨어 레지스터를 설정해야했습니다. 정확히 올바르게 타이밍을하고 모든 스캔 라인을 다시 수행함으로써 전체 부작이 사라졌습니다.
바닥 테두리는 비슷한 속임수로 사라졌습니다. 수직 테두리가 시작된 정확한 스캔 라인에서도 해당 프레임의 하단 테두리를 비활성화 한 비디오 모드를 설정해야했습니다.
실제로이 모든 일은 조립에서 이루어져야했습니다. 그렇지 않으면 타이밍을 정확히 올바르게 얻을 수 없습니다.
부수적으로, 나는 부작용 속임수가 1001 승무원 (네덜란드 그룹)에게 인정되었다고 생각합니다. 누가 첫 번째 바닥 테두리 트릭을 뽑았는지 잘 모르겠습니다.
C64에서 국경을 여는 주제에 대한 좋은 튜토리얼은 Pasi Ojala의 훌륭한 기사를 확인하십시오. C = 해킹 문제 6.
너무 기술적이지 않고 TRICK은 VIC 칩의 기능을 사용하여 25/24 행과 40/38 열의 텍스트/그래픽을 전환 할 수 있으며, 정확한 순간 에이 스위치를 만들기 위해 VIC를 속이는 데 도움이됩니다. 실제로는 그렇지 않을 때 이미 국경을 켜고 있습니다. 코드 예제에 대한보다 철저한 설명은 위의 기사를 확인하십시오.
그것은 오래 전입니다.
모니터의 빈도에 의존하는 솔루션이 있다는 것을 알고 있습니다.
CRT를 사용하면 현재 픽셀이 일반 화면 외부에 있더라도 알려져 있습니다. 그래서 당신은 광선을 조작 할 수 있습니다.
내 정크 파일 어딘가에 C64 책이 있어야합니다.
Offtopic이지만 VIC20 (C64의 전신)과의 그래픽은 재미있었습니다. 각 픽셀을 조작 할 방법은 없었지만 기존 문자를 변경할 수 있습니다. 그래서 당신은 0에서 ... 모든 문자로 화면을 채우고 문자를 변경하여 픽셀을 화면으로 설정했습니다. ;-).
타이밍이 핵심이었습니다. CRT의 빔이 왼쪽에서 오른쪽으로 이동함에 따라 오버 스캔 (테두리) 색상을 변경하여 이미지는 테두리에서 생성되었습니다. 이미지를 생성하는 데 필요한 두 가지 타이밍 신호가 있습니다 - 세로 새로 고침 및 수평 새로 고침. 수평 및 수직 새로 고침이 발생하는시기를 감지함으로써 일련의 어셈블러 지침을 시작하여 테두리 색상을 변경하여 이미지를 생성 할 수 있습니다. 테두리 픽셀 당 CPU 시계 진드기 수를 해결하고이를 사용하여 올바른 지점에서 테두리 색상을 변경하는 코드를 작성해야합니다.
CPU 오버 헤드가 사용자 입력 및 게임 상태를 처리하기 위해 시간 리프트가 있기 때문에 게임을 작성하는 데는 잘 작동하지 않습니다.