bobbimanners / eightball Goto Github PK
View Code? Open in Web Editor NEWThe Eight Bit Algorithmic Language for Apple II, Commodore 64 and VIC20
License: GNU General Public License v3.0
The Eight Bit Algorithmic Language for Apple II, Commodore 64 and VIC20
License: GNU General Public License v3.0
You can do this:
word aa[10]=0;
but not this
word aa[10*10]=0;
This is because the parser is very stupid.
I plan to fix this at some point.
The documentation on the wiki is not very good.
If I set the start address of the generated code to 0x5000 I should be able to compile EightBall code on Linux and run in the the VM on the Apple II. This works with some programs (sieve4.8b
for example) but fails with unittest.8b
. If I compile the failing chunk of the unit tests on Linux as a separate small program it still fails on the Apple II VM, so it is not memory exhaustion. If I compile the same chunk on Apple II it runs fine on Apple II VM. What else is different I wonder?
Right now the comment character ' is handled as a command, which means that a semicolon is needed to comment after a statement:
pr.msg "Hello" ; ' Say hello
This is a bit ugly. The ' character should probably be handled in the parser itself so everything from ' to newline is ignored.
The same character is used for two purposes right now. I need to choose a new character for bitwise OR on Commodore machines.
The reference implementation of the VM is not optimized for speed and has loads of paranoid checks.
Once things stabilize I will attempt an optimized version in 6502 assembly.
Compiler/interpreter code has some bloat that can be removed / refactored.
Compiler/interpreter memory management can be improved. Would be better if source code and variables were allocated in same block rather than two separate blocks, but this would be difficult on VIC20 (due to hole in the memory map.)
This would be nice:
call foo("Hello")
end
sub foo(byte s[])
pr.str s; pr.nl
endsub
One fairly easy way to implement this:
If we implement this, we can probably get rid of the PRMSG VM instruction and the pr.msg
statement, since pr.str "xxxx"
should work.
Copy disconnect_ramdisk()
and associated code from EDIT.SYSTEM
to any and all Eightball executables that use auxiliary memory.
Not all errors paths report an error.
Some errors paths report more than one error.
In general this is a mess!
Compiler omits to set compile=0
after crapping out on error.
This makes the interactive environment very strange, until it is fixed by a successful compile.
It would be nice to be able to switch between 40 and 80 columns within Eightball scripts. Maybe implement a mode statement:
mode 40 ; 40 columns!!
mode 80 ; 80 columns!!
The keyboard input on the Apple II is not buffered at present, which means that if a program is running and the user hits a key other than escape, and the Eightball program does not read that character with kbd.ch or kbd.ln then it will not be possible to interrupt the program with ESC. I probably need to implement a small keyboard buffer and handle ESC specially so it is not queued.
Would be nice to be able to define constants and use them in constant expressions.
For example
const size=10
word A[size*size] = {}
word i=0
for i=1:size
A[i]=1
endfor
However we are super short of memory so we may need to implement this in a devious way.
tetris.8b
uses Apple II lo-res graphics and other Apple II specific low-level hardware access.
Should do a port to C64 and VIC20 also!
I have not yet implemented the pass-by-reference semantics for passing arrays to subroutines as parameters in the compiler.
The tricks I use in the interpreter do not adapt so well to the compiler, so I am working out how to do this easily (and with little code.) For now this only works when interpreted (run
) but not when using the comp
command and the Virtual Machine.
It would be convenient to be able to do:
word xx[3] = {123, 456, 789};
sub recurse3(word x)
if x==0
return 1;
else
return x*recurse2(x-1)
endif
endsub
This works okay in the interpreter but the compiled code does not run. Swapping the order of the arguments to the multiplication resolves the issue!
cc65 provides LOADER.SYS which should allow me to access more main memory on Apple II. I need to experiment with this.
This crashes the interpreter right now:
pr.dec 1**2
I am sure there are other cases too!
Right now the source is always loaded into memory. It would be nice to be able to compile with source direct from disk (loading a line at a time, or using say a 256 byte buffer). This would allow larger programs to be compiled (at the expense of not being able to use the interpreter on such files.)
Works in interpreter, but not in compiler.
I expect it is messing up the addressing (abs vs relative)
Memory allocated by the compiler is always initialized, but this is not true for the compiler. As a result if an array is longer than its initializer, it is not guaranteed that the remaining elements are zero.
It would be handy if:
word xx[10]={}
ensured zero filled array in the interpreter, just as it does in the compiler.
Single line while
loops:
while 1; pr.msg "Hello"; endwhile
Do not compile correctly. The endwhile
seems to be skipped.
Works okay in interpreter though. I should also check single-line forms of if
/else
/endif
and for
/endfor
for the same defect.
Suppose we have a subroutine like this:
sub foo()
word i=0
for i=0:10
if i%3
return 1
endif
endfor
endsub
It works fine interpreted and compiled the first few times, but when compiled it leaks the eval stack each time we do the return 1
. The reason for this is the for
pushes some stuff to the eval stack which the endfor
usually handles, but here we are jumping out. Need to re-work this code. Think it only applies to this specific case with for
loops.
I should find out how to use the other 64K. This project is crying out for more workspace!
At present bytecode uses absolute addresses for branches / jumps and is not relocatable. It may be better to use relative branches / jumps so code can be readily relocated within VM memory.
Advantages:
Drawbacks:
To implement this, we need to add new VM instructions and modify the compiler to use them.
The compiler allocates the linker tables using the same heap as source code (and same allocator). Write an allocator to put them at the top of this heap instead of being interleaved with lines of source. This means they can be easily freed after compilation so we don't leak memory with every comp
.
There is code in eightball.c
(enabled by setting EXTMEMCODE
) to store generated bytecode in extended memory. However it is currently disabled because emit_fixup()
ends up corrupting the bytecode. This seems to be caused by an underlying bug in the cc65 extended memory driver for Apple //e aux memory (a2e.auxmem.emd
). I will investigate further ... first step is a stand-alone demonstration of the problem.
For some reason EightBallVM is not working on VIC20. Seems to be memory corruption.
At present I am setting memory limits manually. I review the cc65 .map
file and find the upper limit of the memory used by cc65 and then set my HEAP1 and HEAP2 limits accordingly. Oliver Schmidt suggested a better way using malloc()
and _heapmaxavail
. See cc65 issue #655 for more details. This applies to Apple II only, as I am not linking in malloc()
on VIC20/C64.
If the array is global, it works okay:
This is okay.
word A[10]=0
call foo(A)
end
sub foo(word A[])
bar(A)
endsub
sub bar(word A[])
...
endsub
However, this fails:
call foo()
end
sub foo(word A[])
word A[10]=0
bar(A)
endsub
sub bar(word A[])
...
endsub
It is almost certainly a screwup with relative vs absolute addresses.
Right now the comp
command always writes bytecode to a file called bytecode
. It should allow the user to specify the name of the file.
The VM code is oblivious to the big hole in the middle of the VIC20 memory. This limits memory usage to 8KB ($A000 block).
cc65 is not compiling the switch()
statement that selects on the opcode into a jump table. This could be made much more efficient!
Most of the infrastructure is there to support multidimensional arrays. Need to finish this.
On CBM you can't just blindly overwrite a file. Should issue code to delete ("scratch") it first. The Commodore DOS 'overwrite' prefix (which I recall is '@') is buggy on original Commodore drives and corrupts disks, so we shouldn't rely on that.
I am using zero page locations for the VM registers and evaluation stack on Apple II, but I have not done this for Commodore VIC20 and C64 yet.
Need a way to invoke a machine language routine from EightBall. It would also be good to be able to pass in register values (A,X,Y). This should work for both interpreted and compiled code.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.