Offline
uhajdafdfdfa

hi, if anyone is interested in writing a c64 music engine

i will get you started

enjoy!

/*
ant1's guide to programming the SID  
this is kick assembler source-code
made in 2012
*/

.pc=$801
:BasicUpstart($810)
.pc=$810

  // clear all sid registers to 0
  ldx #$00
  lda #$00
clearsidloop:
  // SID registers start at $d400
  sta $d400
  inc clearsidloop+1 
  inx
  cpx #$29 // and there are 29 of them
  bne clearsidloop

  // set master volume and turn filter off
  lda #%00001111 
  sta filtermode_volume

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

mainloop:

  // check if rasterline is #$ff 
  // which happens every 20ms
  // do nothing and jump back to mainloop if not
  lda $d012 
  cmp #$ff
  bne mainloop

  // play a single frame of music (if there are any notes to play this frame)
  jsr music

  // loop forever
  jmp mainloop

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

music:

  // tickcounter counts the number of 20ms frames
  inc tickcounter

  // speed is the number of 20ms frames that will happen before the slowtable advances one position
  lda tickcounter
  cmp speed
  beq playnote
  jmp endmusic
  
playnote:

  // flash border and background
  inc $d020
  dec $d021
  
  // reset gatebit/waveform
  lda #%00000000
  sta $d404

  // reset tickcounter as we have got to the next row of the slowtable and we want to start counting towards the next note
  lda #$00
  sta tickcounter
  
  // add slowtablepos to slowtable to get the current position in the slowtable
  ldx slowtablepos
  lda slowtable, x
  
  // get low byte of frequency from slowtable
  sta frequency
  
  // get high byte of frequency from slowtable
  inx
  lda slowtable, x
  sta frequency+1
  
freqcheck1:

  // check if low byte of frequency is #$00, if not, continue to play note
  lda frequency
  cmp #$00
  bne playnote2
  
  // check if high byte of frequency is #$00 (frequency is #$0000), if not, continue to next check
  lda frequency+1
  cmp #$00
  bne freqcheck2
  
  // if it is, reset slowtablepos and start again
  lda #$00
  sta slowtablepos
  jmp playnote  
  
freqcheck2:

  // check if high byte of frequency is #$01 (frequency is #$0001), if not continue to play note
  lda frequency+1
  cmp #$01
  bne playnote2
  
  // if it is, increment slowtablepos to continue moving through the table, but jump back to the start without playing a note
  inc slowtablepos
  inc slowtablepos
  jmp music
    
playnote2:

  // set attack to 0, decay to 6
  lda #$06
  sta attack_decay
  
  // set sustain and release to 0
  lda #$00
  sta sustain_release
  
  // move frequency from frequency variable to sid buffer
  lda frequency
  sta freq_lowbyte
  lda frequency+1
  sta freq_highbyte
  
  // set waveform to saw and turn gatebit on
  lda #%00100001
  sta control

  // increment the slowtablepos twice (twice because there are two bytes for each note in the table)
  inc slowtablepos
  inc slowtablepos

  // write data from the sid buffer to the sid chip
  lda freq_lowbyte
  sta $d400
  lda freq_highbyte
  sta $d401
  lda control
  sta $d404
  lda attack_decay
  sta $d405
  lda sustain_release
  sta $d406
  lda filtermode_volume
  sta $d418

endmusic:

  // back to mainloop
  rts


// variables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// the number of frames to wait before advancing the slowtable, you can set this to anything
speed:
  .byte $1f

// stores the tick (frame) counter
tickcounter:
  .byte $00

// stores the position in the slowtable  
slowtablepos:
  .byte $00

// temporarily stores the frequency of the next note  
frequency:
  .byte $00
  .byte $00

// music data ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// the slowtable is where the note data is stored
slowtable:

  // frequency is a sixteen bit number, a higher number is a higher pitch
  .byte $b1, $25
  .byte $30, $40
  .byte $b1, $25
  
  // a frequency of #$0001 tells the player to play no note on this row
  .byte $00, $01
  
  .byte $b1, $25
  .byte $30, $40
  .byte $b1, $15
  .byte $00, $01
  
  .byte $b1, $25
  .byte $30, $40
  .byte $b1, $25
  .byte $00, $01
  
  .byte $b1, $25
  .byte $30, $40
  .byte $b1, $65
  .byte $00, $01
  
  // a frequency of #$0000 tells the player to loop back to the start of the slowtable
  .byte $00, $00
  
// sid buffer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// values that are going to be written to the sid are stored here and then written in one go

// freq_lowbyte is the low byte of the frequency
// on the SID this is $d400 
freq_lowbyte:
  .byte $00
  
// freq_highbyte is the high byte of the frequency
// on the SID this is $d401
freq_highbyte:  
  .byte $00

// control sets the waveform and gatebit
// on the SID this is $d404
control:
  .byte $00
  
// the first nybble of attack_decay is attack, the second nybble is decay
// on the SID this is $d405
attack_decay:
  .byte $00
  
// the first nybble of sustain_release is sustain, the second nybble is release
// on the SID this is $d406
sustain_release:
  .byte $00
  
// bits 7-4 of filtermode_volume control the filter, bits 3-1 control the master volume
// on the SID this is $d418
filtermode_volume:
  .byte $00

edit:
if you've never done any c64 programming before then you will need, to follow this guide,

something that tells you what all the opcodes do
something that tells you what all the sid registers do
kick assembler

Last edited by ant1 (Aug 19, 2012 5:59 am)

Offline
Savannah, Georgia

jesus, how long have you been working with commodore shit

Offline
uhajdafdfdfa

couple of months smile~ that's why i'm writing all these tutorials (teaching is the best way of learning etc)

Offline
Riverside, CA

Make a guide on how to make the C64 make toast.

Offline
Medina, Ohio
The Silph Scope wrote:

Make a guide on how to make the C64 make toast.

I'm pretty sure you could rip power of the PSU and plug in a toaster. Not sure though....

Offline
Brunswick, GA USA

The instruction manual had schematic diagrams in it, you can use that info to automate the toaster. I also still have a book with the room dumps disassembled and explained.

Offline
uhajdafdfdfa

maybe you will be better off using a PET though: http://www.youtube.com/watch?feature=pl … sWWo#t=37s

Offline

ant1, is there anything you don't know how to do?

Offline
uhajdafdfdfa

well i haven't been able to figure out nanoloop at all

Offline
Riverside, CA
ant1 wrote:

well i haven't been able to figure out nanoloop at all

No one has, some people just pretend.

Offline
Sydney, NSW
ant1 wrote:

well i haven't been able to figure out nanoloop at all

it's not meant to be figured out.
henry homesweet just uses cheat c0dez

Offline
Austin, Texas

Nanoloop has such a different interface from a tracker that it's either really intuitive or really counterintuitive or somehow both at the same time.

I find it really easy to make something that sounds cool and have no idea how I did it or how to make anything else go with it.

And I covered a squarepusher song in Nanoloop iOS once. big_smile

Chainsaw Police wrote:
ant1 wrote:

well i haven't been able to figure out nanoloop at all

it's not meant to be figured out.
henry homesweet just uses cheat c0dez

Dude we should write a GameFAQ walkthrough for nanoloop 2.x

Last edited by Telerophon (Aug 20, 2012 7:44 am)