1658m6As
Nấm bình thường
Đọc tại nguồn:
http://yugisokubodai.blogspot.com/2017/09/asm1.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 1: chuẩn bị môi trường + định dạng
1.1. Mở đầu
1.2. Những thứ cần chuẩn bị:
1.3. Chuẩn bị môi trường:
1.4. Header:
1.5. Vector:
1.6. Format:
1.7. Lặp bất tận:
1.8. Đổi màu màn hình:
Bài sau sẽ nói kỹ hơn về màu sắc và layer Background.
http://yugisokubodai.blogspot.com/2017/09/asm1.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 1: chuẩn bị môi trường + định dạng
1.1. Mở đầu
Trong các ngôn ngữ bậc cao như C, C++ hay đối với các loại CPU cao cấp như x86, bài vỡ lòng luôn là viết dòng chữ "Hello World" ra màn hình.Việc in dòng chữ này ra màn hình rất đơn giản, chỉ gồm 1 đến vài dòng code là có thể thực hiện được.
Thực ra thì quá trình in dòng chữ "Hello World" ra ngoài màn hình không hề đơn giản như nhiều người lầm tưởng.
Đây là ưu điểm và cũng chính là nhược điểm của ngôn ngữ bậc cao. Nó giúp đơn giản hóa mọi việc phức tạp, nhưng cũng chính vì thế mà người học ở giai đoạn đầu không thể hiểu sâu vào bản chất của vấn đề. Để in được dòng chữ "Hello World" thì máy tính phải trải qua nhiều công đoạn khác nhau, nhưng phần lớn các công đoạn đều do máy tự thực hiện nhờ bộ thư viện có sẵn, nên người học tưởng chừng như nó chỉ thực hiện mỗi một vài lệnh do họ viết ra. Chính vì vậy người học gần như không thể hiểu được những gì mình đang làm trong giai đoạn đầu.
Ngược lại, các loại CPU đời cũ như dòng 65816 dùng cho máy Snes của hãng Western Design Center (WDC) sản xuất vào thập niên 1980 không có những tính năng "tự động" như x86 sau này. Người dùng phải tự làm hết mọi công việc và máy (CPU) chỉ làm nhiệm vụ đơn giản là làm theo những chỉ thị (dòng code) của người dùng. Để đạt hiệu quả cao đối với CPU hiệu năng thấp, người ta buộc phải dùng đến ngôn ngữ Assembly, thứ ngôn ngữ gần với ngôn ngữ nhị phân nhất, thứ duy nhất CPU có thể "hiểu" được. Vì vậy mà việc lập trình cho máy Snes, cũng như các hệ máy console đời cũ khác luôn được cho là cực nhọc và khó khăn hơn khi lập trình bằng ngôn ngữ bậc cao như C hay VB cho CPU x86. Nhưng cũng chính vì phải làm mọi việc nên người học dễ dàng hình dung được sâu sắc hơn về cấu trúc, kiến trúc cũng như cách làm việc của CPU đối tượng.
Loạt bài này hướng dẫn các kỹ thuật lập trình cho máy SNES (hay còn gọi là SFC ở Nhật) từ những kiến thức căn bản đến nâng cao.
Vì những lý do nêu trên, nên bài vỡ lòng không phải là bài viết dòng chữ "Hello World" ra màn hình. Để làm được việc này thì trước đó cần định dạng để máy Snes có thể hoạt động đúng chức năng.
Thực ra thì quá trình in dòng chữ "Hello World" ra ngoài màn hình không hề đơn giản như nhiều người lầm tưởng.
Đây là ưu điểm và cũng chính là nhược điểm của ngôn ngữ bậc cao. Nó giúp đơn giản hóa mọi việc phức tạp, nhưng cũng chính vì thế mà người học ở giai đoạn đầu không thể hiểu sâu vào bản chất của vấn đề. Để in được dòng chữ "Hello World" thì máy tính phải trải qua nhiều công đoạn khác nhau, nhưng phần lớn các công đoạn đều do máy tự thực hiện nhờ bộ thư viện có sẵn, nên người học tưởng chừng như nó chỉ thực hiện mỗi một vài lệnh do họ viết ra. Chính vì vậy người học gần như không thể hiểu được những gì mình đang làm trong giai đoạn đầu.
Ngược lại, các loại CPU đời cũ như dòng 65816 dùng cho máy Snes của hãng Western Design Center (WDC) sản xuất vào thập niên 1980 không có những tính năng "tự động" như x86 sau này. Người dùng phải tự làm hết mọi công việc và máy (CPU) chỉ làm nhiệm vụ đơn giản là làm theo những chỉ thị (dòng code) của người dùng. Để đạt hiệu quả cao đối với CPU hiệu năng thấp, người ta buộc phải dùng đến ngôn ngữ Assembly, thứ ngôn ngữ gần với ngôn ngữ nhị phân nhất, thứ duy nhất CPU có thể "hiểu" được. Vì vậy mà việc lập trình cho máy Snes, cũng như các hệ máy console đời cũ khác luôn được cho là cực nhọc và khó khăn hơn khi lập trình bằng ngôn ngữ bậc cao như C hay VB cho CPU x86. Nhưng cũng chính vì phải làm mọi việc nên người học dễ dàng hình dung được sâu sắc hơn về cấu trúc, kiến trúc cũng như cách làm việc của CPU đối tượng.
Loạt bài này hướng dẫn các kỹ thuật lập trình cho máy SNES (hay còn gọi là SFC ở Nhật) từ những kiến thức căn bản đến nâng cao.
Vì những lý do nêu trên, nên bài vỡ lòng không phải là bài viết dòng chữ "Hello World" ra màn hình. Để làm được việc này thì trước đó cần định dạng để máy Snes có thể hoạt động đúng chức năng.
1.2. Những thứ cần chuẩn bị:
- Phần mềm soạn thảo văn bản bất kỳ. Có thể dùng Notepad có sẵn trong Windows. Khuyên dùng EmEditor hoặc Notepad +. Mọi nội dung code sẽ được gõ vào đây.
- Trình biên dịch opcode 65816 thành mã nhị phân để CPU 65816 hiểu được. Có nhiều loại, khuyên dùng xkas.
- Phần mềm Hex editor bất kỳ.
- Phần mềm Lunar Address để chuyển đổi địa chỉ Snes sang địa chỉ PC. Nếu thông thạo cách chuyển đổi thì có thể bỏ qua phần mềm này.
- Phần mềm Tile Editor bất kỳ. Chủ yếu để tạo dữ liệu đồ họa.
- Kiến thức căn bản về ngôn ngữ 65816. Người viết tự đọc sách mà có. Tài liệu ngày nay không hề thiếu.
- Kiến thức căn bản về phần cứng của máy Snes, chủ yếu là hiểu về các Register, Vram, SPC,.... Tài liệu không hề thiếu.
- Phần mềm Debugger bất kỳ. Khuyên dùng Geiger's Snes9x vì tiện lợi. Chủ yếu để thực thi và kiểm tra code, phát hiện chỗ sai.
Tất cả những thứ trên đều có thể tìm dễ dàng qua trang world wide web http://wwww.GOOGLE.com
- Trình biên dịch opcode 65816 thành mã nhị phân để CPU 65816 hiểu được. Có nhiều loại, khuyên dùng xkas.
- Phần mềm Hex editor bất kỳ.
- Phần mềm Lunar Address để chuyển đổi địa chỉ Snes sang địa chỉ PC. Nếu thông thạo cách chuyển đổi thì có thể bỏ qua phần mềm này.
- Phần mềm Tile Editor bất kỳ. Chủ yếu để tạo dữ liệu đồ họa.
- Kiến thức căn bản về ngôn ngữ 65816. Người viết tự đọc sách mà có. Tài liệu ngày nay không hề thiếu.
- Kiến thức căn bản về phần cứng của máy Snes, chủ yếu là hiểu về các Register, Vram, SPC,.... Tài liệu không hề thiếu.
- Phần mềm Debugger bất kỳ. Khuyên dùng Geiger's Snes9x vì tiện lợi. Chủ yếu để thực thi và kiểm tra code, phát hiện chỗ sai.
Tất cả những thứ trên đều có thể tìm dễ dàng qua trang world wide web http://wwww.GOOGLE.com
1.3. Chuẩn bị môi trường:
- Tạo một Folder với tên bất kỳ
- Đặt xkas vào Folder này
- Tạo file bất kỳ, có thể đổi thành định dạng máy Snes (giả lập/Debugger) đọc được là .smc hoặc .sfc. Có thể để bất cứ định dạng gì.
- Tham khảo cách dùng xkas trong file readme. (tạo file .bat có nội dung "xkas.exe -o sample.smc code.asm", khi thực thi thì xkas sẽ biến mọi dòng code trong code.asm thành mã nhị phân vào trong sample.smc)
- Tùy vào phiên bản xkas mà cách khai báo trong code.asm có thể khác nhau. Luôn phải khai báo Rom đối tượng là LoRom hay HiRom. Ở đây ví dụ với LoRom.
- Đặt xkas vào Folder này
- Tạo file bất kỳ, có thể đổi thành định dạng máy Snes (giả lập/Debugger) đọc được là .smc hoặc .sfc. Có thể để bất cứ định dạng gì.
- Tham khảo cách dùng xkas trong file readme. (tạo file .bat có nội dung "xkas.exe -o sample.smc code.asm", khi thực thi thì xkas sẽ biến mọi dòng code trong code.asm thành mã nhị phân vào trong sample.smc)
- Tùy vào phiên bản xkas mà cách khai báo trong code.asm có thể khác nhau. Luôn phải khai báo Rom đối tượng là LoRom hay HiRom. Ở đây ví dụ với LoRom.
1.4. Header:
Nhiều người quen thuộc với Rom Snes cho rằng header là $200 (512) byte đầu tiên của Rom. Thực ra không phải. Đó chỉ là phần header vô thưởng vô phạt mà các công cụ dump (trích xuất) từ Catridge thành file để chạy trên giả lập. Có thể dùng Hex editor xóa đi $200 (512) byte này.
Header thực sự của Rom Snes luôn nằm ở một vị trí cố định trong Rom do hãng Nintendō quy định. Khi máy Snes nhận Rom, đầu tiên nó sẽ tìm đến địa chỉ này và đọc thông tin tại đây. Đó là lý do vì sao máy Snes (hay giả lập Snes) cho biết chính xác tên, loại Rom, checksum của từng Rom khác nhau.
Header thật sự của Rom nằm ở địa chỉ $FFB0 (tương đương với $7FB0 địa chỉ PC đối với LoRom và $FFB0 địa chỉ PC đối với HiRom). Địa chỉ PC là địa chỉ ta nhận thấy được khi mở Rom bằng Hex Editor trên PC.
Thành phần của Header theo thứ tự lần lượt như sau, bắt đầu từ $FFB0:
- 2 byte mã sản xuất do Nintendō quy định. Trường hợp là Rom tự viết thì có thể điền 2 số thập lục bất kỳ.
- 4 byte mã game. Có thể điền 4 chữ cái bất kỳ.
- 7 byte cố định $00.
- 1 byte mô tả kích thước Ram mở rộng. Điền $00 nếu Rom chỉ dùng phần Ram sẵn có của máy Snes như phần lớn trường hợp.
- 1 byte mô tả phiên bản đặc biệt. Phần này dành cho các mục đích đặc biệt như bảo vệ bản quyền. Thường để $00. Các số $01, $03, $05, $06, $07 tương đương với kích thước Ram mở rộng 16Kbit, 64Kbit, 256Kbit, 512Kbit, 1Mbit.
- 1 bye mô tả loại Catridge (Rom) để phân biệt Catridge này với Catridge khác cùng loại. Thường để $00.
- 21 byte mô tả tên Rom (game) chẳng hạn Final_Fantasy_VIII_FIN hay FIRE_EMBLEM_FINAL_VER.
- 1 byte mô tả Map mode, chính là tốc độ của CPU. $20 cho mode 20, 2.68 MHZ (tốc đồ thường, còn gọi là Slow Rom), $35 cho mode 25 (3.58 MHZ hay còn gọi là HiRom),...
- 1 byte mô tả kích thước Rom. $09 cho Rom có kích thước 3 ~4 M Bit, $0A cho kích thước 5~8 M Bit, $0B cho kích thước 9~16 M Bit, $0C cho kích thước 17~32 M Bit và $0D cho kích thước 33~64 M Bit.
- 1 byte cho kích thước Sram. $00 không dùng Sram, $01 cho 16K Bit, $03 cho 64K Bit, $05 cho 256K Bit, $06 cho 512K Bit, $07 cho 1M Bit.
- 1 byte mô tả thị trường bán của Rom. $00 là Nhật, $01 là Bắc Mỹ, $02 là EU,....
- 1 byte cố định là $33.
- 1 byte miêu tả số phiên bản của Rom.
- 2 byte kiểm tra bù: chính là phép toán NOT của checksum.
- 2 byte checksum. Tổng số byte trong Rom và AND với FFFF. Luôn có 2 byte kiểm tra bù + 2 byte checksum = FFFF.
Header thực sự của Rom Snes luôn nằm ở một vị trí cố định trong Rom do hãng Nintendō quy định. Khi máy Snes nhận Rom, đầu tiên nó sẽ tìm đến địa chỉ này và đọc thông tin tại đây. Đó là lý do vì sao máy Snes (hay giả lập Snes) cho biết chính xác tên, loại Rom, checksum của từng Rom khác nhau.
Header thật sự của Rom nằm ở địa chỉ $FFB0 (tương đương với $7FB0 địa chỉ PC đối với LoRom và $FFB0 địa chỉ PC đối với HiRom). Địa chỉ PC là địa chỉ ta nhận thấy được khi mở Rom bằng Hex Editor trên PC.
Thành phần của Header theo thứ tự lần lượt như sau, bắt đầu từ $FFB0:
- 2 byte mã sản xuất do Nintendō quy định. Trường hợp là Rom tự viết thì có thể điền 2 số thập lục bất kỳ.
- 4 byte mã game. Có thể điền 4 chữ cái bất kỳ.
- 7 byte cố định $00.
- 1 byte mô tả kích thước Ram mở rộng. Điền $00 nếu Rom chỉ dùng phần Ram sẵn có của máy Snes như phần lớn trường hợp.
- 1 byte mô tả phiên bản đặc biệt. Phần này dành cho các mục đích đặc biệt như bảo vệ bản quyền. Thường để $00. Các số $01, $03, $05, $06, $07 tương đương với kích thước Ram mở rộng 16Kbit, 64Kbit, 256Kbit, 512Kbit, 1Mbit.
- 1 bye mô tả loại Catridge (Rom) để phân biệt Catridge này với Catridge khác cùng loại. Thường để $00.
- 21 byte mô tả tên Rom (game) chẳng hạn Final_Fantasy_VIII_FIN hay FIRE_EMBLEM_FINAL_VER.
- 1 byte mô tả Map mode, chính là tốc độ của CPU. $20 cho mode 20, 2.68 MHZ (tốc đồ thường, còn gọi là Slow Rom), $35 cho mode 25 (3.58 MHZ hay còn gọi là HiRom),...
- 1 byte mô tả kích thước Rom. $09 cho Rom có kích thước 3 ~4 M Bit, $0A cho kích thước 5~8 M Bit, $0B cho kích thước 9~16 M Bit, $0C cho kích thước 17~32 M Bit và $0D cho kích thước 33~64 M Bit.
- 1 byte cho kích thước Sram. $00 không dùng Sram, $01 cho 16K Bit, $03 cho 64K Bit, $05 cho 256K Bit, $06 cho 512K Bit, $07 cho 1M Bit.
- 1 byte mô tả thị trường bán của Rom. $00 là Nhật, $01 là Bắc Mỹ, $02 là EU,....
- 1 byte cố định là $33.
- 1 byte miêu tả số phiên bản của Rom.
- 2 byte kiểm tra bù: chính là phép toán NOT của checksum.
- 2 byte checksum. Tổng số byte trong Rom và AND với FFFF. Luôn có 2 byte kiểm tra bù + 2 byte checksum = FFFF.
1.5. Vector:
Vector là các Pointer chỉ đến các bộ ngắt (Interrupt). Chẳng hạn Vector Reset luôn nhảy đến địa chỉ bắt đầy định dạng Snes khi ta bật nguồn, load Rom hay sau khi nhấn nút Reset. Còn Vector NMI nhảy đến các địa chỉ thực hiện chức năng do người dùng định nghĩa mỗi khi tia laser của màn hình quét từ trên xuống dưới, từ trái qua phải hết 224 dòng (kích thước màn hình Snes chuẩn: 256x224).
Mọi vector phải nằm trong địa chỉ $00:FFE0-$00:FFFF (tiếp nối ngay sau phần Header).
Mọi vector phải chỉ đến vùng dữ liệu trong bank $00. Máy Snes có 2 loại Vector: Native vector và Emulation vector. Mỗi loại gồm lần lượt:
- 4 byte Vector chưa dùng
- 2 byte Vector Coprocessor empowerment: dùng với các loại CPU phụ đi kèm.
- 2 byte Vector Program break: vector này nhảy tới địa chỉ xử lý do người dùng định nghĩa khi code BRK được thực thi. Vector này dành cho chức năng Debug16 và không mấy khi dùng đến trong thực tế.
- 2 byte Vector Abort: vector này hủy bỏ lệnh thực thi, bảo toàn trạng thái như trước khi thực thi.
- 2 byte Vector NMI: vector này nhảy đến địa chỉ thực thi chức năng riêng biệt do người dùng định nghĩa vào mỗi kỳ V-blank. Chẳng hạn tại mỗi kỳ V-blank (kết thúc chu kỳ quét của tia laser đi hết chiều dọc màn hình) sẽ kiểm tra nút Pause có nhấn hay không, nếu có thì cho dừng mọi hình ảnh trên màn hình.
- 2 byte Vector Reset: vector này nhảy đến địa chỉ thực thi code đầu tiên của Snes khi khởi động hoặc sau khi nhấn nút Reset. Chú ý là Cpu sẽ nhảy đến địa chỉ do Vector Reset ở chế độ Emulation chỉ định.
- 2 byte Vector IRQ: vector này nhảy đến địa chỉ thực hiện chức năng do người dùng chỉ định vào mỗi chu kỳ nhất định. Chu kỳ này do người dùng định nghĩa qua các Register từ $4208 ~ $420A. Chu kỳ có thể bắt đầu vào đầu, giữa hay cuối mỗi dòng quét của tia laser trên màn hình, tùy vào giá trị của các Register này.
Mọi vector phải nằm trong địa chỉ $00:FFE0-$00:FFFF (tiếp nối ngay sau phần Header).
Mọi vector phải chỉ đến vùng dữ liệu trong bank $00. Máy Snes có 2 loại Vector: Native vector và Emulation vector. Mỗi loại gồm lần lượt:
- 4 byte Vector chưa dùng
- 2 byte Vector Coprocessor empowerment: dùng với các loại CPU phụ đi kèm.
- 2 byte Vector Program break: vector này nhảy tới địa chỉ xử lý do người dùng định nghĩa khi code BRK được thực thi. Vector này dành cho chức năng Debug16 và không mấy khi dùng đến trong thực tế.
- 2 byte Vector Abort: vector này hủy bỏ lệnh thực thi, bảo toàn trạng thái như trước khi thực thi.
- 2 byte Vector NMI: vector này nhảy đến địa chỉ thực thi chức năng riêng biệt do người dùng định nghĩa vào mỗi kỳ V-blank. Chẳng hạn tại mỗi kỳ V-blank (kết thúc chu kỳ quét của tia laser đi hết chiều dọc màn hình) sẽ kiểm tra nút Pause có nhấn hay không, nếu có thì cho dừng mọi hình ảnh trên màn hình.
- 2 byte Vector Reset: vector này nhảy đến địa chỉ thực thi code đầu tiên của Snes khi khởi động hoặc sau khi nhấn nút Reset. Chú ý là Cpu sẽ nhảy đến địa chỉ do Vector Reset ở chế độ Emulation chỉ định.
- 2 byte Vector IRQ: vector này nhảy đến địa chỉ thực hiện chức năng do người dùng chỉ định vào mỗi chu kỳ nhất định. Chu kỳ này do người dùng định nghĩa qua các Register từ $4208 ~ $420A. Chu kỳ có thể bắt đầu vào đầu, giữa hay cuối mỗi dòng quét của tia laser trên màn hình, tùy vào giá trị của các Register này.
1.6. Format:
Các Register của Snes có đặc điểm là có thể ở trạng thái không ổn định (mang giá trị ngẫu nhiên) vào lúc đầu khi bật nguồn định. Điều này có thể dẫn tới nhiều hiện tượng không mong muốn như nhiễu hình, vỡ tiếng. Vì vậy cần phải định dạng các Vector này để tránh tình trạng trên. Quy trình gồm:
- Tắt màn hình (ghi giá trị 80/8F vào Register $2100)
- Cho các Register về giá trị $00.
- Format càng nhiều Register càng tốt, nhưng ít nhất phải bảo đảm từ $2101~$2133 và từ $4200~$420D.
Dưới đây là đoạn code đơn giản để format các Register tối thiểu này.
- Tắt màn hình (ghi giá trị 80/8F vào Register $2100)
- Cho các Register về giá trị $00.
- Format càng nhiều Register càng tốt, nhưng ít nhất phải bảo đảm từ $2101~$2133 và từ $4200~$420D.
Dưới đây là đoạn code đơn giản để format các Register tối thiểu này.
Mã:
format_routine:
SEP #$20
REP #$10
LDA #$80
STA $2100
LDX #$0000
LDA #$00
repeat_format:
STA $2101,x
INX
CPX #$0033
BNE repeat_format
LDX #$0000
repeat_format2:
STA $4200,x
INX
CPX #$000D
BNE repeat_format2
RTL
1.7. Lặp bất tận:
Đối với các ngôn ngữ bậc cao, luôn có ký hiệu kết thúc chương trình để máy dừng thực thi mệnh lệnh, trở về trạng thái "thả lỏng". Về thực chất, trạng thái "thả lỏng" này chính là vòng lặp bất tận bằng cách nhảy đến chính nó.
Tuy nhiên máy Snes không thể tự nhảy về trạng thái "thả lỏng" nếu không có sự can thiệp của người viết, dẫn đến crash chương trình sau khi thực hiện xong các code bên trên. Vì nó không hiểu cần phải làm gì tiếp theo nên ta cần phải hướng dẫn nó.
abc:
JMP abc
hoặc
def:
BRA def
đều cho kết quả nhảy đến chính nó, khiến máy luôn ở trạng thái hoạt động. Và đây cũng là trạng thái đúng khi kết thúc một chức năng, một chương trình.
Tuy nhiên máy Snes không thể tự nhảy về trạng thái "thả lỏng" nếu không có sự can thiệp của người viết, dẫn đến crash chương trình sau khi thực hiện xong các code bên trên. Vì nó không hiểu cần phải làm gì tiếp theo nên ta cần phải hướng dẫn nó.
abc:
JMP abc
hoặc
def:
BRA def
đều cho kết quả nhảy đến chính nó, khiến máy luôn ở trạng thái hoạt động. Và đây cũng là trạng thái đúng khi kết thúc một chức năng, một chương trình.
1.8. Đổi màu màn hình:
Đây mới chính là "Hello World" của lập trình Snes. Việc đổi màu được thực hiện qua 2 Register:
- $2121: ghi giá trị vào đây một lần. Register này chỉ thứ tự của slot màu của layer Background.
- $2122: ghi giá trị vào đây hai lần. Tùy vào giá trị được ghi vào Register này mà màn hình sẽ có màu khác nhau. Ghi $00 hai lần vào $2122 sẽ cho màn hình màu đen, ghi $FF hai lần vào $2122 sẽ cho màn hình màu trắng.
Tuy nhiên trước khi có thể thấy màu sắc màn hình thay đổi thì cần phải "bật" nó lên vì màn hình đã bị "tắt" trong quá trình Format. Register quản lý bật tắt màn hình là:
- $2100. Các giá trị từ $00 đến $0F sẽ bật màn hình với 15 cấp độ sáng từ tối nhất ($00) đến sáng nhất ($0F).
- $2121: ghi giá trị vào đây một lần. Register này chỉ thứ tự của slot màu của layer Background.
- $2122: ghi giá trị vào đây hai lần. Tùy vào giá trị được ghi vào Register này mà màn hình sẽ có màu khác nhau. Ghi $00 hai lần vào $2122 sẽ cho màn hình màu đen, ghi $FF hai lần vào $2122 sẽ cho màn hình màu trắng.
Tuy nhiên trước khi có thể thấy màu sắc màn hình thay đổi thì cần phải "bật" nó lên vì màn hình đã bị "tắt" trong quá trình Format. Register quản lý bật tắt màn hình là:
- $2100. Các giá trị từ $00 đến $0F sẽ bật màn hình với 15 cấp độ sáng từ tối nhất ($00) đến sáng nhất ($0F).
Bài sau sẽ nói kỹ hơn về màu sắc và layer Background.