Page 2 of 5
New game uploaded: Core War
Posted: Mon Jun 14, 2021 9:06 pm
by rje
1 hour ago, svenvandevelde said:
What is a CLI?
Sorry about that -- yeah a "command line".
I have to do the hard work and get the opcodes all working properly... then I can put the arena / core into banked RAM.
New game uploaded: Core War
Posted: Mon Jun 14, 2021 10:59 pm
by rje
So I'll ask for the sake of asking. What's the best use for that banked RAM?
I'm just assuming that the "arena" is the best place for it, because that way I can have enough memory for an 8000 location arena, which will need 40k to 48k RAM, depending on what the location record stores.
The downside is that fetching data from the arena becomes a function call, or a macro, instead of directly accessing an array. I mean, array access is WONDERFUL and easy.
But... suppose I only need the current 16K RAM for the 4K arena. Maybe I can get by with that... I still have 6K "golden RAM" free, and I can shove things like the help text (for example) into a single RAM bank.
I'm just asking for the sake of asking. I always feel the need to use up all that free RAM, but that doesn't mean I ought to.
New game uploaded: Core War
Posted: Tue Jun 15, 2021 12:39 am
by Ed Minchau
1 hour ago, rje said:
So I'll ask for the sake of asking. What's the best use for that banked RAM?
I'm just assuming that the "arena" is the best place for it, because that way I can have enough memory for an 8000 location arena, which will need 40k to 48k RAM, depending on what the location record stores.
The downside is that fetching data from the arena becomes a function call, or a macro, instead of directly accessing an array. I mean, array access is WONDERFUL and easy.
But... suppose I only need the current 16K RAM for the 4K arena. Maybe I can get by with that... I still have 6K "golden RAM" free, and I can shove things like the help text (for example) into a single RAM bank.
I'm just asking for the sake of asking. I always feel the need to use up all that free RAM, but that doesn't mean I ought to.
Well, you don't have 6k of Golden RAM, you have 1kb.
Why would an arena cell need more than one byte? The original core war only had something like 10 instructions.
New game uploaded: Core War
Posted: Tue Jun 15, 2021 6:26 am
by BruceMcF
7 hours ago, rje said:
So I'll ask for the sake of asking. What's the best use for that banked RAM?
I'm just assuming that the "arena" is the best place for it, because that way I can have enough memory for an 8000 location arena, which will need 40k to 48k RAM, depending on what the location record stores.
The downside is that fetching data from the arena becomes a function call, or a macro, instead of directly accessing an array. I mean, array access is WONDERFUL and easy.
But... suppose I only need the current 16K RAM for the 4K arena. Maybe I can get by with that... I still have 6K "golden RAM" free, and I can shove things like the help text (for example) into a single RAM bank.
I'm just asking for the sake of asking. I always feel the need to use up all that free RAM, but that doesn't mean I ought to.
If the highest frequency operations fit in under 8K, there's a lot to like for using Banked RAM for the VM itself. If an arena plus the other global transient data that fits into LowRAM, then calling across segments might require doubling the JSR/RTS, but if that is in the ">80% of the code that takes <20% of the cycles", that could be an acceptable overhead for clearing the LowRAM for the arena matrix.
Calls pass information in given locations rather than registers, but when you are defining the calls rather than integrating already-defined standard call, you just design with that in mind. Then at the very end of each CODE segment, you have:
Quote
LONGCALL: LDA RAMBANK : PHA : STY RAMBANK : JSR + : PLA : STA RAMBANK : RTS
+ JMP ($BF00,X)
and you have the banks of your different code banks in zero page, and to make a long call to the "Showit" routine in "HelpBank" (to invent gadget/widget names):
LDY HELPBANK : LDX #SHOWIT : JSR LONGCALL
In that process, in the third instruction of the longcall you have started executing the version of the longcall in the destination bank, and you execute the RTS from the version of the longcall in the caller segment.
And if your "CORE" process fits entirely within a segment and the called routines are lower frequency or I/O functions, so that you do not need a symmetric call, but you have one caller segment and one or more called segments, you can dispense with saving the current bank:
LONGCALL: STY RAMBANK : JSR + : LDA COREBANK : STA RAMBANK : RTS
+ JMP ($BF00,X)
In that process, your caller don't ever execute some of these instructions and your called don't ever execute some, but you still assemble parallel routines for sanity's sake, because it ensures that the locations are correct when the segment changes.
New game uploaded: Core War
Posted: Tue Jun 15, 2021 6:27 pm
by rje
Thank you Bruce! I appreciate the suggestions... and yeah, I have thought about how nice it would be to shove some common operations into assembly into a bank. I'm going to keep that in mind. It's a good idea, since I can start easy and small.
I considered that 8K of static data and routines leveraged into Bank 1 wouldn't require any overhead. And that might be all I need. Maybe.
Re "golden" RAM. Sorry, I meant main RAM. I've got 32K of it filled up, half with the arena. 6K left to cram in the "multi-processing" orchestration. Doable, probably not a problem, but still.
@Ed: Regarding opcodes. The instruction is 32 bits... More if the arena is > 4096 locations. There are only 15 opcodes, but there are two operands, each with four possible addressing modes.
unsigned char opcode: 4;
unsigned char aMode: 2; // immediate, direct, indirect, predecrement indirect
unsigned char bMode: 2; // same modes as above
unsigned char A: 12; // i.e. the size of the arena
unsigned char B: 12; // again, arena size
// = 32 bits.
//
// If the arena size grows to, say, 8000 locations, then:
//
unsigned char opcode: 4;
unsigned char aMode: 2; // immediate, direct, indirect, predecrement indirect
unsigned char bMode: 2; // same modes as above
unsigned char A: 13; // i.e. the size of the arena
unsigned char B: 13; // arena size
// = 34 bits... e.g. 5 bytes.
4096 locations is really not bad for an 8-bit arena... I believe 8000 locations became normal in the 1990s, so let's say 12 bits is OK.
Some simulators have an additional "owner" byte. Suffice to say that 4 bytes is a minimum "cell" size, without doing memory management.
New game uploaded: Core War
Posted: Tue Jun 15, 2021 8:23 pm
by rje
So I've recently re-read articles and postings and webpages on Core War, and after internal debating I'm preferring these assumptions:
Based on 1986 opcodes and modes.
Portable, simplistic file format.
Core size is 4096 cells.
Up to 8 warriors, each with up to 8 processes.
Redcode files have a minimal format that allows portability and bare functionality:
X1A #nnn #nnn
X1B #nnn nnn
X1C #nnn @nnn
X2A nnn #nnn
X2B nnn nnn
X2C nnn @nnn
X3A @nnn #nnn
X3B @nnn nnn
X3C @nnn @nnn
So each valid line has three "words":
Ocode, which can be any length, but currently they're all 3 characters long.
Operand A, which has an optional sigil denoting immediate (#) and indirect-address (@) modes.
No sigil means direct-address mode.
The rest of the operand is a positive or negative number.
Operand B (same format as A).
Everything that doesn't scan is a comment. I may have to tighten that up a bit!
The loader doesn't do pre-processing. So I don't have macro support, I don't have pseudo-opcode support, and I don't have label support. Maybe later. Of course an off-board pre-processor would work just fine.
*1 Opcodes and Modes. I'm using the original 3 modes. These are the opcodes I like currently:
0 HCF
(Used for holding data; remove the process from the system ("Halt and Catch Fire"))
1 MOV
2 ADD
3 SUB
(Funnily enough, it turns out that SUB is not simply a negated ADD.
I was sad when I figured this out.)
4 JMP: unconditional jump
5 JMN: jump if A != 0
6 JMZ: jump if A == 0
7 SEQ: ++ip if A == B ("CMP" = skip if equal)
8 SLT: ++ip if A < B (skip if less than)
9 SNE: ++ip if A != B
10 FLP: ++ip if an essentially random system status word < B
11 reserved
12 reserved
13 reserved
14 XCH: exchange operands
15 SPL: push to process queue
New game uploaded: Core War
Posted: Tue Jun 15, 2021 11:54 pm
by BruceMcF
Yeah, you can get there incrementally, and if it is all called routines in banks, with the calller in LowRAM, all you NEED is zeropage locations to store the bank addresses if you spill over 8k support routines. A parser and help routines makes great examples of the kind of thing that can be put there.
But if the caller is in LowRAM, it's still just
"LDY HELPBANK : STY RAMBANK : JSR routine"
... which you could easily make a ".JBSR bank,address" macro (for jump bank subroutine). The only thing to keep in mind when still in just one bank is to leave on register free for a later bank select operation if/when it spills into two.
New game uploaded: Core War
Posted: Mon Jun 21, 2021 6:41 pm
by rje
LABELS
I am always thinking about labels. Labels are critically important in writing and reading Redcode. For awhile I figured they could be managed off-board with a pre-processor. But, I am not convinced, though I CAN totally defer writing that parsing logic in until I can't stand it any longer.
I think it's going to be a two-pass effort:
Parse each line of code, building up a dictionary of labels and their corresponding line numbers. In other words, something like
char* label[ MAX_NO_OF_LINES ];
Then substitute in the second pass.
I can get away with this because redcode programs are short. In my case, probably to 256 instructions max.
Traditional redcode doesn't have any special characters to denote a label: it just shows up before the opcode. Thus a dumb sscanf might just look for it first, e.g.
if (sscanf(input, "%s %s %s %s", label, opcode, a, b) != 4)
Since I'm already validating the opcode, if it checks out then good-faith suggests that <label> really is a label.
New game uploaded: Core War
Posted: Thu Jun 24, 2021 3:12 pm
by rje
I've added a label for building with CC65 versus CC, and added a Makefile.cc. So now I can run it on my Mac as I work out the kinks.
New game uploaded: Core War
Posted: Fri Jun 25, 2021 12:32 am
by rje
Okay, I've got the arena running, and I believe the opcodes work correctly
? Up to eight warriors can run in the arena at the same time, and each can split into eight processes maximum. I haven't tried the stress test yet...
I added in one more opcode that's been there (in some form) from the very beginning. That brings the total to 13:
HCF (halt and catch fire -- holds data and kills any process that tries to execute it)
MOV
ADD
SUB
JMP
JMN
JMZ
SEQ
SLT
SNE
FLP - an experimental and marginally useless opcode I might remove.
DJN - I resisted adding this for a long time
XCH
SPL
Room for two more. Useless but amusing opcodes are welcome.
I removed the more annoying addressing mode: "indirect address with pre-decrement". Awful. I'm open to suggestions for amusing but not complicated or annoying addressing modes. Maybe an indexed mode?