Turning off OS routines.

Discuss all aspects of programming here. From 8-bit through to modern architectures.
User avatar
sydney
Posts: 1987
Joined: Wed May 18, 2005 9:09 am
Location: Newcastle upon Tyne

Turning off OS routines.

Postby sydney » Wed Jan 11, 2017 2:11 pm

In a thread over at Retrosoftware SteveO asked the following:
SteveO wrote:I seem to remember you can wring slightly more speed out of the Beeb for games by turning off some routine tasks undertaken by the OS. For example keyboard scanning. Now I think I'm already doing this with the code RTW gave me for vertical scrolling. But are there any other areas that can be turned of to improve speed a little ? And if so how ?


It turns out he'd already turned off everything he could and the discussion moved on to other optimisations he could use. I'd like to know what can be 'turned off' and how to do it and what complications can arise from this. I'm happy to be pointed at some books but I'll most likely return with more questions after my reading.

Since I'm currently interested in writing games stopping the OS from butting in seems to be a good idea but I know Tricky has mentioned turning off the OS a few times and how sound in particular can be a problem.

One of the pieces of example code over as RS is 'Reading the keyboard by direct hardware access' by RTW and at the end of the text he writes:

RTW wrote:All of this has to be done either with interrupts disabled, or a custom IRQ handler in place which doesn't let the OS in, otherwise all of the setup will be undone by OS code (because these values are changed to play sounds, for example).


I've written a small piece of code using this technique which checks for the standard beeb game keys of zx:/ and space then prints them to the screen . I'm curious if (1) I've done it correctly and (2) if turning off the OS would satisfy the interrupts disabled part of the above meaning I could remove the sei/cli instructions from my code.

Code: Select all

\\ 'Dirty' keyboard input

oswrch = $ffee

ORG &1900

.start
   \\ MODE 1
   lda #$16
   jsr oswrch
   lda #1
   jsr oswrch
      
   .loop
      jsr movement
   jmp loop
   

rts
\\ readkeys taken from retrosoftware.co.uk example code here
\\ - http://www.retrosoftware.co.uk/wiki/index.php?title=Reading_the_keyboard_by_direct_hardware_access -
\\ written by rtw

.readkeys
   \\ initialisation
   lda #0
   \\set all keys to 0
   sta left
   sta right
   sta up
   sta down
   sta fire
   
   sei;               turn interrupts off
   LDA #&7F:STA &FE43;      set DDRA to 01111111
   LDA #&0F:STA &FE42;      allow write to addressable latch
   LDA #&03:STA &FE40;      set bit 3 to 0
   
   \\ keys checked here
   
   \\ z - left - code 97
   LDA #97:STA &FE4F:LDA &FE4F  \ N flag = whether 'Z' pressed
   bpl not_z
      lda #1
      sta left
   .not_z
   
   \\ x - right - code 66
   LDA #66:STA &FE4F:LDA &FE4F  \ N flag = whether 'X' pressed
   bpl not_x
      lda #1
      sta right
   .not_x
   
   \\ colon - up - code 72
   LDA #72:STA &FE4F:LDA &FE4F  \ N flag = whether ':' pressed
   bpl not_colon
      lda #1
      sta up
   .not_colon
   
   \\ slash - down - code 104
   LDA #104:STA &FE4F:LDA &FE4F  \ N flag = whether '/' pressed
   bpl not_slash
      lda #1
      sta down
   .not_slash
   
   \\ space - fire - code 98
   LDA #98:STA &FE4F:LDA &FE4F  \ N flag = whether ' ' pressed
   bpl not_space
      lda #1
      sta fire
   .not_space

   cli;               turn interrupts back on
rts


.movement
   jsr readkeys

   lda left
   beq no_left
   lda #90
   jsr oswrch
   
   .no_left
   lda right
   beq no_right
   lda #88
   jsr oswrch
   
   .no_right
   lda up
   beq no_up
   lda #58
   jsr oswrch

   .no_up
   lda down
   beq no_down
   lda #47
   jsr oswrch
   
   .no_down
   lda fire
   beq key_end
   lda #32
   jsr oswrch
   
   .key_end
rts

\\store inputs
.left   equb 0
.right   equb 0
.up      equb 0
.down   equb 0
.fire   equb 0

.end
SAVE "KEYS",start,end

User avatar
jbnbeeb
Posts: 368
Joined: Sat Apr 03, 2010 8:16 pm

Re: Turning off OS routines.

