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!

85977ebfe59c2ee669f2196930f1a701?s=128

Michał Taszycki

October 07, 2016
Tweet

Transcript

  1. Lost Art of Code Optimisation or why you should grok

    the
  2. I don’t let old computers die mehowte  Michał Taszycki

    at
  3. I’m making weekly video course on programming Commodore64 64bites.com

  4. Commodore 64 is dead

  5. Today

  6. Back Then

  7. Today

  8. Back Then

  9. Back Then

  10. Back Then?

  11. Today!

  12. Today!

  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
  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
  15. How many years?!

  16. How many years?!

  17. How many years?!

  18. How many years?!

  19. Commodore 64 8 bit registers 64 KB RAM 1 Mhz

    CPU
  20. Commodore 64 legendary sound chip 320x200 resolution 8 hardware sprites

  21. Commodore 64 it can’t even multiply

  22. Modern DEMO! Edge of Disgrace by Booze Design

  23. Coma Light 13 by Oxyron Modern DEMO!

  24. Comaland by Censor Design & Oxyron Modern DEMO!

  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; }
  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
  27. Enough Talking!

  28. Let’s code!

  29. Minimal program :BasicUpstart2(main) main: rts

  30. None
  31. LDA address LDA #value Pamięć RAM ➞ Rejestr A STA

    address Rejestr A ➞ Pamięć RAM Most important instructions
  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)
  33. Macros rts main: lda # sta background_color lda # sta

    border_color GRAY DARK_GRAY
  34. rts main: lda # sta background_color lda # sta border_color

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

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

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

    :background( ) color lda # sta border_color GRAY DARK_GRAY .macro background(color) { } Macros
  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
  39. None
  40. Raster Bar // long delay :background(BLACK) :background(DARK_GRAY)

  41. Delay :background(BLACK) :background(DARK_GRAY) nop

  42. :background(BLACK) :background(DARK_GRAY) nop nop Delay

  43. :background(BLACK) :background(DARK_GRAY) nop nop nop Delay

  44. :background(BLACK) :background(DARK_GRAY) nop // ... many more nops nop nop

    Delay
  45. :background(BLACK) :background(DARK_GRAY) .for (var i = 0; i < ;

    i++) { nop } 230 Delay
  46. .macro nops( ) { } .for (var i = 0;

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

    = 0; i < ; i++) { nop } :background(BLACK) :background(DARK_GRAY) 230 count count Delay
  48. Interrupts raster_bars_irq: jmp irq_handler :nops( ) :background(BLACK) :background(DARK_GRAY) 230

  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
  50. None
  51. // inject the handler lda #<raster_bars_irq sta irq_vector lda #>raster_bars_irq

    sta irq_vector + 1 Turn off timer cli sei
  52. cli sei Turn off timer

  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
  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
  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)
  56. .macro request_raster_irq(line_number, handler) { } Choose raster line

  57. .macro request_raster_irq(line_number, handler) { } lda #<handler sta irq_vector lda

    #>handler sta irq_vector + 1 Choose raster line
  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
  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
  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
  61. Interrupt handled? jmp irq_handler raster_bars_irq: :background(BLACK) :nops(230) :background(DARK_GRAY)

  62. raster_bars_irq: :background(BLACK) :nops(230) :background(DARK_GRAY) lda #%00000001 sta vic2_interrupt_status_register jmp irq_handler

    Interrupt handled?
  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?
  64. None
  65. Stabilization :exit_irq_handler() raster_bars_irq: :nops(14) :background(BLACK) :nops(230) :background(DARK_GRAY)

  66. None
  67. Raster Bars! :exit_irq_handler() raster_bars_irq:

  68. None
  69. None
  70. None
  71. None
  72. None
  73. None
  74. None
  75. None
  76. None
  77. None
  78. None
  79. None
  80. None
  81. None
  82. None
  83. None
  84. None
  85. None
  86. None
  87. None
  88. None
  89. None
  90. None
  91. None
  92. None
  93. None
  94. None
  95. None
  96. None
  97. None
  98. None
  99. None
  100. None
  101. None
  102. None
  103. None
  104. None
  105. None
  106. None
  107. None
  108. None
  109. None
  110. None
  111. None
  112. None
  113. None
  114. None
  115. None