log in | register | forums
Show:
Go:
Forums
Username:

Password:

User accounts
Register new account
Forgot password
Forum stats
List of members
Search the forums

Advanced search
Recent discussions
- Drag'N'Drop Autumn edition now available (News:)
- !DualHead puts 2 screens in one (News:)
- RISC OS London Show 2017 - Notes from the talks (News:6)
- November News (News:)
- !Organizer 2.28 reviewed (News:2)
- !OBrowse reviewed (News:10)
- Aemulor (Gen:16)
- DDE reaches release 28 and above (News:)
- Elesar quicks dispels stormy clouds (News:2)
- RISC OS London Show 2017 (News:)
Latest postings RSS Feeds
RSS 2.0 | 1.0 | 0.9
Atom 0.3
Misc RDF | CDF
Site Search
 
Article archives
The Icon Bar: Programming: Remapping video memory
 
  Remapping video memory
  This is a long thread. Click here to view the threaded list.
 
Jon Abbott Message #121041, posted by sirbod at 20:02, 10/9/2012
Member
Posts: 563
I need to remap the video memory to 1FFFFFF and below to fix hardcoded games, I'm guessing the code below may be sufficient to do that on RO3.5+

SYS "OS_ReadMemMapInfo", TO page_size%

SYS "OS_ReadDynamicArea", 2 TO r0%, r1%
screen_end_address% = r0% + r1%
video% = screen_end_address% - page_size%
old_video% = &2000000 - page_size%

DIM z% 32
z%!12 = -1
REPEAT
!z% = 0
z%!4 = video%
z%!8 = 0
SYS "OS_FindMemMapEntries", z%

IF !z% <> -1 THEN
z%!4 = old_video%
SYS "OS_SetMemMapEntries", z%

old_video% -= page_size%
ENDIF

video% -= page_size%
UNTIL !z% = -1

However my question is, how do I notify RO that the screen address has changed, so it doesn't break?

EDIT: Can the screen memory be double mapped? I've seen a few mentions of it, but haven't found any detail on how.

[Edited by sirbod at 20:39, 11/9/2012]
  ^[ Log in to reply ]
 
qUE Message #121045, posted by qUE at 11:02, 11/9/2012, in reply to message #121041
qUE

Posts: 168
You'll have to reprogram the VIDC video base (vinit) as well if you're moving its physical location to, and bare in mind the physical address is limited in its range.

Afaik, ROS sets certain pages statically so the video should be a certain page in the MEMC CAM table. From what I gather its page 0 and its physical address is &2000000 (0 in the VIDC vinit register).

This is only good for up to 3.11, anything beyond likely has a different bootstrap process. And don't quote me on if ROS fiddles with the pages allocated following CAM 0 on mode change since each page is only 32K.
  ^[ Log in to reply ]
 
Jon Abbott Message #121047, posted by sirbod at 11:41, 11/9/2012, in reply to message #121045
Member
Posts: 563
This is only required on machines running above RO3.1 as RO3.1 has the screen memory in the correct place.

Remapping vinit is easy enough, but will RO know it's moved? I doubt it reads the hardware address from the VIDC before any VDU commands, it more than likely has a local copy of the logical hardware and VDU buffer addresses.
  ^[ Log in to reply ]
 
Jeffrey Lee Message #121048, posted by Phlamethrower at 12:46, 11/9/2012, in reply to message #121047
PhlamethrowerHot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff

Posts: 15057
I don't think OS_SetMemMapEntries would be a particularly safe way of doing things - it'll create a disconnect between where the dynamic area thinks the memory is and where it actually is. I'm not sure offhand what a safer method would be though; maybe destroy and recreate the screen dynamic area?

EDIT: Can the screen memory be double mapped? I've seen a few mentions of it, but haven't found any detail on how.
Screen memory is already doubly mapped. On Arc machines this was done by virtue of the fact that it occupied the first 512K of physical RAM, and was mapped right at the high end of the 32MB MEMC logical address range. So the first mapping would be the MEMC-mapped logical one and the second mapping (right after the first) would be the directly accessed physical one.