Postby jbnbeeb » Wed Jan 11, 2017 9:14 pm

Hi,
1) I think the code will work as it stands - but I'm not sure what will happen OS wise - I think it will over write the settings, which is OK as then the OS will function OK. The OS over write will be OK for you're routine as you're calling it repeatedly in a loop.

2) Disabling the OS is essentially turning off unwanted interrupts. I did something similar to your routine whilst doing jbiplane, but I later encountered problems. Once I started plotting more than one sprite to the screen, I found that I needed all the time I could get to plot, and so used an IRQ handler based on code from Richard Talbot Watkins in the retrosoftware threads. But once I went down that route, the keyboard routine like the above caused other problems.

It seems to me that in games, "turning off the OS" is an all in or all out thing - there doesn't seem to be a halfway house as the OS expects to be "on" all the time.

So if you turn off the OS, you'd only need to set interrupts once between sei /cli.. but then you'd need to write an irq handler. If you went this route, you'd then put the keybd scanning bits in the handler, which wouldn't have sei/cli in it.

It might be worth having a read through of this thread ..which is about handling the joystick in irq handler ..and how I came unstuck because I didn't place the keyboard routine (same RTW code) in the handler. ..For now I think you'll be fine sticking with what you've got and then moving on to irq handler when you need it (IMHO).
http://www.retrosoftware.co.uk/forum/viewtopic.php?f=73&t=936&hilit=handler&start=20

Link to jbip page where you can download source ..http://www.retrosoftware.co.uk/wiki/index.php?title=Jbiplane
I'm going to ..
ABUG North Halifax June 10-12
Image

User avatar
tricky
Posts: 1921
Joined: Tue Jun 21, 2011 8:25 am
Contact:

Re: Turning off OS routines.

Postby tricky » Thu Jan 12, 2017 1:01 pm

When I say turning off the OS, I mean disabling all interrupts and then pointing the main IRQ vector to my code, putting an RTI at &d00 (really I guess you should take ownership of the NMI first - osbyte I think) and then only enabling the interrupts that iI will handle and never calling another OS routine.
In this way, the only OS code ever run is the beginning of the interrupt handler, which stotes A at &FC and does a jmp (&220) - may not be 220!
So it is really shutting the OS out, not turning it off.
This means that you have all of the RAM except about 5 bytes.

User avatar
jgharston
Posts: 2764
Joined: Thu Sep 24, 2009 11:22 am
Location: Whitby/Sheffield

Re: Turning off OS routines.

Postby jgharston » Thu Jan 12, 2017 3:04 pm

If you are turning the whole of the OS off, then all you need to do is store RTI at &D00 (so NMIs are a null routine) and SEI to turn interupts off. Pointing &204/5 to &D00 to point IRQ1V to the same RTI is a useful safety feature to catch if you accidently turn IRQs back on.
SEI
LDA #&40:STA &D00 :\ NMI=null
LDA #&00:STA &204 :\ Point all IRQs to null
LDA #&0D:STA &205

Of course, 'turning off the whole OS' requires you the coder to never call the OS otherwise you are explicity expecting it to be in a 'turned on' state.

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

User avatar
tricky
Posts: 1921
Joined: Tue Jun 21, 2011 8:25 am
Contact:

Re: Turning off OS routines.

Postby tricky » Thu Jan 12, 2017 6:00 pm

I don't, but I thought it would be a good idea to request the NMIs to give any hardware that might be generating them a clue that they won't be answered.
If I did, which I probably will next time, I would still put an RTI at &D00, although I guess it *shouldn't* be necessary.
I think RTW always makes sure that the couple of bits controlling what happens when BREAK is pressed are set correctly to avoid ending up with the beeb thinking it has 16KB and having to do *fx200,3 BREAK.

User avatar
Rich Talbot-Watkins
Posts: 1121
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca

Re: Turning off OS routines.

Postby Rich Talbot-Watkins » Fri Jan 13, 2017 10:47 am

Prior to booting out the OS, I always call OSBYTE &8C too to select the tape filing system - the motivation being for the current filing system (most likely DFS or ADFS) can put its hardware to sleep if necessary and clean up any hooks it has on NMIs. Just seems like good practice. You can also explicitly tell the current NMI owner that it's about to be forcibly kicked out by issuing a ROM service call (OSBYTE &8F with X=&0B), but I'd expect *TAPE to force the old filing system to shut down gracefully anyway. Maybe JGH knows better.

User avatar
jgharston
Posts: 2764
Joined: Thu Sep 24, 2009 11:22 am
Location: Whitby/Sheffield

Re: Turning off OS routines.

Postby jgharston » Fri Jan 13, 2017 12:50 pm

Rich Talbot-Watkins wrote:Prior to booting out the OS, I always call OSBYTE &8C too to select the tape filing system (...) You can also explicitly tell the current NMI owner that it's about to be forcibly kicked out

Good point, best belt and braces would be:

LDA #143:LDX #12:LDY #255:JSR OSBYTE :\ Claim NMIs
LDA #140:JSR OSBYTE :\ Select TAPE
LDA #3:STA &258 :\ *FX200,3 - clear memory on Break
SEI
LDA #&40:STA &D00 :\ NMI=null
LDA #&00:STA &204 :\ Point all IRQs to null
LDA #&0D:STA &205

That results in you having complete control over the whole machine other than the four memory locations &204, &205, &258, &D00.

Selecting TAPE (or ROM) only takes over the filing system. As TAPE/ROM do not use NMIs they don't do anything about telling the current NMI owner to do anything, so selecting TAPE/ROM will not kick the current NMI owner out.

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

User avatar
Rich Talbot-Watkins
Posts: 1121
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca

Re: Turning off OS routines.

Postby Rich Talbot-Watkins » Fri Jan 13, 2017 1:13 pm

jgharston wrote:Selecting TAPE (or ROM) only takes over the filing system. As TAPE/ROM do not use NMIs they don't do anything about telling the current NMI owner to do anything, so selecting TAPE/ROM will not kick the current NMI owner out.

I guess not. Is the NMI owner allowed to leave its NMI code in place if it's a non-active filing system? If so, I guess there's no reason why switching to *TAPE would necessarily put the disk/net hardware into a state where NMIs could no longer occur, in which case it'd definitely be a good idea to do it.

jgharston wrote:That results in you having complete control over the whole machine other than the four memory locations &204, &205, &258, &D00

And &FC too! And also be careful that &287 doesn't contain &4C so the Break vector isn't intercepted.

User avatar
jgharston
Posts: 2764
Joined: Thu Sep 24, 2009 11:22 am
Location: Whitby/Sheffield

Re: Turning off OS routines.

Postby jgharston » Fri Jan 13, 2017 5:44 pm

Rich Talbot-Watkins wrote:
jgharston wrote:Selecting TAPE (or ROM) only takes over the filing system. As TAPE/ROM do not use NMIs they don't do anything about telling the current NMI owner to do anything, so selecting TAPE/ROM will not kick the current NMI owner out.
I guess not. Is the NMI owner allowed to leave its NMI code in place if it's a non-active filing system?

Yes. You don't have to be a filing system to own the NMI. Econet is not a filing system, and uses the NMIs for background network communication regardless of whether the NFS - a filing system - is using it. Anybody can be using Econet regardless of whether NFS is the current filing system - NetPrint which is a printer driver, not a filing system, a file server - which is a file server not a filing system, TelServ - which is a teletext server, not a filing system, NetChat/Cave/Talk/Mugins - which are network communications programs, not filing systems.

Rich Talbot-Watkins wrote:
jgharston wrote:That results in you having complete control over the whole machine other than the four memory locations &204, &205, &258, &D00
And &FC too! And also be careful that &287 doesn't contain &4C so the Break vector isn't intercepted.

Doh! There's always one that slips your memory. So, set IRQ1V to the default IRQ2V which is LDA &FC:RTI. In close to 100% of cases just disabling IRQs will be sufficient. And of course, we're ignoring BRKV on the assumption that we won't be executing any BRK instructions.

LDA #143:LDX #12:LDY #255:JSR OSBYTE :\ Claim NMIs
LDA #140:JSR OSBYTE :\ Select TAPE
LDA #3:STA &258:STA &287 :\ *FX200,3 - clear memory on Break, *FX247,3 - disable BIV
LDA #&40:STA &D00 :\ NMI=null
SEI :\ Disable IRQs
\
\ The following is really belt-and-braces stuff, SEI should be sufficient
LDA &FFB7:STA &FD:LDA &FFB8:STA &FE :\ (&FD)=>default vector table
LDY #6:LDA (&FD),Y:STA &204 :\ Set IRQ1V to default IRQ2V -> LDA &FC,RTI
INY:LDA (&FD),Y:STA &205

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_


Return to “programming”

Who is online

Users browsing this forum: No registered users and 1 guest