Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


dmsc last won the day on July 14 2017

dmsc had the most liked content!

Community Reputation

1,473 Excellent


About dmsc

  • Rank

Profile Information

  • Gender
  • Location
    Viña del Mar, Chile

Recent Profile Visitors

9,135 profile views
  1. Hi! Thank you for your comments!! To not miss this, I added a bug report on github: https://github.com/dmsc/fastbasic/issues/46 Have Fun!
  2. Hi! Try this fixed version: circ.lst Fixed two bugs: - an "STA" instead of an "SBC" in one assembly instruction - missing initialization for a table of powers of two. Also, this is the BASIC program, "circle 5", works for me: circ5.lst Have Fun!
  3. Hi! You seem to think that somehow CLANG is more advanced than GCC. This is false. CLANG is a newer project, and has a lot of commercial baking, so it is catching up to GCC fast, but IMHO, it is still behind: it support less targets, is is less mature and it optimizes about the same in common architectures (it produces code sometimes faster, sometimes slower than GCC). GCC support Link-Time-Optimization from version 4.5, released in 2009, just a few months prior to the release of the first version of CLANG (1.0) that still did not had complete C++ support. So, why LTO is not enabled by default? - It is slow, specially on big C++ projects. As the full source code is "visible" to the compiler, and C++ templates produce code explosion, the compiler has to analyze a lot of code, using a lot of memory. - It can fail in older codebases that cheat with symbol types - this was a common pattern, define one symbol (variable or function) with different types in different source files. Both Chrome and Firefox use LTO for their release builds, as it produces faster and smaller code, specially on those projects that include a lot of libraries internally to avoid shipping DLLs. Have Fun!
  4. Hi! Modern ELF linkers (like LD from binutils/GCC or LLD from CLANG) allows using wildcard in the section specifications, allowing to write one bit object file with one section per function or data object - this allows to filter out individual functions from one object file, reducing the number of source files needed. Currently LD65 does not support this, but it could be added so you could write a linker config like this (simple sample from FastBasic linker config): FEATURES { STARTADDRESS: default = $2000; } SYMBOLS { __STARTADDRESS__: type = export, value = %S; } MEMORY { ZP: file = "", define = yes, start = $0094, size = $0040; MAIN: file = %O, define = yes, start = %S, size = $BC20 - %S; } FILES { %O: format = atari; } FORMATS { atari: runad = start; } SEGMENTS { ZEROPAGE: load = ZP, type = zp, optional = yes; CODE.*: load = MAIN, type = rw, define = yes; DATA.*: load = MAIN, type = rw optional = yes, define = yes; BSS: load = MAIN, type = bss, optional = yes, define = yes; HEAP: load = MAIN, type = bss, optional = yes, define = yes, align = $100; } Now, you could write assembly like this: .secgment "CODE.00001" .proc print_eol .import print_char .export print_eol lda #155 jmp print_char ,endproc .secgment "CODE.00002" .proc print_char .export print_char tay lda ICAX1,X sta ICAX1Z lda ICPTH, x pha lda ICPTL, x pha tya rts ,endproc .secgment "CODE.00003" .proc print_str .import print_char .export print_str ; .......... some code that uses print_char rts ,endproc Now, you need to also implement the option for garbage-collect unused linker sections - this is the most difficult part as you need to only include sections that contains symbols that are referenced, and discard sections that aren't. Hacking LD65 is not that difficult, you could try!. Also, if you are writing a cross-compiler, current PCs are really fast, so this is not really a problem. When compling FastBasic, compiling the C++ parser is ten times slower than compiling the full library 😛 Many compilers (both GCC and CLANG, for example, with the "-flto" option) support link-time-optimizations, and the technology is always the same: instead of compiling to machine language, compile to some intermediate representation. On link time, the liner calls a plugin that is passed all the needed object code, the plugin calls the compiler again passing all the intermediate code as one big chunk. Have Fun!
  5. Hi all! I suspect most early computer algorithms were rediscovered multiple times in the home computers, because we did not had easy access to all the information! About math algorithms, those were known and used from the early history, and binary floating-point algorithms are published from the 1950's. In the 6502 you can find implementation of multiplication and division as old as the Woz 6502 FP math, that uses a lot of tricks to make the code small. About the graphics algorithms, the Atari OS has an implementation of the Bresenham algorithm for line drawing, and the equivalent circle-drawing algorithm was also known, as shown in the article from 1983, were it is called "potential", and a 6502 assembly version is given: https://www.atarimagazines.com/compute/issue38/066_1_CIRCLES.php Have Fun!
  6. Hi! Be careful! - The array is defined from 0...31, but used from 0 to 63. - The memory area is not cleared, so the program will only work of no other program was loaded first in that memory. Have Fun!
  7. Hi! I have a syntax file for FastBasic and one for Turbo Basic XL. I'm not really happy with the FastBasic one, I tried to make it aware of the lack of spaces but it does not always work, look at line 3: Have Fun! fastbasic.vim tbxl.vim
  8. Hi! Congratulations to @vitoco!! Played 10 lines hero to the end, very good game in ten lines: Also payed Rockfall, very good!!, but level 3 is already too difficult for me! Again, congratulations to all participants, it is great to see so many entries Have Fun!
  9. Hi! Yes, but the routine at $0919 starts a simple "bytecode" interpreter from the PC position, it has a three commands depending on the bits 5 & 6 of each byte: - 00 : JSR to any address from $0000 to $1FFF, - 01 : Moves N bytes inside the buffer at $0D8A, N can be up to $1F bytes. - 10 & 11 : moves N bytes from two arbitrary 16 bit addresses. If bit 7 of the bytecode is 0, another bytecode is executed after this, otherwise it returns to the address following the last bytecode. For example, at $07F2 the code does: L07F2: jsr L0919 ' MOVE $0D17, $02E7, 2 .byte $4D,$17,$42,$E7, ' MOVE $07F0, $000A, 2 .byte $47,$F0,$40,$0A ' MOVE $0DF2, $0CF1, 2 : END .byte $CD,$F2,$4C,$F1 txa L0802: sta L0E4C,x cpx #$97 So, it writes the value at $D17 to MEMLO, the value at $7F0 to DOSVEC and the value at $DF2 to $CF1. Have Fun!
  10. Hi! Well, there are (expensive) alternatives: https://www.sindenlightgun.com/videos/ Have Fun!
  11. Hi! Watching the video, it was not the only weird problem in the setup - other games also did not work. Also, while loading TBXL, the screen got corrupted at the end of the loading - that does not happen in a real Atari. Have Fun!
  12. Hi! I thought that you had source for BW-DOS (or contact with the author), but I see that you are starting from a disassembly. I have a slightly better disassembly done about four years ago, with some of the routines identified: main.asm Changing parts of BW-DOS without original sources is difficult because a lot of the disk access code is written in a bytecode with special move and call instructions. I also have format.asm , verify.asm and xfsio.asm disassembled. Have Fun!
  13. Hi! I did a google-translated version a while ago: XDOS-2.4_en.pdf Have Fun!
  14. Hi! Yes, the manual is not very deep in arrays and strings. Perhaps you can suggest some edits to make it better? I would appreciate it. I decided to implement strings differently to make it easier to use strings in simple programs - without the need for DIM using strings is more natural, IMHO. The main problem is that FastBasic string support is really simple, so it does not do garbage-collection like in other BASIC with automatic strings, so I opted for statically allocated strings - basically, whenever you perform a string assignment the code generated is: ' Code for A$="hello" IF NOT ADR(A$) THEN DIM A$(256) MOVE ADR("hello"), ADR(A$), LEN("hello") + 1 The advantage of statically allocates strings are: - you can edit the contents and concatenate it in the same buffer (for example, you can do A$ += "world" to append a word) - you don't loose memory on each assignment - the address is fixed, so you can store machine code or binary data inside. The obvious disadvantages are: - the string always use 256 bytes, even for short strings. - you can't store "constant" strings in a string variable, as they can't be overwriten. Have Fun!
  15. Hi! I prefer this, it is more "idiomatic", as it does not uses PEEK: DIM A$(10) DATA B() BYTE = "Cero","Uno","Dos","Tres","Cuatro","Cinco","Seis","Siete","Ocho","Nueve","Diez" X = ADR(B) FOR I = 0 TO 10 A$(I) = $(X) X = X + LEN($(X)) + 1 NEXT FOR I = 0 TO 10 ? A$(I), ADR(A$(I)) NEXT As Vitoco said, in the above example, FastBasic allocates 256 bytes for each string assignment (the "A$(I) = ...." in the loop), and copies the "constant" string from the DATA array to the new allocated string. If your strings are always constants, and you don't want to use much memory, you can instead store the pointers (address) to the strings in a new array: DIM A(10) DATA B() BYTE = "Cero","Uno","Dos","Tres","Cuatro","Cinco","Seis","Siete","Ocho","Nueve","Diez" X = &B FOR I = 0 TO 10 A(I) = X X = X + LEN( $(X) ) + 1 NEXT FOR I = 0 TO 10 ? $( A(I) ) NEXT
  • Create New...