C64 hội kết xuất một Sprite


8

Tôi đã viết một chương trình ngắn trong trình biên dịch 6502 cho Trình biên dịch 64 bằng cách sử dụng trình biên dịch ca65trình liên kết ld65 . Chương trình sẽ hiển thị một hình vuông đặc ở đâu đó gần trung tâm của màn hình, nhưng tôi không thấy bất cứ điều gì được hiển thị.

Đây là hội đồng của tôi:

    .segment "CODE"

    ; set sprite pointer index
    ; this, multiplied by $40, is the address
    ; in this case, the address is $2000
    ; $80 * $40 = $2000
    lda #$80
    sta $07f8

    ; enable sprite 0
    lda #$01
    sta $d015

    ; set x and y position
    lda #$80
    sta $d001
    sta $d002

loop:
    jmp loop

    .segment "GFXDATA"

    .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
    .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
    .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
    .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
    .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
    .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
    .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
    .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF

Đây là tập lệnh liên kết của tôi, được điều chỉnh từ tập lệnh liên kết được đề xuất của ca65 cho trình biên dịch viết tay trên c64 . Thay đổi duy nhất tôi đã thực hiện là thêm phân đoạn "GFXDATA", để tôi có thể lưu trữ các họa tiết của mình tại địa chỉ $2000.

FEATURES {
    STARTADDRESS: default = $0801;
}
SYMBOLS {
    __LOADADDR__: type = import;
}
MEMORY {
    ZP:       file = "", start = $0002,  size = $00FE,      define = yes;
    LOADADDR: file = %O, start = %S - 2, size = $0002;
    MAIN:     file = %O, start = %S,     size = $D000 - %S;
}
SEGMENTS {
    ZEROPAGE: load = ZP,       type = zp,  optional = yes;
    LOADADDR: load = LOADADDR, type = ro;
    EXEHDR:   load = MAIN,     type = ro,  optional = yes;
    CODE:     load = MAIN,     type = rw;
    RODATA:   load = MAIN,     type = ro,  optional = yes;
    DATA:     load = MAIN,     type = rw,  optional = yes;
    GFXDATA:  load = MAIN, type = ro, optional = yes, start = $2000;
    BSS:      load = MAIN,     type = bss, optional = yes, define = yes;
}

Đây là lệnh tôi đang sử dụng để biên dịch và liên kết:

cl65 -o graphics.prg --mapfile graphics.map -u __EXEHDR__ -t c64 -C linker.cfg graphics.asm

Đây là nội dung của mapfile sau khi biên dịch:

Modules list:
-------------
graphics.o:
    CODE              Offs=000000  Size=000015  Align=00001  Fill=0000
    GFXDATA           Offs=000000  Size=000040  Align=00001  Fill=0000
/usr/share/cc65/lib/c64.lib(exehdr.o):
    EXEHDR            Offs=000000  Size=00000C  Align=00001  Fill=0000
/usr/share/cc65/lib/c64.lib(loadaddr.o):
    LOADADDR          Offs=000000  Size=000002  Align=00001  Fill=0000


Segment list:
-------------
Name                   Start     End    Size  Align
----------------------------------------------------
LOADADDR              0007FF  000800  000002  00001
EXEHDR                000801  00080C  00000C  00001
CODE                  00080D  000821  000015  00001
GFXDATA               002000  00203F  000040  00001


Exports list by name:
---------------------
__EXEHDR__                000001 REA    __LOADADDR__              000001 REA    



Exports list by value:
----------------------
__EXEHDR__                000001 REA    __LOADADDR__              000001 REA    



Imports list:
-------------
__EXEHDR__ (exehdr.o):
    [linker generated]       
__LOADADDR__ (loadaddr.o):
    [linker generated]        linker.cfg(5)

Và một hexdump của tệp nhị phân cuối cùng:

0000000 0801 080b 0320 329e 3630 0031 0000 80a9
0000010 f88d a907 8d01 d015 80a9 018d 8dd0 d002
0000020 1f4c 0008 0000 0000 0000 0000 0000 0000
0000030 0000 0000 0000 0000 0000 0000 0000 0000
*
0001800 ff00 ffff ffff ffff ffff ffff ffff ffff
0001810 ffff ffff ffff ffff ffff ffff ffff ffff
*
0001840 00ff                                   
0001841

Phân đoạn "GFXDATA" là sprite của tôi. Sprite là 64 byte $FF, vì vậy nó sẽ trông giống như một hình vuông rắn. Dữ liệu sprite này được đặt tại địa chỉ $2000.

Đoạn "MÃ" được bắt đầu tại vị trí bắt đầu BASIC thông thường và ca65 đang chèn trình tải BASIC cho tôi để tôi chỉ cần nhập runsau khi tải chương trình.

Tôi chưa chuyển ngân hàng của VIC, vì vậy màn hình vẫn ở dải địa chỉ mặc định ( $0400-$07FF), với 8 byte cuối cùng của phạm vi này là con trỏ sprite của tôi. Tôi chỉ sử dụng con trỏ sprite 0 ( $07f8) vì tôi chỉ có một sprite.

Khi tôi chạy chương trình, mọi thứ sẽ khóa - đó là điều được mong đợi, bởi vì chương trình kết thúc trong một vòng lặp vô hạn. Nhưng tôi không thấy sprite ở bất cứ đâu trên màn hình:

Chương trình đang chạy trong VICE

Tôi đang thiếu gì?


1
Ôi, những kỷ niệm. Tất nhiên, trở lại vào ngày chúng tôi không gặp rắc rối với những thứ liên kết điên rồ :) Dù sao đi nữa, hãy để tôi xem. Để bắt đầu, bạn đã đăng ký X / Y sai. Chúng phải là $ d000 và $ d001.
Jester

@Jester cảm ơn bạn đã xem! yeah, các công cụ liên kết đã mất một thời gian để có được hang của. rất nhiều lời khuyên trực tuyến được sử dụng .orghoặc đặt PC trực tiếp để kiểm soát nơi mọi thứ được lưu trữ. ca65Mặc dù vậy, không khuyến khích điều này, cho rằng cách thích hợp để kiểm soát nơi mọi thứ được đặt trong nhị phân là sử dụng các tập lệnh liên kết. và bây giờ tôi (tôi nghĩ?) đã thiết lập trình liên kết chính xác, tôi thấy quan điểm của họ - việc tổ chức mọi thứ dễ dàng hơn nhiều.
Woodrow Barlow

@Jester tôi nên thêm rằng 99% tập lệnh liên kết đó đến trực tiếp từ ca65 - tất cả những gì tôi đã thêm là phân đoạn "GFXDATA".
Woodrow Barlow

2
@Jester oh my gosh, tôi chắc chắn tôi đã kiểm tra ba lần đăng ký. tôi vừa cập nhật mã của mình để sử dụng các thanh ghi X và Y chính xác ... và nó hoạt động hoàn hảo. Tôi không thể tin rằng tôi đã dành hai buổi chiều cho việc này và không nhận thấy điều đó.
Woodrow Barlow

1
Chỉ trong trường hợp bạn không biết - có Retrocomputing.SE , nơi mọi người yêu thích công cụ này.
tum_

Câu trả lời:


5

Như @Jester đã chỉ ra trong các bình luận, địa chỉ bộ nhớ vị trí X và vị trí Y là sai. Các địa chỉ chính xác là $d000$d001:

; set x and y position
lda #$80
sta $d000
sta $d001

Đây là mã được sửa:

    .segment "CODE"

    ; set sprite pointer index
    ; this, multiplied by $40, is the address
    ; in this case, the address is $2000
    ; $80 * $40 = $2000
    lda #$80
    sta $07f8

    ; enable sprite 0
    lda #$01
    sta $d015

    ; set x and y position
    lda #$80
    sta $d000
    sta $d001

loop:
    jmp loop

    .segment "GFXDATA"

    .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
    .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
    .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
    .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
    .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
    .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
    .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
    .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF

Và đây là một hình ảnh của nó trong hành động:


Xin đừng lạm dụng tính năng "wiki cộng đồng". Câu trả lời này không có kinh doanh là một.
ống

1
@pipe tại sao không? Jester trả lời các câu hỏi trong các ý kiến. tôi mời anh ấy đăng nó như một câu trả lời. anh ta không làm. Vì vậy, tôi đã đăng nó, nhưng vì tôi không phải là người tìm thấy câu trả lời, nên có vẻ như tôi không thích hợp để đặt tên cho nó.
Woodrow Barlow

1
chủ đề này nói rằng thời điểm thích hợp để sử dụng wiki cộng đồng là "nếu câu trả lời của bạn chỉ được tổng hợp cùng với những gì đã được trả lời bởi những người khác trong các bình luận".
Woodrow Barlow

1
chủ đề này, với thậm chí nhiều hơn, thậm chí còn đi xa hơn để nói rằng luôn luôn ổn để đưa ra câu trả lời vào wiki cộng đồng nếu bạn muốn.
Woodrow Barlow

2

Bạn có thể sử dụng VICinksR0_X và VICinksR0_Y nếu bạn bao gồm c64.inc. Điều này có thể làm cho cuộc sống của bạn dễ dàng hơn nhiều.


mẹo tốt, cảm ơn bạn! Tôi sẽ làm điều đó trong tương lai. Bạn có thể thêm câu này vào câu trả lời wiki cộng đồng nếu bạn muốn.
Woodrow Barlow
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.