-
Notifications
You must be signed in to change notification settings - Fork 20
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
Functional enchancements request #26
Comments
Hi!
Thanks! I admit that I have not spent much time improving the Atari IDE, as much of the requests I receive are from people doing development on PC or using other editor, so lets see your suggensitons:
Line delete is the standard SHIFT-DELETE key, I could implement SHIFT-INSERT easily, it is the same as CONTROL-A, ENTER, UP. For go-to-line number, using CONTROL-G seems right? Copy and paste is difficult, as I don't currently have a buffer to store copied text, only a buffer for current line. What I could do is a key that remembers a line and then another that inserts a copy of that line in the current position, to do that I could store the memory address of an edited line. CONTROL-M (mark) and CONTROL-C (copy) ?
That is not as easy as it seems because the program is written without fixed memory locations - at compile time the linker decides where to put each piece of code. One possibility is using the value returned by "FRE()", as the value should be much lower when your program runs in the IDE. This is simple, but does not work if a user runs your program in a computer with less RAM. A more complicated option is using the interpreter pointer (this is like the program-counter of the interpreter) and test if it is greater than a give value, then you are under the IDE. The pointer is currently at ZP locations $85 and $86. Problem is, if your program is big, the code could be bigger even outside the IDE. Currently, in FBI, the IDE uses memory up to about $4140, then there is the program text and after that you have your program code, so you could assume that the code pointer is always > $4150 when run from the IDE. See this program:
It writes 16752 from the integer IDE, 10474 compiled from the IDE to disk, 8648 compiled with the cross-compiler.
I could implement simple shift operators, but I'm not sure about the syntax. Currently the interpreter has two shift tokens, used internally, a simple shift-left by 2 and another shift-left-by 8. The first is used at array access, as the index must be multiplied by 2 to get the memory address, the second is used for SOUND, PMADR, XIO and OPEN. And there is another question - for right-shifts, ¿do you want arithmetic or logic shift? I recommend that you create a new enhancement request with only this, so we can discuss the syntax and options.
There is a LOCATE command in the current version! It is used the same as the Atari BASIC one.
If you have specific requests, please create a separate issue with that, so I can track it. Some of the graphics commands of TurboBasic XL are not that useful (IMHO), and there are ones like the flood-fill that are really complicated - to be as fast as possible there is a custom fast PLOT routine for each Atari graphics mode, and the code is about 1kB.
Problem is that the FastBasic stack is really small, so I don't want to add stack operated calls, but you can call procedures recursively (and the cross compiler even optimizes tail-calls to jumps). Again, it is better to discuss this with specific examples.
I plan to implement PROCedures with parameters, to simplify code with a lot of procedures, but functions are really difficult because the way the compiler generates code. When you write an assignment like "A(3) = B + 5" the compiler calculates the address of the expression "A(3)", and stores it in a special register, like "SADDR = ADR(A) + 3 * 2". Then, the rest of the line calculates the expression "B + 5" and at the end the value is stored to the SADDR location. It is like the code transforms to "SADDR = ADR(A) + 3 * 2 : DPOKE SADDR, B+5 " In fact, the code generated for "DPOKE ADR(A) + 3 * 2, B+5" is exactly the same as the code generated for "A(3) = B + 5". This is simple - as the address to store calculation is separated from the assignment - and also fast, because the store is always to an address in a ZP location, but has a problem. If you could write user-defined functions, any POKE, DPOKE or array store in the function would overwrite the value in SADDR, and make the code invalid. Note that originally FastBasic used the stack for storing the addresses, but this was a lot slower because the 6502 code was bigger for each POKE and DPOKE.
You are welcome! |
Thank you for so fast reply!
Speaking of a mnemonics, G(o), J(ump) or L(ine) should be ok.
I could suggest another way.
Well, since almost any computer system provides some registers for user-defined use, the IDE could set it's own special value to one of the following memory locations which are described in "Mapping the Atari" book:
OK, I will do it.
Oops, but this command isn't listed in the manual! Is there some updated manual version or a file where I can see the full list of implemented commands and operators?
Great, where can I read more about it?
Oh yes, I really noticed that because what I was exactly doing is implementing the closed loop fill function. But really with the need of maintaining the stack pointer manually, it's much easier to make a serious logical error.
Currently I code emulated behaviour of functions this way (which probably is similar to what as I can see in your IDE source code):
Probably, some function defining syntax can be convertible to a form similar to one described above. I see advantage of this approach in possibility to include generation of local variables, although this may be dangerous without storing them in a stack and just leaving at some arbitrary temporary memory locations. |
Look what i've found. I've tested this location under different states of the system and emulator. |
Created issue #28 to track progress.
Tried that before, it was even slower :( The E: handler in the OS is very slow. Try loading an E: accelerator before the IDE, you can use my own https://github.com/dmsc/e-accelerator Try attached ATR, type "EFAST" before loafing FB or FBI.
Problem with the markers is that they would be invalidated on each edit operation, so I would need to keep them updated. With two markers, this is double the code for each operation. I was thinking more on only one marker, but each copy/move operation advances the marker by one line. This way, to copy 5 lines from line 10 to line 100, you do: "CTRL-G 10 CTRL-M CTRL-G 100 CTRL-C CTRL-C CTRL-C CTRL-C CTRL-C", and if instead of CTRL-C you press CTRL-M, you move the lines. Created issue #29 to track progress.
Note that to implement this, both the IDE and the standalone programs needs to write the location (with different values), so that the value is consistent. What do you think on adding BREAK key support? See issue #10
The last version of the manual is always here, https://github.com/dmsc/fastbasic/blob/master/manual.md . I forgot to add LOCATE to the manual in the last version but added it on march 4.
Those are specific to the cross-compiler, so are not in the manual but in the compiler usage text: https://github.com/dmsc/fastbasic/blob/master/compiler/USAGE.md#linking-other-assembly-files As the compiled code is passed to the CA65 assembler, the named locations are really the ones included from the CA65 headers: https://github.com/cc65/cc65/blob/master/asminc/atari.inc , https://github.com/cc65/cc65/blob/master/asminc/atari_gtia.inc , https://github.com/cc65/cc65/blob/master/asminc/atari_antic.inc , https://github.com/cc65/cc65/blob/master/asminc/atari_pokey.inc
Well, I learned a lot about TurboBasic XL when I was a child and hand-disassembled a lot of the code :) You can browse my curren disassembly at https://github.com/dmsc/turbo-dis , the PAINT code starts at https://github.com/dmsc/turbo-dis/blob/master/turbo-mads.asm#L9751 but also uses the code for fast plot at https://github.com/dmsc/turbo-dis/blob/master/turbo-mads.asm#L9635 . Overall, it is about 300 lines of assembly code.
That would be possible with my "procedures with parameters", and I could add an extra parameter to procedures to store a return value into a variable passed as reference, so you can return values that way.
Yes, functions are problematic because you have side-effects, using a proper stack is the only safe way to maintain all state. But, even if FastBasic uses a stack, it compiles code for a register machine. This is because I discovered that using registers is faster in the interpreter, as the 6502 don't have good support for stack based operations. So, the VM has two registers: "AX" (the 16 bit accumulator) and "SADDR" (the 16 bit store-address register). Then, many simple operations (like "A=2", or "POKE 123, 45" don't use the stack at all, the first is transformed to "LOAD_BYTE 2 ; STORE_VAR A", the second to "LOAD_WORD 123; STORE_SADDR ; LOAD_BYTE 45 ; STORE_BYTE_SADDR" |
I think this gonna work. The only thing I feel doubted about is double assignment for Ctrl-M. In this routine I don't understand how to unmark a line or mark another for further copy/move operation. If Ctrl-M is reserved for marking, maybe it's better to assign Ctrl-C for copy and, say, Ctrl-X for movement?
I think, as long as it doesn't need any additional code to be included in the application, the way with the Break key is definitely better. |
Hi!
Just nonsense on my part, I meant CTRL-K form marking, or as you say CTRL-X for move, but in any case different keys!.
Yes, I did a few tests by hooking on the break interrupt vector. Problem is, if you press break in the middle of an OS routine (like LOAD or SAVE from disk) the hardware state would be messed up. |
Hi @rpocc ! Most of the IDE features requested are now implemented in the upcoming v4.4:
It would be great if you could test all the above. Have Fun! |
Thank you for developing this great IDE! Your totally modern and alternative approach to BASIC really reinvents the whole idea of high-level programming for 8-bit. It doesn't have so much optimized commands as Turbo BASIC but anyway, the numberless coding for 8-bit is a fantastic improvement. I keep my eye close on this project and would like to express my big respect!
I've tried to make a complete application with it and find several things, which I miss during development.
And by the way, is there any chance that some time in the future you will implement stack-operated function calls? Currently I've found a way for processing recursive code, using global temporary variables for data interchange between procedures and some array-emulated stack, but it's so complicated and so slow that becomes impractical. Meanwhile, since we are playing by rules of not using line numbers, labels and non-conditional jumps, implementing stack and functions could be super-helpful for keeping the code structured and readable. Sometimes I still miss labels and good old GOTO.
Thanks.
The text was updated successfully, but these errors were encountered: