Jump to content

dmsc

Members
  • Posts

    1,172
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by dmsc

  1. Hi! A really slow prime testing algorithm With my FastBasic, run-time is 11 seconds (NTSC Atari): Program source is (note that FastBasic does not support GOTO):
  2. Hi! Yes, RespeQt is based on AspeQt code with further fixes and additions, developed as open source. You can download over github for Windows/MacOS/Linux https://github.com/jzatarski/RespeQt/releases There is also a dedicated forum here in AA: http://atariage.com/forums/forum/184-respeqt-sio2pc-software/ About the DIY cheap SIO2PC-USB cables, I think that this video is good: The USB serial cable can be purchased cheap, see for example: https://www.aliexpress.com/item/6pin-FTDI-FT232RL-USB-to-Serial-adapter-module-USB-TO-TTL-RS232-Cable/1858974923.html
  3. Hi! I would add to the first post a reference to RespeQt, instead of AspeQT, and also the cheap sio2pc-usb options available today.
  4. Hi! Best advice is simply to get a SIO2PC. You can make one really cheap in about 5 minutes! for a simple tutorial, see:
  5. Hi! Clever. So, only limitation is you can use only 3 colors in the sprites, but changing "oratab" table you can select any three colors. To select the shift, do you modify the "shape" pointer in place, or have different loops?
  6. Hi, For the hardware locations, best reference is the Altirra Hardware Reference Manual, you can download the PDF from http://www.virtualdub.org/downloads/Altirra%20Hardware%20Reference%20Manual.pdf For the OS, there is the Operating System User's Manual, download from http://atariage.com/forums/topic/127483-atari-os-and-hardware-manuals-get-them-here/
  7. Hi! I agree about zero-terminated strings in this context, but as said before, pre-allocating strings does not solve my main worry: all string operations become slower and more complicated with long strings, as you now need to keep the allocation length, and loops are no longer as simple. I really think that most uses of strings are for small (less than 40 bytes even) strings. Even today's languages optimize for short strings. That's why I wrote above that perhaps letting to use byte arrays as (limited) long strings made sense, that way you have fast operations for common short strings and slower operations on uncommon byte arrays. So, another proposed syntax, storing the length as a "hidden" integer variable: dim big(2000) string : ' A big "string" array, compiled to: dim big_data(2000) byte : big_len = 0 big() = "Hello World" : ' Compiled to: tmp$="Hello World": move adr(tmp$), adr(big_data), len(tmp$) : big_len = len(tmp$) big(6,) = "Alfred" : ' Compiled as: tmp$="Alfred": move adr(tmp$), adr(big_data)+6, len(tmp$) : big_len = len(tmp$) ? big() : ' Compiled as: bput #0, adr(big_data), big_len Note that as I don't store allocated length, there is no bounds checking. This is actually more difficult to implement in my parser than before, as currently the parser emits one reference for each parsed element, but I could add stack manipulation tokens to allow the repetition.
  8. Hi! Yes, but that makes string manipulations a lot more time consuming, because you can't simply point to a part of a string. Currently FastBasic stores strings and arrays as simply pointers to the data, with the length as the first byte of the string (like Pascal short strings). String variables are allocated at full 256 bytes on assignment, so there is no memory fragmentation nor garbage collection needed. Also, as length is limited to 255 bytes, string ops are done with small and fast loops. To use dynamic long strings, I would not only need to store the length as two bytes, but also to reallocate the string on each assignment (as you can't simply copy the contents of strings with different lengths), so you wold need to compact the string area on memory exhaustion (as old microsoft basics did) or to implement a memory allocator supporting alloc/free. If on the other hand I implement static strings (like Atari BASIC), each string variable would need 3 integers (6 bytes): a pointer to the data, the allocated length and the current length. This could work in the floating-point version by storing the string descriptors in the floating-point stack, with the TOS at FR0. I'm not fond of AtariBASIC string handling, so I'm not sure that I would like implementing this.
  9. Hi Alfred! As you said, FastBasic currently does not support many string functions and long strings, but you can use byte arrays as longer strings and work directly with them, for example the integrated editor loads the complete file into a byte array and then prints segments using "BPUT", and manipulate parts using MOVE. I'm want FastBasic to grow to a useful language for many types of programs, and extend it to address common needs (always keeping it as fast as possible). Perhaps some additions could be made: - Possibility to treat byte arrays directly as (null-terminated) strings, with a syntax like: dim big(2000) byte : ' A big "string" array big() = "Hello World" : ' Compiled as: tmp$="Hello World": move adr(tmp$), adr(big), len(tmp$) : poke adr(big)+len(tmp$), 0 big(6,) = "Alfred" : ' Compiled as: tmp$="Alfred": move adr(tmp$), adr(big)+6, len(tmp$) : poke adr(big)+6+len(tmp$), 0 ? big() : ' Compiled as: i=0: while big(i) : put big(i) : inc i : wend - Adding functions to search memory/strings, something like " index = memsearch( ADR(haystack$), LEN(haystack$), ADR(needle$), LEN(needle$) ) " What do you think, would that be useful? Main problem with null-terminated strings is that you can't store $0, and in Atari this is the common "hearth" character. Thanks, Daniel.
  10. Hi! that happens when using common names Well, if I ever change the name it would be to something that abbreviates to "FB", so perhaps "FBasic", "FlashBasic", "FleetBasic", "ForwardBasic" ...
  11. Hi! Atari BASIC, in an 800XL *without* DOS, reports 37902 bytes. With BW-DOS reports 31392 bytes. This is why I always used TurboBasicXL I think that the interpreter is rather easy to follow, as each token code is fairly well separated from the rest. Some tokes fall through another, like ADD/SUB, where SUB simply negates the argument and falls to ADD: TOK_SUB: jsr neg_AX ; Fall through .proc TOK_ADD ; AX = (SP+) + AX clc adc stack_l, y pha txa adc stack_h, y tax pla jmp next_ins_incsp .endprocThis is a threaded interpreter, that means that each token jumps to the next one via a dispatch table (the "next_ins" call). As many tokens (like ADD) need the removal of one value from the stack, the jump to "next_ins_incsp" increment the stack before calling the next token. To increase the speed (and reduce space), the dispatch code is in zeropage, and at dispatch time Y register already has the stack position. No, thanks Should I ever get to work on a Basic backend, I should rather go finish my VRBasic compiler for Jaguar (and include Blitter/GPU support finally) And honestly, what else is there to implement in FastBasic anyway? At this point, the language looks pretty much final, you can even choose to compile rather then interpret. Perhaps some graphics / PMG libraries ? What's your top 5 features on the to-do list currently ? My top missing feature (that I already began to implement) is usage of RAM under ROM in XL computers. Currently I have a version that reports 33039 bytes free, but I want to integrate a fast math package and move the interpreter under the ROM also. The most difficult part wold be the compilation from the IDE, as the runtime must be read from memory and written to disk, and that would not be possible directly. Easier than that, I plan to change the code so that the cross-compiler can link only the used parts of the runtime, generating smaller binaries. And after that, perhaps working in a cross-compiler to 6502 code,
  12. Hi! Also, you can always add a new statement or function to make a game smaller. A little tutorial on editing the compiler/interpreter: suppose that you want to add a new statement "FLIP", abbreviated "FL.", and that takes an integer argument: Edit src/basic.syn: At the "TOKENS" group, add a new token, named "TOK_FLIP". At the PARSE_LINE_COMMAND block, add a new line like: "FLip" EXPR emit TOK_FLIP This means: parse a word "FLIP" (or "FL.", or "FLI."), then an integer EXPRession, that would be pushed to the stack, and then emit code for the new token TOK_FLIP. Edit src/interpreter.asm: At the end, there is the same list of tokens that in the syntax file. Add also "TOK_FLIP" here, in the exact same position. Add, before the "segment JUMPTAB" line, the assembly code for the token: .proc TOK_FLIP ; Here, A holds the low part and X the high part of the argument. ; And at the end, remove the value from the stack and continue with the interpreter. jmp pop_stack This is all that is needed. But, many simple statements don't really need any modification to the interpreter. For example, suppose that you want a new statement to write to CHBAS register (to select the character set address), like "CHBAS 120". This can trivially be compiled to "POKE $2E4, 120", so we can instruct the compiler to do just that: Edit src/basic.syn:At the PARSE_LINE_COMMAND block, add a new line like: "CHbas" emit TOK_NUM word CHBAS EXPR emit TOK_POKE This means: parse a word "CHBAS" (or "CH.", etc.), emit a token "TOK_NUM" (this pushes the following word to the stack), emit the 16 bit value "CHBAS" (from "atari.inc" this is already defined as $2E4), parse an integer EXPRession, that would be pushed to the stack, emit the token TOK_POKE. Note that the emitted code can be as complicated as you want, and the parser support subroutines to factorize common stuff, currently this is the parsing code for "SOUND": "SOund" EXPR emit TOK_USHL emit TOK_NUM word AUDF1 emit TOK_ADD "," EXPR "," EXPR_AB emit TOK_SHL8 emit TOK_ADD emit TOK_DPOKE emit TOK_NUM word AUDCTL emit TOK_0 emit TOK_POKE emit TOK_NUM word SKCTL emit TOK_BYTE emit 3 emit TOK_POKE "SOund" emit TOK_SOUND_OFF The first line says: parse a word "SOUND" (or "SO."), parse one integer expression, emit TOK_USHL token, this multiplies the expression by two, emit TOK_NUM with the 16 bit value "AUDF1", emit TOK_ADD, this adds the the last two values (AUDF1 and EXPR * 2), parse a "," parse one integer expression, parse a "," parse EXPR_AB. This is a subroutine that gets two integers and returns the first multiplied by 16 plus the second emit TOK_SHL8, this multiplies the last expression by 256 emit TOK_ADD, this adds the last two expressions emit TOK_DPOKE, this stores the 16 bit expression to the address before and then simply emit the tokens TOK_NUM with value "AUDCTL", TOK_0, TOK_POKE, TOK_NUM with value "SKCTL", TOK_BYTE with value "3", TOK_POKE. With that, the text "SOUND A, B, C, D" is translated to "DPOKE AUDF1 + A*2, B + (C*16+D)*256 : POKE AUDCTL, 0: POKE SKCTL, 3". The parser will try the first line, if it can't match the input to that, all the emitted code is rolled back and the second line is tried.
  13. Hi! Shameless plug, you can use my FastBasic IDE, it's free, faster and IMHO, nicer than BASIC XE. See at http://atariage.com/forums/topic/267929-fastbasic-beta-version-available/?p=3870695
  14. Hi! No, the integer version reports 37662 bytes free. Most of the sise reductions have been in the parser and editor, the runtime is already pretty small, at 2153 bytes (this includes the full interpreter). The floating point runtime is larger at 3038 bytes, a lot of that is used by the math functions. Should not be that difficult, I think that the easiest is as an option to the cross-compiler. In fact, limiting the support to add/sub/mult/div and with a range from -128.0 to 127.99609375 (-$80.00 to $7F.FF) the current interpreter has all the necessary support. More work should be to implement trig and trascendental functions. But I wonder, is such a short range really worth? I think that 24.8 (or even 16.8 ) should be a lot more useful. Remember that, as this is an interpreter, going with smaller numbers is not going to be much faster. And currently, the interpreter keeps the 16bit top-of-stack in the A/X registers (and the floating point top-of-stack in FR0), so all the operations are 16bit. You can take a look at the sources, any help is welcomed
  15. Hi! Thanks, looks good. I know that the name was already taken, but I really like it, so DMSC-FastBasic should be ok. Or perhaps "FastBasic 2017"
  16. Hi! Not a problem, just link to the github page https://github.com/dmsc/fastbasic/releasesand perhaps to the atariage thread.
  17. Hi! I published a new version today, with a lot of changes from the last one: Now the floating point and integer versions are integrated in the same source, "FB.COM" is the full version and "FBI.COM" for the integer only version. A lot of optimizations, now FOR loops are a lot faster so the sieve benchmark is at 1329 jiffies (in NTSC, with screen on). Also, the interpreter is still smaller than before, "?FRE()" gives 29803 bytes, or 31093 bytes in the integer only version. Added all standard floating point functions and operators from Atari Basic: "^" (power), ATN(), SQR(), SIN(), COS(), RND(), DEG, RAD. Note that SQR and RND use the fast algorithms from Altirra Basic, SIN and COS use a new minimax implementation that is faster and more accurate than Atari Basic. Fixes for the INPUT statement. Added a "KEY()" function that returns TRUE if a key is pressed. Completed the manual with all the functions and statements. More information is in the manual at github, also included in the ATR. You can download the release as an ATR at https://github.com/dmsc/fastbasic/releases, there are also cross-compiler binaries for windows and linux. To use the cross-compiler, you need CC65 (from http://cc65.github.io/cc65/), there is a simple script to automate the build. Have fun! fastbasic.atr
  18. Hi!, You can use my FastBasic IDE (editor and compiler), download at https://github.com/dmsc/fastbasic/releases . The sieve benchmark completes in 1329 jiffies (NTSC, screen on), so it's faster than compiler TB-XL. Also, you can mix integer with FP variables, and produce an Atari executable. You only need the ATR image, the other binaries are for cross-compiling. Daniel.
  19. Hi! I tough that you follow the line-pair (vertical segment) by using an inner loop like: for(x=x0; x<x1; x++) { y0 += y0_step; y1 += y1_step; for(y=y0; y<y1; y++) plot(x,y); } This can be made fast as you advance in X one pixel a time, so you can simply rotate a mask (for the pixel color) each iteration, increasing the pointer when the mask rolls. As you need to pre-compute "y0_step" and "y1_step" before calling the code, my idea is that you can pre-compute the steps in object space and then simply project them, and store the steps instead of storing the end points of the segments. But, this won't be a gain, because in the 6502, projecting the pre-computed steps is as expensive as computing the steps afterwards (one division, y0_step = (y1-y0)/(x1-x0) ), to do the projection you need 4 multiplications instead. Modern GPUs do this kind of optimizations, projecting many coefficients and then doing a hit-test for each pixel to determine if they are inside or outside of the triangle being resterized.
  20. Hi! Note that if you use DDA to rasterize, you can pre-calculate coefficients and simply project them, keeping always dy==1 (or min(dx,dy)==1). But in my (limited) experiments, I have found that in the a800 the faster algorithm seems to still be bresenham.
  21. Hi!, Also, you can use "PEEKW" instead of your two PEEK, this should be the same as asigning to a variable: POKE( PEEKW(88) + (x+X_OFFSET) + (y+Y_OFFSET)*20, image->_imageData + image->_color);Or better yet, you can define a macro like: #define SCREEN(x,y) ((unsigned char *)*(unsigned *)88)[x + y * 20]And use it like: SCREEN(x + X_OFFSET,y + Y_OFFSET) = image->_imageData + image->_color;
  22. Hi! Yes, the IDE needs at least 24K RAM, mainly because DOS uses about 6K. But the compiled program will run ok in your 600XL.
  23. Hi! Or, you could use my FastBasic compiler, download from this post Type "FB" to load the IDE, type CONTROL-N and ESC to start a new program, and type your program, for example: OPEN #1,8,0,"P:" IF ERR() > 1 ? "Error opening P:" END ENDIF ? "Type keys, BREAK ends" REPEAT GET KEY PUT #1,KEY UNTIL ERR() > 1 CLOSE #1 Then, you can save the program with CONTROL-S, run with CONTROL-R and write an executable file with CONTROL-W, if you name the resulting program with a ".COM" extension it can be loaded directly from the DOS prompt.
  24. Hi, Yes, I will add a test to carrera3.bas to check if there is enough memory. The program is pretty rough because it was one ten-liner demo, so the memory allocation is hard-coded at start.
  25. Hi! Yes, currently my carrera3.bas uses too much memory to run within the IDE. You need to compile the program directly to disk (using CONTROL-W key) and run the resulting binary from DOS. I have tried to reduce the memory footprint so that there is enough left to actually be able to run it from the IDE, but without using the RAM under the OS it will not be easy, as you need to keep the compiler, editor, program source and compiled binary in RAM at the same time, and Carrera3D needs 32kB free to store all track images, PM graphics and gr.7 screen.
×
×
  • Create New...