Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FR: Oric Atmos support #183

Open
seclorum opened this issue Jan 17, 2025 · 16 comments
Open

FR: Oric Atmos support #183

seclorum opened this issue Jan 17, 2025 · 16 comments

Comments

@seclorum
Copy link
Contributor

Would be great to add Oric Atmos support to Oscar64, somehow:

https://en.wikipedia.org/wiki/Oric_(computer)

An existing OSDK for Oric:

https://osdk.org

.. has docs on zero-page:

https://osdk.org/index.php?page=documentation&subpage=zeropage

.. and the Oric memory map:

https://osdk.org/index.php?page=documentation&subpage=memorymap

All about the Oric ULA (not sure if entirely relevant to Oscar64):

http://oric.free.fr/HARDWARE/ula.html

Schematics:

https://homepages.uni-regensburg.de/~hep09515/oric.html

Great emulator:

https://github.com/pete-gordon/oricutron

Well, anyway, just a suggestion .. if Oscar64 devs have interest and can point me in the right direction, I could maybe participate in adding platform support ..

@drmortalwombat
Copy link
Owner

drmortalwombat commented Jan 17, 2025

A contribution in the form of a pull request would be nice. You can follow the implementation of e.g. the ATARI or X16 variant. Simply follow the TMACH_ATARI or TMACH_X16 enum value in the source.

@seclorum
Copy link
Contributor Author

Thanks for the tip - I will make an attempt at this over the next week or so ..

@seclorum
Copy link
Contributor Author

Okay, made a thread on defence-force, documenting the breadcrumb trail through the code with notes required to add Oric support .. link here:

https://forum.defence-force.org/viewtopic.php?t=2701

Will get some feedback and ideas from the rest of the DF crew and see what sort of progress can be made ..

@seclorum
Copy link
Contributor Author

@drmortalwombat I've begun a 'naive' implementation of Oric support - but I'd like to be using your preferred C/C++ Indent style. Do you have a preferred option for gnu-indent or a similar indent program, which we can use to auto-format the code according to your desires? I've just tried to apply your use-tabs preference to the files I've modified so far, but I've botched it up and ended up reformatting the code (CLion, grr..) rather extensively - I'll back this out in my own branch, because I believe in respecting project-creators' preferences for indent style, but it would be very handy if we could find a way to format the code according to your preferences automatically, so I can switch between styles and then - before submitting a PR - reformatting according to your preferences.

If this doesn't make sense (because you prefer hand-formatted code over gnu-indent/indent tool formatting), no big stress - I will hand-format too.

FWIW, this is my suggested setup of .indent.pro, based on an analysis of your code:

--tab-size4               # Tab size is 4 spaces (but tabs are used, not spaces).
--use-tabs                # Use tabs instead of spaces for indentation.
--braces-after-func       # Place opening braces on a new line for functions.
--braces-on-if-line       # Place opening braces on the same line for control statements.
--indent-level4           # Indent level is 4 spaces (converted to tabs).
--line-length80           # Set maximum line width to 80 characters.
--honour-newlines         # Preserve newlines as they appear in the code.
--no-space-after-function-call # No space between function names and opening parentheses.
--space-after-casts       # Add space after casts (e.g., `(int) var`).
--dont-break-procedure-type # Don’t break return type and function name onto separate lines.
--indent-parameters       # Indent parameters in function declarations/definitions.
--align-with-spaces       # Align multi-line statements with spaces, but use tabs for indentation.

Perhaps you could review this, and if it is satisfactory to your eyes, we can add an .indent.pro settings file to the project to make sure things continue to adhere to your preferences .. ?

@drmortalwombat
Copy link
Owner

Some observations:

  • no space after casts
  • no maximum line length
  • no braces on if line

I have visual studio do the formatting for me

@drmortalwombat
Copy link
Owner

Some comments on your register assignment:
ACCU has to be four bytes
WORK has to be ten bytes
STACK and LOCALS are pointers so two bytes
TMP and TMP_SAVED shpuld be 16 bytes, the more the better
FPARAMS_END is exclusive

@seclorum
Copy link
Contributor Author

seclorum commented Jan 25, 2025

Okay .. after messing with .indent.pro for too long, I'll hold off on auto-formatting the code for now, as its a bit tricky to get this right and match your style automatically without messing up the entire file - but I commit to fixing things that you find unsavoury when you see it. Just don't hold it against me if I accidentally put {}'s where they don't belong, and maybe before my final PR I'll revisit this issue so that it can be automated, or at least semi-sensible according to your needs.

I'm guessing you're watching my branch commits on my fork - if so, I'll continue to push stuff rigorously for your review if that works for you .. and basically will push a final PR some time in the future when my fork is suitable.

Regarding register assignments, I'm a bit confused and probably don't understand this properly yet - these are indices in the zero page .. do the existing definitions for other architectures match the zero page heuristics for those systems, or are they adjusted to 'fit into existing ZP assignments without breaking things'? I'm not as familiar with Atari or C64 as I should be (yet), so maybe you could give a bit more wider context so I can be sure I'm putting things into place properly for the Oric?

This is the Oric Zero Page definition:

Address Range	Purpose
$00-$03	        Temporary storage for values (scratchpad).
$04-$07	        Input/output buffers or secondary pointers.
$08-$0B	        Floating-point accumulator (FACC) for math operations in BASIC.
$0C-$0F	        Temporary storage for floating-point results or intermediate steps.
$10-$17	        Pointers for BASIC stack operations and calculations.
$18-$1F	        Function arguments for mathematical or string functions.
$20-$3F	        Reserved for BASIC interpreter and firmware routines.
$40-$47	        Vector pointers for system routines like IRQ or NMI.
$48-$7F	        General-purpose workspace (may vary depending on ROM version).
$80-$FF	        User-defined variables and data storage during program execution.

So by my reckoning on your advice, would this be correct?

ACCU            $08  - use existing Oric indices for FACC
WORK            $48 - will switch later when Oric-1/Atmos detected
TMP             $WORK + $0A (10 bytes after WORK)
TMP_SAVED       $TMP + $0F (16 bytes after TMP)
LOCALS (ptr)    $TMP_SAVED + $0F (16 bytes after TMP_SAVED) 
STACK (ptr)     $LOCALS + $02 (2 bytes after $LOCALS)
FPARAMS_END     $FF

@seclorum
Copy link
Contributor Author

seclorum commented Jan 25, 2025

Hmm.. still not feeling certain I understand this properly yet, but here's my proposal:

	if (mTargetMachine == TMACH_ORIC) {
		BC_REG_ACCU = 0x08; // use existing Oric indices for FACC
		BC_REG_WORK_Y = 0x48; // 1 byte
		BC_REG_WORK = BC_REG_WORK_Y + 0x01;          // 0x48 + 0x01 = 0x49
		BC_REG_TMP = BC_REG_WORK + 0x0A;             // 0x49 + 0x0A = 0x53
		BC_REG_TMP_SAVED = BC_REG_TMP + 0x10;        // 0x53 + 0x10 = 0x63
		BC_REG_LOCALS = BC_REG_TMP_SAVED + 0x10;     // 0x63 + 0x10 = 0x73
		BC_REG_FPARAMS = BC_REG_LOCALS + 0x02;       // 0x73 + 0x02 = 0x75
		BC_REG_IP = BC_REG_FPARAMS + 0x02;           // 0x75 + 0x02 = 0x77
		BC_REG_ADDR = BC_REG_IP + 0x04;              // 0x77 + 0x04 = 0x81
		BC_REG_STACK = BC_REG_ADDR + 0x04;           // 0x81 + 0x04 = 0x85
		BC_REG_FPARAMS_END = 0xFF;                   // Final fixed value
	}

@drmortalwombat
Copy link
Owner

drmortalwombat commented Jan 25, 2025

Here is a not actual struct that may clear up the requirements:
struct Registers
{
char WORKY;
char WORK[10];
char FPARAMS[12..];
unsigned IP;
char ACCU[4];
unsigned ADDR;
unsigned STACK;
unsigned LOCALS;
char TMP[16..];
char TMP_SAVED[16..];
};

@drmortalwombat
Copy link
Owner

The zero page regions that are used for these fields are picket to plac nicely with the OS of the system, but mostly reusing BASIC addresses. There is the -xz (COPT_EXTENDED_ZERO_PAGE) for the C64 which also disregards the Kernal and uses the first 128 bytes for the compiler needs by extending the space for ZP passed arguments and caller saved local variables.

@seclorum
Copy link
Contributor Author

ah, understood.

I think I got the BC_REG_FPARAMS set up incorrectly - should this be before the stack, and after everything else? I also need to understand the REG_IP and REG_ADDR registers a bit better .. doing some code-reading after lunch ..

@drmortalwombat
Copy link
Owner

There are two fixed placement requirements, BC_REG_FPARAMS_END = BC_REG_FPARAMS + 10 and BC_REG_TMP_SAVED = BC_REG_TMP + 16. The 10 and 16 may be larger if you have ZP to spare. The compiler determines the number of zero page passed arguments and caller saved registers from the distance between the two pairs.

@seclorum
Copy link
Contributor Author

Thanks for the explanation - I will leave these size constants at 10 and 16 - for now, just to avoid any confusion as I proceed, but once the dust settles and .TAP files are being written, we could revisit this and tweak accordingly. For this it would be good to have other Oric boffins' input, just to ensure no other considerations about ZP usage are overlooked - even after 40 years - as an original Oric-1 owner - I still find myself learning a lot from the Oric guru's..

I will do another pass at setting these register values in todays session and then work on .TAP file writing, then .. the situation with crt.o .. which I have to admit is a bit .. messy .. so I will probably also add the rigging needed to isolate the Oric crt from the existing C64/architectures implementations, in order to avoid the somewhat difficult to grok confusion of the existing code, which I understand probably evolved, but I do feel could be a bit better refactor'ed/organized to accommodate new architectures - but I will route around this for now and set things up with a crt_oric.c/.h scenario ..

@drmortalwombat
Copy link
Owner

You might want to look at the more straight forward code writing variants WriteXexFile or WritePrgFile

@seclorum
Copy link
Contributor Author

Yes, I'm proceeding with those as a base, referring to other TAP file writing functions already implemented in the OSDK and elsewhere ..

@seclorum
Copy link
Contributor Author

Okay, I got as far as adding conio functions for Oric .. getting segfaults related to the region calculations, which are just not working yet. Need to also check the CRT code for side effects - there are no Oric-specific changes to the CRT yet.

Will have another pass at it tomorrow - here's a link to the diff for easy reference:

main...seclorum:oscar64.oric:oric-support

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants