It sounds like you have the mode split working OK, but the OS is configured for Mode 5 when displaying characters. So the simplest thing would be to explicitly select Mode 4 instead, and perform your mode split exactly as you are now - and then, calls to OSWRCH should display Mode 4 characters correctly. I'm assuming you don't need any Mode 5 text at all, right?
The mechanics of the mode split are something like this. I'm going to describe a method which uses 'legal' methods, i.e. work alongside the OS without problems, so you can still do character printing and input via the normal calls.
Hook into the VSync event:
- put the address of your handler in &220/&221
- enable the VSync event with *fx 14,4
In the VSync event handler:
- check if it's a VSync event, like this:
Code:
CMP #4
BNE notvsync
<handle vsync here>
- set up the Video ULA (&FE20/&FE21) for the top screen mode.
- set an unused timer (e.g. User VIA T2 at &FE68) to interrupt a certain time later. Do that like this:
Code:
LDA #time MOD 256 ; set timer low byte
STA &FE68
LDA #time DIV 256 ; set timer high byte
STA &FE69
As a rough guide, if the screen is positioned with *TV 0,1, the value of time is (5 + screen character row) * 512. There'll be a fair amount of wobble if you're doing it 'legally' like this, due to the latency which arises from the OS's interrupt handler running with interrupts disabled, and not always letting the split mode interrupt get serviced immediately. I recommend, when trying to get the value right, have it change the background colour, so you can clearly see where the split is. Also leave a blank buffer of at least 3 or 4 pixel lines, to hide any wobble.
Enable and hook into the User VIA T2 interrupt:
- Enable the interrupt, like this:
Code:
LDA #&A0
STA &FE6E
- Claim the IRQ1V, like this:
Code:
SEI
LDA #irqhandler MOD 256
STA &204
LDA #irqhandler DIV 256
STA &205
CLI
- Check for the timer interrupt in irqhandler, like this:
Code:
LDA &FE6D
AND #&20 ; check T2 flag
BNE nottimer
STA &FE6D ; acknowledge interrupt
..
- Then perform palette and mode changes for bottom screen mode (&FE20/&FE21), and finally JMP (oldirq1v) which should contain the previous contents of the IRQ1V.
As long as you touch only A (not X or Y), there's no need to preserve any registers or flags on the stack, because the 6502 has already pushed the flags to the stack, and the OS handler stub has already saved A in &FC.
Also, somewhere on this forum, I
did post some sample code for doing pretty much this, although it was not an OS-friendly method, so it might not be so useful.