Bank switching issue

The place for codemasters or beginners to talk about programming any language for the Spectrum.
User avatar
Prototron
Drutt
Posts: 11
Joined: Thu Mar 07, 2024 2:10 pm
Location: Glasgow, Scotland

Re: Bank switching issue

Post by Prototron »

deanysoft wrote: Tue Apr 09, 2024 5:04 pm OK, I can't quite visualise how that works but you say it does so that's good. I would've thought if graphics data is banked in at $c000 then your screen, in another bank at $c000, is not available. So copying from one to another means you're having to copy bytes to a temp buffer first or hold your bytes in registers, swap bank then copy to screen. Both don't seem very fast methods.

I'm probably just not quite understanding your process here. So long as it works, that's the main thing.
It works but it's maybe not ideal. I was just happy that it was doing what it should. I'll need to try and organise a little better and only use banking for certain things.

I'm trying to reclaim the RAM from $5B00 - $8000 as it's got system stuff in it that I'm not ever going to use, but so far I can only use $6000-$8000 without any issues.

The adventure continues!
"For the money, for the glory, and for the fun! Mostly for the money."
~ Bo "Bandit" Darville
User avatar
ketmar
Manic Miner
Posts: 724
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: Bank switching issue

Post by ketmar »

if you want to use system vars for your code, you will need your own interrupt handler. ROM handler expects IY to point to sysvars area, and hopes to find some sysvars there (FRAMES, keyboard state). also, if you are using RST #10 for printing, you will need sysvars too (and some other ROM routines like PLOT wants sysvars).

