MODULE; RAMXL.ACT
;-------------------------------------
; Copyright 1985 by Daniel L. Moore.
; RAMXL may not be sold, but may be
; freely copied and distributed.
;-------------------------------------
; Last modified on 03/30/85
;-------------------------------------

;   Support routines for the "extra" 
; 14K of RAM in XLs that is located
; under the OS ROM.
;   When an interrupt occurs and the OS
; is banked out, the RAMXL will bank
; the OS in, and then call the ROM OX
; interrupt handler.  When control
; returns from the ROM OS, the OS is 
; banked out, and control is returned
; to the original program.

;   Only the NMI and IRQ vectors are  
; supported, since the XL hardware banks
; the OS ROM in automatically when a 
; chip reset occurs (the RESET button).

DEFINE  INT_VECTOR = "$FFF0"

CARD    NMI_Vector = $FFFA,
        RES_Vector = $FFFC,
        IRQ_Vector = $FFFE,
        Return_Addr 

BYTE    PortB      = $D301,  
        NMIEN      = $D40E,
        X_Storage

PROC OS_In=*() ; ROM OS resident
 ~[$AD PortB    ; LDA PortB
  $09 $01      ; ORA #$01  toggle OS bit to ON
  $8D PortB    ; STA PortB
  $60]         ; RTS

PROC OS_Out=*(); ROM OS not resident
 ~[$AD PortB    ; LDA PortB
  $29 $FE      ; AND #$FE  toggle OS bit to OFF
  $8D PortB    ; STA PortB
  $60]         ; RTS

PROC JMP_Vector=*()
 ~[$4C $FFFF]   ; JMP $FFFF  

PROC Handle_Interrupt=*()             
; Handle the interrupt that just occured.

 ~[$8E X_Storage    ; STX X_Storage
  $AA              ; TAX        A=the interrupt number
  $20 OS_In        ; JSR OS_In 

; Get the address of the desired interrupt routine
  $BD INT_VECTOR   ; LDA INT_VECTOR,X 
  $8D JMP_Vector+1 ; STA JMP_VECTOR
  $BD INT_VECTOR+1 ; LDA INT_VECTOR,X
  $8D JMP_Vector+2 ; STA JMP_VECTOR+1

; Setup the stack to fake an interrupt and call
; the OS ROM interrupt code.

; First the return address
  $AD Return_Addr+1; LDA Return_Addr+1
  $48              ; PHA
  $AD Return_Addr  ; LDA Return_Addr
  $48              ; PHA
; Then the proccessor status register
  $58              ; CLI      enable IRQs, for Stage 2 VBLANK
  $08              ; PHP 
  
  $4C JMP_Vector]  ; JMP JMP_Vector

PROC Return_Here=*()
; Return here after the ROM OS interrupt code runs
; Bank the OS out, the return to the
; original program.
 ~[$20 OS_Out       ; JSR OS_Out
  $AE X_Storage    ; LDX X_Storage
  $68              ; PLA    from NMI.Handler or IRQ.Handler
  $40]             ; RTI 

PROC NMI_Handler=*()
; Handle NMIs that occur while the OS is
; banked out. Save the A reg, then get 
; the vector number and call Handle_Interrupt.
 ~[$48              ; PHA
  $A9 $0A          ; LDA #$0A
  $4C Handle_Interrupt]; JMP Handle_Interrrupt

PROC IRQ_Handler=*()
 ~[$48              ; PHA
  $A9 $0E          ; LDA #$0A
  $4C Handle_Interrupt]; JMP Handle_Interrrupt

;-------------------------------------
; End of actual interrupt code.
; All that is left is installing 
; the vectors to the routines.
;------------------------------------- 

PROC Install_CharSet()
; Copy the ROM char set at $E000 to $E3FF
; to the RAM bank, so that characters do
; not flicker when the RAM is accessed.
; If this is done, do not use the RAM
; from $E000 to $E3FF (57344 to 58367).
 BYTE POINTER where
 BYTE temp
 
 FOR where=$E000 TO $E3FF
 DO
  OS_In()
  temp=where^
  OS_Out()
  where^=temp
 OD
 OS_In()
RETURN

PROC Install_Interrupts()

 Return_Addr=Return_Here; Set the return address pointer

 NMIEN=0  ; Turn all NMI interrupts off.
 ~[$78]    ; SEI  Turn all IRQ interrupts off.

 OS_Out()

; Install the new interrupt routines
; vectors at $FFFA to $FFFF under the
; OS ROM.
 NMI_Vector = NMI_Handler
 IRQ_Vector = IRQ_Handler

 OS_In()

 ~[$58]    ; CLI  Turn IRQs back on.
 NMIEN=$40; Turn NMIs back on.

 Install_CharSet()
RETURN

;-------------------------------------
; Now the routine that lets you get to
; the RAM that is under the OS.
; There are actually 2 memory areas
; present: 
;    4K at $C000 to $CFFF, 49152 to 53247
;   10K at $D800 to $FFFF, 55296 to 65535
;
; The last 6 bytes of the 10K area are not
; usable, since that is where the interrupt
; routines are located.  Therefore do not
; use any RAM above $FFF9 (65529) or you
; will crash the system.
;------------------------------------- 

PROC MoveBlockXL(BYTE POINTER dest,source, CARD size)
; This is a version of MoveBlock that lets
; you use the extra RAM in XLs.

 OS_Out()
 FOR dest=dest TO dest+size
 DO
   dest^=source^ 
   source==+1
 OD
 OS_In()
RETURN

MODULE; For user.

Add new attachment

Only authorized users are allowed to upload new attachments.

List of attachments

Kind Attachment Name Size Version Date Modified Author Change note
pdf
ramxe.PDF 204.4 kB 1 20-Aug-2010 21:35 Carsten Strotmann
« This page (revision-3) was last changed on 07-Feb-2023 02:16 by Peter Dell  
G’day (anonymous guest) My Prefs
© 2010-2021 AtariWiki
All content in the Wiki is licensed under Creative Commons Share Alike License, unless otherwise noted.
JSPWiki v2.8.3