Hallo!
Da jeder einen anderen Kenntnisstand hat, will ich einfach einmal von vorne anfangen
Das RAM unter dem OS kann man genauso wie das RAM unterm BASIC einfach über PORTB einschalten, indem man den ROM-Chip abschaltet.
Es ist somit keinerlei Hexenwerk das RAM unterm OS zu nutzen...
Jedoch wird der ATARI sich aufhängen, wenn man einfach das OS abschaltet, da der ATARI einen Non Maskable Interrupt (NMI) und einen Maskable Interrupt (IRQ) besitzt und diese ohne dem OS ins Nirvana verzweigen und somit den ATARI abstürzen lassen.
Was sind das für Interrupts?
Der NMI kommt ausschließlich vom ANTIC. Der ANTIC signalisiert über NMIEN, ob es durch einen VBI oder DLI ausgelöst wurde.
Der IRQ kommt vom POKEY und vom PIA. Man kann über IRQST des POKEY oder PACTL des PIA auslesen aus welchem Grund ein IRQ ausgelöst wurde.
Der POKEY ist u.a. für die Tastatur zuständig. Ein Tastendruck löst somit den IRQ aus.
Den IRQ kann man einfach per CPU-Flag unterdrücken. "SEI" lässt den IRQ unterdrücken. Mir "CLI" wird dieser wieder berücksichtigt.
Der NMI lässt sich nicht ausschalten... zu mindestens nicht CPU-seitig. Hier kann man aber dem ANTIC über NMIRES mitteilen, dass man keine IRQs wünscht.
Sind die beide IRQs abgeschaltet, kann man den RAM unterm ROM nutzen...
Nun ja, jetzt funktioniert aber nicht mehr viel. Keine Tastatureingaben, kein VBI und kein DLI. Für Spiele ist der VBI und DLI schon sehr wichtig. Und auch die Tastatur wird immer Mal wieder benötigt.
Wichtig zu wissen: Funktionstasten und Joystick benötigen keinen IRQ und funktionieren weiterhin.
Woher weiß eigentlich die CPU, was sie machen soll, wenn ein NMI oder IRQ auftritt?
An den Speicherstellen $FFFA/$FFFB steht die Sprungmarke für den NMI. An $FFFE/$FFFF die Sprungmarke für den IRQ. $FFFC/$FFFD ist beim ATARI 400/800 für den Reset zuständig.
Diese weisen beim eingeschaltetem OS auf die entsprechenden ROM-Routinen. Ist das OS abgeschaltet verweisen diese ins Nirvana.
Es gibt ein Assemblerlisting vom TurboBasic, wie dort mit dem Problem umgegangen wird. Es ist eigentlich sehr elegant.
TB hat zwei eigene Routinen für IRQ und NMI, die im Prinzip den Stack ein wenig manipulieren, damit das ROM zu der eigenen Routine zurück kehrt. Schaltet das OS ein, springt zur gewünschten ROM-Routine, schaltet das OS wieder aus und beendet den Interrupt sozusagen.
Wenn man dauerhaft den RAM unterm OS nutzen möchte, muss man entweder die TB-Routine nutzen, oder sich etwas Eigenes basteln.
Für mein Spiel benötige ich die meisten Schattenregister nicht, sondern nur ein paar (für mich) wichtige Funktionen des System-VBI. Deshalb habe ich mir aus dem OS die interessanten Funktionen in eine eigene Routine kopiert:
Code: Alles auswählen
; --- MADS Assembler-Routine
.PROC MyNMI
BIT NMIST ; Prüfen ob ein DLI ausgelöst wurde
BPL @+
JMP (VDSLST) ; Wenn ja, dann ab in die DLI Routine
@ PHR
INC RTCLOK+2 ; Systemtimer weiterlaufen lassen
BNE @+
INC RTCLOK+1
BNE @+
INC RTCLOK
@ LDA #$00
STA SRTIMR
MVA CHBAS CHBASE ; Zeichensatz Schattenregister umkopieren
MWA SDLSTL DLISTL ; DLI-Schattenregister umkopieren
MWA SDMCTL DMACTL ; DMA-Kontroll-Schattenregister umkopieren
LDA PORTA ; Joystick Port A ist Stick 0 & 1
LSR ; Diese trennen und in die passenden
LSR ; Schattenregister bringen
LSR
LSR
STA STICK1
LDA PORTA
AND #$0F
STA STICK0
LDA TRIG0 ; Feuerknopf ebenfalls im jeweiligen
STA STRIG0 ; Schattenregister kopieren
LDA TRIG1
STA STRIG1
LDX #$03 ; Die einzelnen Paddles in die Schattenregister
@ LDA POT0,X ; umkopieren
STA PADDL0,X
DEX
BPL @-
PLR
RTI
.ENDP
Welchen Vorteil bringt mir dieses Vorgehen? Ich spare ein wenig Rechenzeit im VBI und kann damit mehr eigenen Programmcode im "nichtsichtbaren" Bereich ausführen lassen.
Den IRQ brauche ich größtenteils nicht und kann diesen per SEI abschalten. Aber sollte man doch z.B. die Tastatur nutzen wollen, kann man einfach die Routine des TurboBasics nehmen (leicht abgewandelt):
Code: Alles auswählen
; --- MADS Assembler-Routine
.PROC MyIRQ
PHA ; Akku sichern
LDA #>Exit ; Eigene Exit-Routine in den Stack schreiben
PHA
LDA #<Exit
PHA
PHP ; Prozessorstatus auf den Stack (für RTI)
INC PORTB ; OS-ROM anschalten (wichtig OS-ROM muss vorher aus sein!)
JMP (VIMIRQ) ; Ins Betriebssystem springen
Exit DEC PORTB ; OS-ROM wieder abschalten
PLA ; Akku holen
RTI ; und zurück
.ENDP
Um die Sprungadressen an $FFFA-$FFFF sicher setzen zu können, sollte man vorher kurz die Interrupts abschalten:
Code: Alles auswählen
; --- MADS Assembler-Routine
SEI ; IRQ und VBI deaktivieren
LDA #0
STA NMIEN
LDA PORTB ; OS-ROM und BASIC abschalten
AND #%11111100
ORA #%00000010 ; bit 0==0 OS-RAM bit 1==1 BASIC-RAM
STA PORTB
LDX #0 ; Neue IRQ-Sprungadressen setzen
POINTER_LOOP LDA NEWPOINTER,X
STA $FFFA,X
INX
CPX #6
BNE POINTER_LOOP
LDA #NMIEN_VBI ; VBI und IRQ wieder aktivieren
STA NMIEN
CLI
...
...
NEWPOINTER .WORD MyNMI
.WORD 0
.WORD MyIRQ
.ENDP
Jetzt kann man gefahrlos das OS dauerhaft im Programm abschalten, um den RAM nutzen zu können.
Je nachdem ist es ggf. sinnvoll den Zeichensatz aus dem ROM zu kopieren, sofern man keinen eigenen hat.
Grüße
Janko