Make the Snes great again

Hầu hết những bài đầu tiên trong các chương trình, sách dạy ngôn ngữ lập trình đều là bài hiển thị dòng chữ "Hello World" ra màn hình. Vì vậy mà cụm từ này còn mang nghĩa là "vở lòng", "căn bản". Cụm từ này được cho là có xuất sứ từ cuốn sách "A Tutorial to the Language B" của Brian Wilson Kernighan, được xuất bản từ năm 1973.
Tuy là mài mở đầu, vở lòng trong nhiều ngôn ngữ lập trình, nhưng viết một dòng chữ ra màn hình máy Snes không phải là bài đơn giản. Để hiển thị được một chữ cái ra màn hình Snes thì phải nắm được những kiến thức cơ bản về Register, chức năng của chúng và nắm được nhiều opcode của ngôn ngữ 65816. Chính vì vậy mà bài viết "Hello World" không thể xuất hiện đầu tiên trong loạt bài "Lập trình Snes" này.

Tuy nhiên "Hello World" cũng không phải quá khó. Nó là ứng dụng kiến thức từ các bài trước, hiển thị bối cảnh (Background) ra màn hình.
 
Đọc tại nguồn:

http://yugisokubodai.blogspot.com/2017/12/asm5.html


(Tham khảo video trên và xem phần hướng dẫn bên dưới)

Hướng dẫn lập trình cho máy Snes bằng ngôn ngữ Assembly 65816


Bài 5: Hello World kiểu 2

5.1. Lại nói về Hello World

Trong bài trước có nhắc đến việc có nhiều cách viết chữ ra màn hình, tùy từng mục đích mà cách hiển thị cũng khác nhau. Đa phần game Snes đều chọn cách hiển thị đồng loạt tất cả các chữ cái trong câu ra màn hình cùng một lúc, nhưng cũng có những game như dòng Fire Emblem dùng cách in từng chữ ra màn hình, lần lượt từng chữ từ trước đến sau. Cách viết này phức tạp hơn nhưng mang lại hiệu ứng thẩm mỹ cao hơn.
Trong cách viết từng chữ ra màn hình thì cũng có nhiều phương pháp để thực hiện, nhưng nhìn chung thì có những cách chính sau:
- Chuyển sẵn tileset (dữ liệu hình ảnh) font vào Vram, sau đó đọc chuỗi text rồi ghi tilemap vào Vram sau một chu kỳ.
- Đọc chuỗi text đến đâu thì chuyển tileset của font và tilemap vào Vram đến đấy.

Cách thứ 2 thường được dùng trong trường hợp render font chữ có độ rộng biến thiên (thuật ngữ gọi là "proportional font" hay "variable width font", viết tắt là "vwf") sẽ được đề cập đến trong những bài sau.
Bài này đề cập đến cách 1, cũng là cách đơn giản hơn.


4ePhU5u.gif


5.2.Ví dụ cụ thể

Cách viết từng chữ ra màn hình bằng cách chuyển tileset vào Vram trước rồi định kỳ in tilemap ra màn hình có ưu điểm là đơn giản, tiết kiệm được ram/vram cho tilemap nếu câu dài.
Trong phương pháp này cũng có nhiều cách khác nhau để thực hiện. Trước khi viết dữ liệu chữ vào Register $2118 hoặc DMA vào Vram, chỉ cần thêm 1 bước đợi.
Bước đợi này có thể là:
- Cho nhảy vào vòng lặp đến hết chu trình (1)
- Lợi dụng Nmi và Irq (2)

Đối với (1) thì phải thêm control code đợi (trong Video là XXFC, có thể gán bất kỳ code nào). Sau control code đợi là giá trị đợi. Chẳng hạn giá trị đợi là FFFF được ghi vào ram $0E thì chu trình đợi như sau:
PHP
REP #$20
PHA
wait:
LDA $0E
DEC //giảm A
BNE wait
PLA
PLP

Với chu trình này thì A sẽ giảm lần lượt từ FFFF đến khi còn 0000 thì mới thực hiện bước tiếp theo. Thay các giá trị nhỏ hơn để thời gian đợi ngắn hơn.

Đối với (2) thì lợi dụng các Interrupt (bộ ngắt) như nmi hay irq. Nmi xảy ra vào đầu mỗi chu kỳ V-blank đã được giải thích ở những bài trước. Máy Snes có tần suất 60 nmi/giây, còn tần suất Irq xảy ra theo người dùng chỉ định tại các Register từ $4207~$420A.
Nếu bit 7 của Register $4200 được set giá trị 1 thì nmi sẽ xảy ra tự động vào đầu mỗi chu kỳ V-blank.
Các bit 5, 4 của Register này được dùng để bật/tắt Irq ngang và dọc.

+ 00: tắt Irq
+ 01: chỉ bật Irq dọc
+ 10: chỉ bật Irq ngang
+ 11: bật Irq ngang và dọc

Tần suất của Irq ngang được quản lý ở $4009 và $400A. Chẳng hạn bit 5 của $4200 được set giá trị 1 và $420A có giá trị 00, $4209 có giá trị 0E (14) thì Irq ngang sẽ được kích hoạt khi tia laser quét hết đường ngang thứ 14 trên màn hình.

Ta có thể lợi dụng tính chu kỳ của Nmi và Irq để chuyển tilemap vào Vram định kỳ, tạo nên hiệu ứng từng chữ xuất hiện lần lượt.

 
Back
Top