Commits

Anonymous committed db13474

Initial import of ribos-1.1-2010.0430, petulant-2008.0401.

Comments (0)

Files changed (10)

empty.s

Empty file added.

petulant/petulant.p65

+; petulant.p65 - The PETulant Cursor, a "display hack" for the Commodore 64
+; Originally written by Chris Pressey sometime in the late 1980's
+; Rewritten in P65 assembly and released March 2008
+; This work is part of the public domain.
+
+; ----- BEGIN petulant.p65 -----
+
+; PRG file header
+
+.org 0
+.word $02a7
+.org $02a7
+
+; ----- Constants -----
+
+.alias cinv             $0314   ; hw irq interrupt, 60x per second
+.alias blnon            $cf     ; was last cursor blink on or off?
+.alias color            $286    ; current foreground colour for text
+
+.alias vic              $d000   ; base address of VIC-II chip
+.alias border           vic+$20 ; colour of border of the screen
+.alias background       vic+$21 ; colour of background of the screen
+
+; ----- Start of Program -----
+
+start:          sei             ; disable interrupts
+                lda cinv        ; save low byte of existing handler
+                sta savecinv
+                lda cinv+1      ; save high byte
+                sta savecinv+1
+
+                lda #<newcinv   ; install new interrupt handler
+                sta cinv
+                lda #>newcinv
+                sta cinv+1
+
+                cli             ; re-enable interrupts
+                rts
+
+newcinv:        lda blnon       ; is the cursor on?
+                beq cursor_off
+cursor_on:      lda color       ; yes, get its colour
+                jmp egress
+cursor_off:     lda background  ; no, get the background colour
+egress:         sta border      ; colour the border
+                jmp (savecinv)  ; continue pre-existing interrupt handler
+
+; ----- Uninitialized Data -----
+
+.space savecinv 2
+
+; ----- END of petulant.p65 -----

petulant/petulant.prg