On RiscPC and above it's handled by setting the "doubly mapped" flag when creating the dynamic area. IIRC this causes the second mapping to exist *below* the start address of the area. So if you create a dynamic area of X size at base B you'd get one mapping from B to B+X and another mapping from B-X to B.

The dynamic area will have also requested the use of specific physical pages; I believe this will prevent you from creating a second dummy screen DA which maps to the same pages. So I guess you've got the following options:

* Page table hackery (e.g. OS_SetMemMapEntries) to forcibly remap the pages
* Destroy & recreate the screen DA in the desired location (not sure how many places the DA base logical address will be hardwired into the OS)
* Create your own DA using a different physical address (or perhaps after shrinking the screen DA to 0) and poke all the right places in the OS to make screen output go to your DA instead of the OS's one. Except that might get a bit messy on machines with VRAM (or post-RiscPC stuff like the Iyonix where dedicated VRAM must be used).

It might be worth getting hold of StrongGuard and seeing if you can work out how that did things (or ask Adrian how he does it in Aemulor!)
  ^[ Log in to reply ]
 
Jon Abbott Message #121050, posted by sirbod at 13:54, 11/9/2012, in reply to message #121048
Member
Posts: 563
Destroy & recreate the screen DA in the desired location (not sure how many places the DA base logical address will be hardwired into the OS)
I did try this, however when trying to destroy it you get the error "SWI &6D656D not known" - I've no idea what that is, or why RO is calling it.

Looking at the Kernel header, it looks like I will need to modify the following:

ScreenStart (&10C0)
CursorAddr (&1130)
InputCursorAddr (&113C)
DisplayStart (&1178)
DriverBankAddr (&117C)
DisplayBankAddr (&1180)
DisplayScreenStart (&1190)

It also looks like I may not need to touch Vinit as it appears to be referenced as a physical address, not logical.

[Edited by sirbod at 16:05, 11/9/2012]
  ^[ Log in to reply ]
 
Jeffrey Lee Message #121051, posted by Phlamethrower at 14:15, 11/9/2012, in reply to message #121050
PhlamethrowerHot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff

Posts: 15057
It also looks like I may not need to touch Vinit as it appears to be referenced as a physical address, not logical.
Yes, the addresses VIDC sees will all be physical.
  ^[ Log in to reply ]
 
qUE Message #121055, posted by qUE at 16:05, 11/9/2012, in reply to message #121047
qUE

Posts: 168
...but will RO know it's moved?
No it won't, you'll need to update the CAM table to point to its new physical location. Same goes for logical, since ROS can't read the MEMC it won't know where you've moved anything without updating its internal CAM table, it's located in logical page zero if you want to directly fiddle with it.

Can't see an official way to do it in the PRMs, probably easiest way is to disable interrupts, update MEMC CAM table, update ROS CAM table and then re-enable interrupts.

ROS 2 (and probably 3) CAM table exists at &164 and consists of 128 or 256(depending on MEMC version) * 32-bit values, the top two bits of each value being the protection level and the rest being a logical address.

set I and F in PSR to disable interrupts

;R0 = MEMC CAM entry (physical address=CAM entry*32K), 0 for screen area
;R1 = logical address
;R2 = protection level (probably 0/user)

MOV R3,#&164
ORR R1,R1,R2,LSL#28
STR R1,[R3,R0,LSL#2]

or in BASIC;
!(&164+(camentry<<2))=(logicaladdress OR(ppl<<28))

although I'd expect an explosion in BASIC :)

[Edited by qUE at 17:06, 11/9/2012]
  ^[ Log in to reply ]
 
Jeffrey Lee Message #121057, posted by Phlamethrower at 18:59, 11/9/2012, in reply to message #121055
PhlamethrowerHot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff

Posts: 15057
...but will RO know it's moved?
No it won't, you'll need to update the CAM table to point to its new physical location. Same goes for logical, since ROS can't read the MEMC it won't know where you've moved anything without updating its internal CAM table, it's located in logical page zero if you want to directly fiddle with it.
You're forgetting that he's talking about RISC OS 3.5 and above, where the ARM has its own integrated MMU (with page tables held in RAM) instead of using MEMC (with the page tables held in MEMC).
  ^[ Log in to reply ]
 
Jon Abbott Message #121059, posted by sirbod at 19:57, 11/9/2012, in reply to message #121057
Member
Posts: 563
You're forgetting that he's talking about RISC OS 3.5 and above
Correct, 3.5 and above.

I believe using OS_SetMemMapEntries is the most official way of doing the MEMC remap. It's RO that's the issue is it seems hardcoded to end the video logical memory at &5000000.

Changing via OS_DynamicArea seems a possible route around this, but what on earth is SWI &6D656D?

EDIT: &6D656D in ASCII is "mem", sounds like it may be restricted somehow.

[Edited by sirbod at 21:10, 11/9/2012]
  ^[ Log in to reply ]
 
Jeffrey Lee Message #121061, posted by Phlamethrower at 21:18, 11/9/2012, in reply to message #121059
PhlamethrowerHot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff

Posts: 15057
Which OS version are you trying this on? It sounds like a bug that's causing the CPU to try executing some random data.

I just tried this on my Iyonix, with Aemulor running, and it seemed to work fine. However it does point out a bit of a flaw: my machine didn't immediately crash, because the Iyonix (and the Pi) don't actually use the screen DA. The reason they don't use it is because dynamic areas are only used for mapping ordinary RAM pages, and the Iyonix PCI RAM & Pi VideoCore RAM aren't exposed as ordinary RAM to RISC OS. Instead the drivers just tell RISC OS the physical base & size of the memory, and the OS maps it in itself (using OS_Memory 13). The screen DA is just left knocking around to keep any legacy code happy, I guess.
  ^[ Log in to reply ]
 
Jon Abbott Message #121062, posted by sirbod at 21:36, 11/9/2012, in reply to message #121061
Member
Posts: 563
Which OS version are you trying this on? It sounds like a bug that's causing the CPU to try executing some random data.
RO 3.70. I expect the reason it works is, as you point out, the RAM isn't being used.

This isn't going to work on non-Acorn kit, got to start somewhere though!

Looking at the OS source code, OS_DynamicArea isn't going to work anyway as it tries to shrink it first and the generates a Service call before it exits.

Even worse, #ScreenEndAdr is hardcoded into the OS source.

The fact the old space is documented in the RO 3.5 memory map implies Acorn were going to add backward compatibility. It wouldn't surprise me if there's a reserved call somewhere.

We know it can be done as GameOn/StrongGuard does it, the question is how? I doubt the source is freely available to look.

EDIT: I have it remapping, can see VDU output in BASIC and the input cursor, but it crashes as soon as the screen scrolls or when it goes back to the desktop - the desktop does draw though. If you drag a window off screen, instant crash.

EDIT2: As the OS is hardcoded to &5000000, I need to hook into the mode change Service, to alter the values in page 0 and remap for certain video modes - so the desktop doesn't get knackered.

[Edited by sirbod at 23:02, 11/9/2012]
  ^[ Log in to reply ]
 
Jon Abbott Message #121064, posted by sirbod at 09:26, 12/9/2012, in reply to message #121062
Member
Posts: 563
OS_Word 22 - Write screen base address (PRM1-724)

This sounds like it should update the OS memory addresses, but it doesn't seem to do anything. I'm not even getting an error returned with calling it with &1FED400. After calling the pointers listed above are all still at the original screen address.

As this doesn't work, it looks like I need to hook into OS_Byte 112 / 113 and "fix" the OS's screen address pointers after the OS has done it's thing.

EDIT: Trapping 112 / 113 - Yay, Zarch is now running on RO3.7, need to add code to slow the machine down, to make it playable!

EDIT2: Just realised OS_Word 22 is an offset address from the base of the screen memory, so not applicable. I will need to trap and modify it though, as I suspect it will be hardcoded to <&5000000

[Edited by sirbod at 17:44, 12/9/2012]
  ^[ Log in to reply ]
 
Michael Drake Message #121065, posted by tlsa at 09:55, 12/9/2012, in reply to message #121064

Posts: 1093
Have you seen: http://bass-software.com/wimpzarch/index.html ?
  ^[ Log in to reply ]
 
Jon Abbott Message #121066, posted by sirbod at 13:10, 12/9/2012, in reply to message #121065
Member
Posts: 563
Have you seen
I have. The aim is to get these hardcoded games running in their original format with no user intervention required, other than mounting the floppy and running it.

The technique of using a back buffer and blitting to the screen, may be a requirement for the newer ARM cores. For the time being, I'm concentrating on getting things working on Acorn kit. ie up to A7000, RO3.71 and SA
  ^[ Log in to reply ]
 
Jon Abbott Message #121067, posted by sirbod at 17:33, 12/9/2012, in reply to message #121064
Member
Posts: 563
I've hit a stumbling block, any changes to the VDU addresses crashes the machine before the OS exits:

OS_Word 22 with R1?0 = 1
OS_Byte 112

If I trap them both and return immediately, things work fine.
  ^[ Log in to reply ]
 
Jon Abbott Message #121068, posted by sirbod at 10:16, 13/9/2012, in reply to message #121067
Member
Posts: 563
Looking at the OS source for OSBYTE 112, it calls DoSetDriverBank. Where is that in the source, I can seem to find it?

EDIT: Found it in vdu23, the reason it's crashing is due to a mixture of static and memory read references to the video memory. Looks like I need to put all the memory addresses back to <5000000 let it run it's course and then change them back to <2000000

[Edited by sirbod at 10:24, 14/9/2012]
  ^[ Log in to reply ]
 
Justin Fletcher Message #121070, posted by gerph at 18:47, 13/9/2012, in reply to message #121041
Member
Posts: 9
No. You don't. You need to fix the code to call the defined APIs to read the base of screen properly. OS_ReadVduVariables ScreenStart is what you want. Stop screwing around with page table mappings, and call the defined APIs properly.
________
--
Gerph
  ^[ Log in to reply ]
 
Jon Abbott Message #121074, posted by sirbod at 19:08, 13/9/2012, in reply to message #121070
Member
Posts: 563
I think you missed the point. I'm trying to fix protected games that can't easily be modified.

Useful advice though.
  ^[ Log in to reply ]
 
Jon Abbott Message #121077, posted by sirbod at 10:39, 14/9/2012, in reply to message #121068
Member
Posts: 563
The reason it's crashing is due to a mixture of static and memory read references to the video memory. Looks like I need to put all the memory addresses back to <5000000 let [OSByte 112] run it's course and then change them back to <2000000
The crashing is being caused by the cursor EOR code, DoSetDriverBank calls PreWrchCursor to hide the cursor, this drops through to EORFlashCursor, which fails as the memory is obviously in the wrong place.

So, the fix is to swap all the addresses (ScreenStart, CursorAddr, InputCursorAddr, DisplayStart, DriverBankAddr, DisplayBankAddr, DisplayScreenStart) back to <5000000 except CursorAddr, let the OS run it's course and then swap everything back to <2000000 before exiting the SWI routine.

I expect there's other SWI's I'll need to trap in this way as there's a lot of calls to PreWrchCursor in the source code.

Other than Zarch, is anyone aware of any hardcoded games I can test?
  ^[ Log in to reply ]
 
Justin Fletcher Message #121078, posted by gerph at 13:41, 14/9/2012, in reply to message #121074
Member
Posts: 9
I think *you* missed the point. If you're fixing games to make them work then you should make them work through the interfaces that are present to remove make these things work. ie you should be *fixing* them, not changing the system on which they run. Remapping memory is a) not going to work properly on all systems because the logical address space will have changed, and b) unless you know everything about the system that things are running on, you don't know what the effects are going to be.

There are good solutions and bad solutions to patching things, and you've chosen a bad solution.
________
--
Gerph
  ^[ Log in to reply ]
 
Jon Abbott Message #121085, posted by sirbod at 21:34, 14/9/2012, in reply to message #121078
Member
Posts: 563
If you're fixing games to make them work then you should make them work through the interfaces that are present
Wherever possible, I've used OS interfaces, or where there are none, I've raised a question here.
you should be *fixing* them, not changing the system on which they run.
I agree and where possible, this is being done.
Remapping memory is a) not going to work properly on all systems because the logical address space will have changed
That's a very valid point, are there any branches if RO past 3.71 where the video is logically mapped to anything other than <5000000? Its somewhat academic though, as I'm requesting the logical address from the OS prior to remapping it.
b) unless you know everything about the system that things are running on, you don't know what the effects are going to be.
I agree, and to mitigate remapping will only happen in single thread mode when then game has control of the system. There will also be checks for modes that exceed the 480K limit.
you've chosen a bad solution.
I agree, I'm sure The ARM Club thought the same thing when they wrote GameOn / StrongGuard.
  ^[ Log in to reply ]
 
Justin Fletcher Message #121086, posted by gerph at 22:47, 14/9/2012, in reply to message #121085
Member
Posts: 9
Remapping memory is a) not going to work properly on all systems because the logical address space will have changed
That's a very valid point, are there any branches if RO past 3.71 where the video is logically mapped to anything other than <5000000? Its somewhat academic though, as I'm requesting the logical address from the OS prior to remapping it.
b) unless you know everything about the system that things are running on, you don't know what the effects are going to be.
I agree, and to mitigate remapping will only happen in single thread mode when then game has control of the system. There will also be checks for modes that exceed the 480K limit.
No. You have missed the point entirely. Remapping memory *will not work*. Your suggested method of using OS_SetMemMapEntries will fail where the memory is not RAM. OS_SetMemMapEntries operates (on legacy systems) using RAM page numbers, so attempting to remap memory which *does not have* a RAM page, because it's not part of the memory map, will therefore fail. Later versions use a modified form of physical page numbering, but this should never be used.

YOU do not own the screen memory. YOU do not know what the screen memory even is. YOU should not be screwing with memory regions that you do not own. The graphics driver is quite at liberty to manipulate the screen memory in whatever way it chooses. In the case of (let us say) ViewFinder, the screen memory is not RAM, therefore has no page. The video driver is quite at liberty to remove the screen mapping entirely - making the logical address space unmapped, or temporarily mapped to contain different data. Virtual, paged, memory access can be achieved in this manner and correctly written code will be none the wiser.

Indeed there is no requirement that there actually be *any* memory mapped to the location that the screen exists at.

I'm not sure why your question asks about the memory being mapped to "anything other than <5000000". Screen memory can be mapped anywhere, at the discretion of the video driver. You cannot even assume that the base of screen memory is at a 4K aligned address. You can assume that the base is word aligned, and that's about it - that particular restriction is assumed everywhere.

I cannot tell you what the screen memory is mapped to on any given system, but I can tell you how to obtain the answer - OS_ReadVduVariables calls to read the base of the screen memory.

you've chosen a bad solution.
I agree, I'm sure The ARM Club thought the same thing when they wrote GameOn / StrongGuard.
I cannot speak for what they might have done, only that what you're doing is based on incorrect assumptions.

To summarise: The screen memory may not be RAM pages. The screen memory does not belong to you, and you should not be messing with it. You should assume nothing about its presentation in memory other than that you can write and read from it. The screen memory can be aligned arbitrarily at any alignment greater than a word.

There is an interface to read the base of screen memory, which you should use. Remapping pages you should not do.
________
--
Gerph
  ^[ Log in to reply ]
 
Jon Abbott Message #121087, posted by sirbod at 06:00, 15/9/2012, in reply to message #121086
Member
Posts: 563
No. You have missed the point entirely. Remapping memory *will not work*. Your suggested method of using OS_SetMemMapEntries will fail where the memory is not RAM.
I'm aware of its restricted use, hence my comment above:
The technique of using a back buffer and blitting to the screen, may be a requirement for the newer ARM cores. For the time being, I'm concentrating on getting things working on Acorn kit. ie up to A7000, RO3.71 and SA
Unfortunately, blitting can't be used on the earlier Acorn kit, as its just too slow moving large chunks of memory around.
  ^[ Log in to reply ]
 
