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

Publicado por Paulo Sergio Travaglia 29/06/2009

[ Hits: 7.783 ]

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

Árvore binária de busca em Assembler 8086

Escrita de um número em decimal na tela em Assembly Puro para Linux 64 bits (GNU Assembly)

codigo em assembley que soma dois numeros

ToUpperCase em Assembler 8086

Escrita de um número em octal na tela em Assembly Puro para Linux x86 (Nasm - Netwide Assembler)


  

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




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts