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

Lost Art of Code Optimization (or why you should grok Commodore 64)

Lost Art of Code Optimization (or why you should grok Commodore 64)

I know you!

You craft beautiful object-oriented and functional code every day. I don't need to tell you how to test and maintain it well.
But I want to show you something different...

Remember Commodore 64? The highest selling computer model of all time?

Even though it's not produced anymore for more than two decades, each year at least seventy new games are released!
Every new C64 program is faster and prettier, even though it's processor can't even multiply.
Meanwhile, your smartphone gets slower with every update...

This talk will show you how Commodore 64 programmers 'break' hardware constraints to create jaw-dropping demos.
It will show you an easy and fun way to practice writing low-level code.

Something you'll never do at your day job!

Michał Taszycki

October 07, 2016
Tweet

More Decks by Michał Taszycki

Other Decks in Programming

Transcript

  1. How many games?! 0 10 20 30 40 50 60

    70 80 2010 2011 2012 2013 2014 2015 games demos source - http://csdb.dk
  2. How many releases?! source - http://csdb.dk 0 210 420 630

    840 1050 1260 1470 1680 1890 2100 2010 2011 2012 2013 2014 2015 all releases
  3. 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; }
  4. “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
  5. LDA address LDA #value Pamięć RAM ➞ Rejestr A STA

    address Rejestr A ➞ Pamięć RAM Most important instructions
  6. rts main: lda # sta background_color lda # sta border_color

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

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

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

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

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

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

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

    = 0; i < ; i++) { nop } :background(BLACK) :background(DARK_GRAY) 230 count count Delay
  14. // 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
  15. 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 Turn off timer
  16. Turn on 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
  17. 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)
  18. .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
  19. .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
  20. .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
  21. raster_bars_irq: :background(BLACK) :nops(230) :background(DARK_GRAY) :exit_irq_handler() .macro exit_irq_handler() { } lda

    #%00000001 sta vic2_interrupt_status_register jmp irq_handler Interrupt handled?