qUE Message #121098, posted by qUE at 23:27, 16/9/2012, in reply to message #121057
qUE

Posts: 168
...but will RO know it's moved?
No it won't, you'll need to update the CAM table to point to its new physical location. Same goes for logical, since ROS can't read the MEMC it won't know where you've moved anything without updating its internal CAM table, it's located in logical page zero if you want to directly fiddle with it.
You're forgetting that he's talking about RISC OS 3.5 and above, where the ARM has its own integrated MMU (with page tables held in RAM) instead of using MEMC (with the page tables held in MEMC).
Either I've missed an edit or you've missed an edit. Either way, we're both idiots :D
  ^[ Log in to reply ]
 
Jon Abbott Message #121107, posted by sirbod at 18:44, 17/9/2012, in reply to message #121041
Member
Posts: 563
Daft question, but if RISC OS is hard coded to use 5000000 as the end address for the screen memory, how does that memory get mapped on non Acorn machines?

Is it mapped via a bootstrap that's hardware specific? Or is there a HAL that somehow redirects the OS to the actual video memory address?
  ^[ Log in to reply ]
 
Jeffrey Lee Message #121108, posted by Phlamethrower at 23:48, 17/9/2012, in reply to message #121107
PhlamethrowerHot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff

Posts: 15057
Daft question, but if RISC OS is hard coded to use 5000000 as the end address for the screen memory, how does that memory get mapped on non Acorn machines?
Firstly, don't believe everything you read in the kernel sources! Although ScreenEndAdr is still defined as &5000000, it doesn't look like anything is still using it, apart from a couple of old bits of unused code. I'd guess that (for RISC OS 5) it was removed from active use some time around the HALification, if not earlier.

For RISC OS 5, there are actually three ways the kernel can get hold of the video memory. In order of decreasing precedence:
  • If the HAL/video driver implements HAL_VideoFramestoreAddress/GraphicsV 9, the kernel will use that
  • If the HAL indicated that VRAM was present in a call to RISCOS_AddRAM, the kernel will use that
  • Failing all of the above, the kernel will just claim a chunk of ordinary RAM (typically from the start of the first registered RAM chunk) and use that instead. In this case it clamps the max size to 32MB.
For RISC OS 6, I suspect the memory is specified via VideoV somehow.

[Edited by Phlamethrower at 00:51, 18/9/2012]
  ^[ Log in to reply ]
 
Jon Abbott Message #121119, posted by sirbod at 20:16, 21/9/2012, in reply to message #121041
Member
Posts: 563
If I implement a virtual memory system off the data abort vector, will there be any side effects on later versions of RISC OS?

I'm thinking dynamically remap video RAM pages for Acorn kit with RAM or VRAM for speed. For non-Acorn kit, implement instruction emulation or redirection to the correct location.
  ^[ Log in to reply ]
 
Jon Abbott Message #121124, posted by sirbod at 07:15, 24/9/2012, in reply to message #121119
Member
Posts: 563
OS_AbortTrap looks like an ideal way of implementing what I require, in a forward compatible way. However, was it ever back ported to RO4 and is it in RO5?
  ^[ Log in to reply ]
 
Jeffrey Lee Message #121126, posted by Phlamethrower at 11:29, 24/9/2012, in reply to message #121124
PhlamethrowerHot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff

Posts: 15057
However, was it ever back ported to RO4 and is it in RO5?
No and no. There have been talks about overhauling the RO5 abort handling mechanism to make it easier to implement things like this, but I wouldn't hold your breath waiting for it to happen.
  ^[ Log in to reply ]
 
Jon Abbott Message #121127, posted by sirbod at 16:23, 24/9/2012, in reply to message #121126
Member
Posts: 563
However, was it ever back ported to RO4 and is it in RO5?
No and no.
As I feared, I'll hook directly onto the vector then and pass it on if it's not video related that will be more efficient for games anyway.
  ^[ Log in to reply ]
 
Pages (2): 1 > >|

The Icon Bar: Programming: Remapping video memory