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!

85977ebfe59c2ee669f2196930f1a701?s=128

Michał Taszycki

October 07, 2016
Tweet

Transcript

  1. 5.
  2. 7.
  3. 11.
  4. 12.
  5. 13.

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

    70 80 2010 2011 2012 2013 2014 2015 games demos source - http://csdb.dk
  6. 14.

    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
  7. 25.

    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; }
  8. 26.

    “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
  9. 30.
  10. 31.

    LDA address LDA #value Pamięć RAM ➞ Rejestr A STA

    address Rejestr A ➞ Pamięć RAM Most important instructions
  11. 32.

    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)
  12. 34.

    rts main: lda # sta background_color lda # sta border_color

    GRAY DARK_GRAY .macro background(color) { } Macros
  13. 35.

    lda # sta background_color rts main: :background( ) color lda

    # sta border_color GRAY DARK_GRAY .macro background(color) { } Macros
  14. 36.

    lda # sta background_color rts main: :background( ) color lda

    # sta border_color GRAY DARK_GRAY .macro background(color) { } Macros
  15. 37.

    lda # sta background_color rts main: .macro border(color) { }

    :background( ) color lda # sta border_color GRAY DARK_GRAY .macro background(color) { } Macros
  16. 38.

    :border( ) .macro background(color) { } lda # sta background_color

    rts main: .macro border(color) { } :background( ) color lda # sta border_color GRAY DARK_GRAY color Macros
  17. 39.
  18. 46.

    .macro nops( ) { } .for (var i = 0;

    i < ; i++) { nop } :background(BLACK) :background(DARK_GRAY) 230 count Delay
  19. 47.

    :nops( ) .macro nops( ) { } .for (var i

    = 0; i < ; i++) { nop } :background(BLACK) :background(DARK_GRAY) 230 count count Delay
  20. 49.

    // 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
  21. 50.
  22. 53.

    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
  23. 54.

    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
  24. 55.

    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)
  25. 58.

    .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
  26. 59.

    .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
  27. 60.

    .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
  28. 63.

    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?
  29. 64.
  30. 66.
  31. 68.
  32. 69.
  33. 70.
  34. 71.
  35. 72.
  36. 73.
  37. 74.
  38. 75.
  39. 76.
  40. 77.
  41. 78.
  42. 79.
  43. 80.
  44. 81.
  45. 82.
  46. 83.
  47. 84.
  48. 85.
  49. 86.
  50. 87.
  51. 88.
  52. 89.
  53. 90.
  54. 91.
  55. 92.
  56. 93.
  57. 94.
  58. 95.
  59. 96.
  60. 97.
  61. 98.
  62. 99.
  63. 100.
  64. 101.
  65. 102.
  66. 103.
  67. 104.
  68. 105.
  69. 106.
  70. 107.
  71. 108.
  72. 109.
  73. 110.
  74. 111.
  75. 112.
  76. 113.
  77. 114.
  78. 115.