Subject: Re: [stella] Has anyone tried this before?|
From: Bad Panda Bear <badpandabear@xxxxxxxxxx>
Date: Fri, 06 Feb 2004 23:25:28 -0800
After I saw Thomas' lxa_test program, I started thinking about ways of playing with code executing in RAM. One idea I had was to use a 2600 to dump the ROM of a catridge. The idea is:
1) Load a fully functioning display kernel into RAM.
2) Remove the super charger/catridge from the 2600.
3) Insert the cartridge you wish to dump
4) Have the RAM code dump the cartridge content. I was thinking of doing this by sound (in a format similar to what the super charger uses), or if that doesn't work trying to dump the data over the joystick port over to a PC (or maybe an atari 8 bit).
To experiment with this, I created the attached program. It starts with
a red screen (note PAL colors are different). When select is pressed, it
loads code in to RAM and the screen changes to green to indicate that
the RAM code has control. When select is pressed again it reads from a
byte in ROM and then sets the background color to that byte. I've tried
this and I've found that I can indeed remove the supercharger from the
2600 and then get different colors from different cartridges. This works on all my consoles, including my 7800. BUT, sometimes when I insert a cartridge or remove a cartridgein a slow or awkward way the RAM
code seems to loose control and the screen starts to roll. I think that somehow a reset interrupt is being generated, because one time when I inserted SCSIcide the screen jumped to the SCSIcide title screen.
I think I'll continue with this expeirment with a bit, just as an excuse to learn how to program sound on the 2600. But I was wondering if anyone else had tried this before, and what were the results? Also, if this does work out, does anyone think this would be usefull? I tend to think it isn't very usefull because most ROMs are available on the internet anyway.
Archives (includes files) at http://www.biglist.com/lists/stella/archives/ Unsub & more at http://www.biglist.com/lists/stella/
;; RomDumper.asm ;; This is an experiment in runing code in RAM to dump ROM from different catridges ;; Created 1-31-2004 by Dusty Reichwein with code borrowed from the following: ;; Andrew Davie: ;; Initialization code from the AtariAge "Atari 2600 Programming For Newbies" forum, Session 12 ;; Kirk Isreal: ;; 2600 101 Tutorial ;; And lots of inspiration from the Stella Mailing list PROCESSOR 6502 INCLUDE vcs.h ;;;;;;;;;;;;;;;;;;;;;; constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; NTSC_VBlankTimer = 44 NTSC_VisibleLineCount = 192 NTSC_OverscanCount = 30 PAL_VBlankTimer = 54 PAL_VisibleLineCount = 228 PAL_OverscanCount = 36 IFCONST PAL VBlankTimer = PAL_VBlankTimer VisibleLineCount = PAL_VisibleLineCount OverscanCount = PAL_OverscanCount ENDIF IFCONST NTSC VBlankTimer = NTSC_VBlankTimer VisibleLineCount = NTSC_VisibleLineCount OverscanCount = NTSC_OverscanCount ENDIF ;;; The Atari 2600 RAM area. SEG.U VARS ORG $80 RAM ;; Last state of the select switch. This is used to determine when ;; it has been released LastSelectState DS 1 ;; Background color to use when RAM code is running BkgColor DS 1 ;; I don't actually use this as a variable, but as a pointer where ;; variables end and the RAM code begins StartOfCodeInRAM DS 1 ;;; Start of 4K rom space SEG ROM ORG $F000 ;;; Where code starts executing Start ;;; Initialization stuff, taken from Andrew Davie's code in the AtariAge ;;; "Atari 2600 Programming For Newbies" forum, Session 12 ; CLEARS ALL VARIABLES, STACK ; INIT STACK POINTER ; ALSO CLEARS TIA REGISTERS ; DOES THIS BY "WRAPPING" THE STACK - UNUSUAL ; USES 9 BYTES TOTAL FOR CLEARING STACK, MEMORY ; STACK POINTER NOW $FF, A=X==0 ldx #0 txs pha ; BEST WAY TO GET SP=$FF, X=0 txa Clear pha dex bne Clear ;;; Init variables ;; Set LastSelectState to make it look like select is not pressed lda #02 sta LastSelectState ;; Use a pretty green for the default background when the code in ;; RAM is running lda #$DA STA BkgColor ;;; Start of a screen display FrameStart jsr StartVerticalBlank jsr VerticalBlankCalc jsr ScanlineKernel jsr Overscan jmp FrameStart ;;; Does 3 linesof VSYNC and sets timer at the start of a frame StartVerticalBlank SUBROUTINE lda #2 sta VSYNC sta WSYNC sta WSYNC sta WSYNC lda #VBlankTimer sta TIM64T lda #0 sta VSYNC rts ;;; Performs game logic during vertical blank VerticalBlankCalc SUBROUTINE ;; We will load and run the RAM code when ;; the select key is released ;; Check for select to read from ROM ;; Get current swith state ldy SWCHB ; (3,22) ;; See if the LastSwitchState was pressed. ;; Note the D1 bit is 0 when the switch is pressed lda #%00000010 bit LastSelectState bne .SetLastState ;; It used to be pressed, now see if it has been released sty LastSelectState bit LastSelectState beq .NoRAMLoad ;; Now load the RAM code into RAM ;; If the RAM code gets large enough, it could erase the stack, ;; but that's okay because once we start executing in RAM we don't ;; come back. ldy #(SizeOfRAMCode - 1) .RAMLoad lda #RAMCode,Y sta #StartOfCodeInRAM,Y dey cpy #$FF bne .RAMLoad ;; The RAMCode is loaded, give it control jmp StartOfCodeInRAM .SetLastState sty LastSelectState .NoRAMLoad ;; Set screen color, this is sample code ;; to allow the template to compile and do something lda #$40 sta COLUBK ;; Now wait for the end of vertical blank .loop lda INTIM bne .loop sta WSYNC sta VBLANK ;;; Note A will be 0, so this turns of VBLANK rts ;;; Draws the visible scanlines ScanlineKernel SUBROUTINE ;; Draw scanlines here. ;; Since the only graphics are the background color, ;; all this does is make sure the right # of WSYNCs are done ldx #VisibleLineCount .loop sta WSYNC dex bne .loop rts ;;; Set VBlank for overscan Overscan SUBROUTINE lda #2 sta VBLANK ldy #OverscanCount .loop sta WSYNC dey bne .loop rts ;;; This is the code to run in RAM, it is much like the ROM code except ;;; no subroutines, as I don't want the stack to overide my program! ;;; (Note this is not really a subroutine, I just used SUBROUTINE ;;; to get local symbols) ;;; The comments in parenthesis have the # of bytes for the instructions ;;; and the total bytes so far. RAMCode SUBROUTINE ;; 3 Lines of VSYNC, + setting the timer for the vertical blank section lda #2 ; (2,2) sta VSYNC ; (2,4) sta WSYNC ; (2,6) sta WSYNC ; (2,8) sta WSYNC ; (2,10) lda #VBlankTimer ; (2,12) sta TIM64T ; (3,15) lda #0 ; (2,17) sta VSYNC ; (2,19) ;; Check for select to read from ROM ;; Get current swith state ldy SWCHB ; (3,22) ;; See if the LastSwitchState was pressed. ;; Note the D1 bit is 0 when the switch is pressed lda #%00000010 ; (2,24) bit LastSelectState ; (2,26) bne .SetLastState ; (2,28) ;; It used to be pressed, now see if it has been released sty LastSelectState ; (2,30) bit LastSelectState ; (2,32) beq .NoChange ; (2,34) ;; The select has been released ;; Use the test byte lda TestByte ; (3,37) sta BkgColor ; (2,39) .SetLastState ;; Note this can be executed twice ;; when the switch is released, but that's okay ;; because skipping it would require more space sty LastSelectState ; (2,41) .NoChange lda BkgColor ; (2,43) sta COLUBK ; (2,45) .loop1 lda INTIM ; (3,48) bne .loop1 ; (2,50) sta WSYNC ; (2,52) ;;; Note A will be 0, so this turns of VBLANK sta VBLANK ; (2,54) ;; Draw scanlines here. ;; Since the only graphics are the background color, ;; all this does is make sure the right # of WSYNCs are done ldx #VisibleLineCount ; (2,56) .loop2 sta WSYNC ; (2,58) dex ; (1,59) bne .loop2 ; (2,61) ;; Overscan lda #2 ; (2,63) sta VBLANK ; (2,65) ldy #OverscanCount ; (2,67) .loop3 sta WSYNC ; (2,69) dey ; (1,70) bne .loop3 ; (2,72) JMP StartOfCodeInRAM ; (3,75) EndOfRAMCode SizeOfRAMCode = EndOfRAMCode - RAMCode ;; This is a special place in memory I'll look in to get the screen color ;; Each cart should have a different value here so I can test if I'm ;; actually reading from the new cart ;; I Picked $92 because AFAIK there's no 6507 opcode that matches it ;; This was to minimize the chances that another cart would have the ;; same color TestByte .byte #$92 ;;; Interrupt vector table ORG $FFFA .word Start ;; NMI .word Start ;; Reset .word Start ;; IRQ
Description: Binary data
Description: Binary data