Bài 7: điều khiển tay cầm




[​IMG]

Tất cả chúng ta đều biết, máy Famicom (NES) có 2 tay cầm (Controller) gọi là "máy chính" (Controller 1) và "máy phụ" (Controller 2). Tín hiệu từ tay cầm được truyền đến địa chỉ $4016 (máy chính) và $4017 (máy phụ) trong bộ nhớ. Mọi ví dụ dưới đây đều tập trung vào máy chính. Máy phụ thì tương tự, chỉ cần đổi sang địa chỉ $4017 là được.
Tín hiệu được truyền qua bit 0 của byte tại các địa chỉ này, nếu nút bị nhấn thì giá trị của bit này là 1, nếu không bị nhấn là 0. Khi đã nhấn một lần thì bit 0 giữ nguyên giá trị 1, do vậy mỗi lần cần phải định dạng lại. Để định dạng, cần viết giá trị 1, 0 theo thứ tự vào I/O Register (I/O :Input, Output) như sau.

LDA #$01 ; load giá trị 01 vào A
STA $4016 ; ghi 01 từ A vào $4016
LDA #$00
STA $4016

Tín hiệu nhập từ tay cầm được truyền đi theo thứ tự: nút A, nút B, nút Select, nút Start, nút lên, nút xuống, nút trái, nút phải. Do đó chỉ cần lặp lại 8 lần LDA là được.


Phân nhánh có điều kiện

Assembly có các mệnh lệnh phân nhánh với điều kiện, trong đó có lệnh BNE ta đã biết ở bài 5. BNE là viết tắt của cụm từ "Branch if Not Equal" (phân nhánh nếu không bằng), tức kết quả phép toán trước đó sẽ làm thay đổi flag của Status Register, từ đó nhảy tới label được chỉ định. Dưới đây là ví dụ.

; giả sử có label tên Kage ở đâu đó
BNE Kage ; kết quả so sánh trước đó có bằng không, nếu kết quả phép toán không bằng zero thì nhảy tới label Kage

Ngoài ra còn lệnh BEQ, nhảy đến label nếu kết quả so sánh không bằng.

CPX $12 ; so sánh giá trị của X với 12 (thập lục)
BEQ Kage ; nếu giá trị X khác 12 thì nhảy tới Kage

Lệnh BEQ, BNE phân nhánh dựa trên kết quả Z flag (Zero flag) của Status Register. Ngoài ra còn nhiều lệnh phân nhánh khác, nhưng tạm thời chỉ giới thiệu 2 lệnh này.


Phép diễn toán AND

Thông tin tình trạng nút được nhấn hay không chỉ gửi qua bit 0 của cổng $4016, $4017 nên ta cần xóa hết 7 bit còn lại. Có thể làm điều này với phép diễn toán AND. Mỗi trong số 8 bit này được AND với các bit từ giá trị khác. Phép diễn toán AND có luận lý như dưới đây.

0 AND 0 = 0
0 AND 1 = 0
1 AND 0 = 0
1 AND 1 = 1

Chẳng hạn ta có

+ Giá trị 1: 01011011
AND
+ Giá trị 2: 10101101
+ Kết quả: 00001001


Chương trình đọc tay cầm

Dưới đây là chương trình đọc trạng thái của tay cầm, chỉ quan tâm tới bit 0.

; chuẩn bị I/O Register
LDA #$01
STA $4016
LDA #$00
STA $4016

LDA $4016 ; đầu tiên đọc nút A
AND #000001 ; Accumulator AND 1
BNE Apressed ; nếu kết quả trên khác zero (nút A bị nhấn) thì nhảy tới label Apressed

LDA $4016 ; tiếp theo đọc nút B
AND #000001 ; Accumulator AND 1
BNE Bpressed ; nếu kết quả trên khác zero thì nhảy tới label Bpressed

LDA $4016 ; đọc nút Select, bỏ qua
LDA $4016 ; đọc nút Start
AND #000001 ; Accumulator AND 1
BNE Startpressed ; nếu kết quả trên khác zero thì nhảy tới label Startpress

(Tương tự, dùng LDA và AND để viết code đọc các nút lên, xuống, trái, phải)

JMP Unpressed ; nhảy tới label Unpressed khi không có nút nào được nhấn

Apressed:
; code xử lý khi nút A được nhấn

Bpressed:
; code xử lý khi nút B được nhấn

Startpressed:
; code xử lý khi nút Start được nhấn

Uppressed:
; code xử lý khi nút lên được nhấn

Downpressed:
; code xử lý khi nút xuống được nhấn

Unpressed:
; code xử lý khi không có nút nào được nhấn

0 bình luận :

Post a Comment

 
Top