Autor Tema: Rutinas de ensamblador con Laddh  (Leído 6945 veces)

Laddh

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 255
    • Ver Perfil
Re:Rutinas de ensamblador con Laddh
« Respuesta #15 en: Abril 29, 2024, 11:51:43 »
Y sí, lo de la música es sencillísimo de utilizar, aunque más difícil de entender, el fichero SID es más que la "partitura", es un programa en si mismo con varios datos de formato, de ahí el ,126 que se incluye al final del incbin para saltarse esos datos. Estaría bien que algún virtuoso de la creación de música nos aclarase todo lo que conlleva un fichero SID.

josepzin

  • Administrador
  • Commodore Master
  • *****
  • Mensajes: 13904
  • Commodoreador web
    • Ver Perfil
    • Mi blog
Re:Rutinas de ensamblador con Laddh
« Respuesta #16 en: Abril 29, 2024, 14:37:27 »
Yo tengo entendido que un SID no es solo los datos de la música sino también su propio "player". Pero hasta ahí llegan mis conocimientos.
www.retroinvaders.com | www.commodoreplus.org  | josepzin.blogspot.com

PacoBlog64

  • Commodore Master
  • *****
  • Mensajes: 373
  • INC $D020
    • Ver Perfil
    • PacoBlog64
Re:Rutinas de ensamblador con Laddh
« Respuesta #17 en: Abril 29, 2024, 16:30:33 »
Yo tengo entendido que un SID no es solo los datos de la música sino también su propio "player". Pero hasta ahí llegan mis conocimientos.

Es algo así, @Narcisound lo controla bastante, dicen  ;D ;D ;D Cuando haces la música en un tracker como GoatTracker, al pasarla a SID la conviertes en un programa que te permitirá reproducirla desde otro, con su dirección inicial y otras para controlar volúmenes o efectos, pero luego no puedes convertir un fichero SID en un fichero en formato tracker para modificarlo y volver a pasarlo a SID, porque lo que tiene un fichero SID es código en ensamblador, no las propias notas.
Commodoriano desde mis tiernos 7 añitos. ¿Quién necesita más de 1MHz, 64KB de RAM, 16 colores y 3 canales de sonido?

Narcisound

  • MasterSID
  • Commodore Master
  • *****
  • Mensajes: 498
  • MASTERSID
    • Ver Perfil
Re:Rutinas de ensamblador con Laddh
« Respuesta #18 en: Mayo 01, 2024, 11:34:57 »
Buenas, contesto por alusiones  ;D

Un fichero SID no es más que un programa que se ha compilado en lenguaje máquina.

¿De donde sale la fuente de ese programa?

Puede salir de varios sitios. Hoy en día, lo más común es que salga desde un editor nativo como puede ser el SIDWizard, o desde un editor externo de Windows como es el Goattracker.

En sus primeros años musicales (década de los 80´s y principios de los 90´s), los primeros "SIDs" se creaban directamente en un editor ensamblador, el cual contenía la "routine player" (el motor para la música) y los datos propios de la melodía a componer como son los sonidos o efectos, las notas propias de las melodías (tunes o sub-tunes) y efectos a usar por las melodías (vibrato, filtros, modulaciones de anillo, formas de onda, trémolos, etc).

Por tanto, en nuestro código ensamblador para la música veríamos en primer lugar todas las instrucciones (LDA, STA, BNE, etc..), de la routine player y mas abajo, mogollón de datos (datas), que serviran para dar vida a nuestra melodía.

¿Como se hacía la música desde el editor ensamblador?

Pues era una tarea durísima en la cual a base de prueba y error, ibas alterando los parámetros del SID para lograr crear los sonidos que necesitaba la música (bajos, cajas "snare", bombos, acordes arpegiados, solos "leads", vibes, pics, flautas, violines simulados (Sanxion), etc.

¿Y las melodías?

Pues de igual forma, ibas metiendo datos con la nota que iba a sonar (Do, Re, Mi, Fa.....) y su duración en milisegundos, por ejemplo, éste data: $40,$32 significa que vamos a tocar un DO en la tercera octava del SID durante 2 segundos. Luego claro está, tendremos que meter datas adicionales para decir que sonido del banco disponible va a sonar, si ese sonido va a tener un vibrato, filtro, modulación, forma de onda, etc, y durante cuanto tiempo va a usarse ese efecto en nuestra nota musical, también podemos meter mas datas para controlar el ADSR del sonido:

Ataque = El tiempo que tardará el sonido en alcanzar el volumen máximo que pongamos.

Decaimiento = El tiempo que tardará el sonido en alcanzar el volumen de sostenimiento.

Sostenimiento = El tiempo que el sonido se va a sostener en duración y volumen.

Relajación = El tiempo que tardará el sonido en alcanzar el volumen mínimo que pongamos.

Básicamente para entenderlo un poco mejor, el "Ataque" es el nacimiento del sonido, el "Decaimiento" y "Sostenimiento" es la vida que va a tener el sonido y la "Relajación", corresponde a la muerte del sonido o como éste va a desaparecer y dejarse de oír.

Y ya con todas éstas nociones, pues te ponías a meter datos y mas datos musicales hasta que por fin, compilabas el programa y al ejecutarlo deberías escuchar una hermosa melodía creada para nuestro querido SID.

¿Y hoy en día, como se hacen los SIDs?

Afortunadamente, hoy en día tenemos "editores/trackers" como antes he comentado (SIDWizard, GoatTracker), los cuales nos facilitan mucho la labor de crear música para el SID.

Si bien, en éstos editores, todavía tenemos que crear nuestro sonidos y efectos a base de meter datos (eso apenas ha cambiado), a la hora de componer las notas de nuestras melodías, tendremos la facilidad y claridad que un tracker nos ofrece. Eso si, tu imaginación, destreza y arte para decidir como va a ser la melodía que vas a crear siempre es de la misma forma. Ya sea simplemente tarareando esa melodía (eso hago yo), o improvisando con un piano, flauta, silvando o lo que sea, siempre ha sido y será así.  :)

Bueno, perdonarme el tocho pero creo que ha valido la pena.


Laddh

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 255
    • Ver Perfil
Re:Rutinas de ensamblador con Laddh
« Respuesta #19 en: Mayo 01, 2024, 13:43:56 »
Es una buena aclaración  :D

josepzin

  • Administrador
  • Commodore Master
  • *****
  • Mensajes: 13904
  • Commodoreador web
    • Ver Perfil
    • Mi blog
Re:Rutinas de ensamblador con Laddh
« Respuesta #20 en: Mayo 03, 2024, 00:13:40 »
Transpolando esto del sonido al video, es como si se tuviera que:
- Definir el RGB de la paleta de los 16 colores disponibles
- Crear las rutinas que ponen los pixels en pantalla
- Y luego el gráfico en si, que son los datos que aporta el tracker.

Si la analogía no sirve es que no lo entendí jaja no me peguen...
« última modificación: Mayo 03, 2024, 00:19:31 por josepzin »
www.retroinvaders.com | www.commodoreplus.org  | josepzin.blogspot.com

Laddh

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 255
    • Ver Perfil
Re:Rutinas de ensamblador con Laddh
« Respuesta #21 en: Mayo 03, 2024, 11:32:09 »
Próximo capítulo: que el sprite pase los X > 255

Nos centraremos solo en esto porque lo merece. Al empezar a programar con sprites siempre nos encontraremos con este problema, en un byte solo caben valores de 0 a 255 pero en la pantalla visible se llega hasta la coordenada 346 x en horizontal. Para acceder a esa parte derecha de la pantalla hay que activar el bit correspondiente a cada sprite en el registro $d010, lda #1 sta $d010 para el sprite 0 por ejemplo, y señalar su nueva posición X volviendo a escribir 0 en su coordenada X, o sea 0=256, 1=257, etc, si seguimos avanzando hacia la derecha hasta 96 máximo que ya se saldría de la pantalla.
Y a la inversa si volvemos a la izquierda, habría que poner a 0 el bit correspondiente en el registro $d010 para que nos lo muestre en la parte izquierda de la pantalla, o sea, desactivar registro y poner el valor 255 en la coordenada X del sprite.
Esto es fácil de hacer con un sprite pero se complica cuando estas moviendo los 8 sprites por la pantalla, comprobar todas las posibles combinaciones de si están en el lado derecho o el izquierdo es arduo y farragoso si lo compruebas sprite por sprite, pero no hace mucho encontré una rutina de como lo controla el Richard Bayliss/TND en su excelente tutorial de Assemble it en https://tnd64.unikat.sk/ y es la rutina Expande que añadiremos a nuestro programa, con solo 11 mnemónicos, niquelao, ver para creer.
Ejecutar el programa y analizar la rutina en el listado, con esas simples líneas controla los 8 sprites, estén o no en pantalla en todo momento, lo que hace es crear unas variables spritepos para las coordenadas X,Y de los 8 sprites que estan al final del listado, y en la rutina EXPANDE las convierte a coordenadas hardware. Simple y efectivo. 
He añadido una rutina SpritesWave para que veáis como se mueven todos los sprites por pantalla.

Código: [Seleccionar]
; 10 SYS (2064) línea para que autoarranque el programa

*=$0801

        BYTE    $0E, $08, $0A, $00, $9E, $20, $28,  $32, $30, $36, $34, $29, $00, $00, $00

*=$0810 ;inicio del programa

v = $d000       ;variable que apunta al chip VIC, el que gestiona todo lo gráfico


        jsr musica      ;llama a rutina música por interrupciones
        jsr sprites     ;llamamos a la rutina para presentar el sprite en pantalla
loop    jsr raster_wait ;sin esto no veríamos nada, el código máquina es raaaaaapido               
        jsr PlayerControl ;la rutina para controlar el joystick
        jsr expande     ;controla msb de los sprites, > o < de 255 x
        jmp loop        ;vuelve al bucle principal


expande  ldx #$00       ;posición msb de los sprites
xloop    lda spritepos+1,x
         sta $d001,x
         lda spritepos,x
         asl        ;x position is more
         ror $d010  ;than 256 pixels
         sta $d000,x
         inx
         inx
         cpx #16
         bne xloop
         rts

SpritesWave
        lda contador
        tax
        inc contador

        lda tabla,x
        sta spritepos+4
        lda tabla+$100,x
        sta spritepos+5

        lda tabla,x
        sec
        sbc #10
        sta spritepos+6
        lda tabla+$100,x
        sta spritepos+7

        lda tabla,x
        sec
        sbc #20
        sta spritepos+8
        lda tabla+$100,x
        sta spritepos+9

        lda tabla,x
        sec
        sbc #30
        sta spritepos+2
        lda tabla+$100,x
        sta spritepos+3

        lda tabla,x
        sec
        sbc #40
        sta spritepos+10
        lda tabla+$100,x
        sta spritepos+11

        lda tabla,x
        sec
        sbc #50
        sta spritepos+12
        lda tabla+$100,x
        sta spritepos+13

        lda tabla,x
        sec
        sbc #60
        sta spritepos+14
        lda tabla+$100,x
        sta spritepos+15

        rts

MUSICA    sei
          lda #<irq
          ldx #>irq
          sta $314
          stx $315
          lda #$00
          JSR $1000     ;INITIALIZE MUSIC
          cli
          RTS

irq       lda #$01
          STA $D019     ; ACK ANY RASTER IRQS
          JSR $1003     ;PLAY THE MUSIC
          jsr SpritesWave
          jmp $ea31


PlayerControl
        LDA $DC00   ;LEEMOS JOY
        AND #31     ;LA CUATRO DIRECCIONES ARRIBA ABAJO IZQ DER   
        CMP #30     ;MAS DIAGONALES Y FUEGO
        BEQ ARR
        CMP #29
        BEQ ABJ
        CMP #27
        BEQ IZQ
        CMP #23
        BEQ DER
        cmp #22
        beq derar
        cmp #21
        beq derab
        CMP #25
        BEQ IZQab
        CMP #26
        BEQ IZQar
        cmp #15
        beq fuego
        rts

arr     dec spritepos+1 ;coordenada vertical del sprite 0
        rts
abj     inc spritepos+1
        rts
izq     dec spritepos   ;coordenada horizontal del sprite 0
        rts
der     inc spritepos
        rts
derar   inc spritepos
        dec spritepos+1
        rts
derab   inc spritepos
        inc spritepos+1
        rts
izqab   dec spritepos
        inc spritepos+1
        rts
izqar   dec spritepos
        dec spritepos+1
        rts
fuego   inc $d020       ;cambia color del borde pantalla
        rts

raster_wait             ;espera línea raster 255, el raster pasa 50 veces por segundo
l       LDA #$ff        ;en pantalla
        CMP $D012
        BNE l
        BIT $d011
        BMI l
        rts

*=2368  ; la forma del sprite
 byte 9,86,0
 byte 37,86,0
 byte 149,86,0
 byte 85,86,0
 byte 85,170,170
 byte 86,37,86
 byte 86,37,86
 byte 86,37,86
 byte 86,37,90
 byte 86,42,168
 byte 86,42,168
 byte 86,47,250
 byte 86,47,254
 byte 86,47,254
 byte 86,47,254
 byte 86,42,170
 byte 85,170,0
 byte 85,86,0
 byte 149,86,0
 byte 37,86,0
 byte 9,86,0

sprites lda #255
        sta v+21        ;activamos todos los sprites
        sta v+28        ;activamos modo multicolor del sprite 0
        lda #37         ;puntero para indicar donde estan los datos del sprite, 37*64=2368
        sta 2040
        sta 2041
        sta 2042
        sta 2043
        sta 2044
        sta 2045
        sta 2046
        sta 2048
        lda #1          ;color sprites
        sta v+39
        lda #9          ;color sprites
        sta v+40
        lda #3          ;color sprites
        sta v+41
        lda #4          ;color sprites
        sta v+42
        lda #5          ;color sprites
        sta v+43
        lda #6          ;color sprites
        sta v+44
        lda #7          ;color sprites
        sta v+45
        lda #8          ;color sprites
        sta v+46

        lda #14         ;color multicolor 1, para todos los sprites
        sta v+37
        lda #2          ;color multicolor 2, para todos los sprites
        sta v+38
        lda #100        ;coordenadas x,y del sprite 0
        sta spritepos
        sta spritepos+1
        rts

