From 4cc2c8e712d6a39ad2f65b3abb9831e305793002 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 26 Aug 2015 17:38:18 -0700 Subject: [PATCH] Create assembler_atari2600.asm --- a/assembler_atari2600.asm | 194 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 a/assembler_atari2600.asm diff --git a/a/assembler_atari2600.asm b/a/assembler_atari2600.asm new file mode 100644 index 00000000..12fa519e --- /dev/null +++ b/a/assembler_atari2600.asm @@ -0,0 +1,194 @@ +; +; hello.asm +; +; A "Hello, World!" which illustrates an Atari 2600 programming +; introduction talk (slides at http://slideshare.net/chesterbr). +; +; This is free software (see license below). Build it with DASM +; (http://dasm-dillon.sourceforge.net/), by running: +; +; dasm hello.asm -ohello.bin -f3 +; + + PROCESSOR 6502 + INCLUDE "vcs.h" + + ORG $F000 ; Start of "cart area" (see Atari memory map) + +StartFrame: + lda #%00000010 ; Vertical sync is signaled by VSYNC's bit 1... + sta VSYNC + REPEAT 3 ; ...and lasts 3 scanlines + sta WSYNC ; (WSYNC write => wait for end of scanline) + REPEND + lda #0 + sta VSYNC ; Signal vertical sync by clearing the bit + +PreparePlayfield: ; We'll use the first VBLANK scanline for setup + lda #$00 ; (could have done it before, just once) + sta ENABL ; Turn off ball, missiles and players + sta ENAM0 + sta ENAM1 + sta GRP0 + sta GRP1 + sta COLUBK ; Background color (black) + sta PF0 ; PF0 and PF2 will be "off" (we'll focus on PF1)... + sta PF2 + lda #$FF ; Playfield collor (yellow-ish) + sta COLUPF + lda #$00 ; Ensure we will duplicate (and not reflect) PF + sta CTRLPF + ldx #0 ; X will count visible scanlines, let's reset it + REPEAT 37 ; Wait until this (and the other 36) vertical blank + sta WSYNC ; scanlines are finished + REPEND + lda #0 ; Vertical blank is done, we can "turn on" the beam + sta VBLANK + +Scanline: + cpx #174 ; "HELLO WORLD" = (11 chars x 8 lines - 1) x 2 scanlines = + bcs ScanlineEnd ; 174 (0 to 173). After that, skip drawing code + txa ; We want each byte of the hello world phrase on 2 scanlines, + lsr ; which means Y (bitmap counter) = X (scanline counter) / 2. + tay ; For division by two we use (A-only) right-shift + lda Phrase,y ; "Phrase,Y" = mem(Phrase+Y) (Y-th address after Phrase) + sta PF1 ; Put the value on PF bits 4-11 (0-3 is PF0, 12-15 is PF2) +ScanlineEnd: + sta WSYNC ; Wait for scanline end + inx ; Increase counter; repeat untill we got all kernel scanlines + cpx #191 + bne Scanline + +Overscan: + lda #%01000010 ; "turn off" the beam again... + sta VBLANK ; + REPEAT 30 ; ...for 30 overscan scanlines... + sta WSYNC + REPEND + jmp StartFrame ; ...and start it over! + +Phrase: + .BYTE %00000000 ; H + .BYTE %01000010 + .BYTE %01111110 + .BYTE %01000010 + .BYTE %01000010 + .BYTE %01000010 + .BYTE %00000000 + .BYTE %00000000 ; E + .BYTE %01111110 + .BYTE %01000000 + .BYTE %01111100 + .BYTE %01000000 + .BYTE %01000000 + .BYTE %01111110 + .BYTE %00000000 + .BYTE %00000000 ; L + .BYTE %01000000 + .BYTE %01000000 + .BYTE %01000000 + .BYTE %01000000 + .BYTE %01000000 + .BYTE %01111110 + .BYTE %00000000 + .BYTE %00000000 ; L + .BYTE %01000000 + .BYTE %01000000 + .BYTE %01000000 + .BYTE %01000000 + .BYTE %01000000 + .BYTE %01111110 + .BYTE %00000000 ; O + .BYTE %00000000 + .BYTE %00111100 + .BYTE %01000010 + .BYTE %01000010 + .BYTE %01000010 + .BYTE %01000010 + .BYTE %00111100 + .BYTE %00000000 + .BYTE %00000000 ; white space + .BYTE %00000000 + .BYTE %00000000 + .BYTE %00000000 + .BYTE %00000000 + .BYTE %00000000 + .BYTE %00000000 + .BYTE %00000000 + .BYTE %00000000 ; W + .BYTE %01000010 + .BYTE %01000010 + .BYTE %01000010 + .BYTE %01000010 + .BYTE %01011010 + .BYTE %00100100 + .BYTE %00000000 + .BYTE %00000000 ; O + .BYTE %00111100 + .BYTE %01000010 + .BYTE %01000010 + .BYTE %01000010 + .BYTE %01000010 + .BYTE %00111100 + .BYTE %00000000 + .BYTE %00000000 ; R + .BYTE %01111100 + .BYTE %01000010 + .BYTE %01000010 + .BYTE %01111100 + .BYTE %01000100 + .BYTE %01000010 + .BYTE %00000000 + .BYTE %00000000 ; L + .BYTE %01000000 + .BYTE %01000000 + .BYTE %01000000 + .BYTE %01000000 + .BYTE %01000000 + .BYTE %01111110 + .BYTE %00000000 + .BYTE %00000000 ; D + .BYTE %01111000 + .BYTE %01000100 + .BYTE %01000010 + .BYTE %01000010 + .BYTE %01000100 + .BYTE %01111000 + .BYTE %00000000 ; Last byte written to PF1 (important, ensures lower tip + ; of letter "D" won't "bleeed") + + ORG $FFFA ; Cart config (so 6502 can start it up) + + .WORD StartFrame ; NMI + .WORD StartFrame ; RESET + .WORD StartFrame ; IRQ + + END + +; +; Copyright 2011-2013 Carlos Duarte do Nascimento (Chester). All rights reserved. +; +; Redistribution and use in source and binary forms, with or without modification, are +; permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this list of +; conditions and the following disclaimer. +; +; 2. Redistributions in binary form must reproduce the above copyright notice, this list +; of conditions and the following disclaimer in the documentation and/or other materials +; provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY CHESTER ''AS IS'' AND ANY EXPRESS OR IMPLIED +; WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +; FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR +; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +; ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +; +; The views and conclusions contained in the software and documentation are those of the +; authors and should not be interpreted as representing official policies, either expressed +; or implied, of Chester. +;