// ADSR oscilloscope & bug illustrator by Agemixer/Skalaria // Some definitions: .function pet2asc(p) { .eval p = [ p>$40? p+=$80 : p ] .return [ p<$20? p^$40 : p ] } .macro asctxt(str) { .fill str.size(), pet2asc(str.charAt(i)) } .macro asctxtCR(str) { :asctxt(str) .byte $0d } .const KERNAL_getin = $ffe4 .const KERNAL_chrout = $ffd2 .const editvalues_array_lenght = editvalues_array_end-editvalues_array // Screen setup: .const ADSR1_var_screenpos=$0400+[varpos1y_end-varpos1y_start]*40+[varpos1x_end-varpos1x_start] .const Wave1_var_screenpos=ADSR1_var_screenpos+1*40+2 .const ADSR2_var_screenpos=ADSR1_var_screenpos+2*40 .const Wave2_var_screenpos=ADSR1_var_screenpos+3*40+2 .const Delay_var_screenpos=ADSR1_var_screenpos+5*40+12 .const bitmap = $2000 .const bitmap_ending_ptr = bitmap+[varpos1y_end-varpos1y_start]*40*8-1 .const bitmap_colorscreen_endptr = $0400+[varpos1y_end-varpos1y_start]*40-1 .const Oscscope_bgcolor1=$f .const Oscscope_fgcolor1=$b .const Oscscope_bgcolor2=$b .const Oscscope_fgcolor2=$f .const border_colour=$0 .const textscreen_colour=$0 // Debugging data areas: .const SIDenv3_debug_data_GATE1=$4000 // ADS phase .const SIDenv3_debug_data_GATE0=$4080 // R phase // Oscilloscope drawing: .const zw_draw_ptr=$fc .const zplot_pixel=$fe .const zdiv8_line_offset = $ff .const zwtmp1=$fc // ----------------------- The code --------------------------------- :BasicUpstart2(begin) begin: jsr $ff81 // reset screen ldx #$18 // clear SID lda #$00 !: sta $d400,x dex bpl !- lda #$0f // set up some sound sta $d418 lda #$08 sta $d403+14 jsr clear_bitmap jsr print_text lda #border_colour sta $d020 lda #textscreen_colour sta $d021 ldy #>$0400 ldx #0 !loophi: sty bmp_colorscreen_ptr+1 lda #border_colour // bitmap edges fg/bg color !: sta $0400,x .label bmp_colorscreen_ptr = *-2 cpx #<[bitmap_colorscreen_endptr] beq !+ !next: inx bne !- iny bne !loophi- //jmp !: cpy #>[bitmap_colorscreen_endptr] bne !next- lda #<$0400+4 sta zwtmp1 sta bmp_colorscreen_ptr2 lda #>$0400+4 sta zwtmp1+1 sta bmp_colorscreen_ptr2+1 !loophi: lda #16 sta colorlenght ldy #0 ldx #16 !loop: lda #Oscscope_fgcolor1*16+Oscscope_bgcolor1 // bitmap fg/bg color1 (for "gate on") sta (zwtmp1),y lda #Oscscope_fgcolor2*16+Oscscope_bgcolor2 // bitmap fg/bg color2 (for "gate off") sta $0404+16,x .label bmp_colorscreen_ptr2 = *-2 iny inx cpy #16 .label colorlenght=*-1 bcc !loop- tya clc adc #40-16 tay adc #16 tax sta colorlenght cmp #4*40 bcc !loop- lda zwtmp1 clc adc #4*40 sta zwtmp1 sta bmp_colorscreen_ptr2 bcc !+ inc zwtmp1+1 inc bmp_colorscreen_ptr2+1 !: lda bmp_colorscreen_ptr2+1 cmp #>[bitmap_colorscreen_endptr] bcc !loophi- show_editvalues_loop: // main loop print_editvalues: // print ADSR1 (->gate on): ldx #0 // starting index lda #<[ADSR1_var_screenpos] // screen pointer ldy #>[ADSR1_var_screenpos] jsr setup_printvalue lda #4 // ending index jsr print_value // print Waveform1 (->gate on): lda #<[Wave1_var_screenpos-4] ldy #>[Wave1_var_screenpos-4] jsr setup_printvalue lda #6 // ending index jsr print_value //print ADSR2: (->gate off): lda #<[ADSR2_var_screenpos-6] ldy #>[ADSR2_var_screenpos-6] jsr setup_printvalue lda #10 jsr print_value // print Waveform2 (->gate off): lda #<[Wave2_var_screenpos-10] ldy #>[Wave2_var_screenpos-10] jsr setup_printvalue lda #12 // ending index jsr print_value // print Oscilloscope Delay lda #<[Delay_var_screenpos-12] ldy #>[Delay_var_screenpos-12] jsr setup_printvalue lda #14 // ending index jsr print_value chk_keys_loop: sei jsr wait_1_frame ldx #$18 // VIC bank ldy #$3b // Gfx mode jsr set_screen_params lda #$31+8*[varpos1y_end-varpos1y_start] // wait for screen split rasterline cmp $d012 bcs *-3 ldx #8 // raster fine adjusted delay dex bne *-1 ldx #$16 // VIC bank ldy #$1b // Gfx mode jsr set_screen_params cli jsr KERNAL_getin beq chk_keys_loop // check for hexadecimal chars a...f: cmp #$41 // 'a' bcc chk_keys1 cmp #$46+1 // 'f' bcs chk_keys1 sbc #$41-1-10 // convert ASCII to numerical value: 'a'..'f' -> 10..15 bcs hex_value_key_pressed // jmp chk_keys1: // check for decimal codes 0...9: cmp #'0' bcc chk_keys2 cmp #'9'+1 bcs chk_keys2 and #$0f // convert ASCIi to numerical value: '0'..'9' -> 0...9 hex_value_key_pressed: // write value to editvalues_array ldx editvalues_array_index sta editvalues_array,x lda #29 // CRSR right (= jsr key_CRSRright, jmp show_editvalues_loop) chk_keys2: ldx #[getkey_LUT_ends-getkey_LUT]-2 keyloop: cmp getkey_LUT,x beq key_reached dex dex bpl keyloop bmi chk_keys_loop // jmp chk_keys3: no key pressed key_reached: lda getkey_PTRs,x sta on_key_goto onKEYgoto: ldx editvalues_array_index jsr key_CRSRdown .label on_key_goto = *-2 stx editvalues_array_index jmp show_editvalues_loop key_CRSRdown: //----------- txa clc // limit cursoring to bottom values in array adc #$02 cmp #editvalues_array_lenght bcs !+ tax !: rts key_CRSRup: //--------- txa sec // limit cursoring to top values in array sbc #$02 bcc !+ tax !: rts key_CRSRleft: //----------- beq !+ dex !: rts key_CRSRright: //------------ cpx #editvalues_array_lenght-1 // limit cursoring to last value bcs !+ inx !: rts key_HOME: //------- ldx #0 // set new editvalues_array_index rts key_RET: // apply values //------ jsr convert_editvalues_to_SIDvars jmp SIDenv3_debugger // ------------------------- arrays -------------------------------- editvalues_array_index: .byte 0 // pointer to editvalues_array editvalues_array: .byte $5,$5,$7,$9 // ADSR1 .byte $4,$1 // Wave1 .byte $5,$5,$7,$9 // ADSR2 .byte $4,$0 // wave2 .byte $2,$0 // Delay editvalues_array_end: SID_vars: .byte $11,$11 // AD1,SR1 (gate on) .byte $11 // Wave1 (gate on) .byte $11,$11 // AD2,SR2 (gate off) .byte $11 // Wave2 (gate off) .byte $11 // Delay getkey_LUT: .label getkey_PTRs = *+1 .byte 17, 'a'... !: adc #48 // add cursor: cpx editvalues_array_index bne !+ ora #$80 // use reversed char as a cursor !: // write value to screen: sta ADSR1_var_screenpos,x .label var_printptr = *-2 inx cpx #0 .label printindex_endvalue = *-1 bne !printloop- rts setup_printvalue: sta var_printptr sty var_printptr+1 rts clear_bitmap: //----------- ldy #>bitmap ldx #0 lda #%00000000 !clrbmpy: sty bmp_clr_ptr+1 !clrbmp: sta bitmap,x .label bmp_clr_ptr = *-2 inx bne !clrbmp- iny cpy #>[bitmap_ending_ptr+$0100] bcc !clrbmpy- rts TEXT_inputADSR1: .byte 155 // color = grey .byte 147 // clr //.byte 19 // home .byte 9,14,8 // case change: enable C= + shift, set LowCase, disable varpos1y_start: .byte 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17 // 16 CRSR down varpos1y_end: varpos1x_start: :asctxt("Starting ADSR: $") varpos1x_end: .byte 5 // color=white :asctxtCR("....") .byte 155 // color = grey :asctxt("Starting Wave: $") .byte 5 // color=white :asctxtCR("..") .byte 155 // color = grey :asctxt("Ending ADSR : $") .byte 5 // color=white :asctxtCR("....") .byte 155 // color = grey :asctxt("Ending Wave : $") .byte 5 // color=white :asctxtCR("..") .byte 155 // color = grey :asctxtCR("") :asctxt("Oscilloscope & gate delay: $") .byte 153 // color=lt.grey :asctxtCR("..") .byte 151 // color = gark grey :asctxtCR("") :asctxtCR("") :asctxt("Set values + hit RETURN to trigger note") .byte 0 SIDenv3_debugger: //--------------- lda #$0b // disable bad lines + wait 1 frame complete sta $d011 lda #$08 // reset SID osc's sta $d404 sta $d404+7 sta $d404+14 //ldx #$02 //jsr wait_x_frames jsr clear_bitmap // clear bitmap+delay >2 frames //set up SID waveform and frequency to play a tone sei lda #$20 sta $d401+$0e lda SID_vars+6 sta debug_delay1 sta debug_delay2 lda SID_vars // AD1 sta $d405+$0e lda SID_vars+1 // SR1 sta $d406+$0e lda SID_vars+2 // Wave1 sta $d404+$0e ldx #0 !loopADS: lda $d41c // Read SID ch3 envelope sta SIDenv3_debug_data_GATE1,x // write to debug sample buffer $00..7f (gate on) txa and #$0c // Give some demoeffect sta $d020 ldy #0 .label debug_delay1 = *-1 // incrementing delay loop !: tya sec sbc #1 bne *-2 dey bne !- inx bpl !loopADS- lda SID_vars+3 // AD2 sta $d405+$0e lda SID_vars+4 // SR2 sta $d406+$0e lda SID_vars+5 // Wave2 sta $d404+$0e !loopR: lda $d41c // Read SID ch3 envelope sta SIDenv3_debug_data_GATE1,x // write to debug sample buffer $80..$ff (gate off) txa and #$0c sta $d020 ldy #0 .label debug_delay2 = *-1 !: tya sec sbc #1 bne *-2 dey bne !- inx bmi !loopR- cli draw_oscilloscope: //---------------- lda #$80 sta zplot_pixel ldx #0 stx zdiv8_line_offset lda #8*4 // X offset for screen (8*4=center) sta zw_draw_ptr draw_osc_loop: //ldx #0 // Read amplitude: //lda SIDenv3_debug_data_GATE1,x // read the SID debug data //lsr // convert amplitude resolution from 8 bits to 7 bits //eor #$7f // invert value (turn draw "upside down": 0 at bottom, 255 at top): lda #$ff sre SIDenv3_debug_data_GATE1,x // Convert to amplitude of oscilloscope: tay // pha // fast & small bitmap pixel2ptr algorithm (8bit!) by Agemixer and #$07 sta mod7var tya // pla and #$f8 asl //adc #0 //discard highest bit for screen height =<16 characters) asl adc #0 asl adc #0 // $00,$08,$10,$18,$20..$78 -> $00,$40,$80,$c0,$01...$c3 sta draw_mul8 asl adc #0 asl adc #0 .label draw_mul8 = *-1 // $00,$40,$80,$c0,$01..$c3 -> $00,$01,$02,$03,$04...$0f + draw_mul8 //=$00,$41,$82,$c3,$05..$d2 pha and #$c0 ora #$00 .label mod7var = *-1 clc adc zdiv8_line_offset tay // bitmap pointer lo pla and #$1f adc #>bitmap sta zw_draw_ptr+1 // bitmap pointer hi lda zplot_pixel ora (zw_draw_ptr),y sta (zw_draw_ptr),y lsr zplot_pixel // rotate pixel right for next value bcc !+ ror zplot_pixel !: bpl !+ // if pixel gone round, get next char offset... //clc lda zdiv8_line_offset // xpos=xpos+8 adc #8 sta zdiv8_line_offset !: inx bne draw_osc_loop //ldx #0 stx $d020 rts wait_1_frame: //----------- bit $d011 // wait for frame start bpl *-3 bit $d011 bmi *-3 rts