*=$1000
incbin"commodore_64.sid",126

contador        byte 0

spritepos       BYTE $00,$00 ;SPRITE 0 X/Y
                BYTE $00,$00 ;SPRITE 1 X/Y
                BYTE $00,$00 ;SPRITE 2 X/Y
                BYTE $00,$00 ;SPRITE 3 X/Y
                BYTE $00,$00 ;SPRITE 4 X/Y
                BYTE $00,$00 ;SPRITE 5 X/Y
                BYTE $00,$00 ;SPRITE 6 X/Y
                BYTE $00,$00 ;SPRITE 7 X/Y

tabla     BYTE $B6,$B6,$B6,$B6,$B3,$B0,$AD,$AA,$A7,$A4,$A1,$9E,$9B,$98,$95,$92,$8F,$8C
          BYTE $89,$86,$83,$80,$7D,$7A,$77,$74,$71,$6E,$6B,$68,$65,$62,$5F,$5C,$59,$56,$53,$50
          BYTE $4D,$4A,$47,$44,$41,$3E,$3B,$38,$35,$32,$2F,$2C,$29,$26,$23,$20,$1D,$1A,$17,$14
          BYTE $11,$0E,$0B,$08,$05,$02,$FF,$FC,$F9,$F6,$FC,$FC,$FC,$FF,$02,$05,$08,$0B,$0E,$11
          BYTE $14,$17,$1A,$1D,$20,$23,$26,$29,$2C,$2F,$32,$35,$38,$3B,$3E,$41,$44,$47,$4A,$4D
          BYTE $50,$53,$56,$59,$5C,$5F,$62,$65,$68,$6B,$6E,$71,$74,$77,$7A,$7D,$80,$83,$86,$89
          BYTE $8C,$8F,$92,$95,$98,$9B,$9E,$A1,$A4,$A7,$AA,$AD,$B0,$B3,$B6,$B6,$B9,$B9,$B9,$B9
          BYTE $B9,$B9,$B6,$B3,$B0,$AD,$AA,$A7,$A4,$A1,$9E,$9B,$98,$95,$92,$8F,$8C,$89,$86,$83
          BYTE $80,$7D,$7A,$77,$74,$71,$6E,$6B,$68,$65,$62,$5F,$5C,$59,$56,$53,$50,$4D,$4A,$47
          BYTE $44,$41,$3E,$3B,$38,$35,$32,$2F,$2C,$29,$26,$23,$20,$1D,$1A,$17,$14,$11,$0E,$0B
          BYTE $08,$05,$02,$FF,$FC,$F9,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6
          BYTE $F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6
          BYTE $F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$E6,$36,$36
          BYTE $36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36
          BYTE $36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36
          BYTE $36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36
          BYTE $36,$36,$36,$36,$36,$36,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72
          BYTE $72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72
          BYTE $72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72
          BYTE $72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4
          BYTE $B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4
          BYTE $B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4
          BYTE $B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4
          BYTE $B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4
          BYTE $B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4
          BYTE $B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$5A
« última modificación: Mayo 03, 2024, 11:46:47 por Laddh »

PacoBlog64

  • Commodore Master
  • *****
  • Mensajes: 373
  • INC $D020
    • Ver Perfil
    • PacoBlog64
Re:Rutinas de ensamblador con Laddh
« Respuesta #22 en: Mayo 03, 2024, 17:28:07 »
Próximo capítulo: que el sprite pase los X > 255

Nos centraremos solo en esto porque lo merece. Al empezar a programar con sprites siempre nos encontraremos con este problema, en un byte solo caben valores de 0 a 255 pero en la pantalla visible se llega hasta la coordenada 346 x en horizontal. Para acceder a esa parte derecha de la pantalla hay que activar el bit correspondiente a cada sprite en el registro $d010, lda #1 sta $d010 para el sprite 0 por ejemplo, y señalar su nueva posición X volviendo a escribir 0 en su coordenada X, o sea 0=256, 1=257, etc, si seguimos avanzando hacia la derecha hasta 96 máximo que ya se saldría de la pantalla.
Y a la inversa si volvemos a la izquierda, habría que poner a 0 el bit correspondiente en el registro $d010 para que nos lo muestre en la parte izquierda de la pantalla, o sea, desactivar registro y poner el valor 255 en la coordenada X del sprite.
Esto es fácil de hacer con un sprite pero se complica cuando estas moviendo los 8 sprites por la pantalla, comprobar todas las posibles combinaciones de si están en el lado derecho o el izquierdo es arduo y farragoso si lo compruebas sprite por sprite, pero no hace mucho encontré una rutina de como lo controla el Richard Bayliss/TND en su excelente tutorial de Assemble it en https://tnd64.unikat.sk/ y es la rutina Expande que añadiremos a nuestro programa, con solo 11 mnemónicos, niquelao, ver para creer.
Ejecutar el programa y analizar la rutina en el listado, con esas simples líneas controla los 8 sprites, estén o no en pantalla en todo momento, lo que hace es crear unas variables spritepos para las coordenadas X,Y de los 8 sprites que estan al final del listado, y en la rutina EXPANDE las convierte a coordenadas hardware. Simple y efectivo. 
He añadido una rutina SpritesWave para que veáis como se mueven todos los sprites por pantalla.

Código: [Seleccionar]
; 10 SYS (2064) línea para que autoarranque el programa

*=$0801

        BYTE    $0E, $08, $0A, $00, $9E, $20, $28,  $32, $30, $36, $34, $29, $00, $00, $00

*=$0810 ;inicio del programa

v = $d000       ;variable que apunta al chip VIC, el que gestiona todo lo gráfico


        jsr musica      ;llama a rutina música por interrupciones
        jsr sprites     ;llamamos a la rutina para presentar el sprite en pantalla
loop    jsr raster_wait ;sin esto no veríamos nada, el código máquina es raaaaaapido               
        jsr PlayerControl ;la rutina para controlar el joystick
        jsr expande     ;controla msb de los sprites, > o < de 255 x
        jmp loop        ;vuelve al bucle principal


expande  ldx #$00       ;posición msb de los sprites
xloop    lda spritepos+1,x
         sta $d001,x
         lda spritepos,x
         asl        ;x position is more
         ror $d010  ;than 256 pixels
         sta $d000,x
         inx
         inx
         cpx #16
         bne xloop
         rts

SpritesWave
        lda contador
        tax
        inc contador

        lda tabla,x
        sta spritepos+4
        lda tabla+$100,x
        sta spritepos+5

        lda tabla,x
        sec
        sbc #10
        sta spritepos+6
        lda tabla+$100,x
        sta spritepos+7

        lda tabla,x
        sec
        sbc #20
        sta spritepos+8
        lda tabla+$100,x
        sta spritepos+9

        lda tabla,x
        sec
        sbc #30
        sta spritepos+2
        lda tabla+$100,x
        sta spritepos+3

        lda tabla,x
        sec
        sbc #40
        sta spritepos+10
        lda tabla+$100,x
        sta spritepos+11

        lda tabla,x
        sec
        sbc #50
        sta spritepos+12
        lda tabla+$100,x
        sta spritepos+13

        lda tabla,x
        sec
        sbc #60
        sta spritepos+14
        lda tabla+$100,x
        sta spritepos+15

        rts

MUSICA    sei
          lda #<irq
          ldx #>irq
          sta $314
          stx $315
          lda #$00
          JSR $1000     ;INITIALIZE MUSIC
          cli
          RTS

irq       lda #$01
          STA $D019     ; ACK ANY RASTER IRQS
          JSR $1003     ;PLAY THE MUSIC
          jsr SpritesWave
          jmp $ea31


PlayerControl
        LDA $DC00   ;LEEMOS JOY
        AND #31     ;LA CUATRO DIRECCIONES ARRIBA ABAJO IZQ DER   
        CMP #30     ;MAS DIAGONALES Y FUEGO
        BEQ ARR
        CMP #29
        BEQ ABJ
        CMP #27
        BEQ IZQ
        CMP #23
        BEQ DER
        cmp #22
        beq derar
        cmp #21
        beq derab
        CMP #25
        BEQ IZQab
        CMP #26
        BEQ IZQar
        cmp #15
        beq fuego
        rts

arr     dec spritepos+1 ;coordenada vertical del sprite 0
        rts
abj     inc spritepos+1
        rts
izq     dec spritepos   ;coordenada horizontal del sprite 0
        rts
der     inc spritepos
        rts
derar   inc spritepos
        dec spritepos+1
        rts
derab   inc spritepos
        inc spritepos+1
        rts
izqab   dec spritepos
        inc spritepos+1
        rts
izqar   dec spritepos
        dec spritepos+1
        rts
fuego   inc $d020       ;cambia color del borde pantalla
        rts

raster_wait             ;espera línea raster 255, el raster pasa 50 veces por segundo
l       LDA #$ff        ;en pantalla
        CMP $D012
        BNE l
        BIT $d011
        BMI l
        rts