it is usualy easier to leave sysvars where they are (and don't use IY).
User avatar
Prototron
Drutt
Posts: 11
Joined: Thu Mar 07, 2024 2:10 pm
Location: Glasgow, Scotland

Re: Bank switching issue

Post by Prototron »

ketmar wrote: Fri Apr 12, 2024 1:15 pm if you want to use system vars for your code, you will need your own interrupt handler. ROM handler expects IY to point to sysvars area, and hopes to find some sysvars there (FRAMES, keyboard state). also, if you are using RST #10 for printing, you will need sysvars too (and some other ROM routines like PLOT wants sysvars).

it is usualy easier to leave sysvars where they are (and don't use IY).
I have an IM 2 handler set up, but it's not doing much yet. Got a table at $8000 filled so it'll jump to my handler routine held $8181, and the stack is between them.

There's nothing actually in the handler just yet as I'm not really sure what to put in there.
"For the money, for the glory, and for the fun! Mostly for the money."
~ Bo "Bandit" Darville
User avatar
ketmar
Manic Miner
Posts: 724
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: Bank switching issue

Post by ketmar »

also note that by destroying sysvars you won't be able to use +3DOS. you need to call ROM interrupt handler to eventually turn drive motor off, and it uses some other sysvars too.

tbh, i never bothered to get rid of sysvars, and i don't think you need to. ;-) hey, you wasted 257 bytes on interrupt table, you definitely have plenty of unused RAM! ;-)

for IM2 trick: you don't actually need 257 bytes for the table which is already in ROM. let me quote one of my sources:

Code: Select all

  ;; this is using an old trick:
  ;; 48K ROM has a lot of #FF (more than 256),
  ;; so we can use it as interrupt table.
  ;; this way, the interrupt will jump at #FFFF.
  ;; this is not that useful... but we can put "JR"
  ;; opcode there, and it will jump to #FFF4
  ;; (due to first ROM byte being DI opcode aka #F3).
  ;; and we can put a real jump to our interrupt
  ;; routine at #FFF4.
  ;; so we cannot use last UDG, but meh... not a big deal.
  \ di
  ld    a, # $3B  ;; ROM contains a lot of #FF there
  ;; I register points to area filled with #FF here
  ld    i, a
  ;; write JR opcode to #FFFF
  ld    a, # $18
  ld    $FFFF (), a   ;; jr
  ;; write JP opcode to #FFF4
  ld    a, # $C3      ;; jp
  ld    $FFF4 (), a
  ;; write interrupt handler address to #FFF5
  ld    hl, # .IntrHandler
  ld    $FFF5 (), hl
  ;; switch to second interrupt mode
  im    # 2
many commercial games used this trick, so i consider it as "reliable and stable". ;-)
User avatar
goodboy
Microbot
Posts: 145
Joined: Tue Jul 23, 2019 8:22 am
Location: Russia

Re: Bank switching issue

Post by goodboy »

on the 128k machine you can use im1 for your code subroutine
User avatar
ketmar
Manic Miner
Posts: 724
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: Bank switching issue

Post by ketmar »

goodboy wrote: Sun Apr 14, 2024 10:51 am on the 128k machine you can use im1 for your code subroutine
but only if you have 128K ROM paged in, otherwise SWAP is not called.
AndyC
Dynamite Dan
Posts: 1416
Joined: Mon Nov 13, 2017 5:12 am

Re: Bank switching issue

Post by AndyC »

ketmar wrote: Sun Apr 14, 2024 12:53 am also note that by destroying sysvars you won't be able to use +3DOS. you need to call ROM interrupt handler to eventually turn drive motor off, and it uses some other sysvars too.

tbh, i never bothered to get rid of sysvars, and i don't think you need to. ;-) hey, you wasted 257 bytes on interrupt table, you definitely have plenty of unused RAM! ;-)

for IM2 trick: you don't actually need 257 bytes for the table which is already in ROM. let me quote one of my sources:

Code: Select all

  ;; this is using an old trick:
  ;; 48K ROM has a lot of #FF (more than 256),
  ;; so we can use it as interrupt table.
  ;; this way, the interrupt will jump at #FFFF.
  ;; this is not that useful... but we can put "JR"
  ;; opcode there, and it will jump to #FFF4
  ;; (due to first ROM byte being DI opcode aka #F3).
  ;; and we can put a real jump to our interrupt
  ;; routine at #FFF4.
  ;; so we cannot use last UDG, but meh... not a big deal.
  \ di
  ld    a, # $3B  ;; ROM contains a lot of #FF there
  ;; I register points to area filled with #FF here
  ld    i, a
  ;; write JR opcode to #FFFF
  ld    a, # $18
  ld    $FFFF (), a   ;; jr
  ;; write JP opcode to #FFF4
  ld    a, # $C3      ;; jp
  ld    $FFF4 (), a
  ;; write interrupt handler address to #FFF5
  ld    hl, # .IntrHandler
  ld    $FFF5 (), hl
  ;; switch to second interrupt mode
  im    # 2
many commercial games used this trick, so i consider it as "reliable and stable". ;-)
Will that still work if the +3DOS ROM is paged in? Is there actually a guaranteed 257 byte ramp containing FFh at the same addresses in every ROM? And, of course, you'd have to replicate the interrupt handler in every banked page.

Seems a lot easier just to use your own table, tbh.
User avatar
ketmar
Manic Miner
Posts: 724
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: Bank switching issue

Post by ketmar »

AndyC wrote: Sun Apr 14, 2024 11:15 am Will that still work if the +3DOS ROM is paged in?
i am cheating by switching to IM1 when calling +3DOS. not that you can do much while +3DOS does its business anyway.
AndyC wrote: Sun Apr 14, 2024 11:15 am Is there actually a guaranteed 257 byte ramp containing FFh at the same addresses in every ROM?
it is still there in 48K BASIC, which i page in at the start of all my code. and i am guilty of forgetting to tell about this. ;-)
AndyC wrote: Sun Apr 14, 2024 11:15 am And, of course, you'd have to replicate the interrupt handler in every banked page.
yes, but only those 4 bytes to perform the jump.
AndyC wrote: Sun Apr 14, 2024 11:15 am Seems a lot easier just to use your own table, tbh.
it highly depends of the memory map of your program, and if you want to waste 257 bytes of fast memory for the table. a matter of taste, i guess, but i prefer to not waste fast memory for that, and (usually) to have my interrupt handler in slow memory, and waste fast memory for some other tables, or code for fast screen blitting.

anyway, it's not the only method, of course. altering SWAP routine on 128K/3+ is another good way (but limited to 128K ;-).
tubs74
Drutt
Posts: 3
Joined: Sun Sep 10, 2023 2:29 pm

Re: Bank switching issue

Post by tubs74 »

I’ve been reading with interest your trials and tribulations regarding the bank switching on the 128s – I don’t think I’m ever going to be at a competence to actually use bank switching, and apologies for jumping on your thread :-). But I was wondering if with the double buffering something would need to be like this?

Bank 2, is our main code, held in 0x8000 to 0xC000 (Lets call this LOC2)

Bank 0 is the “original” bank in 0xC000 to 0xFFFF (Lets call this LOC3)

So, the code in LOC2, would be along the lines of
1) Turn off interrupts
2) CALL Your Sub Routine
3) Store the stack pointer into BANK 2 memory
4) Switch LOC3 to BANK7 or 5 (from here on you cannot use any existing RETS or POPS)
a. *Rather than step 3 above, could you flip to the shadow registers?
5) Set the stack pointer to somewhere LOC3
6) DO ALL THE STUFF - drawing sprites, changing screen etc, setting the screen– using Push/ Pop and Calls/Returns etc
7) Finish all your RETURNS and POPS (you won’t be able to use them again)
8) Switch LOC3 to BANK 0
9) Load the stackprnter saved at step 2 into the stack pointer (or flip back the shadow registers?)
10) Turn on interrupts
11) RETURN from your Sub routine

12) Do The Screen Flip

What I’m understanding is that the speccy way, basically means that the only way to get data from Bank 0, to Bank 1,3,4,6 & 7 is to copy it to bank 2 or bank 5 first?

So, basically there will be lots of copying memory from the different banks, probably having to use the spare memory in the main display bank (Bank 5 –sharing with ULA so slower). So the majority of your program code would have to be in bank 2 (or at least this would have to be the “master control” code)

There were basic command for saving to the M: (file commands) - could you create a "files" larger than 16k, (I'd assume you wouldn't be able to span the banks? Were there basic commands or extensions for writing to/flipping the display screen and reading/writing to it?

*From other reading, I understood that the shadow registers are often used by the ROM, so best never to use them …
User avatar
ketmar
Manic Miner
Posts: 724
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: Bank switching issue

Post by ketmar »

it's not that draconian. even if you want to keep basic and IM1, it is enough to properly set BANKM ($5B5C) system variable, and don't have the stack after $C000 (with CLEAR 49151, for example). now you only have to disable interrupts while doing bank switching and updating BANKM, and you can have any bank mapped in.
Timmy
Manic Miner
Posts: 236
Joined: Sat Apr 23, 2022 7:13 pm
Location: The Netherlands

Re: Bank switching issue

Post by Timmy »

It's only complicated because of your setup.

If you put your stack and interrupt related stuff in bank 2, then you can skip half of the steps.

But it's really not a big deal if you keep your stuff in bank 0.
tubs74
Drutt
Posts: 3
Joined: Sun Sep 10, 2023 2:29 pm

Re: Bank switching issue

Post by tubs74 »

> If you put your stack and interrupt related stuff in bank 2, then you can skip half of the steps.

Only thinking of that one faster 16k block that might end up having to be used for everything ... stack, "control code", data to copy to screens etc. It certainly brings it's own challanges (I think I saw the Commander X16 (8bit guys version of a next) has 4GB in that one 16k block ...)

I suppose though, if you were not bothered about ROM at all, the other memory mapping node (special mode?) could be used? But that looks even more complex, as there is no point when 1 bank is available across all modes. You might have your bank 6 for "screen memory" control, bank 3 and 4 for graphics and program, then bank 0,1 & 2 for grapahics data. would certainly take some clever management but would at least mean you cn access 64k of RAM in one go ...
User avatar
1024MAK
Bugaboo
Posts: 3129
Joined: Wed Nov 15, 2017 2:52 pm
Location: Sunny Somerset in the U.K. in Europe

Re: Bank switching issue

Post by 1024MAK »

Well, it all depends on what you are trying to do. Which takes up the most space, executable code or data?

The all RAM mode is only available on the +2A, +2B and +3 models and was presumably intended for CP/M use.

Mark
:!: Standby alert :!:
“There are four lights!”
Step up to red alert. Sir, are you absolutely sure? It does mean changing the bulb :dance
Looking forward to summer later in the year.
User avatar
Seven.FFF
Manic Miner
Posts: 748
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Bank switching issue

Post by Seven.FFF »

1024MAK wrote: Tue May 07, 2024 4:36 pm was presumably intended for CP/M use.
I concur. The banking arrangement has a close correspondence with the suggested internal architecture of the banked version of CP/M 3. CP/M 3 was available in two versions, banked and non-banked, and in the banked version they put some contraints on which parts of the 64K map were swappable and which contained fixed code.

Of course the mode is available for any +2A or +3 program too, but we suffer from the same problem as elsewhere in Spectrum land - people almost always want to target features that will work on all machines, so we end up with a lowest common denominator situation. There are some 128K-only games, borne out of being too big to fit in 48K machines, but there are few if any +2A/+3-only games. There are +3 disk games, but there are generally 48K or 128K with a custom disk loader.

Making a +2A/+3-only game matters less these days when most people are using emulators, but you still exclude many people running on real hardware if you do it.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
Post Reply