Lập trình màn hình hoạt họa “woosh” trên Amiga
(dansalva.to)- Magicore Anomala tận dụng khả năng đồ họa và âm thanh của Amiga ra mắt năm 1985 để thực hiện CG toàn màn hình và các chuyển cảnh kiểu hoạt hình, nhưng bên trong game engine phải đồng thời giải quyết việc bố trí RAM, chia tách màn hình và các ràng buộc của sprite
- Trên cấu hình Amiga 500 thông thường, chỉ có 512KB Chip RAM dùng được cho đồ họa và âm thanh, nên kích thước 48KB không nén của ảnh CG 320x240·32 màu là một gánh nặng lớn
- Ảnh CG được nén bằng ZX0 xuống khoảng 8KB và đặt trong RAM mở rộng, rồi được giải nén sang Chip RAM ngay trước khi hiển thị, đồng thời tái sử dụng 48.000 byte bộ nhớ màn hình hiện có
- Hiệu ứng chuyển cảnh được tạo bằng cách copper thay đổi thanh ghi phần cứng ở các scanline cụ thể và tắt/bật bitplane DMA; CPU sẽ điều chỉnh các giá trị copperlist theo độ rộng split ở mỗi frame
- Các motion lines ở nền phải lách qua các phụ thuộc về màu sắc, tái sử dụng và bitplane của sprite trên Amiga; các cơ chế then chốt là attached sprites, bit điều khiển giả, duy trì 1 bitplane và điều chỉnh
BPLMOD1
Vấn đề RAM khi đưa CG toàn màn hình vào Amiga 500
- Nền tảng mục tiêu của Magicore Anomala là Amiga 500 tiêu chuẩn, với cấu hình 512KB Chip RAM và 512KB RAM mở rộng
- Bộ nhớ mà chipset Amiga có thể dùng để xuất đồ họa và âm thanh chỉ là Chip RAM
- RAM mở rộng chỉ CPU truy cập được, nên khó dùng trực tiếp cho đồ họa và âm thanh
- Đồ họa nhân vật toàn màn hình (CG) là ảnh bitmap 320x240 với 32 màu, chiếm 48KB khi không nén
- Khi tính cả asset dùng chung, dữ liệu level và phân bổ bộ nhớ màn hình, 48KB là một overhead lớn
- Hỗ trợ nén asset được thêm gần đây sử dụng định dạng nén ZX0
- Ảnh CG sau nén giảm còn khoảng 8KB
- Khi nạp asset của level, ảnh CG đã nén được đặt vào RAM mở rộng
- Ngay trước khi hiển thị, nó được giải nén sang Chip RAM
Cách không cần dành thêm 48KB Chip RAM mới
- Thay vì tìm riêng 48KB Chip RAM trống cho CG, tác giả tái sử dụng một phần bộ nhớ màn hình hiện có
- ảnh nền của căn phòng
- lớp màn hình để render các vật thể nguy hiểm
- vùng màn hình của hộp văn bản
- Ba vùng bộ nhớ này nằm liên tiếp trong RAM và tổng kích thước là 48.000 byte, khớp chính xác với kích thước của ảnh CG
- Ảnh nền căn phòng có thể được khôi phục sau khi hiển thị CG xong, nên việc ghi đè không thành vấn đề
- Việc giải nén CG mất khoảng 500ms, nhưng được đưa vào luồng cutscene để không tạo cảm giác như đang tải
- Có thể xem video proof-of-concept gameplay của Magicore Anomala trên YouTube
Hiệu ứng chia màn hình và dùng copper
- Ban đầu tác giả cân nhắc hiệu ứng wipe dọc, nhưng để nhìn đẹp thì cần một gradient điều chỉnh bảng màu theo từng scanline
- Tác giả cho rằng chỉ với copper thì khó thiết lập đủ cả 32 màu trong một khoảng horizontal blank
- Vì không muốn đụng tới kiểu “racing the beam”, tác giả chọn hiệu ứng chia màn hình
- Hiệu ứng chia màn hình trông ấn tượng hơn với người xem phổ thông, và copper của Amiga gần như hoạt động đúng kiểu được thiết kế cho những hiệu ứng như vậy
- Có thể xem một ví dụ hiệu ứng tương tự được tích hợp trong Amiga Workbench ở video này
- Việc triển khai dùng kết hợp hai tính năng của Amiga
- copper tự chạy danh sách lệnh riêng song song với CPU và có thể thay đổi thanh ghi phần cứng tại những dòng màn hình cụ thể
- con trỏ màn hình có thể được đặt qua thanh ghi phần cứng để đổi bộ nhớ màn hình sang bất kỳ vị trí nào trong Chip RAM
Dừng bitplane DMA rồi tiếp tục vẽ trở lại
- Ví dụ nếu bộ nhớ màn hình chính bắt đầu tại
0x20000, bình thường copper sẽ đặt địa chỉ này vào thanh ghi bitplane DMA- Khi bitplane được bật, DMA sẽ tuần tự đọc vùng nhớ đó và vẽ lên màn hình
- Nếu đặt con trỏ màn hình thành
0x20800khi mỗi dòng ngang chiếm0x100byte, màn hình sẽ trông như bị cuộn lên 8 dòng- Vì điểm bắt đầu hiển thị trên màn hình đã dịch xuống 8 dòng trong bộ nhớ
- Nửa trên của phần split được cuộn lên bằng cách này
- Tại điểm split, copper sẽ tắt bitplane DMA và đổi màu nền sang đỏ
- Các thanh ghi phần cứng liên quan tới bitplane về cơ bản bị đóng băng tại thời điểm đó
- Khi tới phần dưới của split, màu nền được khôi phục và bitplane DMA được bật lại
- Màn hình sẽ tiếp tục được vẽ từ đúng vị trí đã dừng, nhưng vị trí hiển thị thực tế lúc này nằm thấp hơn
- Ở mỗi frame, CPU điều chỉnh
vs_TCopTopvàvs_TCopBottomtheo độ rộng hiện tại của split- Việc điều chỉnh con trỏ màn hình cho split phía trên cũng diễn ra cùng lúc, nhưng không được đưa vào ví dụ mã
Lách hạn chế của sprite để tạo motion line “woosh”
- Các motion lines của nền kiểu hoạt họa được vẽ bằng sprite
- Sprite được vẽ và di chuyển độc lập với bộ nhớ màn hình nên rất phù hợp cho mục đích này
- Tuy vậy, sprite trên Amiga có nhiều giới hạn và khá phức tạp để xử lý
-
Ràng buộc màu sắc
- Sprite dùng chung bitplane và bảng màu, nên cần dùng càng ít màu càng tốt
- motion lines chỉ dùng 3 màu để chừa lại 28 màu cho CG và 1 màu cho nền
- Trên Amiga, mỗi cặp sprite dùng một dải màu bảng màu khác nhau
- Hai sprite đầu dùng các màu 16-19
- Hai sprite tiếp theo dùng các màu 20-23
- Khi attach hai sprite, chúng hoạt động như một sprite duy nhất có bảng màu 16 màu và có thể dùng các màu 16-31
- motion lines dùng 4 attached sprites, và trong phần đồ họa chỉ dùng các màu 29-31
-
Dùng cùng một đồ họa sprite ở nhiều vị trí
- 4 byte đầu của đồ họa sprite là bit điều khiển dùng để chỉ định vị trí và chiều cao
- Cấu trúc này gây trở ngại nếu muốn vẽ cùng một đồ họa ở nhiều vị trí khác nhau
- Tác giả từng thử đặt trực tiếp bit điều khiển sprite qua thanh ghi phần cứng, nhưng không thể làm nó hiển thị trên màn hình
- Sprite DMA của Amiga sẽ đi theo con trỏ dữ liệu sprite và vẽ lên màn hình, tương tự bitplane DMA
- Cách giải quyết là tạo 8 sprite giả dài 4 byte
- Các sprite giả này chỉ chứa bit điều khiển
- Trước tiên đặt mọi con trỏ sprite trỏ tới sprite giả
- Sau khoảng 19 dòng, sprite DMA sẽ đọc con trỏ và nạp các bit điều khiển
- Sau đó đổi tất cả con trỏ sang đồ họa “motion line” thật
- Kết quả là DMA được nạp sẵn để vẽ sprite ở các vị trí khác nhau nhưng vẫn dùng cùng một đồ họa, và việc chuyển đổi này được xử lý trong copperlist
Vấn đề sprite cũng biến mất khi tắt bitplane
- Trước khi ảnh CG chạm tới phần trên màn hình, sẽ có một khoảng trống giữa vùng trên cùng và điểm bắt đầu của CG
- Nếu để bitplane bật trong lúc này, dữ liệu rác sẽ bị vẽ lên màn hình
- Ở vùng đó cần tắt bitplane để DMA không đọc dữ liệu rác
- Vấn đề là khi tắt bitplane thì sprite cũng không còn được vẽ
- Điều này khiến motion lines chỉ xuất hiện trong phạm vi biên của CG
- Giải pháp là không tắt hoàn toàn bitplane mà chỉ giữ 1 bitplane bật, đồng thời đặt con trỏ màn hình tới dữ liệu trống
- Màn hình vẫn vẽ một thứ gì đó, nhưng kết quả nhìn như không có gì
- Không cần chuẩn bị cả một màn hình trống hoàn chỉnh
- Với pixel 1 bit, một dòng 320 pixel là 320 bit, tức 40 byte
- Nếu đặt
BPLMOD1thành-40, sau mỗi dòng con trỏ sẽ quay lùi 40 byte để lặp lại cùng 40 byte đó liên tục - Chỉ cần để trống 40 byte đầu trong safety margin của màn hình là đủ
Kết quả và những chi tiết còn lại
- Ban đầu tác giả không chắc có nên đưa kiểu CG này vào game vì yêu cầu RAM, nhưng sau khi triển khai nén dữ liệu thì xác nhận overhead ở mức rất hợp lý
- Nhờ đó Magicore có thể bổ sung thêm các chi tiết trang trí thị giác
- Vẫn còn một số bài toán nhỏ chưa được đề cập
- Ví dụ như cách để motion line dài 100px không bị phần dưới biến mất đột ngột sau khi phần trên đã ra khỏi màn hình
- Hiệu ứng này không dùng blitter chút nào
- Bài viết về blitter có thể xem tại Getting clever with the Amiga blitter
- Cũng như từng gây ấn tượng với mọi người vào cuối thập niên 1980, Amiga đến nay vẫn là một nền tảng có thể khiến người ta ấn tượng nhờ khả năng hiển thị đồ họa màu
1 bình luận
Ý kiến trên Hacker News
Tôi hiểu chính xác “Racing the beam” nghĩa là gì. Ngày xưa, ở đầu và cuối các routine đã vsync, chúng tôi đổi màu beam khác nhau để tính xem mỗi khung hình có thể dùng được bao nhiêu thời gian CPU tính theo số scanline
Tôi nhớ địa chỉ dùng cho việc này là $dff180. Vì là bảng màu 0 nên nó luôn hiện ở cả phần viền màn hình bên ngoài vùng bitmap
Mẹo đó cũng học hoàn toàn qua truyền miệng, không có Internet, và tôi không biết rằng ngày nay vẫn còn có người cố vắt thêm hiệu năng từ chipset đó
Demoscene hiện nay đã trở nên hay đến khó tin từ khoảng năm 2017, và có những tác phẩm tôi thích chạy trên Amiga 500 cơ bản chỉ gắn thêm bộ nhớ trapdoor
https://www.youtube.com/watch?v=2jciCr8zEhw
https://www.youtube.com/watch?v=iD9xk3SDSYc
https://www.youtube.com/watch?v=pYtleuGV7ok
https://www.youtube.com/watch?v=E0OzX7plbeY
https://www.youtube.com/watch?v=rIV4AhfugIs
Tôi thật sự tò mò những người dành thời gian làm game trên Amiga là nhóm nào. Người trẻ có lẽ không quan tâm đến những máy tính cũ như thế này, còn những người lớn lên cùng nó thì có vẻ bận rộn với gia đình và công việc
Ngay cả khi không bận, vẫn có quá nhiều dự án cũng vui không kém mà lại giữ được cảm giác hiện đại. Dù vậy, chuyện này thật sự rất tuyệt
Hiện tôi làm nhà phát triển game indie toàn thời gian. Làm một game Amiga gần như là ước mơ cả đời, và giờ tôi nghĩ mình đã có kỹ năng để làm được điều đó
Tôi muốn cho thấy rằng, bằng cách tận dụng công cụ hiện nay và tri thức đã được phổ biến rộng rãi, ta có thể thổi sức sống mới vào phần cứng cổ điển từng được yêu mến bằng một trải nghiệm game có các nguyên tắc thiết kế hiện đại
Nếu gắn mọi thứ trong đời với sự nghiệp, cả cuộc đời sẽ biến thành công việc
Nó giống như hỏi tại sao lại luyện vẽ sơn dầu khi đã có Photoshop, hay tại sao lại phục chế xe cổ khi đã có Tesla
Bản độ chuyển vùng khá phức tạp vì phải chuyển giữa hai VIC-II và hai bộ dao động. Tôi cũng có MSX2, dù chưa dùng nhiều nhưng nó rất có sức hút
Việc dành thời gian thật sự viết code cho những máy này là khó, nhưng tôi xem nó giống hầu hết sở thích của người đi làm: khi có cảm hứng thì đổ thời gian vào buổi tối và cuối tuần
Retrocomputing là một thú vui tuyệt vời, hấp dẫn và đem lại nhiều cảm giác thành tựu. Chỉ có điều, điều tôi khó chịu hơn cả thời gian là giá cả và độ khó khi kiếm linh kiện
Thật tiếc là có vẻ ngày càng nhiều người muốn bán đắt bất cứ thứ gì trên thị trường máy tính hễ được gắn nhãn “đồ cổ” hay “vintage”
Về phía những người lớn tuổi hơn thì tôi khó nói thay, nhưng trong số những người vẫn làm demo Commodore 64, một số có vẻ rất muốn kết nối lại với tuổi thơ
Có những tác phẩm gần như kể thẳng câu chuyện đó, như demo khá gần đây “Mojo” của Bonzai và Pretzel Logic. Cố gắng kể chuyện “nghiêm túc” trong tác phẩm demoscene thì hơi sến, nhưng vẫn rất có tình nên tôi thích
Đây là một sở thích tốn nhiều thời gian, nhưng nếu thật sự muốn dành thời gian thì cuối cùng cũng sẽ tìm được cách
[1]: https://csdb.dk/release/?id=232966, https://www.youtube.com/watch?v=HXi3oJ9huiI
[1] https://retro.moe/2024/02/04/bluepad32-v4-0/
[2] https://www.youtube.com/watch?v=Nj5fZlt_834
https://www.udemy.com/course/programming-games-for-the-atari...
Tôi từng nghĩ làm việc ở nhà sẽ có thêm thời gian rảnh, nhưng thực tế không phải vậy. Dù sao thì một ngày nào đó tôi vẫn phải tiếp tục làm
Tôi luôn tự hỏi game kiểu console Nhật trên Amiga sẽ trông ra sao, và liệu Amiga thiếu hiệu năng, hay chỉ là thiết kế của phần lớn game không hợp gu tôi
Bonk được Factor 5 port rất xuất sắc, nhưng họ gần như là phù thủy
Đoạn “một chiếc Amiga 500 bình thường có 512KB Chip RAM và 512KB RAM mở rộng” hơi không chính xác. A500 cơ bản chỉ có 512KB Chip RAM
Nhiều người dùng thêm bản mở rộng RAM A501, bổ sung 512KB Fast RAM mà phần cứng đồ họa không thể truy cập trực tiếp
Dù được ghi là Fast RAM, do cấu trúc mở rộng nên nó chậm hơn Fast RAM thật
Hầu hết chủ sở hữu A500 đều có bản mở rộng trapdoor 512KB. Nhiều phần mềm, bao gồm các game như Monkey Island, không chạy nếu không có tổng cộng 1MB RAM
Ngày nay có nhiều bản mở rộng trapdoor giá rẻ dựa trên thiết kế phần cứng mở, cung cấp 1,5MB Slow RAM, 512KB Chip RAM để tổng cộng thành 1MB, và cả RTC
Có điều gì đó hấp dẫn đến khó tin trong việc lập trình trong những ràng buộc như thế này
Mừng khi thấy IE. Rất vui khi thấy bạn đào sâu vào Amiga
Tôi có cảm giác nhiều người đã chơi với một chiếc Amiga khác với chiếc Amiga mà tôi từng dùng. Chắc chắn có những game trông rất ấn tượng, nhưng Nintendo NES cũng vậy, và tôi không nhìn lại cả hai với nhiều lưu luyến đến thế
Dù vậy, việc cho thấy những animation như thế này được tạo ra ra sao là rất tuyệt
Amiga thật sự là một hệ thống có đủ mọi thứ. CPU 32-bit cao cấp, tăng tốc đồ họa, âm thanh tuyệt vời, và lượng RAM đúng nghĩa là gấp 256 lần NES
Ngay cả SNES cũng không tiệm cận được, và phải đến thời Sega Saturn tôi mới thấy một máy vượt qua Amiga
https://www.youtube.com/watch?v=4SB20aFHc08