Relógio em assembly NES 8 bits (variante do 6502)

Publicado por Paulo Sergio Travaglia 29/06/2009

[ Hits: 8.299 ]

Download relogio_nes.zip




Relógio feito em linguagem assembly do nintendo 8 bits (6502).

O clock se baseia na NMI de um sistema NTSC (non-maskable interrupts - Período em que o feixe do televisor está retornando a posição zero após desenhar tela inteira) .

Tenho que admitir que o código não é lá essas coisas, pois muitos techos são redundantes. Mas foi minha primeira aventura com assembly maior do que somar o valor de 2 registradores! :)

Deve ser compilado com o nesasm (pode ser baixado em: http://bobrost.com/nes/files/nbasic_2004_03_14.zip) e executado com um emulador de nintendo 8 bits.

  



Esconder código-fonte

; pt_br: Um relogio simples - Feito por Paulo Sergio Travaglia em 21/06/2009
; pt_br: Utiliza a taxa de refresh do NTSC como base de contagem

; en: A simple clock - Made by Paulo Sergio Travaglia in 2009/06/21
; en: Uses NTSC refresh rate as base for counting time

; pstglia@gmail.com

        .inesprg        1
        .ineschr        1
        .inesmir        1
        .inesmap        0

        .bank 0
        .org $8000

Inicio:
        ; pt_br: Configura a PPU
        ; en: Set up PPU
        lda #%10010000
        sta $2000
        lda #%00011110
        sta $2001

        ; pt_br: Carregando as paletas
        ; en: Loading palletes
        lda #$3F
        sta $2006
        lda #$00
        sta $2006
        ldx #$0
loop_pal:
        lda pallete, x
        sta $2007
        inx
        cpx #$20
        bne loop_pal


        ; pt_br: Definindo valores iniciais para o horario (segundo, minuto, hora)
        ; en: Setting initial value for time (second, minute, hour)
        lda #00
        sta $0200
        lda #00
        sta $0201
        lda #00
        sta $0202
        lda #0

        ; pt_br: Inicializa enderecos que guardam o tile com os digitos a serem impressos
        ; en: Initialize addresses to store the tiles that will be displayed on screen
        sta $0230
        sta $0231
        sta $0232
        sta $0233
        sta $0234
        sta $0235

        ; pr_br: Contador do timer
        ; en: timer counter
        sta $020a

loop_main:

        ; pt_br: Incrementa os valores caso um v_blank esteja acontecendo
        ; en: Increase values when a v_blank is occuring
        lda $2002
        bpl inc_seg
        jmp loop_main

inc_seg:

        ; pt_br: Verifica se ja se passaram 60 segundos (60 NMIs NTSC)
        ; en: check if 60 seconds has passed (60 NTSC NMIs)
        ldx $020a
        cpx #60
        bne loop_main
        ldx #0
        stx $020a

        inc $0200
        lda $0200

        cmp #60
        beq inc_min
        ldx #0
        jsr calc_digitos
        ldx #2
        jsr calc_digitos
        ldx #4
        jsr calc_digitos
        jmp loop_main

inc_min:
        inc $0201
        lda $0201

        cmp #60
        beq inc_hora
        ldx #0
        stx $0200
        ldx #0
        jsr calc_digitos
        ldx #2
        jsr calc_digitos
        ldx #4
        jsr calc_digitos
        jmp loop_main

inc_hora:
        inc $0202
        lda $0202
        cmp #24
        beq reset_hora
        ldx #0
        stx $0200
        stx $0201
        ldx #0
        jsr calc_digitos
        ldx #2
        jsr calc_digitos
        ldx #4
        jsr calc_digitos
        jmp loop_main

reset_hora:
        ldx #0
        stx $0200
        stx $0201
        stx $0202
        ldx #0
        jsr calc_digitos
        ldx #2
        jsr calc_digitos
        ldx #4
        jsr calc_digitos
        jmp loop_main


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; pt_br: Desenha a tela durante a NMI
; en: Draw screen on NMI
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
desenha_tela:

        pha
        txa
        pha
        tya
        pha

        inc $020a

        ; pt_br: Obtem os digitos das horas
        ; en: Get hour digits
        ldx #0
        stx $2003
        stx $2003
        ldx #30
        stx $2004 ; Y-coord
        ldx $0234
        stx $2004 ; Tile
        ldx #0
        stx $2004 ; Attr
        stx $2004 ; X-coord

        ldx #30
        stx $2004 ; Y-coord
        ldx $0235
        stx $2004 ; Tile
        ldx #0
        stx $2004 ; Attr
        ldx #9
        stx $2004 ; X-coord

        ; pt_br: Obtem os digitos dos minutos
        ; en: Get minutes digits
        ldx #30
        stx $2004 ; Y-coord
        ldx $0232
        stx $2004 ; Tile
        ldx #0
        stx $2004 ; Attr
        ldx #18
        stx $2004 ; X-coord

        ldx #30
        stx $2004 ; Y-coord
        ldx $0233
        stx $2004 ; Tile
        ldx #0
        stx $2004 ; Attr
        ldx #27
        stx $2004 ; X-coord

        ; pt_br: Obtem os digitos dos segundos
        ; en: Get seconds digits
        ldx #30
        stx $2004 ; Y-coord
        ldx $0230
        stx $2004 ; Tile
        ldx #0
        stx $2004 ; Attr
        ldx #36
        stx $2004 ; X-coord

        ldx #30
        stx $2004 ; Y-coord
        ldx $0231
        stx $2004 ; Tile
        ldx #0
        stx $2004 ; Attr
        ldx #45
        stx $2004 ; X-coord

        pla
        tay
        pla
        tax
        pla

        rti
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; pt_br: Obtem os digitos para impressao e grava em $0230 e $0231
; en: Get the digits for printing and write on $0230 e $0231
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
calc_digitos:

        lda #0
        sta $0230,x
        sta $0231,x


        ; pt_br: Em que casa de digitos estamos (10, 20, 30, 40 ou 50)
        ldy #10
        sty $0205
        ; pt_br: A cada 10 unidades, incrementa 1
        ldy #0
        sty $0206

loop_inc:

        ; Casa de 10 digitos
        cpy $0205
        bne prox_1

        inc $0206

        lda $0205
        clc
        adc #10
        sta $0205

        ; pt_br: calculo do indice do 1o digito na SPR-RAM
        sec
        sbc $0206
        sta $0207
        lda $0205
        sec
        sbc $0207
        sta $0230,x

prox_1:
        ; pt_br: calculo do indice do 2o. digito na SPR-RAM
        tya
        clc
        adc #10
        sec
        sbc $0205
        sta $0231,x

        ; pr_br: Checa o parametro passado para fazer o deslocamento correspondente
        ; en: Check the passed parameters to do the corresponding shift
        txa
        pha
        cpx #4 ; IF X = 4 THEN $0202
        bne nxt
        ldx #2
        jmp nxt2
nxt:
        cpx #2 ; ELSE IF X = 2 THEN $0201
        bne nxt2
        ldx #1
nxt2:
        lda $0200,x
        sta $0210

        pla
        tax

        cpy $0210
        beq saida_calc_digitos

        iny
        jmp loop_inc

saida_calc_digitos:
        rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; pt_br: Paleta de cores do fundo e dos sprites. Tirada da pagina de tutorial do GbaGuy
; en: Background and colour palletes. It was taken from GbaGuy tutorial site
pallete:
         .db $32,$01,$06,$2A,$32,$03,$10,$00
         .db $32,$38,$33,$3C,$32,$21,$26,$02
         .db $32,$16,$12,$14,$32,$07,$17,$27
         .db $32,$0B,$07,$2D,$32,$3A,$35,$31

        .bank 1
        .org $FFFA
        .dw desenha_tela
        .dw Inicio
        .dw 0

        .bank 2
        .org $0000
        .incbin "pal_spr.scr"
        .incbin "pal_bkg.scr"

Scripts recomendados

Escrita de número em hexadecimal em Assembly Puro para Linux 64bits (Nasm - Netwide Assemble)

Algoritmo de Raiz Quadrada Inteira em Assembly Puro para Linux x86 (GNU Assembler)

Fatorial em assembly

GAS Informações da CPU

Retorna a diferença entre dois vetores em Assemly


  

Comentários
[1] Comentário enviado por pstglia em 29/06/2009 - 22:13h

Só uma pequena errata de comentário no código:

A principio eu fazia os incrementos de valores (segundos, minutos e horas) durante um v_blank. Depois alterei para que fizesse isso quando um v_blank NÃO estiver ocorrendo.

O período da v_blank é muito curto e na maior parte dos casos deve ser reservado para atualizações de tela.



Contribuir com comentário