Upgrade to Pro — share decks privately, control downloads, hide ads and more …

'Raster Shaders' on Commodore 64

'Raster Shaders' on Commodore 64

Video cards can execute small programs whenever a pixel is displayed on screen.
Commodore 64 can execute small programs whenever a raster line is displayed on TV.

Pixel shaders can be used to create realistic lighting, special effects and even compute physics!
‘Raster shaders’ can be used to split screen, display more sprites and even play sound!

Michał Taszycki

June 02, 2016
Tweet

More Decks by Michał Taszycki

Other Decks in Programming

Transcript

  1. Pixel Shader varying vec3 N; varying vec3 v; void main(void)

    { vec3 L = normalize(gl_LightSource[0].position.xyz - v); vec4 Idiff = gl_FrontLightProduct[0].diffuse * max(dot(N,L), 0.0); Idiff = clamp(Idiff, 0.0, 1.0); gl_FragColor = Idiff; }
  2. “Raster Shader” irq: lda #$ff sta $d019 ldx #$05 d:

    dex bne d ldx #$00 c: ldy #$08 a: lda colors,x sta $d020 sta $d021 inx dey beq c txa ldx #$07 b: dex bne b tax cpx #$8c bcc a
  3. LDA adress LDA #value RAM ➞ A register STA address

    A register ➞ RAM Most important instructions
  4. rts main: lda # sta background_color lda # sta border_color

    GRAY DARK_GRAY Border & Backgound Colors .label border_color = $d020 .label background_color = $d021 :BasicUpstart2(main)
  5. rts main: lda # sta background_color lda # sta border_color

    GRAY DARK_GRAY .macro background(color) { } Macros
  6. lda # sta background_color rts main: :background( ) color lda

    # sta border_color GRAY DARK_GRAY .macro background(color) { } Macros
  7. lda # sta background_color rts main: :background( ) color lda

    # sta border_color GRAY DARK_GRAY .macro background(color) { } Macros
  8. lda # sta background_color rts main: .macro border(color) { }

    :background( ) color lda # sta border_color GRAY DARK_GRAY .macro background(color) { } Macros
  9. :border( ) .macro background(color) { } lda # sta background_color

    rts main: .macro border(color) { } :background( ) color lda # sta border_color GRAY DARK_GRAY color Macros
  10. .macro nops( ) { } .for (var i = 0;

    i < ; i++) { nop } :background(BLACK) :background(DARK_GRAY) 230 count Delay
  11. :nops( ) .macro nops( ) { } .for (var i

    = 0; i < ; i++) { nop } :background(BLACK) :background(DARK_GRAY) 230 count count Delay
  12. // Disable IRQ handling sei // inject the handler lda

    #<raster_bars_irq sta irq_vector lda #>raster_bars_irq sta irq_vector + 1 // Enable IRQ handling cli Interrupts
  13. cli sei // Disable the interrupt generated by timers lda

    #%01111111 sta cia1_interrupt_control_register sta cia2_interrupt_control_register // Negate already scheduled interrupts lda cia1_interrupt_control_register lda cia2_interrupt_control_register Let’s Disable Timer
  14. Let’s Enable Raster cli sei // Disable the interrupt generated

    by timers lda #%01111111 sta cia1_interrupt_control_register sta cia2_interrupt_control_register // Negate already scheduled interrupts lda cia1_interrupt_control_register lda cia2_interrupt_control_register // Enable raster interrupts lda #%00000001 sta vic2_interrupt_control_register
  15. Choose Raster Line cli sei // Disable the interrupt generated

    by timers lda #%01111111 sta cia1_interrupt_control_register sta cia2_interrupt_control_register // Negate already scheduled interrupts lda cia1_interrupt_control_register lda cia2_interrupt_control_register // Enable raster interrupts lda #%00000001 sta vic2_interrupt_control_register :request_raster_irq(106, raster_bars_irq)
  16. .macro request_raster_irq(line_number, handler) { } lda #<handler sta irq_vector lda

    #>handler sta irq_vector + 1 lda #line_number sta vic2_rasterline_register Choose Raster Line
  17. .macro request_raster_irq(line_number, handler) { } lda #<handler sta irq_vector lda

    #>handler sta irq_vector + 1 .if (line_number > 255) { :set_bits(screen_control_register, %10000000) } else { :clear_bits(screen_control_register, %10000000) } lda #line_number sta vic2_rasterline_register Choose Raster Line
  18. .macro set_bits(address, bit_mask) { lda address ora #bit_mask sta address

    } .macro clear_bits(address, bit_mask) { lda address and #255 - bit_mask sta address } Choose Raster Line
  19. :nops(14) :background(BLACK) :nops(4) :background(DARK_GRAY) :nops(29) :background(GRAY) :nops(29) :background(LIGHT_GRAY) :nops(29) :background(WHITE)

    Raster Bars! :exit_irq_handler() raster_bars_irq: :nops(29) :background(LIGHT_GRAY) :nops(29) :background(GRAY) :nops(29) :background(DARK_GRAY) :nops(29) :background(BLACK) :nops(4) :background(DARK_GRAY) // ... // ...
  20. // Enable all 8 sprites lda #%11111111 sta sprites.enable_bits .for

    (var i = 0; i < 8; i++) { :set_sprite_position_x(i, 60 + 32 * i) } Hardware Sprites
  21. .macro set_sprite_position_x(index, position_x) { } .if (position_x > 255) {

    :set_bits(sprites.position_x_high_bits,1<<index) } else { :clear_bits(sprites.position_x_high_bits,1<<index) } lda #position_x sta sprites.positions + index*2 + 0 Hardware Sprites
  22. sprite_row_irq1: :exit_irq_handler() // Set the y-position, bitmaps and colors :sprites_row(70,

    0, 3) raster_bars_irq: :exit_irq_handler() // ... :request_raster_irq(60, sprite_row_irq1) :request_raster_irq(106, raster_bars_irq) :nops(14) More Interrupts
  23. sprite_row_irq1: :exit_irq_handler() // Set the y-position, bitmaps and colors :sprites_row(70,

    0, 3) Raster time raster_bars_irq: :exit_irq_handler() // ... :request_raster_irq(60, sprite_row_irq1) :request_raster_irq(106, raster_bars_irq) :nops(14)
  24. sprite_row_irq1: :exit_irq_handler() // Set the y-position, bitmaps and colors :sprites_row(70,

    0, 3) Raster time raster_bars_irq: :exit_irq_handler() // ... :request_raster_irq(60, sprite_row_irq1) :request_raster_irq(106, raster_bars_irq) :border(RED) :border(GRAY) :nops(14)
  25. sprite_row_irq1: :exit_irq_handler() // Set the y-position, bitmaps and colors :sprites_row(70,

    0, 3) Raster time raster_bars_irq: :exit_irq_handler() // ... :request_raster_irq(60, sprite_row_irq1) :request_raster_irq(106, raster_bars_irq) :nops(14) :border(RED) :border(GRAY) :border(GRAY) :border(ORANGE)
  26. sprite_row_irq1: :exit_irq_handler() // Set the y-position, bitmaps and colors :sprites_row(70,

    0, 3) Raster time raster_bars_irq: :exit_irq_handler() // ... :request_raster_irq(60, sprite_row_irq1) :request_raster_irq(106, raster_bars_irq) :nops(7) :border(RED) :border(GRAY) :border(GRAY) :border(ORANGE)
  27. raster_bars_irq: :request_raster_irq( ) :exit_irq_handler() sprite_row_irq2: :border(CYAN) :sprites_row(160, 8, 12) :border(GRAY)

    :request_raster_irq( ) :exit_irq_handler() 60, sprite_row_irq1 sprite_row_irq1: // ... // ... More Sprites
  28. raster_bars_irq: :request_raster_irq( ) :exit_irq_handler() sprite_row_irq2: :border(CYAN) :sprites_row(160, 8, 12) :border(GRAY)

    :request_raster_irq( ) :exit_irq_handler() 60, sprite_row_irq1 sprite_row_irq1: // ... // ... 150, sprite_row_irq2 More Sprites
  29. sprite_row_irq2: :request_raster_irq(248, open_border_irq) :exit_irq_handler() open_border_irq: :request_raster_irq(60, sprite_row_irq1) :exit_irq_handler() // Enable

    24 lines mode :clear_bits(screen_control_register, %00001000) // Enable 25 lines mode :set_bits(screen_control_register, %00001000) Opening the Border
  30. main: // initialize music jsr music // Import music from

    a file .pc=$1000 music: .import binary "music.bin" Music
  31. main: // initialize music jsr music // Import music from

    a file .pc=$1000 music: .import binary "music.bin" play_music: :border(YELLOW) jsr $music + 3 :border(GRAY) :request_raster_irq(248, open_border_irq) :exit_irq_handler() Music