Conjunto C64 que representa un Sprite


8

He escrito un breve programa en el ensamblador 6502 para el Commodore 64 usando el ensamblador ca65 y el enlazador ld65 . El programa debería representar un sprite cuadrado sólido en algún lugar cerca del centro de la pantalla, pero no veo nada renderizado.

Esta es mi asamblea:

    .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

Este es mi script enlazador, adaptado del script enlazador recomendado de ca65 para ensamblador escrito a mano en el c64 . El único cambio que hice fue agregar el segmento "GFXDATA", para poder almacenar mis sprites en la dirección $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;
}

Este es el comando que estoy usando para compilar y vincular:

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

Este es el contenido del archivo de mapa después de compilar:

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)

Y un hexdump del archivo binario final:

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

El segmento "GFXDATA" es mi sprite. El sprite tiene 64 bytes $FF, por lo que debería verse como un cuadrado sólido. Estos datos de sprite se encuentran en la dirección $2000.

El segmento "CÓDIGO" se inicia en la ubicación de inicio BASIC habitual, y ca65 está insertando un cargador BASIC para mí, así que puedo escribir rundespués de cargar el programa.

No he cambiado el banco de VIC, por lo que la pantalla todavía está en su rango de dirección predeterminado ( $0400-$07FF), con los últimos 8 bytes de este rango como mis punteros de sprite. Solo estoy usando el puntero de sprite 0 ( $07f8) porque solo tengo un sprite.

Cuando ejecuto el programa, todo se bloquea, lo cual es de esperar, porque el programa termina en un bucle infinito. Pero no veo el sprite en ninguna parte de la pantalla:

Programa que se ejecuta en VICE

¿Qué me estoy perdiendo?


1
Oh, los recuerdos Por supuesto, en el pasado no nos metimos con cosas locas de enlazador :) De todos modos, déjame echar un vistazo. Para empezar, tienes los registros X / Y incorrectos. Deben ser $ d000 y $ d001.
Jester

@Jester gracias por echar un vistazo! sí, el material del enlazador tardó un tiempo en acostumbrarse. muchos consejos en línea utilizan .orgdirectivas o configuran la PC directamente para controlar dónde se almacenan las cosas. ca65Sin embargo, desalienta esto, argumentando que la forma correcta de controlar dónde se colocan las cosas en el binario es usar scripts de enlazador. y ahora que tengo (creo) la configuración del enlazador correctamente, veo su punto: es mucho más fácil organizar todo.
Woodrow Barlow

@Jester, debo agregar que el 99% de ese script vinculador vino directamente de ca65 ; todo lo que agregué fue el segmento "GFXDATA".
Woodrow Barlow

2
@Jester, Dios mío, estaba seguro de haber verificado tres veces esos registros. Acabo de actualizar mi código para usar los registros X e Y correctos ... y funciona perfectamente. No puedo creer que haya pasado dos tardes en esto y no me haya dado cuenta.
Woodrow Barlow

1
En caso de que no lo sepas, hay Retrocomputing.SE , donde la gente ama estas cosas.
Tum_

Respuestas:


5

Como @Jester señaló en los comentarios, las direcciones de memoria de posición X e Y son incorrectas. Las direcciones correctas son $d000y $d001:

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

Este es el código corregido:

    .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

Y aquí hay una foto en acción:


No abuse de la función "wiki de la comunidad". Esta respuesta no tiene por qué ser una.
tubería

1
@pipe por qué no? Jester respondió las preguntas en los comentarios. Lo invité a publicarlo como respuesta. no lo hizo. así que lo publiqué, pero como no fui yo quien encontró la respuesta, no me pareció apropiado poner mi nombre en él.
Woodrow Barlow

1
Este hilo dice que el momento adecuado para usar un wiki comunitario es "si su respuesta se compila simplemente a partir de lo que otros respondieron en los comentarios".
Woodrow Barlow

1
Este hilo, con aún más votos a favor, incluso llega a decir que siempre está bien hacer una respuesta en una wiki comunitaria si así lo desea.
Woodrow Barlow

2

Puede usar VIC_SPR0_X y VIC_SPR0_Y si lo incluye c64.inc. Esto puede hacer tu vida mucho más fácil.


buen consejo, gracias! Lo haré en el futuro. puedes agregar esto a la respuesta wiki de la comunidad si lo deseas.
Woodrow Barlow
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.