SDFS::RISCOS.$.Coding.Projects.ResFinder.s.ResFinder
; ResFinder
; =========
;
; by Rick Murray
; Version: 0.07 < update also embedded version
; Date : Saturday, 15th February 2014 < string at the end of the code
; Started: Friday, 24th January 2014
;
;
; Replacement for basic "ResFind" (apparently not related to the !ResFind app!?)
; as that chokes if the country is "Default". Plus, we could do more. :-)
;
;
; We expect to be called as follows:
; ResFinder <appname> [<respath>] [-useos]
; where <appname> is the name of the callee application, and <respath> (if specified) is the
; custom system variable to set to point to the resources.
; If <respath> is not specified, then the path will be "<appname>$Path".
; NOTE that this means <App$Dir> and <App$Path> may point to different places, however it
; does mean that you can load resources by using something like App:Templates or
; App:Messages and the appropriate one will be loaded.
; The "-useos" option overrides asking the Territory for the machine language and asks the
; OS. This allows for a different territory and country to be set up, such as RISC OS in
; English (Territory=UK) and applications to prefer German (Country=Gemany), for example.
;
;
; Aplication name approved by Ben Avison on 26th January 2014. While this is not an
; application in the traditional sense (no !directory etc), it allows us to create
; <ResFinder$SomethingHere> system variables.
;
;
; LICENCE:
;
; ResFinder is Copyright © 2014 Richard Murray
; Licensed under the EUPL v1.1 only.
;
;
; EXECUTABLE: The EXECUTABLE may be freely used without undue restrictions; as laid out
; in the EUPL licence (link below). Your use and distribution of this
; EXECUTABLE will be in accorance with the licence.
;
; One specific note, for clarity, is that the open source licence applies
; specifically and only to this EXECUTABLE - and any request for source code
; under the licence will cover ONLY this EXECUTABLE and not any part of that
; which this EXECUTABLE is used alongside; thus this open source executable
; may be used in a closed-source commercial package provided that the various
; terms of the licence are respected (ie, provide source to ResFinder if you
; modify it, or point people to my website if you don't, etc etc).
;
; SOURCE CODE: The EUPL v1.1 applies. There should be a PDF describing the EUPL in the
; archive that you downloaded. Alternatively, you can download the EUPL v1.1
; in all major European languages from here:
; http://ec.europa.eu/idabc/eupl.html (all have the same legal weight)
;
;
; ----display-width-is-92-characters--------------------------------------------------------
; Our inclusions
GET ^.h.EQUx ; EQUB, EQUD, EQUSZ, EQUSZA...
GET ^.h.SWINamesMini ; SWI definitions
GET ^.h.ResFinder ; no magic numbers
; Define as '1' in order to build a talkative version
TRACE * 0
[ TRACE = 1
MACRO
TraWrS $one, $two, $var
; TraWrS = TRAceWRiteString
; Call like: TraWrS 'A', 'B', workspace
; which will print: AB=<whatever is in workspace>
STMFD R13!, {R0-R2} ; better safe than sorry
SWI 256+$one
SWI 256+$two
SWI 256+'='
[ "$var"<>"R11" ; If <$var> is NOT "R11"
ADRL R0, $var ; then it's a pointer
|
MOV R0, R11 ; otherwise, use R11!
]
SWI OS_Write0
SWI OS_NewLine
LDMFD R13!, {R0-R2}
MEND
]
; ===========
; Here we go!
; ===========
; Within this code:
;
; R0 - R5 - working registers, make no assumptions.
; R6 - pointer to end of <appname>, for "$Path" suffix if no custom respath.
; - later used to hold the "platform class" that is detected.
; [->"theextrastuff"]
; R7 - pointer to test paths period prior to territory name being appended.
; - is later used to hold the CPUID. [->"theextrastuff"]
; R8 - is &7FFFFFFF if "-useos" specified, else &00000000.
; - is later used for alphabet version for UTF-8. [->"country_to_name"]
; - is later used by call to HAL via OS_Hardware. [->"theextrastuff"]
; R9 - flag set to indicate that we have a custom resources path (=1 or =0).
; R10 - flag set to indicate custom resources path ends with "$Path" (=1/=0).
; R11 - pointer to composite path (is altered by bytecopy routine).
; R12 - number of current country/territory to skip adding "UK" twice.
; R13 - stack
; R14 - return address (various)
; <terrname> - text of country name of current config ("UK", "France", etc)
; <fallback> - text of 'fallback' country name (if ResFinder$Fallback is defined).
; <progname> - name of caller app (CLI param #1) is copied here.
; <respath> - custom resources path (CLI param #2) is copied here, if specified.
; <workspace>- a wodge of memory to use as... gee... workspace, perhaps?
; <wrksp>+256- where the composite path is constructed (re. R11)
;
; Anybody who modifies this code is absolutely REQUIRED to keep the above up to
; date, under penalty of being shot repeatedly by high velocity baked beans, at
; least as many as are in a standard Heinz can.
AREA |ResFinder$Code|, CODE, PIC, A32bit
ENTRY
entry_point
[ TRACE = 1
SWI 256+'['
SWI OS_NewLine
]
; Read end of workspace and command line
SWI OS_GetEnv
MOV R13, R1 ; RAM limit is a tidy place to put our stack
STR R14, [R13, #-4]!
; Process command string [OS_ReadArgs makes life easier]
MOV R1, R0
ADRL R0, argparams
ADRL R2, workspace ; far away at end of program, needs ADRL
MOV R3, #BUFFERSIZE ; (as do a fair few of the other ADRs)
SWI OS_ReadArgs
; Set a pointer to our composite path
ADRL R0, workspace
ADD R11, R0, #256 ; at <workspace>+256 bytes
; Remember the "-useos" setting
LDR R8, [R2, #ARGPTR_USEOS]
; Extract program name
LDR R0, [R2, #ARGPTR_PROGNAME]
CMP R0, #0
BLE syntax_error
ADRL R1, progname
BL bytecopy ; R0 = src, R1 = dst (returned updated)
MOV R6, R1 ; preserve pointer for later
[ TRACE = 1
TraWrS 'P', 'N', progname ; Program Name
]
; In the copy above and below, there is NO bounds checking as the buffer size given
; to OS_ReadArgs is 128 bytes, both of these are 128 bytes, so cannot overrun.
; Extract the resources variable, if it exists
LDR R0, [R2, #ARGPTR_RESVAR]
CMP R0, #0
MOVLE R9, #NO_CUSTOM_RESVAR ; flag no custom resource variable
BLE no_resources
MOV R9, #CUSTOM_RESVAR ; flag a custom resource variable
MOV R10, #CUSTOM_RESVAR_NOPATH ; flag not-a-path by default
ADRL R1, respath
BL bytecopy
[ TRACE = 1
TraWrS 'S', 'N', respath ; Sysvar Name
]
; Now we need to see if the resources variable ends with "$Path".
SUB R1, R1, #6 ; Back to where '$' would be ($ P a t h <n>)
LDRB R0, [R1], #1
CMP R0, #'$' ; Check there's a $ there
BNE no_resources
MOV R2, #0 ; Read the next four bytes into a register
LDRB R0, [R1], #1
ORR R2, R2, R0
LDRB R0, [R1], #1
ORR R2, R2, R0, LSL#8
LDRB R0, [R1], #1
ORR R2, R2, R0, LSL#16
LDRB R0, [R1], #1
ORR R2, R2, R0, LSL#24
LDR R1, lowercase ; Make it lowercase (assumes plain ASCII)
ORR R2, R2, R1 ; [but, then, anything else won't be "path"!]
LDR R1, pathtext
CMP R2, R1
MOVEQ R10, #CUSTOM_RESVAR_ISPATH
no_resources
; At this point, <progname> will contain the name of the program, and <respath> may
; contain the name of the resources variable to set (or null).
; If there is a resources variable, then that will be set to point to the given
; string to call the variable.
; If there is NO custom resources variable, then the default will be
; "<[progname]$Path>".
; Now, to determine the language.
CMP R8, #ARG_ISSET ; "-useos" set?
BNE use_territory ; if NOT, go to ask Territory module
; else fall through to ask the OS
MOV R0, #OSB_RW_COUNTRY ; Read country number
MOV R1, #JUST_READ_COUNTRY
SWI OS_Byte
CMP R1, #IS_DEFAULT ; was it "Default"?
MOVNE R0, R1
BNE country_to_name
MOV R0, #OSB_RW_KEYALPHA ; Read keyboard
MOV R1, #JUST_READ_KEYBOARD ; (shonky last ditch attempt)
SWI OS_Byte
CMP R1, #IS_DEFAULT ; sanity check it!
MOVEQ R1, #IS_UK ; (4=UK)
MOV R0, R1 ; we need this to be in R0
CMP R0, R0 ; set an EQ state to skip following SWI
use_territory ; and save having to have a branch. :-)
SWINE Territory_Number
country_to_name
MOV R12, R0 ; keep a copy for later
ADRL R1, terrname
MOV R2, #16 ; buffer length
SWI Territory_NumberToName
[ TRACE = 1
TraWrS 'T', 'N', terrname ; Territory Name
]
;; <aside>
;; We could alternatively use Service_International (&43) with R2=2, R3=number,
;; R4=<buffer>, and R5=<bufflen>.
;; Bizarrely, both methods seem to use *different* data sources. The Territory
;; Manager calls MessageTrans to parse a message comprised of "T"+"<$num>", you can
;; see the list at Resources:$.Resources.TerrMgr.Messages; while the ServiceCall
;; method uses a lookup table baked into the International module (which is at the
;; end of <devpath>.castle.RiscOS.Sources.Internat.Inter.s.InterBody. There appear
;; to be discrepancies - Arabic, Hong Kong, and Maori. Probably of minor importance
;; given the pitiful state of internationalisation generally (part of what ResFinder
;; is aiming to fix), but it does seem strange to have two not-quite-the-same lists,
;; instead of, say, the ServiceCall passing the buck to the Territory Manager or
;; something...
;; </aside>
; Now load <progname> and check if it is "null". This is a special reserved value
; for when we want to read the various pieces of info without checking/setting
; any resource path.
ADRL R3, progname
LDR R0, [R3]
LDR R1, isnull
CMP R0, R1
BEQ the_extra_stuff ; skip the path stuff
; Do we have a preferred fallback language?
ADRL R0, rffallback
ADRL R1, fallback
MOV R2, #16
MOV R3, #0
MOV R4, #3
SWI XOS_ReadVarVal
CMP R2, #0
MOVEQ R0, #TERMINULL ; no fallback, null-terminate (it should be
STREQB R0, [R1] ; but don't rely on it if we later rely on it!)
; Build the initial path:
; <[progname]$Dir>.Resources. [and something gets added here]
ADRL R1, workspace
MOV R2, #'<' ; write initial '<'
STRB R2, [R1], #1
ADRL R0, progname ; copy <progname>
BL bytecopy
SUB R1, R1, #1
ADRL R0, respathmiddle ; copy "$Dir>.Resources."
BL bytecopy
SUB R1, R1, #1
MOV R7, R1 ; preserve this for later
; Now look to see if we are operating in a UTF-8 alphabet.
MOV R0, #OSB_RW_KEYALPHA ; read alphabet
MOV R1, #JUST_READ_ALPHABET
SWI OS_Byte
MOV R8, R1 ; stash this in R8 (##trashes "-useos" flag##)
CMP R1, #IS_UTF8
BNE check_primary ; not a UTF-8 setup
check_primary_utf8
; If we are here, this machine is operating in UTF-8 mode.
; So we look for the UTF-8 version of the primary language.
; <[progname]$Dir>.Resources.[terrname].UTF8
ADRL R0, terrname ; copy primary territory name
MOV R1, R7
BL bytecopy ; from R0(terrname) to R1(wrkspc ptr)
SUB R1, R1, #1 ; suffix ".UTF8"
MOV R2, #'.'
STRB R2, [R1], #1
MOV R2, #'U' ; It is four instructions to set up <bytecopy>
STRB R2, [R1], #1 ; plus two words of data, and 30 instructions
MOV R2, #'T' ; with eight branches in order to copy the six
STRB R2, [R1], #1 ; bytes of ".UTF8<null>".
MOV R2, #'F' ;
STRB R2, [R1], #1 ; Or we do it the "long winded" way, and it is
MOV R2, #'8' ; done and dusted in twelve instructions with
STRB R2, [R1], #1 ; no branches whatsoever.
MOV R2, #TERMINULL ;
STRB R2, [R1], #1 ; nb: ADRL is synthesised from 2 instructions
[ TRACE = 1
TraWrS 'P', 'U', workspace ; Primary Utf8
]
BL does_this_exist
; Note - we store a pointer to the end of the "Resources" part of the path,
; and not the start of the .UTF8 as the extra work in re-copying the territory
; name is offset by the ease of which we can swap in the fallback language, UK,
; and clip to just Resources.
check_primary
; Now look for the regular version of the primary language.
; <[progname]$Dir>.Resources.[terrname]
ADRL R0, terrname
MOV R1, R7
BL bytecopy
[ TRACE = 1
TraWrS 'P', 'L', workspace ; Primary Latin
]
BL does_this_exist
CMP R0, #0 ; don't fallback if primary found
BNE check_uk_utf8
; We only come through to HERE if we do NOT have a primary language resource.
; So now time to consider the fallback language, if one was specified.
ADRL R0, fallback
LDRB R1, [R0]
CMP R1, #TERMINULL
BEQ check_uk_utf8 ; no fallback, skip on to checking UK.UTF8
check_fallback_utf8
; We have a fallback, so copy this over and look for UTF8 version.
; <[progname]$Dir>.Resources.[fallback].UTF8
CMP R8, #IS_UTF8
BNE check_fallback ; not a UTF-8 setup
; R0 already set (=fallback)
MOV R1, R7
BL bytecopy ; from R0(fallback) to R1(wrkspc ptr)
SUB R1, R1, #1 ; suffix ".UTF8"
MOV R2, #'.'
STRB R2, [R1], #1
MOV R2, #'U'
STRB R2, [R1], #1
MOV R2, #'T'
STRB R2, [R1], #1
MOV R2, #'F'
STRB R2, [R1], #1
MOV R2, #'8'
STRB R2, [R1], #1
MOV R2, #TERMINULL
STRB R2, [R1], #1
[ TRACE = 1
TraWrS 'F', 'U', workspace ; Fallback Utf8
]
BL does_this_exist
check_fallback
; We have a fallback, so look for it.
; <[progname]$Dir>.Resources.[fallback]
ADRL R0, fallback
MOV R1, R7
BL bytecopy
[ TRACE = 1
TraWrS 'F', 'L', workspace ; Fallback Latin
]
BL does_this_exist
check_uk_utf8
; If current *is* UK, don't construct it again!
CMP R12, #1
BEQ check_resources_only
; Now see if UK.UTF8 exists as a possible fallback language.
CMP R8, #IS_UTF8
BNE check_uk ; not a UTF-8 setup
MOV R1, R7
MOV R2, #'U' ; suffix "UK.UTF8"
STRB R2, [R1], #1
MOV R2, #'K'
STRB R2, [R1], #1
MOV R2, #'.'
STRB R2, [R1], #1
MOV R2, #'U'
STRB R2, [R1], #1
MOV R2, #'T'
STRB R2, [R1], #1
MOV R2, #'F'
STRB R2, [R1], #1
MOV R2, #'8'
STRB R2, [R1], #1
MOV R2, #TERMINULL
STRB R2, [R1], #1
[ TRACE = 1
TraWrS 'U', 'U', workspace ; UK Utf8
]
BL does_this_exist
check_uk
; Now look for UK.
; <[progname]$Dir>.Resources.UK
MOV R1, R7
MOV R0, #'U'
STRB R0, [R1], #1
MOV R0, #'K'
STRB R0, [R1], #1
MOV R0, #TERMINULL
STRB R0, [R1]
[ TRACE = 1
TraWrS 'U', 'L', workspace ; UK Latin
]
BL does_this_exist
check_resources_only
; Now we remove the country specifier, to leave just:
; <[progname]$Dir>.Resources
SUB R1, R7, #1 ; back up over the trailing '.'
MOV R0, #TERMINULL ; and terminate it there
STRB R0, [R1]
[ TRACE = 1
TraWrS 'R', 'D', workspace ; Resource Directory
]
BL does_this_exist
check_appdir
; And, finally, build and set the application's own directory...
; <[progname]$Dir>
SUB R1, R7, #11 ; back up over ".Resources."
MOV R0, #TERMINULL ; and terminate it at that point
STRB R0, [R1] ; to leave just "<[progname]$Dir>"
[ TRACE = 1
TraWrS 'A', 'D', workspace ; Application Directory
]
BL does_this_exist
; At this point, <workspace>+256 points to a resources path which will be in
; the form:
; <[progname]$Dir>.Resources.[terrname],<[progname]$Dir>.Resources.UK,
; <[progname]$Dir>.Resources,<[progname]$Dir>
; Exactly what is present depends upon the situation. It could be all four,
; it could be just the base application directory... With or without UTF-8.
; Do we have a custom variable name?
CMP R9, #CUSTOM_RESVAR
ADREQ R0, respath
BEQ do_set_path
; else...
SUB R1, R6, #1
MOV R0, #'$'
STRB R0, [R1], #1
MOV R0, #'P'
STRB R0, [R1], #1
MOV R0, #'a'
STRB R0, [R1], #1
MOV R0, #'t'
STRB R0, [R1], #1
MOV R0, #'h'
STRB R0, [R1], #1
MOV R0, #TERMINULL
STRB R0, [R1]
ADR R0, progname
do_set_path
; Behaviour is as follows:
;
; If this is a PATH, we write the entire composite path.
; If this is NOT a PATH, we truncate at the first ',' and write only that.
; Restore <R11> to point back to start of composite path
ADRL R11, workspace
ADD R11, R11, #256
CMP R9, #NO_CUSTOM_RESVAR ; if NOT a custom resources variable
CMPNE R10, #CUSTOM_RESVAR_ISPATH ; or custom resources variable IS a path...
BEQ skip_to_set_path ; jump over to set what we have
MOV R2, R11 ; else...
look_for_end_loop
LDRB R1, [R2], #1
CMP R1, #',' ; look for comma
CMPNE R1, #TERMINULL ; or terminull (so we don't overshoot)
BNE look_for_end_loop
SUB R2, R2, #2 ; back up over comma/terminull and '.'
MOV R1, #TERMINULL ; paste a terminull there
STRB R1, [R2]
skip_to_set_path
; at this point, the composite string holds what we want to set
; count length of string in <workspace>+256
MOV R2, #0
MOV R3, R11
count_loop
LDRB R1, [R3], #1
CMP R1, #CTRLCHAR
ADDGT R2, R2, #1
BGT count_loop
; Set the variable - and note that this WILL not blow up on older machines if
; the path is long.
; I just tried the following on RISC OS 3.70:
; DIM x% 4096
; FOR l% = 0 TO 4095 : x%?l% = ASC("?") : NEXT
; SYS "OS_SetVarVal", "Test$Val", x%, 4096, 0, 0
; *Show Test$Val
; And it works.
; You *could* replace 4096 with 131072 (128K!), and it *might* work. Seemed to
; sometimes in a TaskWindow, but it made WindowManager kinda crashy. Always hung
; up the machine in the F12 prompt. Hmmm... Probably not such a smart idea, but
; just used to illustrate that it won't immediately keel over dead if the path
; hits the command line length limit.
; It works, too. I also tried:
; Set Test$Path <OvationPro$Dir>., [repeated +/- a dozen times so it was long]
; Type Test:!Run
; and the file appeared. [ yay RISC OS (^_^) ]
; R0 set above <progname> or <respath>
MOV R1, R11
; R2 set above (counter)
MOV R3, #0 ; name pointer
MOV R4, #SET_STRING ; string, GSTrans it
SWI OS_SetVarVal
[ TRACE = 1
TraWrS 'O', 'V', R11 ; Output Variable
]
; NOTE:
; If you are coming here trying to work out why you get weird results, like:
; *UnSet AppName$Dir
; *ResFinder AppName -useos
; *Show AppName*
; AppName$Path : .
; *
; then this is because we pass "<AppName$Dir>." to the OS which tries to expand
; that to be a canonicalised path, and fails because "<AppName$Dir>" does not
; exist. The result is the path becomes a single dot.
; Moral of the story? Set your app$dir stuff first, like any sane person would.
the_extra_stuff
; Now some value-added extras
;
; ResFinder$Language
; Set to textual name of country/territory *used*. On multilingual
; systems this may change depending on whether or not "-useos" was
; specified. This is mostly provided as an easy way to see what
; language ResFiler was looking for, if it doesn't exist.
;
; ResFinder$PlatformClass
; 0 = not identified
; 1 = 26 bit Archimedes or RiscPC
; 2 = 32 bit RiscPC (or RiscPC like)
; 3 = Iyonix
; 4 = OMAP3 (Beagle, xM, IGPV, etc)
; 5 = OMAP4 (Pandaboard, etc)
; 6 = RaspberryPi
; 7 = }
; 8 = >- undefined
; 9 = }
; You can assume that all platform classes EXCEPT #1 are 32bit.
;
; ResFinder$CPUID [undocumented]
; Hex value of CPUID read (except on 26 bit machines).
; Added to aid in supporting anything that is classed as "unknown", and may
; be useful to others (ie to determine various CPU features in later ARMs).
; ResFinder$Language
; ------------------
MOV R2, #0
ADR R3, terrname
count_loop_b ; "count_loop_b"? Dude...lame.
LDRB R1, [R3], #1
CMP R1, #CTRLCHAR
ADDGT R2, R2, #1
BGT count_loop_b
ADR R0, rflangvar
ADR R1, terrname
; R2 set above (counter)
MOV R3, #0 ; name pointer
MOV R4, #SET_STRING ; string, GSTrans it
SWI OS_SetVarVal
; ResFinder$PlatformClass
; -----------------------
MOV R6, #DEVICE_UNKNOWN ; default to "not idenitfied"
; Do the easy one first.
CMP PC, PC
MOVNE R6, #DEVICE_MESOLITHIC ; PC does not equal PC, it's a 26 bit machine.
BNE set_class ; (don't care what, damn thing is Mesolithic!)
; After this point, we can assume we are running on a 32 bit machine, which means
; we will have - at the very least - CPSR, MSR/MRS, and CP15 to play with.
; So read the CPUID into R7. We'll need it later as it's an undocumented SysVar.
MRS R1, CPSR ; remember our current state (prob. USR32)
SWI OS_EnterOS ; go SVC32
MRC p15, 0, R7, c0, c0, 0 ; read CPU ID
MSR CPSR_c, R1 ; back to previous state
; The next round of tests are for OMAP3/OMAP4,RPi. We will basically cheat and ask
; the HAL what the CPU type is. I *still* think this ought to be a simple
; OS_ReadSysInfo call...
; Ensure we actually HAVE a HAL! (or its a RiscPC)
MOV R0, #PLATFORMCLASS
SWI XOS_ReadSysInfo
BVS set_class ; a 32 bit RISC OS that doesn't ReadSysInfo 8?
; (does such a thing exist? we just give up)
; [A9Home? Does RO4.4x/32 use a HAL?]
; While OS_ReadSysInfo 8 can return an ID of RiscPC, A7000, etc - we do not check
; this as the 32 bit version of RISC OS, namely RISC OS 5, works with a HAL; so
; it will return "HAL" both on a RiscPC and on a RaspberryPi; so we can only assume
; that this will indicate the HALness of the OS.
; Of course, a non-HAL 32 bit version of RISC OS would be a non-standard oddity, so
; we just ignore this unlikely possibility (now that RISC OS Ltd is no longer).
CMP R0, #HAS_A_HAL ; HAL
BNE set_class ; 32bit and not a HAL, just give up
MOV R0, #HALDEVTYPE_COMMS ; HALDeviceType_Comms
ADD R0, R0, #HALDEVCOMMS_GPIO ; HALDeviceComms_GPIO
MOV R1, #0
MOV R8, #4 ; just trashed alphabet number, no biggie now
SWI XOS_Hardware ; prod the HAL gently, for it may be grumpy
BVS set_class ; failed? just give up
CMP R1, #NO_MATCH ; didn't match?
BEQ is_this_an_iyonix ; (not a GPIO-able HAL; RPC or Iyonix?)
LDRB R1, [R2, #2] ; read processor type into R1
ADD R6, R1, #DEVICE_HALCPUTYPE ; cheat - we have OMAP3=0, OMAP4=1, RPi=2
B set_class ; and we want OMAP3=4, OMAP4=5, RPi=6, so...
; (any new HAL CPUs will just extend the list)
is_this_an_iyonix
; Okay, so here we know three things:
; #1 We are running a 32 bit version of RISC OS.
; #2 We have a HAL (so it is something RISC OS 5 works with).
; #3 We don't have GPIO capabilities, so it is NOT an OMAP3/4 or Pi.
;
; While there are build options for the Samsung S32440 (an ARM926T board) and a
; Samsung S3C6410 (an ARM11 board), these are not part of the regular downloadable
; builds, so they will not be checked for (and thus ought to appear as "Unknown").
;
; This limits our options to:
; Iyonix - CPU is an XScale
; RiscPC(like) - CPU is an ARM610/710/SA110/7500(FE).
;
; Note that we use "magic numbers" in the CPU detection as burying the actual
; values in a header file would make it harder to see what is going on. This is
; not a problem, however, as the CPU IDs are listed to make it clear how the
; numbers relate and what they are for.
; CPUID already read, value is in R7.
; XScale X80200 ID is &xx052000
; XScale X80321 ID is &69052400
; we look for ^^^
LDR R1, cpuxscalemask
AND R0, R7, R1
LDR R1, cpuxscaletype
CMP R0, R1
MOVEQ R6, #DEVICE_IYONIX ; XScale - it's an Iyonix
BEQ set_class
; Now to probe RiscPC class machines
; ARM610 ID is &xx000610
; ^^
; ARM710 ID is &xx007100
; or &xx047100
; ARM7500 ID is &xx027100
; ARM7500FE ID is &xx077100
; StrongARM ID is &xx01A100
; or &xx01A110
; or &xx01B110
; ^^
; We will strip this down to a single byte value of the unique parts, for
; determining what CPU is in use. This makes a hell of an assumption that we
; can ID processors from a single byte, but we are aided greatly by the fact
; that older style hardware upon which RISC OS runs is a limited subset of the
; amazing plethora of ARM devices available.
; First, deal with the ARM610
MOV R0, R7, LSR#4 ; &0610 -> &0061
AND R0, R0, #&FF ; clip to a single byte
CMP R0, #&61
MOVEQ R6, #DEVICE_RISCPC ; RiscPC-like with ARM610
BEQ set_class
; Now the ARM710/7500(FE)
MOV R0, R7, LSR#8 ; &7100 -> &0071
AND R0, R0, #&FF ; clip to a single byte
CMP R0, #&71
MOVEQ R6, #DEVICE_RISCPC ; RiscPC-like with ARM710 or ARM7500(FE)
BEQ set_class
; The Bush Internet set top box would be classed as RiscPC-like, should anybody
; attempt porting RISC OS to it...!
; But, then, one could argue that it IS a RiscPC, with all the good bits taken out.
; Finally the StrongARM
CMP R0, #&A1 ; is it the 'A1' type?
CMPNE R0, #&B1 ; if not, is it the 'B1' type?
BNE set_class ; if not, assume unknown
MOV R6, #DEVICE_RISCPC ; RiscPC-like with some sort of StrongARM
; fall through to
set_class
; Okay, R6 holds some sort of system type ID (can be "dunno" (=0)), so time to set
; this as a numeric system variable.
ADR R0, rfcpuvar
ADR R1, workspace
STR R6, [R1] ; write value there
MOV R2, #4 ; what is length for a numerical word?!?
MOV R3, #0
MOV R4, #SET_NUMBER ; number
SWI OS_SetVarVal
; ResFinder null ResFinder$Test
; If "<ResFinder$PlatformClass>"=6 Then Echo This is a RaspberryPi!
; ResFinder$CPUID (undocumented)
; ---------------
CMP R6, #DEVICE_MESOLITHIC ; No CPUID for 26 bit systems.
BEQ sayonara ; ARM2 doesn't have it, ARM3 is different...
MOV R0, R7
ADR R1, workspace
MOV R2, #16
SWI OS_ConvertHex8
ADR R0, rfcpuidvar
ADR R1, workspace
MOV R2, #8 ; Hex8 = 8 characters
MOV R3, #0
MOV R4, #SET_STRING
SWI OS_SetVarVal
[ TRACE = 1
TraWrS 'C', 'I', workspace ; Cpu Id
]
; ======================
; That's it, we're DONE.
; ======================
sayonara
[ TRACE = 1
SWI 256+']'
SWI OS_NewLine
]
LDR PC, [R13], #4
; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
bytecopy
; Copies a null terminated string from <R0> to <R1> - COPIES TERMINULL.
; In:
; R0 = Source (null terminated)
; R1 = Destination
; Out:
; R0 = Corrupted
; R1 = Points to null byte at end of string.
STR R2, [R13, #-4]! ; preserve R2
bytecopyloop
LDRB R2, [R0], #1
STRB R2, [R1], #1
CMP R2, #CTRLCHAR
BGT bytecopyloop
LDR R2, [R13], #4 ; restore R2
MOV PC, R14
does_this_exist
; Check if the directory pointed to by <workspace> exists. If it does, add it
; to the composite path string.
STMFD R13!, {R1-R5, R14}
MOV R0, #READ_CATALOGUE ; read catalogue info, no path
ADR R1, workspace
SWI XOS_File
MOVVS R0, #NOT_FOUND ; error? [will cause R0=0 on return]
CMP R0, #IS_A_DIRECTORY
LDMNEFD R13!, {R1-R5, PC} ; return if nothing found
; fall through to...
; Append whatever is at <workspace> to the composite path pointed to by <R11>.
ADR R0, workspace ; source pointer
ADD R1, R0, #256 ; derive pointer to composite
CMP R1, R11 ; is our pointer same as real pointer?
MOVNE R1, #',' ; if NOT, prefix our path with a comma
STRNEB R1, [R11], #1
MOV R1, R11 ; destination pointer
BL bytecopy
SUB R11, R1, #1 ; update destination (back over terminull)
MOV R0, #'.'
STRB R0, [R11], #1 ; add a '.' suffix to the path
MOV R0, #TERMINULL ; then terminate
STRB R0, [R11] ; but don't update pointer
MOV R0, #-1 ; make R0 non-zero to indicate success
LDMFD R13!, {R1-R5, PC}
syntax_error
; whinge that the command line options are all wrong, wah, wah, waaaaah!
ADR R0, syntaxmsg
SWI OS_Write0
LDR PC, [R13], #4
; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
syntaxmsg
EQUS "Syntax: ResFinder <program name> [<resource variable>] [-useos]\r\n"
EQUSZA " ResFinder is licensed under the EUPL v1.1 only.\r\n"
argparams
EQUSZA "a,b,c,useos/S" ; us, appname, res string, -useos option
respathmiddle
EQUSZA "$Dir>.Resources."
rflangvar
EQUSZA "ResFinder$Language"
rffallback
EQUSZA "ResFinder$Fallback"
rfcpuvar
EQUSZA "ResFinder$PlatformClass"
rfcpuidvar
EQUSZA "ResFinder$CPUID"
isnull
EQUS "null"
cpuxscalemask
EQUD &00FFF000
cpuxscaletype
EQUD &00052000
lowercase
EQUD &20202020
pathtext
EQUS "path" ; or &68746170
terrname
% 16 ; long enough for "Azerbaijani" etc, so...
fallback
% 16 ; as above
progname
% BUFFERSIZE
respath
% BUFFERSIZE ; args string path is same, so can't overrun
workspace
; last thing in the program, so from code end to the stack can be workspace
; the least this will be is 4096 bytes - (<progsize>+4); which will still be
; something like 2K-odd. The more likely... 640K or so; depends if WimpSlot
; has already been processed when ResFinder is called.
; Anyway, there's plenty.
; Embedded string that we will trash... [must finish on a word boundary]
EQUS " \n\nResFinder v0.06 2014/02/12\n© 2014 Richard Murray\n"
EQUS "http://www.heyrick.co.uk/software/resfinder/\n\n"
EQUS "Sono mukashi hito datta koto mo wasureta shinkaigyo.\n"
; Now I'm a fish in the deep sea, having forgotten
; that I used to be a human long ago.
; [from "Ryugu no Tsukai" by Chitose Hajime,
; http://www.youtube.com/watch?v=BWvvOohnBWA]
END
Created by ROView by Rick Murray.