*=2368  ; la forma del sprite
 byte 9,86,0
 byte 37,86,0
 byte 149,86,0
 byte 85,86,0
 byte 85,170,170
 byte 86,37,86
 byte 86,37,86
 byte 86,37,86
 byte 86,37,90
 byte 86,42,168
 byte 86,42,168
 byte 86,47,250
 byte 86,47,254
 byte 86,47,254
 byte 86,47,254
 byte 86,42,170
 byte 85,170,0
 byte 85,86,0
 byte 149,86,0
 byte 37,86,0
 byte 9,86,0

sprites lda #255
        sta v+21        ;activamos todos los sprites
        sta v+28        ;activamos modo multicolor del sprite 0
        lda #37         ;puntero para indicar donde estan los datos del sprite, 37*64=2368
        sta 2040
        sta 2041
        sta 2042
        sta 2043
        sta 2044
        sta 2045
        sta 2046
        sta 2048
        lda #1          ;color sprites
        sta v+39
        lda #9          ;color sprites
        sta v+40
        lda #3          ;color sprites
        sta v+41
        lda #4          ;color sprites
        sta v+42
        lda #5          ;color sprites
        sta v+43
        lda #6          ;color sprites
        sta v+44
        lda #7          ;color sprites
        sta v+45
        lda #8          ;color sprites
        sta v+46

        lda #14         ;color multicolor 1, para todos los sprites
        sta v+37
        lda #2          ;color multicolor 2, para todos los sprites
        sta v+38
        lda #100        ;coordenadas x,y del sprite 0
        sta spritepos
        sta spritepos+1
        rts

*=$1000
incbin"commodore_64.sid",126

contador        byte 0

spritepos       BYTE $00,$00 ;SPRITE 0 X/Y
                BYTE $00,$00 ;SPRITE 1 X/Y
                BYTE $00,$00 ;SPRITE 2 X/Y
                BYTE $00,$00 ;SPRITE 3 X/Y
                BYTE $00,$00 ;SPRITE 4 X/Y
                BYTE $00,$00 ;SPRITE 5 X/Y
                BYTE $00,$00 ;SPRITE 6 X/Y
                BYTE $00,$00 ;SPRITE 7 X/Y

tabla     BYTE $B6,$B6,$B6,$B6,$B3,$B0,$AD,$AA,$A7,$A4,$A1,$9E,$9B,$98,$95,$92,$8F,$8C
          BYTE $89,$86,$83,$80,$7D,$7A,$77,$74,$71,$6E,$6B,$68,$65,$62,$5F,$5C,$59,$56,$53,$50
          BYTE $4D,$4A,$47,$44,$41,$3E,$3B,$38,$35,$32,$2F,$2C,$29,$26,$23,$20,$1D,$1A,$17,$14
          BYTE $11,$0E,$0B,$08,$05,$02,$FF,$FC,$F9,$F6,$FC,$FC,$FC,$FF,$02,$05,$08,$0B,$0E,$11
          BYTE $14,$17,$1A,$1D,$20,$23,$26,$29,$2C,$2F,$32,$35,$38,$3B,$3E,$41,$44,$47,$4A,$4D
          BYTE $50,$53,$56,$59,$5C,$5F,$62,$65,$68,$6B,$6E,$71,$74,$77,$7A,$7D,$80,$83,$86,$89
          BYTE $8C,$8F,$92,$95,$98,$9B,$9E,$A1,$A4,$A7,$AA,$AD,$B0,$B3,$B6,$B6,$B9,$B9,$B9,$B9
          BYTE $B9,$B9,$B6,$B3,$B0,$AD,$AA,$A7,$A4,$A1,$9E,$9B,$98,$95,$92,$8F,$8C,$89,$86,$83
          BYTE $80,$7D,$7A,$77,$74,$71,$6E,$6B,$68,$65,$62,$5F,$5C,$59,$56,$53,$50,$4D,$4A,$47
          BYTE $44,$41,$3E,$3B,$38,$35,$32,$2F,$2C,$29,$26,$23,$20,$1D,$1A,$17,$14,$11,$0E,$0B
          BYTE $08,$05,$02,$FF,$FC,$F9,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6
          BYTE $F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6
          BYTE $F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$F6,$E6,$36,$36
          BYTE $36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36
          BYTE $36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36
          BYTE $36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36
          BYTE $36,$36,$36,$36,$36,$36,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72
          BYTE $72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72
          BYTE $72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72
          BYTE $72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$72,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4
          BYTE $B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4
          BYTE $B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4
          BYTE $B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4
          BYTE $B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4
          BYTE $B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4
          BYTE $B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$B4,$5A

Excelente explicación, simplemente añadir que la posición x=0 para los sprites está 24 píxeles a la izquierda del 0 de los caracteres, esto es así para poder hacer que un sprite aparezca píxel a píxel por el margen izquierdo, desde detrás del borde. Por ejemplo, si tienes el registro $d010 a 0 y pones $d000 (posición x del primer sprite) a 0 y $d001 (posición y del primer sprite) a 100 , el sprite no se verá porque quedará detrás del borde izquierdo. La última posición en la que puedes poner un sprite por la derecha es la que indicas por lo mismo, para poder esconderlo total o parcialmente en el borde derecho.
Commodoriano desde mis tiernos 7 añitos. ¿Quién necesita más de 1MHz, 64KB de RAM, 16 colores y 3 canales de sonido?

josepzin

  • Administrador
  • Commodore Master
  • *****
  • Mensajes: 13904
  • Commodoreador web
    • Ver Perfil
    • Mi blog
Re:Rutinas de ensamblador con Laddh
« Respuesta #23 en: Mayo 13, 2024, 16:52:33 »
Esto es fácil de hacer con un sprite pero se complica cuando estas moviendo los 8 sprites por la pantalla, comprobar todas las posibles combinaciones de si están en el lado derecho o el izquierdo es arduo y farragoso si lo compruebas sprite por sprite, pero no hace mucho encontré una rutina de como lo controla el Richard Bayliss/TND en su excelente tutorial de Assemble it en https://tnd64.unikat.sk/ y es la rutina Expande que añadiremos a nuestro programa, con solo 11 mnemónicos, niquelao, ver para creer.

Y habrá que verlo, porque 11 parecen muy poquitos!!
www.retroinvaders.com | www.commodoreplus.org  | josepzin.blogspot.com

Laddh

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 255
    • Ver Perfil
Re:Rutinas de ensamblador con Laddh
« Respuesta #24 en: Mayo 13, 2024, 19:17:27 »
Pues míratelo, ahí los tienes en la rutina expande, y en el ejecutable en acción.

Laddh

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 255
    • Ver Perfil
Re:Rutinas de ensamblador con Laddh
« Respuesta #25 en: Mayo 17, 2024, 12:36:09 »
En esta entrega toca el ejemplo de scroll por hardware o scroll fino, pixel a pixel, que siempre diferencio nuestro c64 de otras máquinas de la época.
Lo primero de todo es poner la pantalla en modo 38 columnas para el scroll horizontal. Los tres primeros bits del registro $d016 controlan el scroll horizontal y los del registro $d011 el vertical, el funcionamiento es el mismo y afecta a toda la pantalla.
Con 3 bits llegamos de 0 a 7, o sea 8 pixeles, justo el tamaño de un carácter, con lo que sumando haríamos scroll a la derecha y restando hacia la izquierda, como en el ejemplo que os pongo hoy, la rutina left, pero ojo, justo al llegar a 0 toca hacer un scroll por soft de todas las líneas que queráis mover sino el scroll hard entraría en bucle y volvería a poner el carácter en su posición de inicio, en el listado lo tenéis comentado, junto con el ejecutable para que lo veáis en acción.
Código: [Seleccionar]
; 10 SYS (2064) línea para que autoarranque el programa

*=$0801

        BYTE    $0E, $08, $0A, $00, $9E, $20, $28,  $32, $30, $36, $34, $29, $00, $00, $00

screen_control_register1 = $d011
screen_control_register2 = $d016

*=$0810 ;inicio del programa

v = $d000       ;variable que apunta al chip VIC, el que gestiona todo lo gráfico


        LDA screen_control_register2
        AND #$F7    ;pon pantalla en 38 columnas
        STA screen_control_register2
 
        jsr sprites     ;llamamos a la rutina para presentar el sprite en pantalla
loop    jsr raster_wait ;sin esto no veríamos nada, el código máquina es raaaaaapido               
        jsr PlayerControl ;la rutina para controlar el joystick
        jsr expande     ;controla msb de los sprites, > o < de 255 x
        jsr left        ;rutina scroll
        jmp loop        ;vuelve al bucle principal

left                    ; scroll por hardware pixel a pixel
    LDX screen_offset
    DEX                 ; decrementa variable de 7 a 0
    STX screen_offset
    CPX #$FF
    BEQ continue        ;hemos llegado a 0? vuelve el valor a 7
    JMP end
continue
    LDX #$07
    STX screen_offset
        jsr move_rows_left
        jsr advance_scroll
end
    LDA screen_control_register2
    AND #$F8            ;11111000 pone los 3 primeros bits del registro a 0
    ORA screen_offset   ; le va restando de 7 a 0
    STA screen_control_register2 ; y lo guarda en el registro de scroll $d016
        rts

move_rows_left          ; scroll por soft, mueve una columna a la izquierda
    LDX #$00
