- CPU within the 3DO is an ARM60 of the ARMv3 architecture.
- 12.5Mhz, ~10MIPS, big endian, 16 32bit registers, 32bit data bus, 32bit address bus.
- No integer division instructions, uses C library functions
__rt_sdivand__rt_udivfor signed and unsigned division respectively. Can take 20-140 cycles. See armdbccg for optimized code to divide by known values. - No floating point hardware.
- No 16bit integer instructions. Reads/writes to memory will be more expensive.
- Registers are 32bit so best to avoid using
charandshortfor local variables. Otherwise will need to sign-extend or zero-extend. - Data should be word aligned (4 bytes). See the data sheet for details on how unaligned loads/stores behave.
- Function calls with more than 4 arguments will store additional arguments on the stack.
- There are NO data or instruction caches on the ARM60.
- Writing Efficient C for ARM
- More ARM60 details
- 2MiB DRAM
- 1MiB VRAM
- Different parts of the system have limits on what RAM they can use. See the developer docs for specific functions for details. However, VRAM is generally accessible just as DRAM and DRAM is valid (and preferred) location for CEL data.
- The system could technically handle upto 16MiB of total RAM in a number of combinations including 14MiB DRAM and 2MiB VRAM. This is only available via the Opera emulator.
- No access to Redbook audio from Portfolio.
- If you want CD quality audio you need to stream from a file on the filesystem.
- You will read details about a "free running" mode for the DSP in the original developer docs but no such ability was made available in the original SDK.
- There is currently no tooling to write DSP programs. There are remnants of a PForth based assembler in the Portfolio M2 repo but has not been reworked for modern systems.
- 2x CDROM drive
- Abstracted behind drivers and IO library.
- Primary way to access data is via the Opera Filesystem APIs.
- Is possible to access raw blocks rather than using the filesystem but not terribly useful. Perhaps if you wished to remove uncertainty regarding the filesystem from loading data. Could use the filesystem to find the file's data block address and perform raw reads.
- Only supports quads. No distinction between texture and polygon (no UV.)
- Can not run in parallel with the CPU.
- Call
DrawCels()orDrawScreenCels()as few times as possible. Instead chain together CELs and call draw once if possible. DrawCels()is faster thanDrawScreenCels().- Larger CELs are more expensive to draw than smaller even if scaled up. Use LODs / manual mipmaps if possible.
- Avoid VRAM as a source for CELs. Reduces performance.
MapCel()is slower thanFastMapCel()but the latter has limitation.- No Z-buffer. Need to sort CELs for painters algo yourself.
- Uses forward rasteriation. Performance is directly related to CEL data size.
- No hardware mip-mapping.
- Does support backface culling and clipping.
- CEL Engines are pipelined and work on rows. This means that every row of CEL data must be word aligned and a minimum of 2 words (8 bytes) even if not used. Not the width and height or related. Just the data.
- The "Pixel Processor" (also referred to as PIXC and PPMP) provides fixed function color arithmetic but has a large number of settings making it a bit complex to use.
- Part of the MADAM chip. Memory mapped fixed point matrix arithmetic mostly. Technically asynchronous but practically can not run in parallel to the CPU.
- Wrapped by API due to different hardware support on different hardware variants.
- Supports arrays as input which should be used to reduce library call overhead.
- Portfolio is a high level, preemptive multitasking operating system developed by the 3DO Company.
- Portfolio, leveraging a MMU within MADAM (referred to as memory fences), restricts direct access to hardware by the user. Direct hardware access requires a privileged driver.
- Usage of the Portfolio OS is currently not optional. An entire new OS and hardware abstractions would need to be created to replace it.
- Portfolio supports multiple processes and threading.
- Shared libraries are supported, including privileged calls, however multiprocess development is rare so of limited use except for getting privileged access for interacting with hardware.
CreateBitmap()has a bug in it where it sets REGCTL1 (which controls the clipping width and height) to the bitmap width and height rather than the clip values if provided. When/if we rebuild the library this can be fixed.
- The Lib3DO TextLib and FontLib provide decent, flexible functions for fonts and text generation. TextLib provides a “TextCel” object which has a Cel CCB which can then be used to render to a Bitmap. No documentation but look at “DrawTextString()” for an example.
- Unless doing a lot of text it is probably better/easier to do bitmap based fonts.
https://3dodev.com/documentation/development/opera/pf25/ppgfldr/smmfldr/cdmfldr/07cdm002
- Don't assume a certain data delivery rate from an IO request.
- When using
DoIO()be sure to check both the return value and on successio_req->io_Error. - Don't alternate reads, rapidly, between two or more files. This will almost certainly require seeking and impose serious delay in IO requests.
- Issue read requests in 32KiB or larger chunks when possible.
- Use adequate buffering to survive a rotation of the CDROM (up to 150 milliseconds).
- Use multiplex data streams rather than multiple open files.
- Concat files into a single file and split in memory to improve loading time.
- The current ISO builder app is not sophisticated as the original and have some bugs but plans exist to build a new one.
https://3dodev.com/documentation/development/opera/pf25/ppgfldr/smmfldr/gspfldr/06pgstoc
- As mentioned in the docs you must open any Devices, Drivers, Folios, etc. before using them in a thread. While memory may be shared between Tasks and Threads it does not appear Items share ownership or exist within one's scope.
- While it may appear that threads can't take arguments due to the CreateThread signature you can in fact pass two values via the CREATETASK_TAG_ARGC and CREATETASK_TAG_ARGV tags via CreateItem/CreateItemVA.
- When using CREATETASK_TAG_SP the ta_Arg value should be set to the bottom of the stack. malloc(stacksize) + stacksize.
Uncomment the line in takeme/AppStartup regarding sysload to add a
CPU and DSP resource overlay to your app.
- ANSI C compatible
- Do NOT use
<>angle brackets for#includeing headers asarmccwill use builtin variants intended for ARM's libc. - User Guide
- Reference Guide
- Custom 3DO created (and community tweaked) libc.
- Not a complete library.
- Missing
FILEbased filesystem functions. - Missing
scanffamily of functions. - Plans exist to add missing features and generally improve the libc.
- ARM C++ 1.11 is a pre-standard compiler. From section 3.10 in the ref guide:
- Exceptions are NOT supported
- Namespaces are NOT supported
- RTTI is only partially supported
- C++ style casting is only partially supported
- While technically mostly supported templates can be buggy and complex usage may crash the compiler
- User Guide
- Reference Guide
- A version of RogueWave's STL was originally included but found to be troublesome to use and occasionally broken.
ttlTrapexit's Template Library was created to replace it but is incomplete.
ARM C++ 1.11 treats POD (plain old data) and objects differently so POD must be
expressly handled/ignored when worrying about object destruction. There are no
default destructors for objects either meaning it is not possible to simulate a
'placement delete' to force destruction. obj->~OBJ() will not work unless
expressly defined. As a result it is difficult to write generic template
based data types. To work around this the STL like library provided removed
memory freeing from 'delete' to force its use as a placement delete. Meaning
that when wanting to free data from 'new' one should use memory_delete(ptr).
That said best to use or create higher level objects to manage such things.
Simple versions of shared_ptr and unique_ptr are provided.
There might be a better solution to this problem but after many attempts, including attempting to use the strategy by RogueWave which didn't seem to work, this was settled on till something better could be be done.