+�x�����������X`�����L��!Ѝ �l�

petulant/readme.txt

+The PETulant Cursor
+===================
+
+This is a tiny (44 bytes long) machine-language demo for the Commodore 64,
+somewhat in the style of later "display hacks" for the Amiga -- surprising
+and silly ways to play with the user interface.
+
+So as not to not spoil the fun, try running it before reading the source.
+
+To run it, make the file PETULANT.PRG accessible to your favourite Commodore
+64 (or Commodore 64 emulator) in your favourite way, then
+
+  LOAD "PETULANT.PRG",8,1
+  SYS 679
+
+For further fun, try changing the text colour (hold the C= or CTRL key while
+pressing a number) or the background colour (POKE 53281 with a number from
+0 to 15) while it is running.
+
+I must have originally wrote this sometime in the late 80's.  I disassembled
+and rewrote it (to make it play more nicely with existing interrupt handlers)
+in 2008.
+
+Who knows -- this could actually be useful, in a ridiculously minor way: it
+makes it much more obvious when control has returned to BASIC immediate mode
+(e.g., when a program has finished loading.)
+
+Enjoy!
+
+-Chris Pressey
+April 1, 2008
+Chicago, IL
+Ribos
+=====
+
+This little demo is intended to be a well-commented example of how to
+program a raster interrupt in 6502 assembly language on a Commodore 64.
+
+This (r)aster (i)nterrupt changes the colour of a region of the
+(bo)rder of the C64 (s)creen; thus, RIBOS.  Also, it's the name of a
+planet from Dr. Who, if that means anything.
+
+
+How to Run the Demo (using the VICE C64 emulator, x64)
+------------------------------------------------------
+
+0. Obtain VICE from http://www.viceteam.org/, install it,
+   and run x64
+
+1. Mount this project's directory as drive 8:
+
+   Make sure
+     Peripheral settings > Device #8 > Enable IEC Device
+   is checked, then select
+     Peripheral settings > Device #8 > File system directory...
+   and enter the path to the project directory.
+
+2. LOAD "RIBOS.PRG",8,1
+
+3. SYS 49152
+
+4. You should see the colour of the middle of the border change
+   while you get a READY. prompt and can continue working.
+
+
+How to Assemble the Program (using the p65 assembler)
+-----------------------------------------------------
+
+0. Obtain p65 from http://hkn.berkeley.edu/~mcmartin/P65/
+   (I used p65-Perl version 1.1) and install it somewhere
+   on your path.  If your Perl interpreter isn't located at
+   /usr/bin/perl, change the first line of p65 appropriately.
+
+1. p65 -v -t -b ribos.p65 ribos.prg
+
+   The switches aren't necessary, but they make it feel like
+   p65 is doing something difficult and important.  It also
+   isn't necessary to add the '.prg' extension on the end of
+   the binary object's filename, since it will appear as a
+   PRG file to VICE anyway, but it's nice as a reminder when
+   you're working in a modern operating system.
+
+2. Follow the steps under 'How to Run this Demo' to see that
+   it worked.
+
+
+How it Works
+------------
+
+Read the source!  I've tried to make it very well-commented,
+including what happens when you leave out some steps.
+
+I wrote this demo because it was a long time since I had done any C64
+programming, and, having just obtained a copy of the 'Commodore 64
+Programmer's Reference Guide,' I wanted to code something challenging,
+yet not too involved.  I remembered raster interrupts as one of those
+quintessential C64 low-level graphics tricks, so I decided to try my
+hand at that.  Looking around on the Internet, I found this page:
+
+  http://everything2.com/index.pl?node_id=79254
+
+Although it's a fairly detailed description, it took me a couple of
+frustrating hours to implement it successfully - both the everything2
+article and the Reference Guide were pretty muddy on a couple of
+points.  What I learned in the process is written into the comments.
+
+Happy raster-interrupting!
+
+-Chris Pressey
+April 10, 2007
+Vancouver, BC
+; ribos.p65 - p65 assembly source for RIBOS:
+; Demonstration of the VIC-II raster interrupt on the Commodore 64:
+; Alter the border colour in the middle part of the screen only.
+; Original (hardware IRQ vector) version.
+;
+; Copyright (c)2007-2010 Cat's Eye Technologies.  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
+;    notices, this list of conditions and the following disclaimer.
+; 2. Redistributions in binary form must reproduce the above copyright
+;    notices, this list of conditions, and the following disclaimer in
+;    the documentation and/or other materials provided with the
+;    distribution.
+; 3. Neither the names of the copyright holders nor the names of their
+;    contributors may be used to endorse or promote products derived
+;    from this software without specific prior written permission. 
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; ``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 THE
+; COPYRIGHT HOLDERS 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.
+
+; ----- BEGIN ribos.p65 -----
+
+; This source file is intented to be assembled to produce a PRG file
+; which can be loaded into the C64's memory from a peripheral device.
+; All C64 PRG files start with a 16-bit word which represents the
+; location in memory to which they will be loaded.  We can provide this
+; using p65 directives as follows:
+
+.org 0
+.word $C000
+
+; Now the actual assembly starts (at memory location 49152.)
+
+.org $C000
+
+; ----- Constants -----
+
+; We first define some symbolic constants to add some clarity to our
+; references to hardware registers and other locations in memory.
+; Descriptions of the registers follow those given in the 'Commodore 64
+; Programmer's Reference Guide'.
+
+; The CIA #1 chip.
+
+.alias cia1             $dc00        ; pp. 328-331
+.alias intr_ctrl        cia1+$d      ; "CIA Interrupt Control Register
+                                     ; (Read IRQs/Write Mask)"
+
+; The VIC-II chip.
+
+.alias vic              $d000        ; Appendix G:
+.alias vic_ctrl         vic+$11      ; "Y SCROLL MODE"
+.alias vic_raster       vic+$12      ; "RASTER"
+.alias vic_intr         vic+$19      ; "Interrupt Request's" (sic)
+.alias vic_intr_enable  vic+$1a      ; "Interrupt Request MASKS"
+.alias border_color     vic+$20      ; "BORDER COLOR"
+
+; The address at which the IRQ vector is stored.
+
+.alias irq_vec          $fffe        ; p. 411
+
+; The zero-page address of the 6510's I/O register.
+
+.alias io_ctrl          $01          ; p. 310, "6510 On-Chip 8-Bit
+                                     ; Input/Output Register"
+
+; KERNAL and BASIC ROMs, p. 320
+
+.alias kernal           $e000
+.alias basic            $a000
+
+; Zero-page addresses that the memory-copy routine uses for
+; scratch space: "FREKZP", p. 316
+
+.alias zp               $fb
+.alias stop_at          $fd
+
+; ----- Main Routine -----
+
+; This routine is intended to be called by the user (by, e.g., SYS 49152).
+; It installs the raster interrupt handler and returns to the caller.
+
+; Key to installing the interrupt handler is altering the IRQ service
+; vector.  However, under normal circumstances, the address at which
+; this vector is stored ($ffffe) maps to the C64's KERNAL ROM, which
+; cannot be changed.  So, in order to alter the vector, we must enable
+; the RAM that underlies the ROM (i.e. the RAM that maps to the same
+; address space as the KERNAL ROM.)  If we were writing a bare-metal
+; game, and didn't need any KERNAL routines or support, we could just
+; switch it off.  But for this demo, we'd like the raster effect to
+; occur in the background as we use BASIC and whatnot, so we need to
+; continue to have access to the KERNAL ROM.  So what we do is copy the
+; KERNAL ROM to the underlying RAM, then switch the RAM for the ROM.
+
+                jsr copy_rom_to_ram
+
+; Interrupts can occur at any time.  If one were to occur while we were
+; changing the interrupt vector - for example, after we have stored the
+; low byte of the address but before we have stored the high byte -
+; unpredictable behaviour would result.  To be safe, we disable interrupts
+; with the 'sei' instruction before changing anything.
+
+                sei
+
+; We obtain the address of the current IRQ service routine and save it
+; in the variable 'saved_irq_vec'.
+
+                lda irq_vec   ; save low byte
+                sta saved_irq_vec
+                lda irq_vec+1 ; save high byte
+                sta saved_irq_vec+1
+
+; We then store the address of our IRQ service routine in its place.
+
+                lda #<our_service_routine
+                sta irq_vec
+                lda #>our_service_routine
+                sta irq_vec+1
+
+; Now we must specify the raster line at which the interrupt gets called.
+
+                lda scanline
+                sta vic_raster
+
+; Note that the position of the raster line is given by a 9-bit value,
+; and we can't just assume that, because the raster line we want is less
+; than 256, that the high bit will automatically be set to zero, because
+; it won't.  We have to explicitly set it high or low.  It is found as
+; the most significant bit of a VIC-II control register which has many
+; different functions, so we must be careful to preserve all other bits.
+
+                lda vic_ctrl
+                and #%01111111
+                sta vic_ctrl
+
+; Then we enable the raster interrupt on the VIC-II chip.
+
+                lda #$01
+                sta vic_intr_enable
+
+; The article at everything2 suggests that we read the interrupt control
+; port of the CIA #1 chip, presumably to acknowledge any pending IRQ and
+; avoid the problem of having some sort of lockup due to a spurious IRQ.
+; I've tested leaving this out, and the interrupt handler still seems get
+; installed alright.  But, I haven't tested it very demandingly, and it's
+; likely to open up a race condition that I just haven't encountered (much
+; like if we were to forget to execute the 'sei' instruction, above.)
+; So, to play it safe, we read the port here.
+
+                lda intr_ctrl
+
+; We re-enable interrupts to resume normal operation - normal, that is,
+; except that our raster interrupt service routine will be called the next
+; time the raster reaches the line stored in the 'vic_raster' register of
+; the VIC-II chip.
+
+                cli
+
+; Finally, we return to the caller.
+
+                rts
+
+; ----- Raster Interrupt Service Routine ------
+
+our_service_routine:
+
+; This is an interrupt service routine (a.k.a. interrupt handler,) and as
+; such, it can be called from anywhere.  Since the code that was interrupted
+; likely cares deeply about the values in its registers, we must be careful
+; to save any that we change, and restore them before switching back to it.
+; In this case, we only affect the processor flags and the accumulator, so
+; we push them onto the stack.
+
+                php
+                pha
+
+; The interrupt service routine on the Commodore 64 is very general-purpose,
+; and may be invoked by any number of different kinds of interrupts.  We,
+; however, only care about a certain kind - the VIC-II's raster interrupt.
+; We check to see if the current interrupt was caused by the raster by
+; looking at the low bit of the VIC-II interrupt register.  Note that we
+; immediately store back the value found there before testing it.  This is
+; to acknowledge to the VIC-II chip that we got the interrupt.  If we don't
+; do this, it won't send us another interrupt next time.
+
+                lda vic_intr
+                sta vic_intr
+                and #$01
+                cmp #$01
+                beq we_handle_it
+
+; If the interrupt was not caused by the raster, we restore the values
+; of the registers from the stack, and continue execution as normal with
+; the existing interrupt service routine.
+
+                pla
+                plp
+                jmp (saved_irq_vec)
+
+we_handle_it:
+
+; If we got here, the interrupt _was_ caused by the raster.  So, we get
+; to do our thing.  To keep things simple, we just invert the border colour.
+
+                lda border_color
+                eor #$ff
+                sta border_color
+
+; Now, we make the interrupt trigger on a different scan line so that we'll
+; invert the colour back to normal lower down on the screen.
+
+                lda scanline
+                eor #$ff
+                sta scanline
+                sta vic_raster
+
+; Restore the registers that we saved at the beginning of this routine.
+
+                pla
+                plp
+
+; Return to normal operation.  Note that we must issue an 'rti' instruction
+; here, not 'rts', as we are returning from an interrupt.
+
+		rti
+
+
+; ----- Utility Routine: copy KERNAL ROM to underlying RAM -----
+
+copy_rom_to_ram:
+
+; This is somewhat more involved than I let on above.  The memory mapping
+; facilities of the C64 are a bit convoluted.  The Programmer's Reference
+; Guide states on page 261 that the way to map out the KERNAL ROM, and
+; map in the RAM underlying it, is to set the HIRAM signal on the 6510's
+; I/O line (which is memory-mapped to address $0001) to 0.  This is true.
+; However, it is not the whole story: setting HIRAM to 0 *also* maps out
+; BASIC ROM and maps in the RAM underlying *it*.  I suppose this makes
+; sense from a design point of view; after all, BASIC uses the KERNAL, so
+; there wouldn't be much sense leaving it mapped when the KERNAL is mapped
+; out.  Anyway, what this means for us is that we must copy both of these
+; ROMs to their respective underlying RAMs if we want to survive returning
+; to BASIC.
+
+                ldx #>basic
+                ldy #$c0
+                jsr copy_block
+
+                ldx #>kernal
+                ldy #$00
+                jsr copy_block
+
+; To actually substitute the RAM for the ROM in the memory map, we
+; set HIRAM (the second least significant bit) to 0.
+
+                lda io_ctrl
+                and #%11111101
+                sta io_ctrl
+
+                rts
+
+
+; ----- Utility Routine: copy a ROM memory block to the underlying RAM -----
+
+; Input: x register = high byte of start address (low byte = #$00)
+;        y register = high byte of end address (stops at address $yy00 - 1)
+
+; This subroutine is a fairly straightforward memory copy loop.  A somewhat
+; counter-intuitive feature is that we immediately store each byte in the
+; same location where we just read it from.  We can do this because, even
+; when the KERNAL or BASIC ROM is mapped in, writes to those locations still
+; go to the underlying RAM.
+
+copy_block:     stx zp+1
+                sty stop_at
+                ldy #$00
+                sty zp
+
+copy_loop:      lda (zp), y
+                sta (zp), y
+                iny
+                cpy #$00
+                bne copy_loop
+                ldx zp+1
+                inx
+                stx zp+1
+                cpx stop_at
+                bne copy_loop
+                rts
+
+; ----- Variables -----
+
+; 'scanline' stores the raster line that we want the interrupt to trigger
+; on; it gets loaded into the VIC-II's 'vic_raster' register.  
+
+scanline: .byte %01010101
+
+; We also reserve space to store the address of the interrupt service
+; routine that we are replacing in the IRQ vector, so that we can transfer
+; control to it at the end of our routine.
+
+.space saved_irq_vec 2
+
+; ----- END of ribos.p65 -----

ribos/ribos.png

Added
New image

ribos/ribos.prg

Binary file added.
+; ribos2.p65 - p65 assembly source for RIBOS2:
+; Demonstration of the VIC-II raster interrupt on the Commodore 64:
+; Alter the border colour in the middle part of the screen only,
+; Simplified (KERNAL IRQ vector) version.
+;
+; Copyright (c)2008-2010 Cat's Eye Technologies.  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
+;    notices, this list of conditions and the following disclaimer.
+; 2. Redistributions in binary form must reproduce the above copyright
+;    notices, this list of conditions, and the following disclaimer in
+;    the documentation and/or other materials provided with the
+;    distribution.
+; 3. Neither the names of the copyright holders nor the names of their
+;    contributors may be used to endorse or promote products derived
+;    from this software without specific prior written permission. 
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; ``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 THE
+; COPYRIGHT HOLDERS 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.
+
+; ----- BEGIN ribos2.p65 -----
+
+; This is a simplified version of ribos.p65 which uses the Commodore 64
+; KERNAL's support for interrupt handling.  Whereas ribos.p65 could run
+; with the KERNAL completely disabled, ribos2.p65 relies on it.
+
+; I'll assume you've read through ribos.p65 at least once, and won't
+; say much about the code that's shared between the two programs.
+; Again, page references are from the 'Commodore 64 Programmer's
+; Reference Guide'.
+
+.org 0
+.word $C000
+.org $C000
+
+; ----- Constants -----
+
+; The CIA #1 chip.
+
+.alias cia1             $dc00        ; pp. 328-331
+.alias intr_ctrl        cia1+$d      ; "CIA Interrupt Control Register
+                                     ; (Read IRQs/Write Mask)"
+
+; The VIC-II chip.
+
+.alias vic              $d000        ; Appendix G:
+.alias vic_ctrl         vic+$11      ; "Y SCROLL MODE"
+.alias vic_raster       vic+$12      ; "RASTER"
+.alias vic_intr         vic+$19      ; "Interrupt Request's" (sic)
+.alias vic_intr_enable  vic+$1a      ; "Interrupt Request MASKS"
+.alias border_color     vic+$20      ; "BORDER COLOR"
+
+; The address at which the IRQ vector is stored.
+
+.alias cinv             $0314        ; p. 319, "Vector: Hardware
+                                     ; IRQ Interrupt"
+
+; ----- Main Routine -----
+
+; This routine is intended to be called by the user (by, e.g., SYS 49152).
+; It installs the raster interrupt handler and returns to the caller.
+
+; Key to installing the interrupt handler is altering the IRQ service
+; vector.  As I learned from a careful reading of Sheldon Leemon's
+; "Mapping the Commodore 64", if we wish to leave the KERNAL intact and
+; operational, it gives us an easy way to do that.  Whenever it handles
+; an IRQ, it has to decide whether the IRQ was generated by a BRK
+; instruction, or some external device issuing an interrupt request.  In
+; either case, it jumps indirectly through its IRQ-handling vector.  We
+; can simply modify this vector (at $314) to point to our routine.  In
+; fact, this is the "CINV" vector, which may already be familiar to you
+; if you have done any modest amount of C64 machine language programming;
+; it is normally called every 1/60 of a second due to the interrupt
+; request generated by CIA#1 Timer B.  Here we will simply be using it
+; to detect when a raster interrupt has occurred, as well.
+
+; First, disable interrupts before changing interrupt vectors.
+
+                sei
+
+; We obtain the address of the current IRQ service routine in CINV
+; and save it in the variable 'saved_irq_vec'.
+
+                lda cinv
+                sta saved_irq_vec
+                lda cinv+1
+                sta saved_irq_vec+1
+
+; We then store the address of our IRQ service routine in its place.
+
+                lda #<our_service_routine
+                sta cinv
+                lda #>our_service_routine
+                sta cinv+1
+
+; Now we must specify the raster line at which the interrupt gets called,
+; setting the ninth bit to zero.
+
+                lda scanline
+                sta vic_raster
+                lda vic_ctrl
+                and #%01111111
+                sta vic_ctrl
+
+; Then we enable the raster interrupt on the VIC-II chip.
+
+                lda #$01
+                sta vic_intr_enable
+
+; We read the interrupt control port of CIA #1 for good measure.
+
+                lda intr_ctrl
+
+; And we re-enable interrupts to resume normal operation -- plus our jazz.
+
+                cli
+
+; Finally, we return to the caller.
+
+                rts
+
+; ----- Raster Interrupt Service Routine ------
+
+our_service_routine:
+
+; First, we check to see if the current interrupt was caused by the raster.
+
+                lda vic_intr
+                sta vic_intr
+                and #$01
+                cmp #$01
+                beq we_handle_it
+
+; If the interrupt was not caused by the raster, we continue execution as
+; normal, with the existing interrupt service routine.
+
+                jmp (saved_irq_vec)
+
+we_handle_it:
+
+; If we got here, the interrupt was caused by the raster, so we do our thing.
+
+                lda border_color
+                eor #$ff
+                sta border_color
+
+; Now, we make the interrupt trigger on the other scan line next time.
+
+                lda scanline
+                eor #$ff
+                sta scanline
+                sta vic_raster
+ 
+; Return to normal operation.  If we simply continue with the standard
+; interrupt service routine by jumping through saved_irq_req, we will
+; confuse it a bit, as it expects to be called 60 times per second, and
+; continuing it here would make it occur more frequently.  The result
+; would be the cursor blinking more frequently and the time of day clock
+; running fast.
+
+; So, we issue a plain return from interrupt (RTI) here.  But first, we
+; must make sure that the state of the system is back to the way it was
+; when the interrupt service routine was called.  Since it can be called
+; from anywhere, and since the code that was interrupted likely cares
+; deeply about the values in its registers, the KERNAL routine which
+; dispatches through CINV first carefully saves the contents of the
+; registers on the stack.  We must be equally careful about restoring
+; those values before switching back to that interrupted code.
+
+                pla
+                tay
+                pla
+                tax
+                pla
+
+                rti
+
+
+; ----- Variables -----
+
+; 'scanline' stores the raster line that we want the interrupt to trigger
+; on; it gets loaded into the VIC-II's 'vic_raster' register.  
+
+scanline: .byte %01010101
+
+; We also reserve space to store the address of the interrupt service
+; routine that we are replacing in the IRQ vector, so that we can transfer
+; control to it at the end of our routine.
+
+.space saved_irq_vec 2
+
+; ----- END of ribos2.p65 -----

ribos/ribos2.prg

Binary file added.