l2
    lda $0429,x
    sta $0428,x
    LDA $0451,X
    STA $0450,X
    LDA $0479,X
    STA $0478,X
    LDA $04A1,X
    STA $04A0,X
    LDA $04C9,X
    STA $04C8,X
    LDA $04F1,X
    STA $04F0,X
    LDA $0519,X
    STA $0518,X
    LDA $0541,X
    STA $0540,X
    LDA $0569,X
    STA $0568,X
    LDA $0591,X
    STA $0590,X
    LDA $05B9,X
    STA $05B8,X
    LDA $05E1,X
    STA $05E0,X
    INX
    CPX #39
    BNE l2
        rts

advance_scroll;efecto persiana, pasa la primera columna izquierda a la última por la derecha
        lda $0428
        sta $044f
        lda $0450
        sta $0477
        lda $0478
        sta $049f
        lda $04a0
        sta $04c7
        lda $04c8
        sta $04ef
        lda $04f0
        sta $0517
        lda $0518
        sta $053f
        lda $0540
        sta $0567
        lda $0568
        sta $058f
        lda $0590
        sta $05b7
        lda $05b8
        sta $05df
        lda $05e0
        sta $0607
        rts
screen_offset byte $07

PlayerControl
        LDA $DC00   ;LEEMOS JOY
        AND #31     ;LA CUATRO DIRECCIONES ARRIBA ABAJO IZQ DER   
        CMP #30     ;MAS DIAGONALES Y FUEGO
        BEQ ARR
        CMP #29
        BEQ ABJ
        CMP #27
        BEQ IZQ
        CMP #23
        BEQ DER
        cmp #22
        beq derar
        cmp #21
        beq derab
        CMP #25
        BEQ IZQab
        CMP #26
        BEQ IZQar
        cmp #15
        beq fuego
        rts

arr     dec spritepos+1 ;coordenada vertical del sprite 0
        rts
abj     inc spritepos+1
        rts
izq     dec spritepos   ;coordenada horizontal del sprite 0
        rts
der     inc spritepos
        rts
derar   inc spritepos
        dec spritepos+1
        rts
derab   inc spritepos
        inc spritepos+1
        rts
izqab   dec spritepos
        inc spritepos+1
        rts
izqar   dec spritepos
        dec spritepos+1
        rts
fuego   inc $d020       ;cambia color del borde pantalla
        rts

raster_wait             ;espera línea raster 255, el raster pasa 50 veces por segundo
l       LDA #$ff        ;en pantalla
        CMP $D012
        BNE l
        BIT $d011
        BMI l
        rts

sprites lda #1
        sta v+21        ;activamos sprite 0
        sta v+28        ;activamos modo multicolor del sprite 0
        lda #128         ;puntero para indicar donde estan los datos del sprite, 128*64=8192 $2000
        sta 2040

        lda #1          ;color sprite
        sta v+39

        lda #14         ;color multicolor 1, para todos los sprites
        sta v+37
        lda #2          ;color multicolor 2, para todos los sprites
        sta v+38
        lda #100        ;coordenadas x,y del sprite 0
        sta spritepos
        sta spritepos+1
        rts

expande  ldx #$00       ;posición msb de los sprites
xloop    lda spritepos+1,x
         sta $d001,x
         lda spritepos,x
         asl        ;x position is more
         ror $d010  ;than 256 pixels
         sta $d000,x
         inx
         inx
         cpx #16
         bne xloop
         rts

*=$2000 ; la forma del sprite
 byte 9,86,0
 byte 37,86,0
 byte 149,86,0
 byte 85,86,0
 byte 85,170,170
 byte 86,37,86
 byte 86,37,86
 byte 86,37,86
 byte 86,37,90
 byte 86,42,168
 byte 86,42,168
 byte 86,47,250
 byte 86,47,254
 byte 86,47,254
 byte 86,47,254
 byte 86,42,170
 byte 85,170,0
 byte 85,86,0
 byte 149,86,0
 byte 37,86,0
 byte 9,86,0

spritepos   BYTE $00,$00 ;SPRITE 0 X/Y
                BYTE $00,$00 ;SPRITE 1 X/Y
                BYTE $00,$00 ;SPRITE 2 X/Y
                BYTE $00,$00 ;SPRITE 3 X/Y
                BYTE $00,$00 ;SPRITE 4 X/Y
                BYTE $00,$00 ;SPRITE 5 X/Y
                BYTE $00,$00 ;SPRITE 6 X/Y
                BYTE $00,$00 ;SPRITE 7 X/Y

Con solo todas la rutinas que os he mostrado en estos mensajes, lo creáis o no, ya tenéis el armazón para construir vuestro propio primer juego en ensamblador, solo añadiendo la lógica que queráis que tenga vuestro programa. Es cuestión de probar y perseverar hasta que lo consigáis. Crear tu propio programa, parir tu propia creación os aseguro que llena de orgullo y satisfacción, mucho más que solo jugar partidas al juego que sea. Animo y queda este hilo para las dudas que os surjan.