1 điểm bởi GN⁺ 2024-02-26 | 1 bình luận | Chia sẻ qua WhatsApp
  • 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 0x20800 khi mỗi dòng ngang chiếm 0x100 byte, 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_TCopTopvs_TCopBottom theo độ 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 BPLMOD1 thà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
  • 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

 
GN⁺ 2024-02-26
Ý 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 đó

  • 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

    • Tôi sinh năm 1991, và trước khi chuyển sang PC Windows 95, nhà tôi có một chiếc Amiga 1000. Vì vậy tôi luôn có cảm giác hoài niệm với Amiga, và tình cảm đó càng lớn hơn khi tôi hiểu hơn về những con chip độc đáo và mạnh mẽ đã tạo nên hiệu năng của nó
      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
    • Với nhiều người, không có gì vui bằng Amiga, C64, Atari, ZX Spectrum
      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
    • Có thể tôi không đủ trẻ để thuộc nhóm này, nhưng tôi rất thích nhiều máy tính ra đời hơi trước thời của mình. Tôi đã kiếm một chiếc Commodore 64, thay tụ, thay PLA, rồi còn độ thêm dual SID và “chuyển vùng”
      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
    • Tôi có một người bạn làm interface để kết nối tay cầm game mới với máy tính cũ. Ở đây, anh ấy nối Nintendo Balance Board để chơi Decathlon trên Commodore 64
      [1] https://retro.moe/2024/02/04/bluepad32-v4-0/
      [2] https://www.youtube.com/watch?v=Nj5fZlt_834
    • Tôi lớn hơn tác giả bài gốc 5 tuổi. Đầu đại dịch, tôi đã gom Atari, Amiga và một số tài liệu để học assembly cho vui. Có cả khóa Udemy
      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

    • Đó là thứ gọi là Slow RAM
      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

    • “Kẻ thù của nghệ thuật là sự vắng mặt của ràng buộc
  • 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

    • Tôi từng có cả hai, và nói thật Amiga giống như một cỗ máy đi trước hai thế hệ. Nhìn vào khác biệt phần cứng thì cũng không có gì lạ
      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
    • Chỉ hỏi để xác nhận, bạn biết đây là một game mới đang được phát triển chứ?
      https://www.youtube.com/watch?v=4SB20aFHc08