Last active
          November 20, 2020 05:50 
        
      - 
      
- 
        Save JettMonstersGoBoom/62a6ef6d6f60bb4d92f8a55dfd91697d to your computer and use it in GitHub Desktop. 
    C64 CIA example with Kickasm
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | .file [name="test.prg", segments="CODE,DATA"] | |
| .segment CODE [start=$0801] | |
| .segment DATA [startAfter="CODE"] | |
| // PAL | |
| .label CPU_FREQ = $4cc8 | |
| VIC: { | |
| .label RASTER = $d012 | |
| .label BORDER = $d020 | |
| .label BACKGROUND = $d021 | |
| } | |
| CIA: { | |
| // irq ctrl status bits | |
| .label TIMER_A_UNDERFLOW = %00000001 // triggered or enable timer a Rw | |
| .label TIMER_B_UNDERFLOW = %00000010 // triggered or enable timer b Rw | |
| .label TOD_ALARM = %00000100 // time of day alarm | |
| .label BYTE_RECIEVE = %00001000 // tape stuff | |
| .label DATASET = %00010000 // | |
| .label IRQ_GENERATED = %10000000 // irq triggered or enable Rw | |
| // control bits | |
| .label TIMER_START = %00000001 | |
| .label TIMER_RESTARTS = %00000000 // will restart on underflow | |
| .label TIMER_STOPS = %00001000 // will stop | |
| .label TIMER_RELOAD = %00010000 // reload on underflow from set values | |
| .label TIMER_COUNTS_CYCLES = %00000000 // count cpu cycles | |
| .label TIMER_COUNTS_EDGES = %00100000 // count edges | |
| .label TIMER_COUNTS_A_UNDERFLOW = %01000000 // count timer a underflow | |
| .label TIMER_COUNTS_A_UNDERFLOW_EDGES = %01100000 // both | |
| .label TOD_50hz = %10000000 // time of day clock is 50hz | |
| .label TOD_60hz = %00000000 // time of day clock is 60hz | |
| } | |
| // CIA1 causes IRQ interupt | |
| CIA1: { | |
| .label PORT_A = $dc00 | |
| .label PORT_B = $dc01 | |
| .label DDR_A = $dc02 | |
| .label DDR_B = $dc03 | |
| .label Timer_A = $dc04 | |
| .label Timer_A_l = $dc04 | |
| .label Timer_A_h = $dc05 | |
| .label Timer_B = $dc06 | |
| .label Timer_B_l = $dc06 | |
| .label Timer_B_h = $dc07 | |
| .label IRQCtrlStatus = $dc0d | |
| .label Timer_A_Control = $dc0e | |
| .label Timer_B_Control = $dc0f | |
| } | |
| // CIA2 causes NMI | |
| CIA2: { | |
| .label PORT_A = $dd00 | |
| .label PORT_B = $dd01 | |
| .label DDR_A = $dd02 | |
| .label DDR_B = $dd03 | |
| .label Timer_A = $dd04 | |
| .label Timer_A_l = $dd04 | |
| .label Timer_A_h = $dd05 | |
| .label Timer_B = $dd06 | |
| .label Timer_B_l = $dd06 | |
| .label Timer_B_h = $dd07 | |
| .label IRQCtrlStatus = $dd0d | |
| .label Timer_A_Control = $dd0e | |
| .label Timer_B_Control = $dd0f | |
| } | |
| // NOTE: doesn't get written to the prg | |
| .segment ZP [start=$02] | |
| result: .word 0 | |
| .segment CODE | |
| //------------------------------------------------------------- | |
| // This creates a basic sys line that can start your program | |
| //------------------------------------------------------------- | |
| BasicUpstart2(Start) | |
| // Our code | |
| Start: | |
| { | |
| // stop IRQ | |
| sei | |
| // set to black | |
| lda #$00 | |
| sta VIC.BORDER | |
| sta VIC.BACKGROUND | |
| // clear screen | |
| ldx #$00 | |
| !: | |
| lda #$20 | |
| sta $0400,x | |
| sta $0500,x | |
| lda #$1 | |
| sta $d800,x | |
| sta $d900,x | |
| dex | |
| bne !- | |
| // set A & B for display above | |
| lda #$01 | |
| sta $0401 | |
| lda #$02 | |
| sta $0403 | |
| // copy names to screen | |
| ldx #$00 | |
| !: | |
| lda irqs,x | |
| sta $0428+8,x | |
| lda nmis,x | |
| sta $0428+48,x | |
| inx | |
| cpx #3 | |
| bne !- | |
| // | |
| // Disable all interrupts.. | |
| // | |
| lda #$7f | |
| sta CIA1.IRQCtrlStatus | |
| sta CIA2.IRQCtrlStatus | |
| // poll | |
| lda CIA1.IRQCtrlStatus | |
| lda CIA2.IRQCtrlStatus | |
| // set IRQ to our routine | |
| lda #<Irq | |
| sta $0314 | |
| lda #>Irq | |
| sta $0315 | |
| // set NMI to our routine | |
| lda #<Nmi | |
| sta $0318 | |
| lda #>Nmi | |
| sta $0319 | |
| // set timer A to CPU_Frequency (irq) | |
| lda #<CPU_FREQ | |
| sta CIA1.Timer_A_l | |
| lda #>CPU_FREQ | |
| sta CIA1.Timer_A_h | |
| // second timer | |
| // 15 frames | |
| lda #15 | |
| sta CIA1.Timer_B_l | |
| lda #$00 | |
| sta CIA1.Timer_B_h | |
| // set timer A to CPU_Frequency (nmi) | |
| lda #<CPU_FREQ | |
| sta CIA2.Timer_A_l | |
| lda #>CPU_FREQ | |
| sta CIA2.Timer_A_h | |
| // second timer | |
| // 50 frames | |
| lda #50 | |
| sta CIA2.Timer_B_l | |
| lda #$00 | |
| sta CIA2.Timer_B_h | |
| // cia 1 irq | |
| // trigger when timer A hits | |
| lda #CIA.IRQ_GENERATED | CIA.TIMER_A_UNDERFLOW | |
| sta CIA1.IRQCtrlStatus | |
| // cia 2 nmi | |
| // trigger when timer A hits | |
| lda #CIA.IRQ_GENERATED | CIA.TIMER_A_UNDERFLOW | |
| sta CIA2.IRQCtrlStatus | |
| // wait until we're in the middle before starting timer 1 | |
| vwait: | |
| lda VIC.RASTER | |
| cmp #$80 | |
| bne vwait | |
| // we want the CIA to auto reload and auto restart the timer and tell it to start here | |
| lda #CIA.TIMER_RELOAD | CIA.TIMER_RESTARTS | CIA.TIMER_START | CIA.TIMER_COUNTS_CYCLES | |
| sta CIA1.Timer_A_Control | |
| // we want the CIA to auto reload and auto restart the timer and count timer A underflow ( 0 ) | |
| lda #CIA.TIMER_RELOAD | CIA.TIMER_RESTARTS | CIA.TIMER_START | CIA.TIMER_COUNTS_A_UNDERFLOW | |
| sta CIA1.Timer_B_Control | |
| // polling this register starts | |
| lda CIA1.IRQCtrlStatus | |
| lda CIA1.IRQCtrlStatus | |
| // wait until we're a bit below before starting timer 2 | |
| vwait2: | |
| lda VIC.RASTER | |
| cmp #$c0 | |
| bne vwait2 | |
| // we want the CIA to auto reload and auto restart the timer and tell it to start here | |
| lda #CIA.TIMER_RELOAD | CIA.TIMER_RESTARTS | CIA.TIMER_START | CIA.TIMER_COUNTS_CYCLES | |
| sta CIA2.Timer_A_Control | |
| // we want the CIA to auto reload and auto restart the timer and count timer A underflow ( 0 ) | |
| lda #CIA.TIMER_RELOAD | CIA.TIMER_RESTARTS | CIA.TIMER_START | CIA.TIMER_COUNTS_A_UNDERFLOW | |
| sta CIA2.Timer_B_Control | |
| // polling this register starts | |
| lda CIA2.IRQCtrlStatus | |
| lda CIA2.IRQCtrlStatus | |
| cli | |
| jmp * | |
| rts | |
| } | |
| Nmi: | |
| { | |
| pha | |
| // grab status bits | |
| // we use this to offset our increment of $428 , x | |
| // should be 1 ( timer A ) | |
| // or 3 ( timer A & B ) | |
| lda CIA2.IRQCtrlStatus | |
| and #$7f | |
| tax | |
| lda $042b+40 | |
| sta VIC.BORDER | |
| sta VIC.BACKGROUND | |
| // we can figure out what timer here | |
| inc $0428+40,x | |
| pla | |
| bit $2 | |
| bit $2 | |
| bit $2 | |
| bit $2 | |
| lda #$00 | |
| sta VIC.BORDER | |
| sta VIC.BACKGROUND | |
| rti | |
| } | |
| Irq: | |
| { | |
| pha | |
| // grab status bits | |
| // we use this to offset our increment of $400 , x | |
| // should be 1 ( timer A ) | |
| // or 3 ( timer A & B ) | |
| lda CIA1.IRQCtrlStatus | |
| and #$7f | |
| tax | |
| lda $0403+40 | |
| sta VIC.BORDER | |
| sta VIC.BACKGROUND | |
| // we can figure out what timer here | |
| inc $0400+40,x | |
| // inc $d020 | |
| pla | |
| bit $2 | |
| bit $2 | |
| bit $2 | |
| bit $2 | |
| lda #$00 | |
| sta VIC.BORDER | |
| sta VIC.BACKGROUND | |
| jmp $ea81 | |
| } | |
| irqs: .text "irq" | |
| nmis: .text "nmi" | |
| .segment DATA | |
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment