.include "../inc/common.i" .include "../inc/commonprint.i" .include "../inc/net.i" .ifndef NB65_API_VERSION_NUMBER .define EQU = .include "../inc/nb65_constants.i" .endif .import get_key .import copymem .importzp copy_src .importzp copy_dest temp_buff=copy_dest .import url_download .import url_download_buffer .import url_download_buffer_length .import parser_init .import parser_skip_next SCREEN_RAM = $0400 COLOUR_RAM = $d800 VIC_CTRL_A = $d011 VIC_RASTER_REG = $d012 VIC_CTRL_B = $d016 VIC_MEMORY_CTRL=$d018 VIC_IRQ_FLAG = $d019 IRQ_VECTOR=$fffe BORDER_COLOR = $d020 BACKGROUND_COLOR_0 = $d021 SCROLL_DELAY=4 CHARS_PER_LINE = 40 SCROLL_LINE=12 SCROLL_RAM = SCREEN_RAM+(SCROLL_LINE*CHARS_PER_LINE) TOP_BORDER_SCAN_LINES = 50 BLACK = 0 WHITE = 1 RED = 2 CYAN = 3 PURPLE = 4 GREEN = 5 BLUE = 6 YELLOW = 7 ORANGE = 8 BROWN = 9 LIGHT_RED = 10 DARK_GRAY = 11 GRAY = 12 LIGHT_GREEN = 13 LIGHT_BLUE = 14 LIGHT_GRAY = 15 .macro start_irq pha txa pha tya pha .endmacro .macro end_irq pla tay pla tax pla .endmacro .macro wait_next_raster lda VIC_RASTER_REG @loop: cmp VIC_RASTER_REG beq @loop .endmacro .bss current_input_ptr_ptr: .res 2 param_offset: .res 1 scroll_state: .res 1 download_buffer: download_buffer_length=7600 .res download_buffer_length scroll_buffer_0: .res 2000 scroll_buffer_1: .res 2000 string_offset: .res 1 .segment "STARTUP" ;this is what gets put at the start of the file on the C64 .word basicstub ; load address basicstub: .word @nextline .word 2003 .byte $9e .byte <(((init / 1000) .mod 10) + $30) .byte <(((init / 100 ) .mod 10) + $30) .byte <(((init / 10 ) .mod 10) + $30) .byte <(((init ) .mod 10) + $30) .byte 0 @nextline: .word 0 init: jsr ip65_init jsr dhcp_init jsr setup_static_scroll_text lda #0 jsr clear_screen lda #DARK_GRAY sta BORDER_COLOR lda #YELLOW sta BACKGROUND_COLOR_0 lda #<(charset_font >>10)+$10 sta VIC_MEMORY_CTRL sei ;disable maskable IRQs lda #$7f sta $dc0d ;disable timer interrupts which can be generated by the two CIA chips sta $dd0d ;the kernal uses such an interrupt to flash the cursor and scan the keyboard, so we better ;stop it. lda $dc0d ;by reading this two registers we negate any pending CIA irqs. lda $dd0d ;if we don't do this, a pending CIA irq might occur after we finish setting up our irq. ;we don't want that to happen. lda #$01 ;this is how to tell the VICII to generate a raster interrupt sta $d01a lda #$00 ;this is how to tell at which rasterline we want the irq to be triggered sta VIC_RASTER_REG ;copy KERNAL to the RAM underneath, in case any ip65 routines need it ldax #$e000 stax copy_src stax copy_dest ldax #$1FFF jsr copymem lda #$35 ;we turn off the BASIC and KERNAL rom here, so we can overwrite the IRQ vector at $fffe sta $01 ;the cpu now sees RAM everywhere except at $d000-$e000, where still the registers of ;SID/VICII/etc are visible jsr setup_sprites jsr set_next_irq_jump cli ;enable maskable interrupts again lda #0 sta scroll_state ;position for the first text ldax #scroll_buffer_0 stax current_input_ptr_ptr jsr reset_input_buffer ;now download the feed @download_feed: ldax #download_buffer stax url_download_buffer ldax #download_buffer_length stax url_download_buffer_length ldax #feed_url jsr url_download lda #1 sta scroll_state ldax #scroll_buffer_1 stax current_output_ptr jsr emit_titles ldax #scroll_buffer_1 stax current_input_ptr_ptr ;will get picked up once we have finished going through the message once @endless_loop: jsr ip65_process jmp @endless_loop reset_input_buffer: ldax current_input_ptr_ptr stax current_input_ptr rts setup_sprites: ;turn on all 8 sprites lda #$FF sta $d015 ldx #$07 @setup_sprite: ;position each sprite txa asl tay lda sprite_x_pos,x sta $d000,y ;sprite 0 X pos (LSB) lda 0 sta $d001,y ;sprite 0 Y pos ;colour sprite 0 lda #BLUE sta $d027,x ;sprite 0 color ;select bitmap for sprite sec lda sprite_text,x sbc #'A' clc adc #<(sprite_font/64) sta SCREEN_RAM+$03f8,x dex bpl @setup_sprite lda sprite_x_msb sta $d010 ;turn on multicolor mode for all 8 sprites lda #$FF sta $d01c lda #DARK_GRAY sta $d025 ;sprite multicolor register 0 lda #LIGHT_GRAY sta $d026 ;sprite multicolor register 1 rts clear_screen: ldx #$00 lda #$20 : sta SCREEN_RAM,x sta SCREEN_RAM+$100,x sta SCREEN_RAM+$200,x sta SCREEN_RAM+$300,x sta COLOUR_RAM,x sta COLOUR_RAM+$100,x sta COLOUR_RAM+$200,x sta COLOUR_RAM+$300,x dex bne :- rts set_next_irq_jump: inc jump_counter lda jump_counter asl asl load_next_raster_entry: tax lda raster_jump_table,x ;bit 9 of raster to trigger on cmp #$ff bne not_last_entry lda #0 sta jump_counter jmp load_next_raster_entry not_last_entry: ora #$18 ;turn on bits 3 & 4 sta VIC_CTRL_A lda raster_jump_table+1,x ;bits 0..7 of raster to trigger on sta VIC_RASTER_REG lda raster_jump_table+2,x ;LSB of IRQ handler sta IRQ_VECTOR lda raster_jump_table+3,x ;LSB of IRQ handler sta IRQ_VECTOR+1 rts exit_from_irq: jsr set_next_irq_jump lda #$ff ;this is the orthodox and safe way of clearing the interrupt condition of the VICII. sta VIC_IRQ_FLAG;if you don't do this the interrupt condition will be present all the time and you end ;up having the CPU running the interrupt code all the time, as when it exists the ;interrupt, the interrupt request from the VICII will be there again regardless of the ;rasterline counter. end_irq rti scroll_text_irq: start_irq lda scroll_timer bne done_scrolling_message lda #SCROLL_DELAY sta scroll_timer ldx #1 ldy #0 scroll_1_char: lda SCROLL_RAM,x sta SCROLL_RAM,y lda SCROLL_RAM+40,x sta SCROLL_RAM+40,y inx iny cpx #CHARS_PER_LINE bne scroll_1_char jsr get_a cmp #0 beq last_char_in_message sta SCROLL_RAM+CHARS_PER_LINE-1 clc adc #$80 sta SCROLL_RAM+CHARS_PER_LINE+40-1 jmp done_scrolling_message last_char_in_message: jsr reset_input_buffer done_scrolling_message: dec scroll_timer jmp exit_from_irq scroll_timer: .byte 1 scroll_counter: .byte 0 pixel_scroll_irq: start_irq wait_next_raster ; set X scroll offset lda scroll_timer clc asl clc and #$07 sta VIC_CTRL_B jmp exit_from_irq move_sprites_irq: start_irq wait_next_raster ldy sprite_ticker inc sprite_ticker ldx #$0e ;7*2 @position_sprite: lda sprite_y_pos,y sta $d001,x ;sprite 0 Y pos ;change colour when the sprite goes off screen ; cmp #$ff ;are we off the screen? ; bne @not_off_screen ; txa ; pha ; lsr ; tax ; inc $d027,x ;sprite color ; pla ; tax ;@not_off_screen: txa beq @y_set dex dex @mod_y: iny iny iny dex dex bpl @mod_y @y_set: tax dex dex bpl @position_sprite jmp exit_from_irq setup_static_scroll_text: ldax #scroll_buffer_0 stax current_output_ptr ldax #scroll_template stax current_input_ptr @next_byte: jsr get_a cmp #'%' beq @operator pha jsr emit_a pla bne @next_byte rts @operator: jsr get_a cmp #'i' bne @not_ip lda #NB65_CFG_IP jmp @loaded_offset @not_ip: cmp #'g' bne @not_gateway lda #NB65_CFG_GATEWAY jmp @loaded_offset @not_gateway: cmp #'d' bne @not_dns lda #NB65_CFG_DNS_SERVER jmp @loaded_offset @not_dns: cmp #'f' bne @not_feed_url ldy #0 @copy_feed_url_loop: lda feed_url,y beq @next_byte jsr emit_a iny bne @copy_feed_url_loop @not_feed_url: jmp @next_byte @loaded_offset: sta param_offset jsr cfg_get_configuration_ptr ;ax=base config, carry flag clear adc param_offset bcc :+ inx : jsr emit_dotted_quad jmp @next_byte ;emit the 4 bytes pointed at by AX as dotted decimals emit_dotted_quad: sta pptr stx pptr + 1 ldy #0 lda (pptr),y jsr emit_decimal lda #'.' jsr emit_a ldy #1 lda (pptr),y jsr emit_decimal lda #'.' jsr emit_a ldy #2 lda (pptr),y jsr emit_decimal lda #'.' jsr emit_a ldy #3 lda (pptr),y jsr emit_decimal rts emit_decimal: ;emit byte in A as a decimal number pha sta temp_bin ;save sed ; Switch to decimal mode lda #0 ; Ensure the result is clear sta temp_bcd sta temp_bcd+1 ldx #8 ; The number of source bits : asl temp_bin+0 ; Shift out one bit lda temp_bcd+0 ; And add into result adc temp_bcd+0 sta temp_bcd+0 lda temp_bcd+1 ; propagating any carry adc temp_bcd+1 sta temp_bcd+1 dex ; And repeat for next bit bne :- cld ;back to binary pla ;get back the original passed in number bmi @emit_hundreds ; if N is set, the number is >=128 so emit all 3 digits cmp #10 bmi @emit_units cmp #100 bmi @emit_tens @emit_hundreds: lda temp_bcd+1 ;get the most significant digit and #$0f clc adc #'0' jsr emit_a @emit_tens: lda temp_bcd lsr lsr lsr lsr clc adc #'0' jsr emit_a @emit_units: lda temp_bcd and #$0f clc adc #'0' jsr emit_a rts top_sprite_color_irq: start_irq wait_next_raster dec $d025 ;sprite multicolor register 0 dec $d026 ;sprite multicolor register 1 jmp exit_from_irq bottom_sprite_color_irq: start_irq wait_next_raster inc $d025 ;sprite multicolor register 0 inc $d026 ;sprite multicolor register 1 jmp exit_from_irq emit_titles: ldax #download_buffer jsr parser_init @next_title: ldax #title jsr parser_skip_next bcs @done jsr emit_tag_contents lda #' ' jsr emit_a lda #'/' jsr emit_a lda #' ' jsr emit_a jmp @next_title @done: rts emit_tag_contents: stax temp_buff lda #0 sta string_offset @next_byte: jsr @get_next_byte cmp #0 beq @done cmp #'<' beq @done cmp #'&' beq @entity jsr emit_a beq @done jmp @next_byte @entity: jsr @get_next_byte cmp #'a' bne @not_amper lda #'&' jsr emit_a @not_amper: cmp #'g' bne @not_gt lda #'>' jsr emit_a @not_gt: cmp #'l' bne @not_lt lda #'<' jsr emit_a @not_lt: @loop_till_semi_colon: jsr @get_next_byte cmp #0 beq @done cmp #';' bne @loop_till_semi_colon jmp @next_byte @get_next_byte: ldy string_offset lda (temp_buff),y inc string_offset @done: rts .data sprite_ticker: .byte 0 emit_a: current_output_ptr=emit_a+1 sta $ffff inc current_output_ptr bne :+ inc current_output_ptr+1 : rts get_a: current_input_ptr=get_a+1 lda $ffff inc current_input_ptr bne :+ inc current_input_ptr+1 : rts raster_jump_table: ;format: ;offset meaning ; $00 BIT 9 OF RASTER TO TRIGGER ON ($00 if bit 8 =0 , $80 if bit 8 =1) ; $01 BITS 0..7 OF RASTER TO TRIGGER ON ; $02 LSB OF ROUTINE TO JUMP TO ; $03 MSB OF ROUTINE TO JUMP TO ;table needs to end with a single byte $ff ;table needs to be sorted by scanlines .byte $0,$01 .word scroll_text_irq .byte $0,$1b ; .word top_sprite_color_irq ; .byte $0,$20 .word pixel_scroll_irq .byte $0,$80 ; .word bottom_sprite_color_irq ; .byte $0,255 .word move_sprites_irq .byte $ff ;end of list jump_counter: .byte 0 sprite_x_pos: .byte $38,$58,$78,$98,$B8,$D8,$F8,$18 sprite_x_msb: .byte $80 sprite_y_pos: .include "sine_data.i" .include "sine_data.i" scroll_template: sprite_text: .byte "COMATOMX" .byte " configured via dhcp - ip: %i / gateway: %g / dns server %d / polling %f /" .byte " ",0 feed_url: .byte "http://search.twitter.com/search.atom?q=kipper",0 .byte "http://static.cricinfo.com/rss/livescores.xml",0 title: .byte "",0 .segment "VIC_DATA" charset_font: .incbin "font16x8.bin" sprite_font: .incbin "spud_letters.spr"