首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >渲染精灵的C64程序集

渲染精灵的C64程序集
EN

Stack Overflow用户
提问于 2020-02-14 06:50:26
回答 2查看 917关注 0票数 9

我使用ca65 assemblerld65 linker,用6502汇编程序为Commodore 64编写了一个简短的程序。程序应该在靠近显示中心的某个地方渲染一个实心的正方形精灵,但我没有看到任何渲染。

这是我的程序集:

代码语言:javascript
复制
    .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

这是我的链接器脚本,改编自ca65's recommended linker script for hand-written assembler on the c64。我所做的唯一更改是添加了"GFXDATA“段,这样我就可以将精灵存储在地址$2000中。

代码语言:javascript
复制
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;
}

这是我用来编译和链接的命令:

代码语言:javascript
复制
cl65 -o graphics.prg --mapfile graphics.map -u __EXEHDR__ -t c64 -C linker.cfg graphics.asm

编译后的mapfile内容如下:

代码语言:javascript
复制
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)

和最终二进制文件的十六进制转储:

代码语言:javascript
复制
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

"GFXDATA“部分是我的精灵。sprite是64字节的$FF,所以它看起来应该像一个实心正方形。该子画面数据位于地址$2000

“代码”段是从通常的基本开始位置开始的,ca65为我插入了一个基本加载器,这样我就可以在加载程序后输入run

我没有切换VIC的内存条,所以屏幕仍然是它的默认地址范围($0400-$07FF),这个地址范围的最后8个字节是我的子画面指针。我只使用了精灵指针0 ($07f8),因为我只有一个精灵。

当我运行程序时,一切都锁定了--这是意料之中的,因为程序在无限循环中结束。但我在屏幕上的任何地方都看不到精灵:

我遗漏了什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-02-14 22:23:31

正如@Jester在评论中指出的那样,X位置和Y位置的内存地址是错误的。正确的地址是$d000$d001

代码语言:javascript
复制
; set x and y position
lda #$80
sta $d000
sta $d001

这是更正后的代码:

代码语言:javascript
复制
    .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

这是它在运行中的一张图片:

票数 6
EN

Stack Overflow用户

发布于 2020-02-28 21:51:08

如果包含c64.inc,则可以使用VIC_SPR0_X和VIC_SPR0_Y。这会让你的生活变得更轻松。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60217647

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档