From 6e8dc9782620aa6f7fcb9f9b63113a2995693569 Mon Sep 17 00:00:00 2001 From: Chris Pressey Date: Thu, 29 Mar 2018 12:11:38 +0100 Subject: [PATCH] Fork the Atari 2600 Ophis example for easier comparing to 60p. --- eg/atari2600/atari-2600-example.oph | 117 ++++--- eg/atari2600/build.sh | 11 +- .../{atari-2600-example.60p => smiley.60p} | 24 +- eg/atari2600/smiley.oph | 285 ++++++++++++++++++ 4 files changed, 368 insertions(+), 69 deletions(-) rename eg/atari2600/{atari-2600-example.60p => smiley.60p} (86%) create mode 100644 eg/atari2600/smiley.oph diff --git a/eg/atari2600/atari-2600-example.oph b/eg/atari2600/atari-2600-example.oph index 8ab1c3f..836a64a 100644 --- a/eg/atari2600/atari-2600-example.oph +++ b/eg/atari2600/atari-2600-example.oph @@ -114,9 +114,8 @@ zero_loop: main: jsr vertical_blank jsr display_frame - ;;; jsr read_joystick + jsr read_joystick jmp main - rts ;;; ; ; Vertical blank routine. @@ -256,63 +255,63 @@ _image_loop: ; of the player. ; -;;; .scope -;;; read_joystick: -;;; lda joystick_delay -;;; beq _continue -;;; -;;; dec joystick_delay -;;; rts -;;; -;;; _continue: -;;; lda SWCHA -;;; and #$f0 -;;; cmp #$e0 -;;; beq _up -;;; cmp #$d0 -;;; beq _down -;;; cmp #$b0 -;;; beq _left -;;; cmp #$70 -;;; beq _right -;;; jmp _tail -;;; -;;; _up: -;;; inc luminosity -;;; jmp _tail -;;; _down: -;;; dec luminosity -;;; jmp _tail -;;; _left: -;;; dec colour -;;; jmp _tail -;;; _right: -;;; inc colour -;;; ;jmp _tail -;;; -;;; _tail: -;;; lda colour -;;; and #$0f -;;; sta colour -;;; -;;; lda luminosity -;;; and #$0f -;;; sta luminosity -;;; -;;; lda colour -;;; clc -;;; rol -;;; rol -;;; rol -;;; rol -;;; ora luminosity -;;; sta COLUP0 -;;; -;;; lda #$06 -;;; sta joystick_delay -;;; -;;; rts -;;; .scend +.scope +read_joystick: + lda joystick_delay + beq _continue + + dec joystick_delay + rts + +_continue: + lda SWCHA + and #$f0 + cmp #$e0 + beq _up + cmp #$d0 + beq _down + cmp #$b0 + beq _left + cmp #$70 + beq _right + jmp _tail + +_up: + inc luminosity + jmp _tail +_down: + dec luminosity + jmp _tail +_left: + dec colour + jmp _tail +_right: + inc colour + ;jmp _tail + +_tail: + lda colour + and #$0f + sta colour + + lda luminosity + and #$0f + sta luminosity + + lda colour + clc + rol + rol + rol + rol + ora luminosity + sta COLUP0 + + lda #$06 + sta joystick_delay + + rts +.scend ; ; Player (sprite) data. diff --git a/eg/atari2600/build.sh b/eg/atari2600/build.sh index 1cb7509..1430812 100755 --- a/eg/atari2600/build.sh +++ b/eg/atari2600/build.sh @@ -1,10 +1,9 @@ #!/bin/sh -sixtypical --prelude=atari2600 atari-2600-example.60p > atari-2600-example-60p.bin +sixtypical --prelude=atari2600 smiley.60p > smiley-60p.bin if [ "x$COMPARE" != "x" ]; then - ophis atari-2600-example.oph -o atari-2600-example.bin - dcc6502 -o 0xf000 -m 200 atari-2600-example.bin > atari-2600-example.bin.disasm.txt - dcc6502 -o 0xf000 -m 200 atari-2600-example-60p.bin > atari-2600-example-60p.bin.disasm.txt - paste atari-2600-example.bin.disasm.txt atari-2600-example-60p.bin.disasm.txt | pr -t -e24 - #diff -ru atari-2600-example.bin.disasm.txt atari-2600-example-60p.bin.disasm.txt + ophis smiley.oph -o smiley.bin + dcc6502 -o 0xf000 -m 200 smiley.bin > smiley.bin.disasm.txt + dcc6502 -o 0xf000 -m 200 smiley-60p.bin > smiley-60p.bin.disasm.txt + paste smiley.bin.disasm.txt smiley-60p.bin.disasm.txt | pr -t -e24 fi diff --git a/eg/atari2600/atari-2600-example.60p b/eg/atari2600/smiley.60p similarity index 86% rename from eg/atari2600/atari-2600-example.60p rename to eg/atari2600/smiley.60p index fad76c3..c66d966 100644 --- a/eg/atari2600/atari-2600-example.60p +++ b/eg/atari2600/smiley.60p @@ -1,4 +1,5 @@ -// atari-2600-example.60p - SixtyPical translation of atari-2600-example.oph +// smiley.60p - SixtyPical translation of smiley.oph (2018), +// which is itself a stripped-down version of atari-2600-example.oph byte VSYNC @ $00 byte VBLANK @ $01 @@ -147,10 +148,25 @@ define display_frame routine st a, COLUBK } +define colourize_player routine + inputs colour, luminosity + outputs COLUP0 + trashes a, z, c, n +{ + ld a, colour + st off, c + shl a + shl a + shl a + shl a + or a, luminosity + st a, COLUP0 +} + define main routine inputs image_data, INTIM - outputs CTRLPF, colour, luminosity, NUSIZ0, VSYNC, WSYNC, TIM64T, HMOVE, VBLANK, RESP0, GP0, PF0, PF1, PF2, COLUPF, COLUBK - trashes a, x, y, z, n + outputs CTRLPF, colour, luminosity, NUSIZ0, VSYNC, WSYNC, TIM64T, HMOVE, VBLANK, RESP0, GP0, PF0, PF1, PF2, COLUPF, COLUBK, COLUP0 + trashes a, x, y, z, c, n { ld a, $00 st a, CTRLPF @@ -163,6 +179,6 @@ define main routine repeat { call vertical_blank call display_frame - // call read_joystick + call colourize_player } forever } diff --git a/eg/atari2600/smiley.oph b/eg/atari2600/smiley.oph new file mode 100644 index 0000000..19d4335 --- /dev/null +++ b/eg/atari2600/smiley.oph @@ -0,0 +1,285 @@ +; +; smiley.oph (2018) +; stripped-down version of atari-2600-example.oph (2012) +; +; This work is in the public domain. See the file UNLICENSE for more info. +; +; to build and run in Stella: +; ophis smiley.oph -o smiley.bin +; stella smiley.bin + +; +; Useful system addresses (TODO: briefly describe each of these.) +; + +.alias VSYNC $00 +.alias VBLANK $01 +.alias WSYNC $02 +.alias NUSIZ0 $04 +.alias NUSIZ1 $05 +.alias COLUPF $08 +.alias COLUBK $09 +.alias PF0 $0D +.alias PF1 $0E +.alias PF2 $0F +.alias SWCHA $280 +.alias INTIM $284 +.alias TIM64T $296 +.alias CTRLPF $0A +.alias COLUP0 $06 +.alias COLUP1 $07 +.alias GP0 $1B +.alias GP1 $1C +.alias HMOVE $2a +.alias RESP0 $10 +.alias RESP1 $11 + +; +; Cartridge ROM occupies the top 4K of memory ($F000-$FFFF). +; Thus, typically, the program will occupy all that space too. +; +; Zero-page RAM we can use with impunity starts at $80 and goes +; upward (at least until $99, but probably further.) +; + +.alias colour $80 +.alias luminosity $81 +.alias joystick_delay $82 + +.org $F000 + +; +; Standard prelude for Atari 2600 cartridge code. +; +; Get various parts of the machine into a known state: +; +; - Disable interrupts +; - Clear the Decimal flag +; - Initialize the Stack Pointer +; - Zero all bytes in Zero Page memory +; + +start: + sei + cld + ldx #$FF + txs + lda #$00 + +zero_loop: + sta $00, x + dex + bne zero_loop + + ; and fall through to... + +; +; Initialization. +; +; - Clear the Playfield Control register. +; - Set the player (sprite) colour to light green (write to COLUP0.) +; - Set the player (sprite) size/repetion to normal (write to NUSIZ0.) +; + + lda #$00 + sta CTRLPF + lda #$0c + sta colour + lda #$0a + sta luminosity + lda #$00 + sta NUSIZ0 + + ; and fall through to... + +; +; Main loop. +; +; A typical main loop consists of: +; - Waiting for the frame to start (vertical blank period) +; - Displaying stuff on the screen (the _display kernel_) +; - Doing any processing you like (reading joysticks, updating program state, +; etc.), as long as you get it all done before the next frame starts! +; + +main: + jsr vertical_blank + jsr display_frame + jsr colourize_player + jmp main + rts ; NOTE just to pad out to match the SixtyPical version + +; +; Vertical blank routine. +; +; In brief: wait until it is time for the next frame of video. +; TODO: describe this in more detail. +; + +vertical_blank: + ldx #$00 + lda #$02 + sta WSYNC + sta WSYNC + sta WSYNC + sta VSYNC + sta WSYNC + sta WSYNC + lda #$2C + sta TIM64T + lda #$00 + sta WSYNC + sta VSYNC + rts + +; +; Display kernal. +; +; First, wait until it's time to display the frame. +; + +.scope +display_frame: + lda INTIM + bne display_frame + +; +; (After that loop finishes, we know the accumulator must contain 0.) +; Wait for the next scanline, zero HMOVE (for some reason; TODO discover +; this), then turn on the screen. +; + + sta WSYNC + sta HMOVE + sta VBLANK + +; +; Actual work in the display kernal is done here. +; +; This is a pathological approach to writing a display kernal. +; This wouldn't be how you'd do things in a game. So be it. +; One day I may improve it. For now, be happy that it displays +; anything at all! +; + +; +; Wait for $3f (plus one?) scan lines to pass, by waiting for +; WSYNC that many times. +; + + ldx #$3F +_wsync_loop: + sta WSYNC + dex + bpl _wsync_loop + sta WSYNC + +; +; Delay while the raster scans across the screen. The more +; we delay here, the more to the right the player will be when +; we draw it. +; + + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + +; +; OK, *now* display the player. +; + + sta RESP0 + +; +; Loop over the rows of the sprite data, drawing each to the screen +; over four scan lines. +; +; TODO understand this better and describe it! +; + + ldy #$07 +_image_loop: + lda image_data, y + sta GP0 + + sta WSYNC + sta WSYNC + sta WSYNC + sta WSYNC + dey + bpl _image_loop + + lda #$00 + sta GP0 + +; +; Turn off screen display and clear display registers. +; + + lda #$02 + sta WSYNC + sta VBLANK + lda #$00 + sta PF0 + sta PF1 + sta PF2 + sta COLUPF + sta COLUBK + + rts +.scend + +; +; Modify the colour and luminosity of the player. +; + +.scope +colourize_player: + lda colour + clc + rol + rol + rol + rol + ora luminosity + sta COLUP0 + rts +.scend + +; +; Player (sprite) data. +; +; Because we loop over these bytes with the Y register counting *down*, +; this image is stored "upside-down". +; + +image_data: + .byte %01111110 + .byte %10000001 + .byte %10011001 + .byte %10100101 + .byte %10000001 + .byte %10100101 + .byte %10000001 + .byte %01111110 + +; +; Standard postlude for Atari 2600 cartridge code. +; Give BRK and boot vectors that point to the start of the code. +; + +.advance $FFFC + .word start + .word start