Jump to content
IGNORED

Bankswitching with OS disabled, not possible?


Recommended Posts

I am trying to write some code that should run on a 130XE (and best case, other models with >=128kb RAM).

I want full access to as much RAM as possible, so I run with PORTB ($d301) set to $F2 normally, that is BASIC off, OS off etc.

That works fine, I can access all RAM except for $d000-$d7ff

Now I am incorporating bankswitching as well, to gain access to the extra 64kb on the 130XE.

The really strange thing is, I can't get the bankswitching to work without setting the lowest bit of PORTB, that is switching in OS stuff that eat up $c000-$ffff essentially.

 

It makes no sense to me, in my test program I run with interrupts disabled (SEI) so there is no way that the CPU can be running code "without my knowledge", yet it still seems like it needs to have access to the OS for the bankswitching to work. WTF? What am I doing wrong?

 

For example, this does NOT work, the second write to $4000 just overwrites the first.

 

.pc = $3000 "Code"
sei
lda #$a2+0*4
sta PORTB
lda #$55
sta $4000
lda #$a2+1*4
sta PORTB
lda #$77
sta $4000

 

However the following works:

.pc = $3000 "Code"
sei
lda #$a3+0*4
sta PORTB
lda #$55
sta $4000
lda #$a3+1*4
sta PORTB
lda #$77
sta $4000

 

???

Link to comment
Share on other sites

It should work, OS in or out makes no difference to low memory Ram banking, it only affects Self-Test, ie if OS is out Self-Test Rom also gets swapped out.

 

Also it's a good idea to leave bit 6 set to it's default state of 1, some Ram expansions >128K use it for bank selection.

 

Additionally NMIs can still fire off while you have the OS switched out, a good idea is to either disable via NMIEN or have a check to ensure one isn't about to occur.

 

The only reason I can see for your code failing is that the Assembler you're using might be doing the maths for your bank number in a way you don't expect. Some assemblers simply process the maths from left to right without giving precedence to the types of operations.

 

e.g. with Atari's Asm/Ed cart:

 

LDA # 4+1*5

will generate decimal 25, not 9 as you'd otherwise expect.

Edited by Rybags
Link to comment
Share on other sites

  • 1 year later...

Various ways - you could provide a replacement IRQ.

Or you could just read keys manually from the Pokey registers. The keycode register retains the previous keypress so on it's own isn't the full solution.

SKSTAT has the key-down status bit which you should take as prompt to read the keycode.

Debounce can be an issue (one keypress registering 2-3 times) - generally you'd do what the OS does, ie remember previous keypress and maintain a 3 frame timer when keyup occurs. Then ignore any keydown that is the same as the previous for that period.

  • Like 1
Link to comment
Share on other sites

You could use a wrapper so the IRQ and NMI still use the OS - something like this:

	.proc NMIHand
	bit nmist
	bpl NotDLI
	jmp (vdslst)
NotDLI
	pha
	txa
	pha
	lda #> [ExitInt.NMI]
	pha
	lda #< [ExitInt.NMI]
	pha
	tsx
	lda $0105,x ; get pushed flags
	pha
	cld
	pha
	txa
	pha
	tya
	pha
	inc portb ; enable OS
	sta nmires
	jmp (vvblki)
	.endp




	.proc IRQHand
	pha
	lda #> [ExitInt.IRQ]
	pha
	lda #< [ExitInt.IRQ]
	pha
	php
	inc portb ; enable OS
	jmp (vimirq)
	.endp



	.proc ExitInt
NMI
	pla
	tax
IRQ
	dec portb
	rti
	.endp




	.proc Ciov
	inc portb ; re-enable OS
	jsr $e456
	php ; save flags
	dec portb ; disable OS again
	plp
	rts
	.endp



	.proc Initialize
	lda #0
	sta nmien ; turn off NMI
	sei ; and IRQ
	lda $d301
	and #$fe ; switch out ROM
	sta $d301
	lda #< IntHand
	sta $fffa
	lda #> IntHand
	sta $fffb
	lda #< IRQHand
	sta $fffe
	lda #> IRQHand
	sta $ffff
	lda #96 ; re-enable interrupts
	sta nmien
	cli
	rts
	.endp

Obviously you need to manually re-enable the OS when calling it (as does the CIOV routine). The above method is exactly how Turbo Basic XL works.

Link to comment
Share on other sites

You also need the OS VBlank, Stage 2 especially, for the key processing to function properly.

Without it, pressing the same key twice in a row won't work - the VBlank takes care of repeat and debounce - the timer method I mentioned earlier is used and the default IRQ uses it's value to decide if a keypress should be ignored.

 

I'd agree with the wrapper method - just point the IRQ+NMIs to your routine in low memory, but you need to do VBlank as well as IRQ.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...