From 42864bf12558e9399333e1e29f11e75ebcb9b278 Mon Sep 17 00:00:00 2001 From: Chris Pressey Date: Thu, 15 Mar 2018 10:56:09 +0000 Subject: [PATCH] Add SixtyPical translations of Ribos and "The PETulant Cursor". --- HISTORY.md | 2 + eg/c64/README.md | 14 ++ eg/c64/petulant/build.sh | 9 + eg/c64/petulant/petulant-60p.prg | Bin 0 -> 48 bytes eg/c64/petulant/petulant.60p | 54 ++++++ eg/c64/petulant/petulant.p65 | 52 ++++++ eg/c64/petulant/petulant.prg | 1 + eg/c64/petulant/readme.txt | 32 ++++ eg/c64/ribos/build.sh | 9 + eg/c64/ribos/readme.txt | 79 +++++++++ eg/c64/ribos/ribos.p65 | 291 +++++++++++++++++++++++++++++++ eg/c64/ribos/ribos.png | Bin 0 -> 5863 bytes eg/c64/ribos/ribos.prg | Bin 0 -> 142 bytes eg/c64/ribos/ribos2-60p.prg | Bin 0 -> 91 bytes eg/c64/ribos/ribos2.60p | 103 +++++++++++ eg/c64/ribos/ribos2.p65 | 179 +++++++++++++++++++ eg/c64/ribos/ribos2.prg | Bin 0 -> 90 bytes 17 files changed, 825 insertions(+) create mode 100644 eg/c64/README.md create mode 100755 eg/c64/petulant/build.sh create mode 100644 eg/c64/petulant/petulant-60p.prg create mode 100644 eg/c64/petulant/petulant.60p create mode 100644 eg/c64/petulant/petulant.p65 create mode 100644 eg/c64/petulant/petulant.prg create mode 100644 eg/c64/petulant/readme.txt create mode 100755 eg/c64/ribos/build.sh create mode 100644 eg/c64/ribos/readme.txt create mode 100644 eg/c64/ribos/ribos.p65 create mode 100644 eg/c64/ribos/ribos.png create mode 100644 eg/c64/ribos/ribos.prg create mode 100644 eg/c64/ribos/ribos2-60p.prg create mode 100644 eg/c64/ribos/ribos2.60p create mode 100644 eg/c64/ribos/ribos2.p65 create mode 100644 eg/c64/ribos/ribos2.prg diff --git a/HISTORY.md b/HISTORY.md index 980b77b..e89461d 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -11,6 +11,8 @@ History of SixtyPical insisting that `goto` only appears in it. * Fixed bug when `--prelude` option was missing. * Fixed bug when reporting line numbers of scanner-level syntax errors. +* Translated the small demo project Ribos and "The PETulant Cursor" + to SixtyPical and added them to the `eg/c64/` section of the repo. 0.13 ---- diff --git a/eg/c64/README.md b/eg/c64/README.md new file mode 100644 index 0000000..35f8fb2 --- /dev/null +++ b/eg/c64/README.md @@ -0,0 +1,14 @@ +This directory contains SixtyPical example programs +specifically for the Commodore 64. + +Subdirectories of note: + +* [demo-game](demo-game/): a little game-like program written as a + "can we write something you'd see in practice?" test case for SixtyPical. +* [ribos](ribos/): a well-commented example of a C64 raster interrupt + routine. Originally written with the P65 assembler (now Ophis). + The second version of it has been translated to SixtyPical. +* [petulant](petulant/) -- "The PETulant Cursor", a tiny (44 bytes) + "display hack". Originally written in the late 80's. Rewritten with + the P65 assembler (now Ophis) and re-released April 1, 2008 (a + hint as to its nature). Translated to SixtyPical, it's 48 bytes. diff --git a/eg/c64/petulant/build.sh b/eg/c64/petulant/build.sh new file mode 100755 index 0000000..e7af197 --- /dev/null +++ b/eg/c64/petulant/build.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +sixtypical --output-format=prg --origin=0x02a7 petulant.60p > petulant-60p.prg +if [ "x$COMPARE" != "x" ]; then + dcc6502 petulant.prg > petulant.prg.disasm.txt + dcc6502 petulant-60p.prg > petulant-60p.prg.disasm.txt + paste petulant.prg.disasm.txt petulant-60p.prg.disasm.txt | pr -t -e24 + rm -f *.disasm.txt +fi diff --git a/eg/c64/petulant/petulant-60p.prg b/eg/c64/petulant/petulant-60p.prg new file mode 100644 index 0000000000000000000000000000000000000000..2ce000006345020d4891f08c96505bd8e1fee85c GIT binary patch literal 48 zcmV-00MGxY0(h+y1C7-JtrY`})&i-(jT8f^0*w^|SYWNs0PqH_h5}5^0<9s?jUdo$ G)dFC_U=s=e literal 0 HcmV?d00001 diff --git a/eg/c64/petulant/petulant.60p b/eg/c64/petulant/petulant.60p new file mode 100644 index 0000000..be818e1 --- /dev/null +++ b/eg/c64/petulant/petulant.60p @@ -0,0 +1,54 @@ +// petulant.60p - 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 +// Rewritten in SixtyPical in March 2018 +// This work is part of the public domain. + +// ----- Types ----- + +typedef routine + inputs border, blnon, color, background + outputs border + trashes a, z, n + irq_handler + +// ----- Addresses ----- + +vector irq_handler cinv @ $314 // hw irq interrupt, 60x per second + +byte blnon @ $cf // was last cursor blink on or off? +byte color @ $286 // current foreground colour for text + +byte border @ $d020 // colour of border of the screen +byte background @ $d021 // colour of background of the screen + +// ----- Variables ----- + +vector irq_handler save_cinv + +// ----- Interrupt Handler ----- + +define our_cinv irq_handler +{ + ld a, blnon + if not z { + ld a, color + } else { + ld a, background + } + st a, border + goto save_cinv +} + +// ----- Main Program ----- + +define main routine + inputs cinv + outputs cinv, save_cinv + trashes a, n, z +{ + with interrupts off { + copy cinv, save_cinv + copy our_cinv, cinv + } +} diff --git a/eg/c64/petulant/petulant.p65 b/eg/c64/petulant/petulant.p65 new file mode 100644 index 0000000..6fec4dd --- /dev/null +++ b/eg/c64/petulant/petulant.p65 @@ -0,0 +1,52 @@ +; 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 + 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 ----- diff --git a/eg/c64/petulant/petulant.prg b/eg/c64/petulant/petulant.prg new file mode 100644 index 0000000..3ecb862 --- /dev/null +++ b/eg/c64/petulant/petulant.prg @@ -0,0 +1 @@ +xX`L!Ѝ l \ No newline at end of file diff --git a/eg/c64/petulant/readme.txt b/eg/c64/petulant/readme.txt new file mode 100644 index 0000000..6ad011d --- /dev/null +++ b/eg/c64/petulant/readme.txt @@ -0,0 +1,32 @@ +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 diff --git a/eg/c64/ribos/build.sh b/eg/c64/ribos/build.sh new file mode 100755 index 0000000..a6c5db3 --- /dev/null +++ b/eg/c64/ribos/build.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +sixtypical --output-format=prg --origin=0xc000 ribos2.60p > ribos2-60p.prg +if [ "x$COMPARE" != "x" ]; then + dcc6502 ribos2.prg > ribos2.prg.disasm.txt + dcc6502 ribos2-60p.prg > ribos2-60p.prg.disasm.txt + paste ribos2.prg.disasm.txt ribos2-60p.prg.disasm.txt | pr -t -e24 + rm -f *.disasm.txt +fi diff --git a/eg/c64/ribos/readme.txt b/eg/c64/ribos/readme.txt new file mode 100644 index 0000000..65af99c --- /dev/null +++ b/eg/c64/ribos/readme.txt @@ -0,0 +1,79 @@ +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 diff --git a/eg/c64/ribos/ribos.p65 b/eg/c64/ribos/ribos.p65 new file mode 100644 index 0000000..297aea3 --- /dev/null +++ b/eg/c64/ribos/ribos.p65 @@ -0,0 +1,291 @@ +; 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. +; By Chris Pressey, Cat's Eye Technologies. +; This work has been placed in the public domain. + +; ----- 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+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 ----- diff --git a/eg/c64/ribos/ribos.png b/eg/c64/ribos/ribos.png new file mode 100644 index 0000000000000000000000000000000000000000..21a9c50318f2d6fc9335a0b3af5c3f1131457348 GIT binary patch literal 5863 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 literal 0 HcmV?d00001 diff --git a/eg/c64/ribos/ribos2-60p.prg b/eg/c64/ribos/ribos2-60p.prg new file mode 100644 index 0000000000000000000000000000000000000000..c11bfc54826dab52b5597eb1755b930293dd4fe5 GIT binary patch literal 91 zcmZQLP_b5oxi|8_T2bcSr~@nYdqtR69_STiUK??sSLni8!3&!8y@D53GWJScSj&4S sB4MrMgour_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 ----- diff --git a/eg/c64/ribos/ribos2.prg b/eg/c64/ribos/ribos2.prg new file mode 100644 index 0000000000000000000000000000000000000000..a35625f6ca79adb01046abec1932c610d564839d GIT binary patch literal 90 zcmZQLP_b5oxi{j#T2bcS$O9|&dqtR69_STiUK@U(SLni8!3&!8y@D53GWJScSj&4S qB4MrMg