Re: [stella] Has anyone tried this before?

Subject: Re: [stella] Has anyone tried this before?
From: Bad Panda Bear <badpandabear@xxxxxxxxxx>
Date: Fri, 06 Feb 2004 23:25:28 -0800
DOH! I *knew* I'd forget the attachments!

Bad Panda Bear wrote:
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.

Dusty Reichwein


----------------------------------------------------------------------------------------------


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

Attachment: RomDumper_NTSC.bin
Description: Binary data

Attachment: RomDumper_PAL.bin
Description: Binary data

Current Thread