Initial import

This commit is contained in:
David Schmenk 2018-04-25 09:13:44 -07:00
commit 1066a69950
258 changed files with 116171 additions and 0 deletions

13
BUILD.TXT Executable file
View File

@ -0,0 +1,13 @@
This is the initial build process based on my very crusty and horrible makefile. This should improve as help arrives.
1. Download/build/install cc65
2. Install Java developers kit
3. Check out vm02 source
4. 'cd vm02/src'
5. 'make clean'
6. 'make'
7. 'make image'
This will put the binary files into the vm02/release-$(VERSION) and vm02/samples-$(VERSION) directories in Virtual ][ name format. You can use something like CiderPress to copy the files into a disk image if you don't use Virtual ][.
Dave...

317
DESIGN.TXT Executable file
View File

@ -0,0 +1,317 @@
VM02 V1.0 Design
================
Author: Dave Schmenk
Date: 4/2/2010
Revision: 1.3
Introduction
============
VM02 is a Java compatible VM written in 6502 assembly language for the Apple II series of computers. Everything has been implemented from scratch using the JVM specification and black-boxing the Sun JVM with sample code. Certian aspects of the JVM have been simplified or removed to fit the target machine. This document is an attempt to record the design of VM02 for other developers to come up to speed, as well as to jog the memory of the original developer who has a tendency to forget what he has done.
VM02 has quite a diversity of technology. Some is rather sophisticated and not deeply discussed. Floating point operations, DVM implementation, IRQ support, and other details are left out, but a perusal of the source should answer most questions.
The design document will follow the implementation of VM02 as that was how many decisions were made along the way. Starting with the memory manager and class file loader which drives much of the following implementation through the class database, frame manager, thread scheduler, device drivers, and ending with DVM, the hope is that many questions can be answered by reading through this document.
Before delving into the design, a little history is in order. The genesis for VM02 starts way back with the development of Apple Pascal around 1978. UCSD Pascal was brought to the Apple II and became one of the most powerful development environments for the fledging microcomputer market. Indeed, Apple Pascal was the first real computer language I learned in 1979 (after toying with with a TRS-80 Model 1 in school). Many years later, the retro-computing bug hit and I wanted to bring a modern, up-to-date programming environment to my favorite computer. After thinking about developing my own custom VM and language, a post on comp.sys.apple2 from Oliver Schmidt about porting a very limited Java-like VM to the Apple II got me thinking. Oliver's experiment was a success in that he got it working, but it was much too slow and cumbersome to be really useful. I decided then that a real JVM was possible and the performance issues could be solved with a clever assembly language implementation. The beginning of VM02 involved deciding what could be feasibly incorporated into a VM and what had to be left out. Ultimately I picked 64 bit data types as the cut-off for functionality. Everything else should be implemented in some fashion. Lastly, a JVM is only part of the equation when it comes to supporting a language like Java. Most of the language involves a huge library of classes that provide the functionality to be useful. I have attempted to write the bare minimum of classes to make the Apple II a viable Java target.
External Linkeage (global.inc)
------------------------------
Page 3 ($0300-$03EF) is used for external entrypoints into VM02. Since the 6502 doesn't support indirect subroutine calls, the values have to be copied to a suitable location for calling. DVM has an indirect call opcode to simplify calling VM02 from native methods. Device drivers are accessed through function pointers as well as a few choice variables for global access. These links will remain stable for all of version 1.
Initiallization (vm02.s thread.s)
---------------------------------
Initialization is a process to get every module of VM02 ready to execute the main class. All module's init code is called, then the inital class is searched for. Either a command string can be passed in from a previous program, the existance of a STARTUP class, or the user is prompted for an initial class to execute. The command string or command line is then parsed for parameters and installed into and argument string. An initial thread is created and the name of the main class is pushed on the stack for the thread to load and call. The thread is then started. Execution returns to VM_EXIT after all threads have finished. VM02 then reloads itself and begins the search again. Command strings and return values can be passed from one class to the next to create an exec chain.
Memory Management (memmgr.s fames.s ops.s sysclass.s)
-----------------------------------------------------
Even before the decision to implement a JVM, a memory manager had been worked out to provide a handle-based manager for a VM. The reason was to allow for ease of garbage collection, memory flexibility, and eventually memory swapping to disk. Memory blocks can be allocated, freed, moved, locked, and unlocked. The memory handle table is defined at the top of main memory, right below ProDOS, in the 64K configuration. The 128K VM places the handle table in the second bank of the AUX language card area. The number of memory handles is a define in global.inc. In the 64K configuration, the memory table takes up space in main memory so there is a tradeoff between the size of the table and free main memory.
A memory handle is an entry in the handle table that points to the actual memory block, plus some flags in the low-order 3 bits. These bits are masked off when converting to an address. It also means that the memory blocks are multiples of 8 bytes. An allocated memory block has a 4 byte header containing the size of the block, the reference count of the block, and an accessed flag. A free block contains the size of the block and a handle to the next free block in the free list. The free list header is located in zero page. The smallest available memory block is thus 4 bytes (8 byte block minimum - 4 header bytes). It makes sense to try and allocate blocks that are as large as possible to avoid wasting memory and handles, thus causing fragmentation.
Memory blocks can be allocated, freed, locked, unlocked, and reference counted. Memory can be optionally allocated at fixed addresses to support mapping the framebuffer or fullfilling the alignment requirements of ProDOS and other hardware/software. Memory can be code or data. In the 128K configuration, bytecode is actually stored in AUX memory, but the details are retained in a main memory block. This gives the system enough flexibility to manage memory in a very constrained environment.
In the apple2/ProDOS.java class is a method: ioAllocBuffer() which calls an internal VM02 routine to allocate a fixed memory block. It actually scans from the bottom of memory to the top until it succeeds in allocating the block. If it fails, it forces GC and tries again. It will fail eventually, so it is best to allocate the IO buffer early on in the program to guarantee getting it. The HGR2 buffer is allocated using the same call in apple2/AppleStuff.java, although it fails immediately if it can't get the memory. VM02 uses it's own buffers for class loading and swapping that are independent of the Java class's file I/O. All operate independently. Java threads should use the Java synchronization features if doing I/O to the same file, otherwise they too are independent. The number of files open is only limited by available memory and ProDOS.
Reference count incrementing is handled throught the VM, but reference decrementing is only handled through the object unreference routine (UNREF_OBJ) in sysclass.s. Whenever a new value is written into a variable or a local method frame is destroyed, reference counts to the current values are decremented. If the reference count goes to zero, then any objects made reference to by the object to be freed must also be decremented. It can get quite recursive. The finalize() method on any object to be freed is called immediately. This way memory can be returned to the pool as quickly as possible. Background memory collection is expensive both in time and space; VM02 has neither. Reference counting goes hand-in-hand with garbage collecting.
Garbage collection is discussed in more detail later, but briefly it combines adjacent free space and shifts free memory down in memory. The concept is to keep allocated memory blocks as high up in memory as possible. One reason is that the VM itself exists in low memory, right below the second hi-res page. Keeping low memory free makes usage of the hi-res graphics more possible. There is a routine called from the scheduler and any time free memory is exhausted to first combine any adjacent free space, the move and allocated blocks up in memory. This process is repeated a given number of times. If called from the memory allocator and it is unable to satisfy the request, an out-of-memory error will be thrown. These algorithms can be combined with a build-optional demand swapping feature described next.
Demand memory swapping to disk is supported through the use of a SWAP directory. Handles are converted to filenames and the data is read/written from/to the file. Accessed tags are incrementally cleared through the THREAD_YIELD routine. The memory allocator will now call two swapping routines when RAM is exhausted. The first will swap out all unaccessed blocks, the other will aggressively swap out all unlocked blocks. The idle loop garbage collector will combine any free blocks, try to move free space to lower memory, and write out any blocks which have been unaccessed for some time. Swap volumes are intelligently determined at init time. RAM disks of sufficient size have precedence over hard media. Finally, the SWAP directory is cleaned up at exit time.
Strings (strpools.s)
--------------------
Strings in Jave are immutable - they don't change. Whenever a change is made, a new String object is created. VM02 works in concert with the memory manager to reference count strings. Only one copy of a string is kept. In VM02, if two strings are the same, their object references are the same too. Only strings of 255 charcters or less are permitted, and they are only 8 bit characters (UTF8), so no unicode support. Strings are hashed and searched through a linked list per hash table entry. Efficient searching, adding, and deleting of strings is important.
Class File Loader (classload.s class.inc)
-----------------------------------------
Class file loading is one of the most fundamental operations of VM02. One of the most important requirements for VM02 was that it use the well defined Java Class File Format. Many other small JVM implementations remove this requirement and create their own file format that eases the class field and offset resolution operations. Luckily, ProDOS provides a fairly sophisticated file system for directory and file management.
The Java Class File Format is available on-line and should be reviewed to understand the internals of VM02. It is the basis for the single inheritence model of Java, as well as the exception and bytecode definitions. The class file maps the Java class into a binary representation, similar to a .o file in UNIX, or a .OBJ in MS-DOS/Windows. Linking occurs at runtime, and can be either lazy or immediate. VM02 chooses the lazy linking method as it only allocates resources for a class when it is called. This keeps the memory footprint as small as possible but can pause a running program to load referenced classes. The class file has four major sections: the constant pool, the interfaces, the fields, and the methods. Due to the way the class file is laid out, the size of the sections isn't known until each section is read in. This creates a little difficulty in allocating a data structure to contain the full class. Instead, the class loader allocates a data structure big enough to contain counts and handles for the interface descriptors, field descriptors, and method descriptors as well as the constant pool itself. Each constant pool entry is 5 bytes: one type bye and 4 data bytes. In the class file, they are dynamic in size, but to make the offset calculation easy, they are fixed in the class data structure. All the other sections are read in order, allocating a memory block to hold each section's descriptors. Method sections also call a code loader to install the method's code into the code manager (codemgr.s). After all the sections have been successfully loaded, a check is made to see if the superclass has beenn loaded. If not, the class loader is recursively called to load the superclass. Once all superclasses are available, the fields and methods are fixed up based on the superclass. This is probably the hardest code in all of VM02 to follow. This is where the fundamentals of the inheritance model come in to play. Fields shadow any superclass fields. Static methods shadow any superclass methods, whereas virtual methods have to override any superclass virtual methods in a virtual method table. This is not pretty code to write in 6502 assembly, it was rewritten in DVM code and makes following the code somewhat easier when you get accustomed to it. Finally, any class initializer is called to set up the class. Calling code asynchronously, as the class initializer is done, is covered in the frame manager code (frame.s).
Class Class (classclass.s)
--------------------------
Class references are held in a table. There can be no more than 128 classes loaded in a program. With the other memory constraints of VM02, this shouldn't be a problem. In fact, the default table size is currently 64 entries. Class data strutures can be interrogated through the routines found in this file. If the class data structure changes in the future, most of the changes can be limited to this file. Java uses strings from the class file to name classes, methods, and fields. Routines to search the class table and class structure to resolve the name and description are here. These are called from the (ops.s) bytecode interpreter whenever method invokations are made or fields are accessed. The interpreter will stick the handles resolved by the routines here into the class structure so that the string names will no longer have to be resolved, the handle will be used directly.
Threads (thread.s)
------------------
Again, pre-emptive multithreading was a design requirement even before a JVM was settled on. The Apple II is probably the least friendly to pre-emptive multi-threading of any computer. The 6502 just doesn't fit well into a threaded environment, unless that environment is a VM. Then, adding pre-emptive multi-threading to a virtual instruction set becomes pretty easy. Since the 6502 will be interpreting the Java bytecodes, I simply implemented a byte counter after each interpreted bytecode and call the scheduler when it reaches zero. The scheduler can also be called directly by way of THREAD_YIELD. If an asynchronous event requires the scheduler to run immediately (such as an interrupt waking up a thread), the count can be set to one so that the scheduler will run after the current bytecode finishes up. The scheduler itself has a table of threads which it scans looking for the best candidate to execute. This table is fixed and represents the maximum threads in the system. A define in global.inc sets the maximum number of threads (current default is 4). Each thread has 20 bytes of zero page for the bytecode interpreter state plus the 6502 hardware stack. Both are swapped during a thread re-schedule. Only the active part of the 6502 stack is read/written which is rarely more than 16 bytes. Swapping threads is pretty light-weight. If there are no threads ready to run, the idle loop will call the garbage collector to iteratively do any collecting and swapping of unaccessed memory. The GC will wait for a configurable time before starting, then it will delay between each iteration. Threads can wait on I/O events, synchronized objects, or just sleep. Threads wait on I/O by using a bitmask to identify which slot it is waiting on. Multiple slots can be waited on by setting the appropriate bits. The notifying slot will be returned to the thread in the accumulator (or multiple slots if more than one had pending I/O). If a timeout is included, VM02 will wake the thread after the timeout expires with an InterruptedException. Because the Apple II has no time base by default, it will estimate time based on the number of bytecodes interpreted. This is a pretty coarse estimate, but is a good first order approximation. The Apple IIc and any Apple II with a mouse card can use the VBL interrupt to establish a consistent time base. Timing then becomes quite accurate, at least to the resolution of 60 Hz. Other timing hardware can implement the time base with the addition of a device driver.
Execution Frames and Code Manager (frames.s codemgr.s)
------------------------------------------------------
Whenever a thread of execution invokes a new method, a frame must be created to hold the local state for that method. Conversely, when a method is exited it's frame must be broken down and cleaned up. With Java and automatic garbage collection and exception handling, this becomes somewhat of an involved task. There are two ways to invoke methods. The most common is through the invoke bytecodes that call interfaces, static, and virtual methods. The other way to call is asynchronously by way of class loading or finalizers. Current state is pushed in a way that it can be restored when it exits. Either way, the called method is checked for a native vs bytecode implementation. Native, 6502 machine code, is then called directly without further ado, making native methods very lightweight. For bytecode methods, the code manager is used to recall important details about the method so a stack frame can be allocated. Once allocated, the current frame execution state is saved and the new frame is prepared for execution. The parameters are pulled off the stack and copied into the local variables. Object parameters get their reference count incremented. Finally, all the local variable types are set to zero.
When the method exits, the local variables are scanned for object references and reference count decremented. If the method is returning due to an exception, then exception handling code is searched for and run if found. If the method was asynchronous, the previous execution state is restored and returned to. Realize that asynchronous method calls return to 6502 code (usually the class loader for <clinit>() or the object unreference routine for finalize()).
Bytecode Interpreter (ops.s)
----------------------------
The Java bytecode interpreter is mostly located in the 2nd bank of the Language Card memory. Due to the large size of the interpreter, some of the code lies in main memory. Floating point instructions are optional although the are built by default. They can be disabled by a define in global.inc, freeing up valuable main memory. In the 128K configuration, bytecodes are be read from auxiliary memory. Care must be taken to keep code that reference aux main memory in the language card. Main memory code cannot directly read from aux main memory. The unenhanced IIe doesn't like the aux memory mapped in when interrupts are enabled. The same is true when accessing other tables in aux langauage card space (memmgr.s strpool.s classclass.s). Interrupts are disabled whenever aux memory is accessed.
The interpreter optimizes access to fields and methods by caching handles and offsets (classclass.s) in the constant pool the first time they are accessed. The MSB will be set for cached values. Class, field, and method reference code will check the MSB to determine if a full lookup is required. With classes, this can lead to loading a class (and it's superclasses) the first time it is referenced. Once a class is in memory, it can never be removed.
The bytecode interpreter implements pre-emptive mutlithreading by calling the scheduler whenever opcount reaches zero. Runtime errors and exceptions are implemented by asynchronously calling a class - apple2/SystemException, that will throw the exception associated with parameter. This keeps all the exceptions themselves out of memory unless they are required. The asynchronous call is described more in the frame manager.
System Calls (sysclass.s)
-------------------------
VM02 provides a low level interface into the VM itself. Memory $0300-$03E0 is a jump table to various routines, as well as the device drivers. The apple2/vm02 class has an interface which provides a system level call into the VM or ROM, depending on the address. Addresses below $0100 will be treated as calls through the jump table, not zero page calls as this makes no sense with VM02. Global.inc contains the definitions of the jump table entries.
Garbage Collection and Finalizers (memmgr.s sysclass.s)
-------------------------------------------------------
The UNREF_OBJECT routine is located here. All object reference decrements are done here so that the recursive calls to unreference other objects can be somewhat managed. This is one of the most nerve-wracking routines you will ever encounter. Instance field references and array references are recursively dereferenced. Oh my head.
GC and finalizers are closely related in VM02. Memory is reference counted and reclaimed immediately when the count reaches zero. VM02 is extremely resource constrained, so deferring GC makes little sense. When the memory being freed is an object, it's finalizer is asynchronously called first. Once the finalizer is called, all the object referenced from this object have their reference counts decremented, and recursively freed if zero. This code gets quite messy with all the possible recursion. Care must be taken when modifying any of it.
It must be noted that reference counted GC is hardly robust. It is quite easy to have a dangling reference keep memory around, or mutually reference objects to never be freed (even if indirectly referenced). One can help the GC recover memory by explicitly setting unused references to null. This is been known to help other GC implementations as well, so isn't as horrible and anti-GC as it sounds.
Exceptions (except.s)
---------------------
Exceptions are handled through a combination of the bytecode interpreter and the frame manager. When built with DEBUG enabled, VM02 will spit out a stack trace with a little extra information. VM02 doesn't incorporate all the exception logging and trace information that a real JVM does.
Device Drivers and I/O (io.s *drvr.s)
-----------------------------
Device drivers were one of the last things added to VM02. In the middle of functional development, it was clear that adding support for additional hardware was needed but ProDOS didn't provide a driver model and VM02 didn't want to be loaded down with static hardware support. So, basic device driver laoding was added. Interrupts are fully supported through a pseudo-priority scheme that scans lower numbered slots first. Read/write and control entry points in the VM02 jump table call into the device drivers for each slot. Every slot has a real or dummy control routine that will identify the device (or no device) in that slot. One requirement of the device driver is address independence. The driver can be laoded into any avaiable memory, so it must be written position independent. With the very simple functions required of the device driver, this isn't too much of a problem. Some fixups can also be done at driver load time (mousedrvr.s) Look to the included drivers for examples. Interrupts from devices can wake up threads waiting on I/O for that slot.
Device I/O is abstracted using a slot index, not unlike file descriptors in unix. However, the Apple only has seven slots so things are a little simpler. In io.s, all the devices VM02 supports with a device driver are scanned and the driver is attached to whichever slot the hardware is found. Entries in the LINK page are fixed up to point to the driver entrypoints for that slot (global.inc). The only slot that is hard-coded is slot #3, defined as the console. Java code can interrogate each slot in turn, looking for a unique ID (defined in global.h) for the type of hardware it's looking for. Once the slot(s) is identified, it can proceed to make IOCTL calls and READ/WRITE calls. The calls are handled in a device dependent way - the mouse driver will respond to READ differently than a serial port driver. A thread will block waiting for input if nothing is available. Output usually waits for available space to write before returning. A thread can wait on multiple devices at the same time. See TestSelect.java to see how a thread can wait on keyboard and mouse input simultaneously. A bitmask is returned signaling which slot(s) have available input. A thread can also set a timeout before waiting on input. If the timeout occurs before input arrives, an InterruptedException will be generated. Again, TestSelect.java is a good example as well as org/vm02/cui/cui.java.
One nice thing that the architecture of VM02 allowed was to treat the Uthernet card just like an interrupting device. Devices are polled during THREAD_YIELD if no timer hardware is installed, originally to have a type-ahead buffer for the keyboard. I tweaked it slightly when I added the Uthernet driver to generalize it for all devices. If timer hardware (like the mouse) exists, everything gets polled 60 times a second - regardless wether they generate IRQs or not. The Uthernet driver checks for any new packets when finished servicing the current packet to keep bandwidth high.
Dave's Virtual Machine (dvm.s)
------------------------------
In order to overcome some deficencies of the 6502 processor, namely 16 bit operations and position independence, a small pseudo, or virtual, machine was written. Somewhat of a cross between the Pascal p-machine and Sweet-16, it offers a compact code representation with full 16 bit operation and position independence. This allows non-time critical code to be implemented in a manner to take up less space, be moveable (and swappable), or both. The file class loader and fixed-address memory allocater was re-implemented using DVM to reduce space, simplify code, and allow it to be swapped in and out when needed. See below for a thorough description.
I originally pulled VM02 back out of mothballs to add Uthernet and TCP/IP support. I quickly ran out of memory, so that is why I had to implement swapping. What a round-about way to get networking! It quickly became apparent that a Java solution to TCP/IP would be just too big. My ARP test pretty much consumes a 64K machine. So DVM to the rescue. VM02 has a requirement of position independent code for native methods - doing an entire TCP/IP stack in 6502 like that would be killer. I created DVM to fill just such a problem The screen driver for the CUI classes (org/vm02/cui/cuiDriver.clasm) is written in a DVM+6502 hybrid, so I'm pretty confident in it's ability. 6502 code can be easily inserted for inner loop performance critical stuff.
Object Reference Definition
===========================
Object references are 32 bits, just like the other basic data types, int and float. The value is broken up into three parts. The lower 16 bits are the memory handle to the object memory. The next higher byte is the class index, and the highest byte is class specific type data. For strings, it's the hash value of the string. For arrays, it's the type and dimension of the array. If a class doesn't have a specific use for the fourth byte, just replicate the class index byte - this makes it easy to identify object handles when debugging.
Psuedo Machine for VM coding
============================
Because the JVM is such a large app, a more sophisticated and compact code representation was needed to make it fit in the limited space of the Apple II. Macros were created to assemble into a p-code that is interpreted by yet another VM. Non-performance critical code is interpreted to save space. Native methods have access to DVM through a LINK_TABLE entrypoint. This is quite beneficial as native methods require position independence. Look at org/vm02/cui/cuiDriver.clasm for a sophisticated DVM method implementation. It is also quite easy to intersperse 6502 code inside DVM blocks. Use DVM for the position independence and overall control, 6502 for tight inner loops.
The p-code is defined as such:
$00-$07/$80-$87
LD0B (Load 0 Byte) - load zero value byte on stack
LD0W (Load 0 Word) - load zero value word on stack
LD1B (Load 1 Byte) - load one value byte on stack
LD1W (Load 1 Word) - load one value word on stack
LD2B (Load 2 Byte) - load two value byte on stack
LD2W (Load 2 Word) - load two value word on stack
LD3B (Load 3 Byte) - load three value byte on stack
LD3W (Load 3 Word) - load three value word on stack
LD4B (Load 4 Byte) - load four value byte on stack
LD4W (Load 4 Word) - load four value word on stack
LD5B (Load 5 Byte) - load five value byte on stack
LD5W (Load 5 Word) - load five value word on stack
DUPB (DUPlicate Byte) - copy top byte on stack
DUPW (DUPlicate Word) - copy top word on stack
DUP2B (DUPlicate 2 Bytes) - copy top two bytes on stack (same as DUPW)
DUP2W (DUPlicate 2 Words) - copy top two words on stack
$08-$0F/$88-$8F
SWAPB (SWAP Bytes) - swap bytes on stack
SWAPW (SWAP Words) - swap words on stack
LDCB (LoaD Constant Byte) - load constant value byte onto stack
LDCW (LoaD Constant Word) - load constant value word onto stack
LDZPB (LoaD Zero Page Byte) - load zero page memory onto stack
LDZPW (LoaD Zero Page Word) - load zero page memory onto stack
LDB (LoaD Byte) - load absolute memory onto stack
LDW (LoaD Word) - load absolute memory onto stack
LDPB (LoaD Pointer Byte) - load memory thru pointer+offset onto
stack
LDPW (LoaD Pointer Word) - load memory thru pointer+offset onto
stack
LDPINCB (LoaD Pointer Inc Byte) - load memory thru pointer onto stack
and increment pointer
LDPINCW (LoaD Pointer Inc Word) - load memory thru pointer onto stack
and increment pointer
LDPDECB (LoaD Pointer Dec Byte) - load memory thru pointer onto stack
and decrement pointer
LDPDECW (LoaD Pointer Dec Word) - load memory thru pointer onto stack
and decrement pointer
LDINDB (LoaD INDirect Byte) - load memory thru pointer from stack
onto stack
LDINDW (LoaD INDirect Word) - load memory thru pointer from stack
onto stack
$10-$17/$90-$97
POPB (POP Byte) - remove top byte on stack
POPW (POP Word) - remove top word on stack
POP2B (POP 2 Bytes) - remove top two bytes on stack (POPW)
POP2W (POP 2 Words) - remove top two words on stack
STZPB (STore Zero Page Byte) - store zero page memory from stack
STZPW (STore Zero Page Word) - store zero page memory from stack
STB (STore Byte) - store absolute memory from stack
STW (STore Word) - store absolute memory from stack
STPB (STore Pointer Byte) - store memory thru pointer+offset from
stack
STPW (STore Pointer Word) - store memory thru pointer+offset from
stack
STPINCB (STore Pointer INC Byte) - store memory thru pointer from stack
and increment pointer
STPINCW (STore Pointer INC Word) - store memory thru pointer from stack
and increment pointer
STPDECB (STore Pointer DEC Byte) - store memory thru pointer from stack
and decrement pointer
STPDECW (STore Pointer DEC Word) - store memory thru pointer from stack
and decrement pointer
STINDB (STore INDirect Byte) - store memory thru pointer, both from
stack
STINDW (STore INDirect Word) - store memory thru pointer, both from
stack
$18-$1F/$98-$9F
ZEXTB (Zero EXTend Byte) - zero extend byte to word
SEXTB (Sign EXTend Byte) - sign extend byte to word
NEGB (NEGate Byte) - negate top byte on stack
NEGW (NEGate Word) - negate top word on stack
NOTB (NOT Byte) - not top byte on stack
NOTW (NOT Word) - not top word on stack
ADDB (ADD Byte) - add top bytes on stack
ADDW (ADD Word) - add top words on stack
SUBB (SUBtract Byte) - add top bytes on stack
SUBW (SUBtract Word) - add top words on stack
ANDB (AND Bytes) - and top bytes on stack
ANDW (AND Words) - and top words on stack
ORB (OR Bytes) - or top bytes on stack
ORW (OR Words) - or top words on stack
XORB (XOR Bytes) - xor top bytes on stack
XORW (XOR Words) - xor top words on stack
$20-$27/$A0-$A7
BRZB (BRanch Zero Byte) - branch byte on stack zero
BRZW (BRanch Zero Word) - branch word on stack zero
BRNZB (BRanch Not Zero Byte) - branch byte on stack not zero
BRNZW (BRanch Not Zero Word) - branch word on stack not zero
BRPOSB (BRanch Positive Byte) - branch byte on stack positive
BRPOSW (BRanch Positive Word) - branch word on stack positive
BRNEGB (BRanch NEGative Byte) - branch byte on stack negative
BRNEGW (BRanch NEGative Word) - branch word on stack negative
BREQUB (BRanch EQUal Bytes) - branch if top bytes equal
BREQUW (BRanch EQUal Words) - branch if top words equal
BRNEQB (BRanch Not EQual Bytes) - branch if top bytes not equal
BRNEQW (BRanch Not EQual Words) - branch if top words not equal
BRGTB (BRanch Greater Than Bytes) - branch if top-1 byte greater than top
BRGTW (BRanch Greater Than Words) - branch if top-1 word greater than top
BRLEB (BRanch Less than or Equal Bytes) - branch if top-1 byte less or equal than top
BRLEW (BRanch Less than or Equal Words) - branch if top-1 word less or equal than top
$28-$2F/$A8-$AF
BRAB (BRanch Above Bytes) - branch if top-1 byte bigger than top
BRAW (BRanch Above Words) - branch if top-1 word bigger than top
BRBEB (BRanch Below or Equal Bytes) - branch if top-1 byte bigger than top
BRBEW (BRanch Below or Equal Words) - branch if top-1 word bigger than top
BRNCH (BRaNCH) - branch to offset
""
DECJNZB (DECrement memory Jump Not Zero Byte) - decrement memory byte and
jump not zero
DECJNZW (DECrement memory Jump Not Zero Word) - decrement memory word and
jump not zero
SHLB (SHift Left Byte) - shift byte on stack left
SHLW (SHift Left Word) - shift word on stack left
SHRB (SHift Right Byte) - shift byte on stack right
SHRW (SHift Right Word) - shift word on stack right
INCRB (INCRement Byte) - increment byte on stack
INCRW (INCRement Word) - increment word on stack
DECRB (DECRement Byte) - decrement byte on stack
DECRW (DECRement Word) - decrement word on stack
$30-$37/$B0-$B7
EXIT (EXIT) - exit VM
""
JUMP (JUMP) - jump to address
JUMPIND (JUMP) - jump to address on stack
CALL (CALL) - call subroutine address
CALLIND (CALL) - call subroutine address on stack
RET (RETurn) - return from subroutine
""
CALL_02 (CALL 6502) - call 6502 subroutine address
CALLIND_02 (CALL 6502) - call 6502 subroutine address on stack
SWTCHB (SWiTCH Byte) - switch to matching byte value on stack
SWTCHW (SWiTCH Word) - switch to matching word value on stack
This is what an example DVM program looks like that fills the hi-res screen in an incrementing value until a key is pressed:
.INCLUDE "dvm.inc"
HRPTR = $60
.CODE
LDX #$FF
TXS
DVM_BEGIN
CALL GRAPHMODE ; BASIC CALL TO SUBROUTINE
LD0B ; SET INITIAL VALUE TO ZERO
STB HRVAL
HRFILL: LDCW $4000 ; HR ADDRESS
STZPW HRPTR ; STORE IN ZP
LDCW $1000 ; HR SIZE IN WORDS
STW HRCOUNT
LDB HRVAL
DUPB ; EXPAND FILL TO WORD SIZE
HRLOOP: DUPW
STPIW (HRPTR) ; FILL SCREEN A WORD AT A TIME
DECJNZW HRCOUNT, HRLOOP ; HANDY LOOP OPCODE
POPB
INCRB
STB HRVAL
LDB $C000 ; CHECK KEYBOARD
BRPOSB HRFILL
LDB $C010 ; CLEAR STROBE
POPB ; THROW AWAY VALUE
LDCW TEXTMODE ; INDIRECT CALL TO SUBROUTINE
CALLIND ; CALL ADDRESS IS ABSOLUTE
JUMP HREXIT ; SIGNED 16 BIT OFFSET DEST
GRAPHMODE: LDB $C057
POPB
LDB $C050
POPB
LDB $C055
POPB
RET
TEXTMODE: DVM_END ; POP OUT OF DVM FOR THINGS
LDA $C051 ; BETTER DONE IN 6502
LDA $C054
DVM_BEGIN
RET
HREXIT: DVM_END
RTS
HRVAL: .BYTE 0
HRCOUNT: .WORD 0

280
LICENSE.TXT Executable file
View File

@ -0,0 +1,280 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS

88
README.TXT Executable file
View File

@ -0,0 +1,88 @@
VM02 Apple II Java Virtual Machine
==================================
Introduction:
-------------
VM02 is a Java compatible environment for the Apple II series of computers. Most basic features of a Java VM are implemented to allow direct execution of standard Java class files.
However, in order to fit in the constraints of a 64K, 8 bit, 1 MHz computer, some aspects of a JVM have been reduced or removed.
What is implemented:
- Standard Java class file loading and execution.
- Full object inheritence
- Multithreading (4 threads max by default)
- Exception handling
- Arrays up to 15 dimension
- 32 bit integers and single precision floating point
- Garbage collection
- Demand memory swapping to RAM disk or other available volume
- Finalizers
- Software and hardware implemented timing
- Device drivers for common hardware
- 128K memory support for //e and //c
- Exec-ing another class
What is missing:
- 64 bit data types unimplemented
- Standard class library missing or limited implementation
- Lots of memory
Running VM02:
-------------
VM02 is run by executing the JAVA.SYSTEM file. You must start JAVA.SYSTEM from the prefix where it exists. This is required to find the class base path to the support classes. Parameter passing is supported if your shell implements it. If no paramter is passed in and a file named STARTUP exists, it will be loaded as the initial class. Otherwise, you will be greeted with with a prompt to type in the class name to execute. You can start classes in other directories by typing in the fully qualified path. Class filenames under ProDOS are missing the ".class" suffix due to limited filename lengths. For example, to execute the Hello.class file on the /VM02.EXTRAS/SAMPLES volume, with VM02 you would type:
/VM02.EXTRAS/SAMPLES/HELLO
at the "Main class:" prompt. You would see this:
Main class:/VM02.EXTRAS/SAMPLES/HELLO
and then VM02 would attempt to find and load the class file. If an error occurs along the way, you will get an Unhandled Exception message, probably because the file (or superclass file) was not found. The preferred directory structure is to place all classes as subdirectories of the main VM02 directory.
Model Compatibility:
--------------------
VM02 has been tested on a variety of Apple II models from a Rev 0 Apple ][ with Integer Basic to a //c+ and much in-between. Most models run without issue, however some need a little support. Noteably, my ROM 1 IIgs needs to run VM02 under GS/OS to run without problems. Without pathces applied by GS/OS, the system quickly gets random values blasted throughout memory. When I added support for 128K and more sophisticated memory management, it caused the IIgs to falter more and more. Rock solid under GS/OS. I was unable to test a ROM 3 IIgs, so I don't know if those problems persist. Earlier models of the //c might lose VBL interrupts after being run for awhile. The unenhanced IIe should run the CUI programs but will look funny without the MouseText characters. Pre-IIe models won't run the CUI programs at all.
Implementation of VM02:
-----------------------
VM02 is implemented from scratch in 6502 assembly, optimized for the 6502 and Apple II platform. The entire VM fits in about 20K of RAM. This leaves about 30K of RAM available for data and code in the 64K version, or about 32K for data and 44K for bytecode in the 128K version. Not a lot, but Java was defined for small platforms so you can get some reasonable programs even in such a small space. Swapping from main memory extends the available RAM, dependent on the swap volume. A new low level pseudo-machine was written to implement some of the non-time critical routines. Somewhat of a cross between the Pascal p-machine and Sweet-16, DVM (Dave's Virtual Machine) is optimized for position independent 16 bit operations. The class loader and some memory manager routines are implemented in DVM to save code space (about 4X) or allow for on-the-fly relocation. A high-resolution graphics page is available for use with small programs. Performance is acceptable for a 1 MHz, 8 bit CPU; on par with the UCSD p-System VM used in Apple Pascal. All features of the Apple II are made available through either specific classes, a low-level class that can call ROM routines, or both. There is a device driver architecture that currently supports 80 column cards, the Super Serial card, and the Apple Mouse card with preliminary support of the Uthernet card and Apple Graphics Tablet. Probing for the Uthernet card can cause problems in some machines with hardware VM02 doesn't detect. If probing for the Uthernet card causes the machine to hang at VM02 init time, hold down the Open-Apple key (or PushButton 1) during initialization and the Uthernet probe will be skipped.
As noted earlier, class filenames are missing the ".class" suffix, however the file type of $ED is used to identify class files and are given the type identifier of JVM. System classes are in the JAVA/* subdirectories. Apple II specific classes are found in the APPLE2/ directory. VM02 specific class are found in the ORG/VM02/* subdirectories.
Developing for VM02:
--------------------
There isn't a native Java compiler for the Apple II (yet). All Java source must be cross-developed on a capable computer. The resulting class file needs to be transferred to an Apple or emulator using any number of available tools. One way is to use a tool like a2tools, AppleCommander, or CiderPress to copy the class file to a .DSK disk image file. The disk image can be run directly from an emulator or copied to real hardware with ADT or ADTPro. To compile against the Apple II specific classes, either download the source package (you will also need cc65, the 6502 C compiler package) or copy the APPLE2/ directory contents and rename the files with mixed case and add the .class suffix.
The sample classes:
-------------------
Included with VM02 are sample classes that show off the capabilites of the environment. They can be executed from the samples disk or copied to another location.
HELLO - A simple text entry program
HELLOWORLD - sample multi-threaded program
MOIRE - Hires example, requires AppleSoft in ROM
HIRESDEMO - Another hires demo
RODSCOLORS - Lores demo
SIMPLEPONG - Lores demo with paddle input
TERMINAL - Simple terminal program using the SSC
VOLUMES - List online volumes
CATALOG - Catalog a directory
LIST - List a text file to the screen
STRESSMEM - Allocate 64K 2D array. Stresses swapping code
TESTSELECT - select() type call using mouse, keyboard, and timeouts
TESTCHAIN - Chain to another class passing parameters and exit status
TESTCUI - Show off the CUI's controls (needs 128K)
The Launcher class:
-------------------
With the release of version 1.0, a file launcher is included to navigate through volumes and directories and execute Java classes. Files of type $ED show up as JVM executable files.
Release Version 1.0:
--------------------
This represents the first release of VM02. Much of the implementation exists as skeletons of a complete Java environment. There is enough to run basic programs and do minimalistic file I/O.
Known issues:
-------------
No know issues exist.
March 31st 2010, 11:59:59 PM
Dave Schmenk...

126
plasma2/FIRE.PLA#040000 Executable file
View File

@ -0,0 +1,126 @@
CONST FALSE = 0
CONST TRUE = NOT FALSE
CONST SHOWLORES = $C056
CONST KEYBOARD = $C000
CONST KEYSTROBE = $C010
CONST EMPTY = 0
CONST TREE = 4
CONST FIRE = 13
CONST FORESTSIZE = 42*42
BYTE HELLOMSG[] = "PRESS ANY KEY TO BEGIN..."
BYTE EXITMSG[] = "PRESS ANY KEY TO EXIT."
BYTE GOODBYE[] = "THAT'S ALL FOLKS!"
BYTE TREES1[FORESTSIZE]
BYTE TREES2[FORESTSIZE]
WORD RNDNUM
DEF TEXTMODE
DROP ROMCALL(0, 0, 0, 0, $FB39)
END
DEF HOME
DROP ROMCALL(0, 0, 0, 0, $FC58)
END
DEF GOTOXY(X, Y)
^($24) = X
DROP ROMCALL(Y, 0, 0, 0, $FB5B)
END
DEF GRMODE
DROP ROMCALL(0, 0, 0, 0, $FB40)
DROP ^SHOWLORES
END
DEF RANDOMIZE(SEED)
RNDNUM = (SEED >> 8) + (SEED << 8) + SEED
END
DEF RND
RNDNUM = (RNDNUM << 8) + RNDNUM + 12345
RETURN RNDNUM & $7FFF
END
DEF BYFIRE(TREEPTR)
IF ^(TREEPTR - 43) == FIRE
RETURN TRUE
ELSIF ^(TREEPTR - 42) == FIRE
RETURN TRUE
ELSIF ^(TREEPTR - 41) == FIRE
RETURN TRUE
ELSIF ^(TREEPTR - 1) == FIRE
RETURN TRUE
ELSIF ^(TREEPTR + 1) == FIRE
RETURN TRUE
ELSIF ^(TREEPTR + 41) == FIRE
RETURN TRUE
ELSIF ^(TREEPTR + 42) == FIRE
RETURN TRUE
ELSIF ^(TREEPTR + 43) == FIRE
RETURN TRUE
FIN
RETURN FALSE
END
DEF FORESTFIRE
WORD NEWTREES, OLDTREES, NEWTREE, OLDTREE, YROW
BYTE X, Y
MEMSET(EMPTY, @TREES1, FORESTSIZE)
MEMSET(EMPTY, @TREES2, FORESTSIZE)
OLDTREES = @TREES1
NEWTREES = @TREES2
FOR Y = 1 TO 40
YROW = Y * 42
FOR X = 1 TO 40
IF RND < 8000
^(OLDTREES + X + YROW) = TREE
FIN
NEXT
NEXT
WHILE ^$C000 < 128
FOR Y = 1 TO 40
YROW = Y * 42
FOR X = 1 TO 40
OLDTREE = OLDTREES + X + YROW
NEWTREE = NEWTREES + X + YROW
WHEN ^OLDTREE
IS EMPTY
IF RND < 5000
^NEWTREE = TREE
ELSE
^NEWTREE = EMPTY
FIN
IS TREE
IF RND < 5 OR BYFIRE(OLDTREE)
^NEWTREE = FIRE
ELSE
^NEWTREE = TREE
FIN
IS FIRE
^NEWTREE = EMPTY
WEND
DROP ROMCALL(^NEWTREE, 0, 0, 0, $F864)
DROP ROMCALL(Y - 1, 0, X - 1, 0, $F800)
NEXT
NEXT
NEWTREES =, OLDTREES = OLDTREES, NEWTREES
LOOP
DROP ^$C010
END
PRSTR(@HELLOMSG)
WHILE ^$C000 < 128
RNDNUM = RNDNUM + 1
LOOP
RANDOMIZE(RNDNUM)
DROP ^$C010
GRMODE
HOME
GOTOXY(10,22)
PRSTR(@EXITMSG)
FORESTFIRE
TEXTMODE
HOME
PRSTR(@GOODBYE)
DONE

1
plasma2/autorun#040000 Executable file
View File

@ -0,0 +1 @@
PLED READ.ME

BIN
plasma2/bytedump Executable file

Binary file not shown.

29
plasma2/bytedump.c Executable file
View File

@ -0,0 +1,29 @@
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
unsigned char buf[256];
int main(int argc, char **argv)
{
int fd, offset;
if (argc < 2)
{
printf("Usage: %s <binfile>\n", argv[0]);
return (1);
}
if ((fd = open(argv[1], O_RDONLY, 0)) > 0)
{
offset = 0;
while (read(fd, buf, 1) == 1)
{
if (offset++ & 0x0F)
printf(",$%02X", buf[0]);
else
printf("\n\t.BYTE\t$%02X", buf[0]);
}
printf("\n");
}
close(fd);
}

492
plasma2/cmd.pla Executable file
View File

@ -0,0 +1,492 @@
const iobuffer = $0800
const databuff = $0C00
const autorun = $01FF
byte version[] = "PLASMA ][ VM VERSION 0.8"
byte errorstr[] = "ERROR: $"
byte okstr[] = "OK"
byte prefix[32] = ""
byte perr
word cmdptr
;
; Utility functions
;
; CALL PRODOS
; SYSCALL(CMD, PARAMS)
;
asm prodos
LDA ESTKL,X
LDY ESTKH,X
STA PARAMS
STY PARAMS+1
INX
LDA ESTKL,X
STA CMD
STX ESP
JSR $BF00
CMD: DB 00
PARAMS: DW 0000
BIT LCBNK2
LDX ESP
STA ESTKL,X
LDY #$00
STY ESTKH,X
end
;
; CALL LOADED SYSTEM PROGRAM
;
asm exec
LDX #$FF
TXS
BIT ROMIN
JMP $2000
end
;
; SET MEMORY TO 0
; MEMCLR(ADDR, SIZE)
;
asm memclr
LDY #$00
LDA ESTKL+1,X
STA DSTL
LDA ESTKH+1,X
STA DSTH
INC ESTKL,X
INC ESTKH,X
TYA
SETMLP: DEC ESTKL,X
BNE :+
DEC ESTKH,X
BEQ :++
: STA (DST),Y
INY
BNE SETMLP
INC DSTH
BNE SETMLP
: INX
INX
end
;
; COPY MEMORY
; MEMCPY(SRCADDR, DSTADDR, SIZE)
;
asm memcpy
LDY #$00
LDA ESTKL,X
BNE :+
LDA ESTKH,X
BEQ MEMEXIT
: LDA ESTKL+1,X
STA DSTL
LDA ESTKH+1,X
STA DSTH
LDA ESTKL+2,X
STA SRCL
LDA ESTKH+2,X
STA SRCH
CMP DSTH
BCC REVCPY
BNE FORCPY
LDA SRCL
CMP DSTL
BCS FORCPY
REVCPY: ; REVERSE DIRECTION COPY
; CLC
LDA ESTKL,X
ADC DSTL
STA DSTL
LDA ESTKH,X
ADC DSTH
STA DSTH
CLC
LDA ESTKL,X
ADC SRCL
STA SRCL
LDA ESTKH,X
ADC SRCH
STA SRCH
INC ESTKH,X
REVCPYLP:
LDA DSTL
BNE :+
DEC DSTH
: DEC DSTL
LDA SRCL
BNE :+
DEC SRCH
: DEC SRCL
LDA (SRC),Y
STA (DST),Y
DEC ESTKL,X
BNE REVCPYLP
DEC ESTKH,X
BNE REVCPYLP
BEQ MEMEXIT
FORCPY: INC ESTKH,X
FORCPYLP:
LDA (SRC),Y
STA (DST),Y
INC DSTL
BNE :+
INC DSTH
: INC SRCL
BNE :+
INC SRCH
: DEC ESTKL,X
BNE FORCPYLP
DEC ESTKH,X
BNE FORCPYLP
MEMEXIT: INX
INX
INX
end
;
; CHAR OUT
; COUT(CHAR)
;
asm cout
LDA ESTKL,X
INX
ORA #$80
BIT ROMIN
JSR $FDED
BIT LCBNK2
end
;
; CHAR IN
; RDKEY()
;
asm cin
BIT ROMIN
STX ESP
JSR $FD0C
LDX ESP
BIT LCBNK2
DEX
STA ESTKL,X
LDY #$00
STY ESTKH,X
end
;
; PRINT STRING
; PRSTR(STR)
;
asm prstr
LDY #$00
LDA ESTKL,X
STA SRCL
LDA ESTKH,X
STA SRCH
BIT ROMIN
LDA (SRC),Y
STA ESTKL,X
BEQ :+
_PRS1: INY
LDA (SRC),Y
ORA #$80
JSR $FDED
TYA
CMP ESTKL,X
BNE _PRS1
: INX
BIT LCBNK2
end
;
; PRINT BYTE
;
asm prbyte
LDA ESTKL,X
INX
STX ESP
BIT ROMIN
JSR $FDDA
BIT LCBNK2
LDX ESP
end
;
; READ STRING
; STR = RDSTR(PROMPTCHAR)
;
asm rdstr
LDA ESTKL,X
STA $33
STX ESP
BIT ROMIN
JSR $FD6A
BIT LCBNK2
STX $01FF
: LDA $01FF,X
AND #$7F
STA $01FF,X
DEX
BPL :-
LDX ESP
LDA #$FF
STA ESTKL,X
LDA #$01
STA ESTKH,X
end
asm toupper
LDA ESTKL,X
CMP #'a'
BCC :+
CMP #'z'+1
BCS :+
SEC
SBC #$20
STA ESTKL,X
:
end
;
; EXIT
;
asm reboot
BIT ROMIN
LDA #$00
STA $3F4 ; INVALIDATE POWER-UP BYTE
JMP ($FFFC) ; RESET
end
def crout
cout($0D)
end
;
; ProDOS routines
;
def getpfx(path)
byte params[3]
^path = 0
params.0 = 1
params:1 = path
perr = prodos($C7, @params)
return path
end
def setpfx(path)
byte params[3]
params.0 = 1
params:1 = path
perr = prodos($C6, @params)
return path
end
def online
byte params[4]
params.0 = 2
params.1 = 0
params:2 = $2000
perr = prodos($C5, @params)
return $2000
end
def open(path, buff)
byte params[6]
params.0 = 3
params:1 = path
params:3 = buff
params.5 = 0
perr = prodos($C8, @params)
return params.5
end
def close(refnum)
byte params[2]
params.0 = 1
params.1 = refnum
perr = prodos($CC, @params)
return perr
end
def read(refnum, buff, len)
byte params[8]
params.0 = 4
params.1 = refnum
params:2 = buff
params:4 = len
params:6 = 0
perr = prodos($CA, @params)
return params:6
end
;
; Command mode
;
def volumes
word strbuf
byte i
strbuf = online()
for i = 0 to 15
^strbuf = ^strbuf & $0F
if ^strbuf
cout('/')
prstr(strbuf)
crout()
fin
strbuf = strbuf + 16
next
end
def catalog(optpath)
byte path[64]
byte refnum
byte firstblk
byte entrylen, entriesblk
byte i, type, len
word entry, filecnt
if ^optpath
memcpy(optpath, @path, ^optpath + 1)
else
drop getpfx(@path)
prstr(@path)
crout()
fin
refnum = open(@path, iobuffer);
if perr
return perr
fin
firstblk = 1
repeat
if read(refnum, databuff, 512) == 512
entry = databuff + 4
if firstblk
entrylen = databuff.$23
entriesblk = databuff.$24
filecnt = databuff:$25
entry = entry + entrylen
fin
for i = firstblk to entriesblk
type = ^entry
if type <> 0
len = type & $0F
^entry = len
prstr(entry)
if type & $F0 == $D0 ; Is it a directory?
cout('/')
len = len + 1
elsif (entry).$10 == $FF
cout('*')
len = len + 1
fin
for len = 19 - len downto 0
cout(' ')
next
filecnt = filecnt - 1
fin
entry = entry + entrylen
next
firstblk = 0
else
filecnt = 0
fin
until filecnt == 0
drop close(refnum)
crout()
return 0
end
def stripchars(strptr)
while ^strptr and ^(strptr + 1) <> ' '
memcpy(strptr + 2, strptr + 1, ^strptr)
^strptr = ^strptr - 1
loop
return ^strptr
end
def stripspaces(strptr)
while ^strptr and ^(strptr + ^strptr) <= ' '
^strptr = ^strptr - 1
loop
while ^strptr and ^(strptr + 1) <= ' '
memcpy(strptr + 2, strptr + 1, ^strptr)
^strptr = ^strptr - 1
loop
end
def striptrail(strptr)
byte i
for i = 1 to ^strptr
if (strptr)[i] == ' '
^strptr = i - 1
return
fin
next
end
def parsecmd(strptr)
byte cmd
cmd = 0
stripspaces(strptr)
if ^strptr
cmd = ^(strptr + 1)
memcpy(strptr + 2, strptr + 1, ^strptr)
^strptr = ^strptr - 1
fin
stripspaces(strptr)
return cmd
end
def resetmemfiles
;
; Close all files
;
^$BFD8 = 0
drop close(0)
;
; Set memory bitmap
;
memclr($BF58, 24)
^$BF58 = $CF
^$BF6F = $01
end
def execsys(sysfile)
byte refnum
word len
if ^sysfile
memcpy(sysfile, $280, ^sysfile + 1)
striptrail(sysfile)
refnum = open(sysfile, iobuffer)
if refnum
len = read(refnum, $2000, $FFFF)
resetmemfiles()
if len
memcpy($280, sysfile, ^$280 + 1)
if stripchars(sysfile) and ^$2000 == $4C and *$2003 == $EEEE
stripspaces(sysfile)
if ^$2006 <= ^sysfile
memcpy(sysfile, $2006, ^sysfile + 1)
fin
fin
striptrail($280)
exec()
fin
fin
fin
end
resetmemfiles()
execsys(autorun)
prstr(@version)
crout();
while 1
prstr(getpfx(@prefix))
cmdptr = rdstr($BA)
when toupper(parsecmd(cmdptr))
is 'Q'
reboot()
is 'C'
drop catalog(cmdptr)
is 'P'
drop setpfx(cmdptr)
is 'V'
volumes();
is '-'
execsys(cmdptr)
perr = $46
wend
if perr
prstr(@errorstr)
prbyte(perr)
else
prstr(@okstr)
fin
crout()
loop
done

1372
plasma2/cmd.s Executable file

File diff suppressed because it is too large Load Diff

10
plasma2/cmdloader.cfg Executable file
View File

@ -0,0 +1,10 @@
MEMORY {
RAM: start = $1007, size = $1000, file = %O;
}
SEGMENTS {
CODE: load = RAM, type = rw;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = rw;
}

1098
plasma2/codegen.c Executable file

File diff suppressed because it is too large Load Diff

55
plasma2/codegen.h Executable file
View File

@ -0,0 +1,55 @@
#define EDASM 1
void emit_flags(int flags);
int optimization(int level);
void emit_header(void);
void emit_trailer(void);
void emit_comment(char *s);
void emit_asm(char *s);
void emit_idlocal(char *name, int value);
void emit_idglobal(int value, int size, char *name);
void emit_idfunc(int value, char *name);
void emit_idconst(char *name, int value);
int emit_data(int vartype, int consttype, long constval, int constsize);
void emit_codetag(int tag);
void emit_const(int cval);
void emit_lb(void);
void emit_lw(void);
void emit_llb(int index);
void emit_llw(int index);
void emit_lab(int tag);
void emit_law(int tag);
void emit_sb(void);
void emit_sw(void);
void emit_slb(int index);
void emit_slw(int index);
void emit_dlb(int index);
void emit_dlw(int index);
void emit_sab(int tag);
void emit_saw(int tag);
void emit_dab(int tag);
void emit_daw(int tag);
void emit_call(int tag);
void emit_ical(void);
void emit_localaddr(int index);
void emit_globaladdr(int tag, int type);
void emit_globaladdrofst(int tag, int offset, int type);
void emit_indexbyte(void);
void emit_indexword(void);
int emit_unaryop(int op);
int emit_op(t_token op);
void emit_skptru(int tag);
void emit_skpfls(int tag);
void emit_skpgt(int tag);
void emit_skplt(int tag);
void emit_skpne(int tag);
void emit_skip(int tag);
void emit_swap(void);
void emit_dup(void);
void emit_push(void);
void emit_pull(void);
void emit_drop(void);
void emit_leave(int framesize);
void emit_ret(void);
void emit_def(int defopt);
void emit_enter(int framesize, int cparams);
void emit_start(void);

BIN
plasma2/codegen.o Executable file

Binary file not shown.

10
plasma2/default.cfg Executable file
View File

@ -0,0 +1,10 @@
MEMORY {
RAM: start = $2000, size = $2800, file = %O;
}
SEGMENTS {
CODE: load = RAM, type = rw;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = rw;
}

189
plasma2/dumprel.pla Executable file
View File

@ -0,0 +1,189 @@
const keyboard=$C000
const keystrobe=$C010
const iobuffer=$0800
const databuff=$0C00
const inbuff=$01FF
byte loadadr[] = "LOAD ADDRESS: $"
byte datasz[] = "DATA SIZE: $"
byte RLD[] = "RELOCATION DIRECTORY:"
byte ESD[] = "SYMBOL TABLE:"
byte errstr[] = "ERROR: "
byte perr
def home
drop romcall(0, 0, 0, 0, $FC58)
end
def gotoxy(x, y)
^($24) = x
drop romcall(y, 0, 0, 0, $FB5B)
end
def prbyte(val)
drop romcall(val, 0, 0, 0, $FDDA)
end
def prword(val)
drop romcall(val >> 8, val, 0, 0, $F941)
end
def crout
drop romcall(0, 0, 0, 0, $FD8E)
end
def getpfx(path)
byte params[3]
^(path) = 0
params.0 = 1
params:1 = path
perr = syscall($C7, @params)
return path
end
def getfileinfo(path, infoptr)
byte params[18]
params.0 = 10
params:1 = path
perr = syscall($C4, @params)
if not perr
memcpy(@params.3, infoptr, 15)
fin
return perr
end
def open(path, buff)
byte params[6]
params.0 = 3
params:1 = path
params:3 = buff
params.5 = 0
perr = syscall($C8, @params)
return params.5
end
def close(refnum)
byte params[2]
params.0 = 1
params.1 = refnum
perr = syscall($CC, @params)
return perr
end
def read(refnum, buff, len)
byte params[8]
params.0 = 4
params.1 = refnum
params:2 = buff
params:4 = len
params:6 = 0
perr = syscall($CA, @params)
return params:6
end
def dumpln(memptr, ofst, len)
byte i
cout('$')
prword(ofst)
cout(':')
cout(' ')
len = len - 1
for i = 0 to len
prbyte((memptr).[i])
if i & 1
cout(' ')
fin
next
cout(' ')
for i = 0 to len
if (memptr).[i] & $7F < ' '
cout ('.')
else
cout((memptr).[i])
fin
next
crout
end
def dumprld(rld)
cout('$')
prbyte(^rld)
cout(':')
cout(' ')
cout('$')
prword(*(rld + 1))
cout(' ')
cout('$')
prbyte(^(rld + 3))
crout
return rld + 4
end
def dumpesd(esd)
while ^esd & $80
cout(^esd)
esd = esd + 1
loop
cout(^esd)
cout(':')
cout(' ')
cout('$')
prbyte(^(esd + 1))
cout(' ')
cout('$')
prword(^(esd + 2))
crout
return esd + 4
end
def dump(path)
byte refnum, info[15]
word len, ofst, datalen, rld, esd
getfileinfo(path, @info)
prstr(@loadadr)
prword(info:2)
crout
refnum = open(path, iobuffer)
len = read(refnum, databuff, 512)
datalen = databuff:0
prstr(@datasz)
prword(datalen)
crout
rld = databuff + datalen + 2
ofst = 0
while datalen > 8
dumpln(databuff + 2 + ofst, ofst, 8)
ofst = ofst + 8
datalen = datalen - 8
loop
dumpln(databuff + 2 + ofst, ofst, datalen)
crout
prstr(@RLD)
crout
while ^rld
rld = dumprld(rld)
loop
crout
prstr(@ESD)
crout
esd = rld + 1
while ^esd
esd = dumpesd(esd)
loop
drop close(refnum)
end
def getlin
^inbuff = romcall(0, 0, 0, 0, $FD6A).1
return inbuff
end
home
dump(getlin)
done

BIN
plasma2/fire#ff0000 Executable file

Binary file not shown.

269
plasma2/fire.pla Executable file
View File

@ -0,0 +1,269 @@
CONST FALSE = 0
CONST TRUE = NOT FALSE
CONST SHOWLORES = $C056
CONST KEYBOARD = $C000
CONST KEYSTROBE = $C010
CONST EMPTY = 0
CONST TREE = 4
CONST FIRE = 13
CONST FORESTSIZE = 42*42
BYTE HELLOMSG[] = "PRESS ANY KEY TO BEGIN..."
BYTE EXITMSG[] = "PRESS ANY KEY TO EXIT."
BYTE GOODBYE[] = "THAT'S ALL FOLKS!"
BYTE TREES1[FORESTSIZE]
BYTE TREES2[FORESTSIZE]
WORD RNDNUM
;
; Defines for ASM routines
;
ASM EQUATES
SRC EQU $F0
SRCL EQU SRC
SRCH EQU SRC+1
DST EQU SRC+2
DSTL EQU DST
DSTH EQU DST+1
ESP EQU DST+2
END
;
; CALL 6502 ROUTINE
; ROMCALL(AREG, XREG, YREG, STATUS, ADDR)
;
ASM ROMCALL
TMP EQU $06
PHP
LDA ESTKL,X
STA TMP
LDA ESTKH,X
STA TMP+1
INX
LDA ESTKL,X
PHA
INX
LDA ESTKL,X
TAY
INX
LDA ESTKL+1,X
PHA
LDA ESTKL,X
INX
STX TMP+2
TAX
PLA
BIT ROMIN
PLP
JSR JMPTMP
PHP
BIT LCBNK2
STA REGVALS+0
STX REGVALS+1
STY REGVALS+2
PLA
STA REGVALS+3
LDX TMP+2
LDA #<REGVALS
LDY #>REGVALS
STA ESTKL,X
STY ESTKH,X
PLP
RTS
JMPTMP: JMP (TMP)
REGVALS: DS 4
END
;
; GRCOLOR(COLOR)
;
ASM GRCOLOR
LDA ESTKL,X
INX
STX TMP+2
BIT $C081
JSR $F864
BIT $C080
LDX TMP+2
END
;
; GRPLOT(X, Y)
;
ASM GRPLOT
LDA ESTKL,X
INX
LDY ESTKL,X
INX
STX TMP+2
BIT $C081
JSR $F800
BIT $C080
LDX TMP+2
END
;
; SET MEMORY TO VALUE
; MEMSET(VALUE, ADDR, SIZE)
;
ASM MEMSET
LDY #$00
LDA ESTKL+1,X
STA DSTL
LDA ESTKH+1,X
STA DSTH
INC ESTKL,X
INC ESTKH,X
SETMEM: DEC ESTKL,X
BNE :+
DEC ESTKH,X
BEQ MEMEXIT
: LDA ESTKL+2,X
STA (DST),Y
INY
BNE :+
INC DSTH
: DEC ESTKL,X
BNE :+
DEC ESTKH,X
BEQ MEMEXIT
: LDA ESTKH+2,X
STA (DST),Y
INY
BNE SETMEM
INC DSTH
BNE SETMEM
MEMEXIT: INX
INX
INX
END
;
; PRINT STRING
; PRSTR(STR)
;
ASM PRSTR
LDY #$00
LDA ESTKL,X
STA SRCL
LDA ESTKH,X
STA SRCH
BIT ROMIN
LDA (SRC),Y
STA ESTKL,X
BEQ :+
_PRS1: INY
LDA (SRC),Y
ORA #$80
JSR $FDED
TYA
CMP ESTKL,X
BNE _PRS1
: INX
BIT LCBNK2
END
DEF TEXTMODE
DROP ROMCALL(0, 0, 0, 0, $FB39)
END
DEF HOME
DROP ROMCALL(0, 0, 0, 0, $FC58)
END
DEF GOTOXY(X, Y)
^($24) = X
DROP ROMCALL(Y, 0, 0, 0, $FB5B)
END
DEF GRMODE
DROP ROMCALL(0, 0, 0, 0, $FB40)
DROP ^SHOWLORES
END
DEF RANDOMIZE(SEED)
RNDNUM = (SEED << 8) ? (SEED >> 8 & $FF) + SEED
END
DEFOPT RND
RNDNUM = (RNDNUM << 8) + RNDNUM + 12345
RETURN RNDNUM & $7FFF
END
DEFOPT BYFIRE(TREEPTR)
IF ^(TREEPTR - 43) == FIRE
RETURN TRUE
ELSIF ^(TREEPTR - 42) == FIRE
RETURN TRUE
ELSIF ^(TREEPTR - 41) == FIRE
RETURN TRUE
ELSIF ^(TREEPTR - 1) == FIRE
RETURN TRUE
ELSIF ^(TREEPTR + 1) == FIRE
RETURN TRUE
ELSIF ^(TREEPTR + 41) == FIRE
RETURN TRUE
ELSIF ^(TREEPTR + 42) == FIRE
RETURN TRUE
ELSIF ^(TREEPTR + 43) == FIRE
RETURN TRUE
FIN
RETURN FALSE
END
DEFOPT FORESTFIRE
WORD NEWTREES, OLDTREES, NEWTREE, OLDTREE, YROW
BYTE X, Y
MEMSET(EMPTY, @TREES1, FORESTSIZE)
MEMSET(EMPTY, @TREES2, FORESTSIZE)
OLDTREES = @TREES1
NEWTREES = @TREES2
FOR Y = 1 TO 40
YROW = Y * 42
FOR X = 1 TO 40
IF RND < 16384
^(OLDTREES + X + YROW) = TREE
FIN
NEXT
NEXT
WHILE ^$C000 < 128
FOR Y = 1 TO 40
YROW = Y * 42
FOR X = 1 TO 40
OLDTREE = OLDTREES + X + YROW
NEWTREE = NEWTREES + X + YROW
WHEN ^OLDTREE
IS EMPTY
IF RND < 400
^NEWTREE = TREE
ELSE
^NEWTREE = EMPTY
FIN
IS TREE
IF RND < 10 OR BYFIRE(OLDTREE)
^NEWTREE = FIRE
ELSE
^NEWTREE = TREE
FIN
IS FIRE
^NEWTREE = EMPTY
WEND
GRCOLOR(^NEWTREE)
GRPLOT(X - 1, Y - 1)
NEXT
NEXT
NEWTREES =, OLDTREES = OLDTREES, NEWTREES
LOOP
DROP ^$C010
END
PRSTR(@HELLOMSG)
WHILE ^$C000 < 128
RNDNUM = RNDNUM + 1
LOOP
RANDOMIZE(RNDNUM)
DROP ^$C010
GRMODE
HOME
GOTOXY(10,22)
PRSTR(@EXITMSG)
FORESTFIRE
TEXTMODE
HOME
PRSTR(@GOODBYE)
DONE

1375
plasma2/fire.s Executable file

File diff suppressed because it is too large Load Diff

BIN
plasma2/fire.sys Executable file

Binary file not shown.

1023
plasma2/interp6502.s Executable file

File diff suppressed because it is too large Load Diff

314
plasma2/lex.c Executable file
View File

@ -0,0 +1,314 @@
#include <stdio.h>
#include "tokens.h"
char *statement, *scanpos, *tokenstr;
t_token scantoken, prevtoken;
int tokenlen;
long constval;
int lineno = 0;
t_token keywords[] = {
IF_TOKEN, 'I', 'F',
ELSE_TOKEN, 'E', 'L', 'S', 'E',
ELSEIF_TOKEN, 'E', 'L', 'S', 'I', 'F',
FIN_TOKEN, 'F', 'I', 'N',
WHILE_TOKEN, 'W', 'H', 'I', 'L', 'E',
LOOP_TOKEN, 'L', 'O', 'O', 'P',
CASE_TOKEN, 'W', 'H', 'E', 'N',
OF_TOKEN, 'I', 'S',
DEFAULT_TOKEN, 'O', 'T', 'H', 'E', 'R', 'W', 'I', 'S', 'E',
ENDCASE_TOKEN, 'W', 'E', 'N', 'D',
FOR_TOKEN, 'F', 'O', 'R',
TO_TOKEN, 'T', 'O',
DOWNTO_TOKEN, 'D', 'O', 'W', 'N', 'T', 'O',
STEP_TOKEN, 'S', 'T', 'E', 'P',
NEXT_TOKEN, 'N', 'E', 'X', 'T',
REPEAT_TOKEN, 'R', 'E', 'P', 'E', 'A', 'T',
UNTIL_TOKEN, 'U', 'N', 'T', 'I', 'L',
BREAK_TOKEN, 'B', 'R', 'E', 'A', 'K',
ASM_TOKEN, 'A', 'S', 'M',
IFUNC_TOKEN, 'D', 'E', 'F',
NFUNC_TOKEN, 'D', 'E', 'F', 'O', 'P', 'T',
DROP_TOKEN, 'D', 'R', 'O', 'P',
RETURN_TOKEN, 'R', 'E', 'T', 'U', 'R', 'N',
END_TOKEN, 'E', 'N', 'D',
START_TOKEN, 'S', 'T', 'A', 'R', 'T',
DONE_TOKEN, 'D', 'O', 'N', 'E',
LOGIC_NOT_TOKEN, 'N', 'O', 'T',
LOGIC_AND_TOKEN, 'A', 'N', 'D',
LOGIC_OR_TOKEN, 'O', 'R',
BYTE_TOKEN, 'B', 'Y', 'T', 'E',
WORD_TOKEN, 'W', 'O', 'R', 'D',
CONST_TOKEN, 'C', 'O', 'N', 'S', 'T',
FUNC_TOKEN, 'F', 'U', 'N', 'C',
EOL_TOKEN
};
void parse_error(char *errormsg)
{
char *error_carrot = statement;
fprintf(stderr, "\n%4d: %s\n ", lineno, statement);
for (error_carrot = statement; error_carrot != tokenstr; error_carrot++)
putc(*error_carrot == '\t' ? '\t' : ' ', stderr);
fprintf(stderr, "^\nError: %s\n", errormsg);
}
t_token scan(void)
{
prevtoken = scantoken;
/*
* Skip whitespace.
*/
while (*scanpos && (*scanpos == ' ' || *scanpos == '\t')) scanpos++;
tokenstr = scanpos;
/*
* Scan for token based on first character.
*/
if (*scanpos == '\0' || *scanpos == '\n' ||*scanpos == ';')
scantoken = EOL_TOKEN;
else if ((scanpos[0] >= 'a' && scanpos[0] <= 'z')
|| (scanpos[0] >= 'A' && scanpos[0] <= 'Z')
|| (scanpos[0] == '_'))
{
/*
* ID, either variable name or reserved word.
*/
int keypos = 0, matchpos = 0;
do
{
scanpos++;
} while ((*scanpos >= 'a' && *scanpos <= 'z')
|| (*scanpos >= 'A' && *scanpos <= 'Z')
|| (*scanpos == '_')
|| (*scanpos >= '0' && *scanpos <= '9'));
scantoken = ID_TOKEN;
tokenlen = scanpos - tokenstr;
/*
* Search for matching keyword.
*/
while (keywords[keypos] != EOL_TOKEN)
{
while (keywords[keypos + 1 + matchpos] == toupper(tokenstr[matchpos]))
matchpos++;
if (IS_TOKEN(keywords[keypos + 1 + matchpos]) && (matchpos == tokenlen))
{
/*
* A match.
*/
scantoken = keywords[keypos];
break;
}
else
{
/*
* Find next keyword.
*/
keypos += matchpos + 1;
matchpos = 0;
while (!IS_TOKEN(keywords[keypos])) keypos++;
}
}
}
else if (scanpos[0] >= '0' && scanpos[0] <= '9')
{
/*
* Number constant.
*/
for (constval = 0; *scanpos >= '0' && *scanpos <= '9'; scanpos++)
constval = constval * 10 + *scanpos - '0';
scantoken = INT_TOKEN;
}
else if (scanpos[0] == '$')
{
/*
* Hexadecimal constant.
*/
constval = 0;
while (scanpos++)
{
if (*scanpos >= '0' && *scanpos <= '9')
constval = constval * 16 + *scanpos - '0';
else if (*scanpos >= 'A' && *scanpos <= 'F')
constval = constval * 16 + *scanpos - 'A' + 10;
else if (*scanpos >= 'a' && *scanpos <= 'f')
constval = constval * 16 + *scanpos - 'a' + 10;
else
break;
}
scantoken = INT_TOKEN;
}
else if (scanpos[0] == '\'')
{
/*
* Character constant.
*/
scantoken = CHAR_TOKEN;
if (scanpos[1] != '\\')
{
constval = scanpos[1];
if (scanpos[2] != '\'')
{
parse_error("Bad character constant");
return (-1);
}
scanpos += 3;
}
else
{
switch (scanpos[2])
{
case 'n':
constval = '\n';
break;
case 'r':
constval = '\r';
break;
case 't':
constval = '\t';
break;
case '\'':
constval = '\'';
case '\\':
constval = '\\';
case '0':
constval = '\0';
break;
default:
parse_error("Bad character constant");
return (-1);
}
if (scanpos[3] != '\'')
{
parse_error("Bad character constant");
return (-1);
}
scanpos += 4;
}
}
else if (scanpos[0] == '\"')
{
/*
* String constant.
*/
scantoken = STRING_TOKEN;
constval = (long)++scanpos;
while (*scanpos && *scanpos != '\"')
scanpos++;
if (!*scanpos++)
{
parse_error("Unterminated string");
return (-1);
}
}
else switch (scanpos[0])
{
/*
* Potential two and three character tokens.
*/
case '>':
if (scanpos[1] == '>')
{
scantoken = SHR_TOKEN;
scanpos += 2;
}
else if (scanpos[1] == '=')
{
scantoken = GE_TOKEN;
scanpos += 2;
}
else
{
scantoken = GT_TOKEN;
scanpos++;
}
break;
case '<':
if (scanpos[1] == '<')
{
scantoken = SHL_TOKEN;
scanpos += 2;
}
else if (scanpos[1] == '=')
{
scantoken = LE_TOKEN;
scanpos += 2;
}
else if (scanpos[1] == '>')
{
scantoken = NE_TOKEN;
scanpos += 2;
}
else
{
scantoken = LT_TOKEN;
scanpos++;
}
break;
case '=':
if (scanpos[1] == '=')
{
scantoken = EQ_TOKEN;
scanpos += 2;
}
else if (scanpos[1] == ',')
{
scantoken = SETLIST_TOKEN;
scanpos += 2;
}
else
{
scantoken = SET_TOKEN;
scanpos++;
}
break;
case '+':
if (scanpos[1] == '+')
{
scantoken = INC_TOKEN;
scanpos += 2;
}
else
{
scantoken = ADD_TOKEN;
scanpos++;
}
break;
case '-':
if (scanpos[1] == '-')
{
scantoken = DEC_TOKEN;
scanpos += 2;
}
else
{
scantoken = SUB_TOKEN;
scanpos++;
}
break;
default:
/*
* Simple single character tokens.
*/
scantoken = TOKEN(*scanpos++);
}
tokenlen = scanpos - tokenstr;
return (scantoken);
}
void scan_rewind(char *backptr)
{
scanpos = backptr;
}
char inputline[128];
int next_line(void)
{
gets(inputline);
lineno++;
statement = inputline;
scanpos = inputline;
scantoken = EOL_TOKEN;
scan();
printf("; %4d: %s\n", lineno, inputline);
return (1);
}

9
plasma2/lex.h Executable file
View File

@ -0,0 +1,9 @@
extern char *statement, *scanpos, *tokenstr;
extern t_token scantoken, prevtoken;
extern int tokenlen;
extern long constval;
extern char inputline[];
void parse_error(char *errormsg);
int next_line(void);
void scan_rewind(char *backptr);
t_token scan(void);

BIN
plasma2/lex.o Executable file

Binary file not shown.

92
plasma2/loadcmd.s Executable file
View File

@ -0,0 +1,92 @@
.PC02
.DEFINE EQU =
.DEFINE DB .BYTE
.DEFINE DW .WORD
.DEFINE DS .RES
;*
;* LANGUAGE CARD CONTROL
;*
LCBNK2 EQU $C080
ROMIN EQU $C081
;**********************************************************
;*
;* VM ZERO PAGE LOCATIONS
;*
;**********************************************************
ESTKSZ EQU $20
ESTK EQU $C0
ESTKL EQU ESTK
ESTKH EQU ESTK+ESTKSZ/2
FRMP EQU ESTK+ESTKSZ
FRMPL EQU FRMP
FRMPH EQU FRMP+1
TMP EQU $F0
TMPL EQU TMP
TMPH EQU TMP+1
SRC EQU TMP
SRCL EQU SRC
SRCH EQU SRC+1
DST EQU SRC+2
DSTL EQU DST
DSTH EQU DST+1
ESP EQU DST+2
;*
;* PAGE 3 ENTRYPOINTS TO INTERNAL ROUTINES
;*
_INTERP EQU $03D0
LEAVE EQU $03DC
ENTER EQU $03E2
;*
;* CLEAR COMMAND LINE LENGTH BYTE IF CALLED FROM 'BYE'
;*
LDY #$00
LDX #$FE ; LEAVE ROOM FOR COMMAND LINE LENGTH BYTE
TXS
BVS :+
STY $01FF ; CLEAR AUTORUN COMMAND WHEN CALLED FROM 'BYE'
;*
;* MOVE REST OF CMD FROM LANGUAGE CARD
;*
: STY $06
STY $08
LDA #$D2
STA $07
LDA #$11
STA $09
BIT LCBNK2
MVVM: LDA ($06),Y
STA ($08),Y
INY
BNE MVVM
INC $07
INC $09
LDA $07
CMP #$E0
BNE MVVM
;*
;* DEACTIVATE 80 COL CARDS
;*
BIT ROMIN
LDY #4
: LDA DISABLE80,Y
JSR $FDED
DEY
BPL :-
BIT $C054 ; SET TEXT MODE
BIT $C051
BIT $C058
JSR $FC58 ; HOME
;*
;* JUMP TO INTERPRETER
;*
BIT LCBNK2
LDX #$00
LDA #$BF
STX FRMPL
STA FRMPH
LDY #>START
LDA #<START
JMP $D104
DISABLE80: DB 21, 13, '1', 26, 13
.INCLUDE "cmd.s"

811
plasma2/loadrel.pla Executable file
View File

@ -0,0 +1,811 @@
CONST FALSE = 0
CONST TRUE = NOT FALSE
CONST IOBUFFER = $BB00
CONST SYMBUFF = $B000
WORD HIMEM = $BF00 ; MUST BE FIRST DEFINED VARIABLE
WORD LOMEM = $0800
WORD MODICT = $0000
WORD ENTRY
BYTE PLASMASTR[] = "PLASMA 0.2"
BYTE MEMSETSTR[] = "MEMSET"
BYTE MEMCPYSTR[] = "MEMCPY"
BYTE ROMCALLSTR[] = "ROMCALL"
BYTE SYSCALLSTR[] = "SYSCALL"
BYTE COUTSTR[] = "COUT"
BYTE CINSTR[] = "CIN"
BYTE PRSTRSTR[] = "PRSTR"
BYTE RDSTRSTR[] = "RDSTR"
BYTE NULLSTR[] = ""
BYTE BADMODSTR[] = "MODULE NOT FOUND"
BYTE ASMADR[] = "ASM ADDRESS: $"
BYTE LOADADR[] = "LOAD ADDRESS: $"
BYTE DATASZ[] = "DATA SIZE: $"
BYTE RELOFSTSTR[] = "REL OFFSET: $"
BYTE FIX16STR[] = "FIXUP 16-BIT ADDRESS: $"
BYTE FIX8STR[] = "FIXUP 8-BIT ADDRESS: $"
BYTE RLDLBL[] = "RELOCATION DIRECTORY:"
BYTE ESDLBL[] = "SYMBOL TABLE:"
BYTE MATCHEXTRNSTR = "MATCH EXTRN: "
BYTE PRESSANYKEY[] = "PRESS ANY KEY TO CONTINUE..."
BYTE PERR
;
; SYMBOL TABLE TYPE CONSTANTS
;
CONST LOBYTE_TYPE = $01
CONST HIBYTE_TYPE = $02
CONST WORD_TYPE = $03
CONST FUNC_TYPE = $04
CONST CONST_TYPE = $08
FUNC INITPLASMA,LOADMOD ; MUST BE FIRST DEFINED FUNCTIONS
;
; CODE GENERATION FUNCTIONS
;
CONST OPTBL = $D000
FUNC GEN_ZERO, GEN_ADD, GEN_SUB, GEN_MUL, GEN_DIV, GEN_MOD, GEN_INCR, GEN_DECR
FUNC GEN_NEG, GEN_COMP, GEN_BAND, GEN_IOR, GEN_XOR, GEN_SHL, GEN_SHR, GEN_IDXW
FUNC GEN_NOT, GEN_LOR, GEN_LAND, GEN_LA, GEN_LLA, GEN_CB, GEN_CW, GEN_SWAP
FUNC GEN_DROP, GEN_DUP, GEN_PUSH, GEN_PULL, GEN_BRLT, GEN_BRGT, GEN_BREQ, GEN_BRNE
FUNC GEN_ISEQ, GEN_ISNE, GEN_ISGT, GEN_ISLT, GEN_ISGE, GEN_ISLE, BRFLS, BRTRU
FUNC GEN_JUMP, GEN_IJMP, GEN_CALL, GEN_ICAL, GEN_ENTER, GEN_LEAVE, GEN_RET, GEN_XCALL
FUNC GEN_LB, GEN_LW, GEN_LLB, GEN_LLW, GEN_LAB, GEN_LAW, GEN_DLB, GEN_DLW
FUNC GEN_SB, GEN_SW, GEN_SLB, GEN_SLW, GEN_SAB, GEN_SAW, GEN_DAB, GEN_DAW
FUNC GEN_NOP
WORD PCPTR
WORD GEN_OPTBL[]
WORD = GEN_ZERO, GEN_ADD, GEN_SUB, GEN_MUL, GEN_DIV, GEN_MOD, GEN_INCR, GEN_DECR
WORD = GEN_NEG, GEN_COMP, GEN_BAND, GEN_IOR, GEN_XOR, GEN_SHL, GEN_SHR, GEN_IDXW
WORD = GEN_NOT, GEN_LOR, GEN_LAND, GEN_LA, GEN_LLA, GEN_CB, GEN_CW, GEN_SWAP
WORD = GEN_DROP, GEN_DUP, GEN_PUSH, GEN_PULL, GEN_BRLT, GEN_BRGT, GEN_BREQ, GEN_BRNE
WORD = GEN_ISEQ, GEN_ISNE, GEN_ISGT, GEN_ISLT, GEN_ISGE, GEN_ISLE, BRFLS, BRTRU
WORD = GEN_JUMP, GEN_IJMP, GEN_CALL, GEN_ICAL, GEN_ENTER, GEN_LEAVE, GEN_RET, GEN_XCALL
WORD = GEN_LB, GEN_LW, GEN_LLB, GEN_LLW, GEN_LAB, GEN_LAW, GEN_DLB, GEN_DLW
WORD = GEN_SB, GEN_SW, GEN_SLB, GEN_SLW, GEN_SAB, GEN_SAW, GEN_DAB, GEN_DAW
WORD = GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP
WORD = GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP
WORD = GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP
WORD = GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP
WORD = GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP
WORD = GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP
WORD = GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP
WORD = GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP, GEN_NOP
DEF BADMOD
PRSTR(@BADMODSTR)
COUT($0D)
END
DEF CROUT
RETURN COUT($0D)
END
DEF PRBYTE(VAL)
RETURN ROMCALL(VAL, 0, 0, 0, $FDDA)
END
DEF PRWORD(VAL)
ROMCALL(VAL >> 8, VAL, 0, 0, $F941)
END
DEF ADDSYM(TYPE, ADDR, SYMSTR)
(LOMEM).0 = TYPE
(LOMEM):1 = ADDR
(LOMEM).3 = ^SYMSTR
MEMCPY(SYMSTR + 1, LOMEM + 4, ^SYMSTR)
LOMEM = LOMEM + 4 + ^SYMSTR
END
DEF INITPLASMA
BYTE PARAMS[2]
CROUT
PRSTR(@PLASMASTR)
CROUT
^$BFD8 = 0 ; CLOSE ALL OPEN FILES
PARAMS.0 = 1
PARAMS.1 = 0
SYSCALL($CC, @PARAMS)
MEMSET($0000, $BF58, 24) ; RESET SYS BITMAP
^$BF58 = $C0
^$BF6F = $01
;
; SET INIT MEMORY BOUNDARIES
;
HIMEM = $BF00
LOMEM = $0800
MODICT = LOMEM
;
; INIT SYMBOL DICTIONARY
;
ADDSYM(FUNC_TYPE, @MEMSET, @MEMSETSTR)
ADDSYM(FUNC_TYPE, @MEMCPY, @MEMCPYSTR)
ADDSYM(FUNC_TYPE, @ROMCALL, @ROMCALLSTR)
ADDSYM(FUNC_TYPE, @SYSCALL, @SYSCALLSTR)
ADDSYM(FUNC_TYPE, @COUT, @COUTSTR)
ADDSYM(FUNC_TYPE, @CIN, @CINSTR)
ADDSYM(FUNC_TYPE, @PRSTR, @PRSTRSTR)
ADDSYM(FUNC_TYPE, @RDSTR, @RDSTRSTR)
ADDSYM(0, 0, @NULLSTR) ; THIS MARKS END OF MODULE DICTIONARY
END
DEF ALLOC(SIZE)
WORD ADDR
ADDR = LOMEM
LOMEM = LOMEM + SIZE
RETURN ADDR
END
DEF RELEASE(ADDR)
LOMEM = ADDR
END
;
; BASIC FILE I/O
;
DEF GETFILEINFO(PATH, INFOPTR)
BYTE PARAMS[18]
PARAMS.0 = 10
PARAMS:1 = PATH
PERR = SYSCALL($C4, @PARAMS)
IF NOT PERR
MEMCPY(@PARAMS.3, INFOPTR, 15)
FIN
RETURN PERR
END
DEF OPEN(PATH, BUFF)
BYTE PARAMS[6]
PARAMS.0 = 3
PARAMS:1 = PATH
PARAMS:3 = BUFF
PARAMS.5 = 0
PERR = SYSCALL($C8, @PARAMS)
RETURN PARAMS.5
END
DEF CLOSE(REFNUM)
BYTE PARAMS[2]
PARAMS.0 = 1
PARAMS.1 = REFNUM
PERR = SYSCALL($CC, @PARAMS)
RETURN PERR
END
DEF READ(REFNUM, BUFF, LEN)
BYTE PARAMS[8]
PARAMS.0 = 4
PARAMS.1 = REFNUM
PARAMS:2 = BUFF
PARAMS:4 = LEN
PARAMS:6 = 0
PERR = SYSCALL($CA, @PARAMS)
RETURN PARAMS:6
END
;
; CODE GENERATION
;
; ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR : 00 02 04 06 08 0A 0C 0E
DEF GEN_ZERO
^LOMEM = $00
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_ADD
^LOMEM = $02
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_SUB
^LOMEM = $04
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_MUL
^LOMEM = $06
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_DIV
^LOMEM = $08
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_MOD
^LOMEM = $0A
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_INCR
^LOMEM = $0C
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_DECR
^LOMEM = $0E
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
; NEG,COMP,BAND,IOR,XOR,SHL,SHR,IDXW : 10 12 14 16 18 1A 1C 1E
DEF GEN_NEG
^LOMEM = $10
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_COMP
^LOMEM = $12
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_BAND
^LOMEM = $14
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_IOR
^LOMEM = $16
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_XOR
^LOMEM = $18
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_SHL
^LOMEM = $1A
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_SHR
^LOMEM = $1C
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_IDXW
^LOMEM = $1E
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
; NOT,LOR,LAND,LA,LLA,CB,CW,SWAP : 20 22 24 26 28 2A 2C 2E
DEF GEN_NOT
^LOMEM = $20
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_LOR
^LOMEM = $22
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_LAND
^LOMEM = $24
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_LA
^LOMEM = $26
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_LLA
^LOMEM = $28
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_CB
(LOMEM).0 = $2A
(LOMEM).1 = (PCPTR).1
LOMEM = LOMEM + 2
PCPTR = PCPTR + 2
END
DEF GEN_CW
(LOMEM).0 = $2C
(LOMEM):1 = (PCPTR):1
LOMEM = LOMEM + 3
PCPTR = PCPTR + 3
END
DEF GEN_SWAP
^LOMEM = $2E
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
; DROP,DUP,PUSH,PULL,BRLT,BRGT,BREQ,BRNE : 30 32 34 36 38 3A 3C 3E
DEF GEN_DROP
^LOMEM = $30
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_DUP
^LOMEM = $32
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_PUSH
^LOMEM = $34
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_PULL
^LOMEM = $36
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_BRLT
^LOMEM = $38
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_BRGT
^LOMEM = $3A
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_BREQ
^LOMEM = $3C
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_BRNE
^LOMEM = $3E
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
; ISEQ,ISNE,ISGT,ISLT,ISGE,ISLE,BRFLS,BRTRU : 40 42 44 46 48 4A 4C 4E
DEF GEN_ISEQ
^LOMEM = $40
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_ISNE
^LOMEM = $42
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_ISGT
^LOMEM = $44
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_ISLT
^LOMEM = $46
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_ISGE
^LOMEM = $48
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_ISLE
^LOMEM = $4A
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF BRFLS
^LOMEM = $4C
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF BRTRU
^LOMEM = $4E
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
; JUMP,IJMP,CALL,ICAL,ENTER,LEAVE,RET,XCALL : 50 52 54 56 58 5A 5C 5E
DEF GEN_JUMP
^LOMEM = $50
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_IJMP
^LOMEM = $52
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_CALL
^LOMEM = $54
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_ICAL
^LOMEM = $56
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_ENTER
^LOMEM = $58
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_LEAVE
^LOMEM = $5A
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_RET
^LOMEM = $5C
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_XCALL
^LOMEM = $5E
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
; LB,LW,LLB,LLW,LAB,LAW,DLB,DLW : 60 62 64 66 68 6A 6C 6E
DEF GEN_LB
^LOMEM = $60
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_LW
^LOMEM = $62
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_LLB
(LOMEM).0 = $64
(LOMEM).1 = (PCPTR).1
LOMEM = LOMEM + 2
PCPTR = PCPTR + 2
END
DEF GEN_LLW
(LOMEM).0 = $66
(LOMEM).1 = (PCPTR).1
LOMEM = LOMEM + 2
PCPTR = PCPTR + 2
END
DEF GEN_LAB
^LOMEM = $68
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_LAW
^LOMEM = $6A
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_DLB
(LOMEM).0 = $6C
(LOMEM).1 = (PCPTR).1
LOMEM = LOMEM + 2
PCPTR = PCPTR + 2
END
DEF GEN_DLW
(LOMEM).0 = $6E
(LOMEM).1 = (PCPTR).1
LOMEM = LOMEM + 2
PCPTR = PCPTR + 2
END
; SB,SW,SLB,SLW,SAB,SAW,DAB,DAW : 70 72 74 76 78 7A 7C 7E
DEF GEN_SB
^LOMEM = $70
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_SW
^LOMEM = $72
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_SLB
(LOMEM).0 = $74
(LOMEM).1 = (PCPTR).1
LOMEM = LOMEM + 2
PCPTR = PCPTR + 2
END
DEF GEN_SLW
(LOMEM).0 = $76
(LOMEM).1 = (PCPTR).1
LOMEM = LOMEM + 2
PCPTR = PCPTR + 2
END
DEF GEN_SAB
^LOMEM = $78
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_SAW
^LOMEM = $7A
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_DAB
^LOMEM = $7C
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_DAW
^LOMEM = $7E
LOMEM = LOMEM + 1
PCPTR = PCPTR + 1
END
DEF GEN_OP
*(GEN_OPTBL + ^PCPTR)()
END
DEF GEN_DEF(NPARAM, FRAMESZ)
END
DEF GEN_END(NPARAM, FRAMESZ)
END
DEF GENCODE(PCODEPTR, PCODELEN, RLD, ES)
END
;
; REL MODULE FIXUPS
;
DEF DUMPRLD(RLD)
COUT('$')
PRBYTE(^RLD)
COUT(':')
COUT(' ')
COUT('$')
PRWORD(*(RLD + 1))
COUT(' ')
COUT('$')
PRBYTE(^(RLD + 3))
CROUT
RETURN RLD + 4
END
DEF DUMPESD(ESD)
WHILE ^ESD & $80
COUT(^ESD)
ESD = ESD + 1
LOOP
COUT(^ESD)
COUT(':')
COUT(' ')
COUT('$')
PRBYTE(^(ESD + 1))
COUT(' ')
COUT('$')
PRWORD(^(ESD + 2))
CROUT
RETURN ESD + 4
END
DEF MATCHSTR(STR1, STR2)
BYTE I
IF ^STR1 == ^STR2
FOR I = ^STR1 DOWNTO 1
IF (STR1).[I] <> (STR2).[I]
RETURN FALSE
FIN
NEXT
RETURN TRUE
FIN
RETURN FALSE
END
DEF SEARCHDICT(SYMSTR)
WORD DICTPTR
DICTPTR = MODICT
;
; SEARCH MODULE DICTIONARY LOOKING FOR MATCH
;
WHILE DICTPTR
IF ^DICTPTR
; CROUT
; PRSTR(DICTPTR + 3)
IF MATCHSTR(DICTPTR + 3, SYMSTR)
; COUT('$')
; PRWORD(*(DICTPTR + 1))
RETURN *(DICTPTR + 1)
FIN
DICTPTR = DICTPTR + 4 + ^(DICTPTR + 3) ; NEXT ENTRY
ELSE
DICTPTR = *(DICTPTR + 1) ; NEXT MODULE SYM TABLE
FIN
LOOP
END
DEF DUMPDICT
WORD DICTPTR
DICTPTR = MODICT
;
; SEARCH MODULE DICTIONARY LOOKING FOR MATCH
;
WHILE DICTPTR
IF ^DICTPTR
CROUT
PRSTR(DICTPTR + 3)
COUT('$')
PRWORD(*(DICTPTR + 1))
CROUT
DICTPTR = DICTPTR + 4 + ^(DICTPTR + 3) ; NEXT ENTRY
ELSE
DICTPTR = *(DICTPTR + 1) ; NEXT MODULE SYM TABLE
FIN
LOOP
END
DEF TOUPPER(C)
IF C >= 'a'
IF C <= 'z'
RETURN C - $20
FIN
FIN
RETURN C
END
DEF MATCHEXTRN(INDEX, ESD)
BYTE SYMSTR[$81], I
WORD SYMPTR
;
; FIND MATCHING ESD INDEX
;
WHILE ^ESD
; DUMPESD(ESD)
SYMPTR = ESD
I = 1
WHILE ^ESD & $80
SYMSTR[I] = TOUPPER(^ESD & $7F)
I = I + 1
ESD = ESD + 1
LOOP
SYMSTR[I] = TOUPPER(^ESD & $7F)
SYMSTR = I
; CROUT
IF ^(ESD + 1) & $10
; PRSTR(@MATCHEXTRNSTR)
; PRSTR(@SYMSTR)
IF ^(ESD + 2) == INDEX
RETURN SEARCHDICT(@SYMSTR)
FIN
FIN
ESD = ESD + 4
LOOP
RETURN 0
END
DEF FIXUP(SEGPTR, RLD, OFST, ESD)
WORD FIXVAL, FIXADDR, EXTRNVAL
WHILE ^RLD
; DUMPRLD(RLD)
FIXADDR = SEGPTR + *(RLD + 1)
IF ^RLD & $80
;
; 16 BIT FIXUP
;
; PRSTR(@FIX16STR)
; PRWORD(FIXADDR)
; CROUT
FIXVAL = *FIXADDR
IF ^RLD & $10
;
; EXTERNAL SYMBOL
;
EXTRNVAL = MATCHEXTRN(^(RLD + 3), ESD)
IF EXTRNVAL
FIXVAL = FIXVAL + EXTRNVAL
ELSE
RETURN -1
FIN
ELSE
FIXVAL = FIXVAL + OFST
FIN
IF ^RLD & $20 ; REVERSE HI AND LO BYTES
FIXVAL = ((FIXVAL >> 8) & $FF) ? (FIXVAL << 8)
FIN
*FIXADDR = FIXVAL
ELSE
;
; 8 BIT FIXUP
;
; PRSTR(@FIX8STR)
; PRWORD(FIXADDR)
; CROUT
IF ^RLD & $10
;
; EXTERNAL SYMBOL
;
FIXVAL = MATCHEXTRN(^(RLD + 3), ESD)
IF NOT EXTRNVAL
RETURN -1
FIN
ELSE
IF ^RLD & $40
FIXVAL = ^FIXADDR << 8 ? ^(RLD + 3)
FIXVAL = FIXVAL + OFST
ELSE
FIXVAL = ^(RLD + 3) << 8 ? ^FIXADDR
FIXVAL = FIXVAL + OFST
FIN
FIN
IF ^RLD & $40
^FIXADDR = FIXVAL >> 8
ELSE
^FIXADDR = FIXVAL
FIN
FIN
RLD = RLD + 4
LOOP
END
DEF LOADMOD(MODSTR)
BYTE REFNUM, I, INFO[15], SYMSTR[81]
WORD RELOFST, MODPTR, MODSYMTBL, MODSYMSZ, LEN, DATALEN, RLD, ESD
WORD PCODESEG, PCODEPTR, PCODELEN, CODEPTR, CODELEN
GETFILEINFO(MODSTR, @INFO)
IF INFO.1 <> $FE ; REL FILE TYPE
RETURN @BADMOD
FIN
RELOFST = INFO:2
; PRSTR(@ASMADR)
; PRWORD(RELOFST)
; CROUT
;
; READ REL FILE
;
REFNUM = OPEN(MODSTR, IOBUFFER)
LEN = READ(REFNUM, LOMEM, 32768)
CLOSE(REFNUM)
; PRSTR(@LOADADR)
; PRWORD(LOMEM)
; CROUT
;
; GET POINTERS TO IMPORTANT SECTIONS
;
IF (LOMEM):4 <> $BEE2
RETURN BADMOD
FIN
DATALEN = *LOMEM
MODPTR = LOMEM + 2
LOMEM = LOMEM + LEN
ENTRY = MODPTR + 6
PCODEPTR = MODPTR + (MODPTR):0
RELOFST = MODPTR - (MODPTR):4
RLD = MODPTR + DATALEN
ESD = RLD
WHILE ^ESD ; SKIP OVER RLD
ESD = ESD + 4
LOOP
ESD = ESD + 1
; PRSTR(@RELOFSTSTR)
; PRWORD(RELOFST)
; CROUT
;
; EXPAND BYTECODE
;
PCODELEN = RLD - PCODEPTR
IF CODELEN
CODEPTR = LOMEM
GENCODE(PCODEPTR, PCODELEN, RLD, ESD)
CODELEN = LOMEM - CODEPTR
FIN
;
; RUN THROUGH DATA FIXUP TABLE
;
IF FIXUP(MODPTR, RLD, RELOFST, ESD) < 0
RETURN @BADMOD
FIN
;
; CREATE SYMBOL TABLE FOR EXPORTS
;
WHILE ^ESD
; DUMPESD(ESD)
I = 1
WHILE ^ESD & $80
SYMSTR[I] = TOUPPER(^ESD & $7F)
I = I + 1
ESD = ESD + 1
LOOP
SYMSTR[I] = TOUPPER(^ESD & $7F)
SYMSTR = I
IF ^(ESD + 1) & $08 ; ENTRY SYMBOL
ADDSYM(FUNC_TYPE, *(ESD + 2), @SYMSTR)
FIN
ESD = ESD + 4
LOOP
ADDSYM(0, MODICT, @NULLSTR) ; LINK TO PREVIOUS MODULE DICTIONARY
MODSYMTBL = ESD
;
; MOVE SYM TABLE TO END OF DATA SEGMENT
;
MODSYMSZ = LOMEM - MODSYMTBL
MEMCPY(MODSYMTBL, RLD, MODSYMSZ)
;
; UPDATE POINTERS
;
MODICT = RLD
LOMEM = RLD + MODSYMSZ
; DUMPDICT
RETURN ENTRY
END
INITPLASMA
(LOADMOD(RDSTR($BA)))()
PRSTR(@PRESSANYKEY)
WHILE ^$C000 < 128
LOOP
^$C010
DONE

117
plasma2/loadvm.s Executable file
View File

@ -0,0 +1,117 @@
.PC02
.DEFINE EQU =
.DEFINE DB .BYTE
.DEFINE DW .WORD
.DEFINE DS .RES
;*
;* LANGUAGE CARD CONTROL
;*
LCBNK2 EQU $C080
ROMIN EQU $C081
;*
;* PRODOS
;*
PRODOS EQU $BF00
;*
;* LOAD VMCORE FILE
;*
;LOADVM:
LDA #$00
INC ; ONLY WORKS ON 65C02
CMP #$01
BEQ LDVMC02
LDVM02: LDA #<VMCORE
STA $06
LDA #>VMCORE
STA $07
BNE :+
LDVMC02: LDA #<VMCOREC
STA $06
LDA #>VMCOREC
STA $07
;*
;* MOVE VM INTO LANGUAGE CARD
;*
: LDA #$00
STA $08
LDA #$D0
STA $09
LDY #$00
BIT $C083 ; SELECT AND WE LC BANK 2
BIT $C083
MVVM: LDA ($06),Y ; COPY VM+CMD INTO LANGUAGE CARD
STA ($08),Y
INY
BNE MVVM
INC $07
INC $09
LDA $09
CMP #$E0
BNE MVVM
LDX #$FE
TXS
LDX #$00
STX $01FF
;*
;* LOOK FOR STARTUP FILE
;*
JSR PRODOS ; OPEN AUTORUN
DB $C8
DW OPENPARMS
BCC :+
JMP EXIT
: LDA REFNUM
STA NLPARMS+1
JSR PRODOS
DB $C9
DW NLPARMS
BCC :+
JMP EXIT
: LDA REFNUM
STA READPARMS+1
JSR PRODOS
DB $CA
DW READPARMS
BCC :+
JMP EXIT
: LDX READPARMS+6
STX $01FF
EXIT: JSR PRODOS
DB $CC
DW CLOSEPARMS
LDY #$00
STY $06
LDA #$D1
STA $07
LDVM: LDA ($06),Y ; LOAD FIRST PAGE OF CMD INTO PLACE
STA $1000,Y
INY
BNE LDVM
LDA #$7F
ADC #$01 ; SET V FLAG
JMP $1007 ; CALL CMD
;EXIT: JSR PRODOS
; DB $65
; DW EXITPARMS
;EXITPARMS: DB 4
; DB 0
AUTORUN: DB 7,"AUTORUN"
OPENPARMS: DB 3
DW AUTORUN
DW $0800
REFNUM: DB 0
NLPARMS: DB 3
DB 0
DB $7F
DB $0D
READPARMS: DB 4
DB 0
DW $0200
DW $0080
DW 0
CLOSEPARMS: DB 1
DB 0
VMCORE:
.INCLUDE "vmcore.byte"
VMCOREC:
.INCLUDE "vmcorec.byte"

127
plasma2/makefile Executable file
View File

@ -0,0 +1,127 @@
.SUFFIXES =
AFLAGS = -o $@
LFLAGS = -C default.cfg
PLCOMP = plc
BYTEDUMP = bytedump
OBJS = parse.o lex.o codegen.o
PLASMASYS = plasma.sys
PLEDPLA = pled.pla
PLEDSYS = pled.sys
PLEXPLA = plex.pla
PLEXSYS = plex.sys
PLASMPLA = plas.pla
PLASMSYS = plas.sys
RODPLA = rod.pla
RODSYS = rod.sys
FIREPLA = fire.pla
FIRESYS = fire.sys
VMLDR = loadvm.s
CMDPLA = cmd.pla
CMDLDR = loadcmd.s
CMDBYT = cmd.byte
PLIDEPLA = plide.pla
PLIDESYS = plide.sys
PLINKPLA = plink.pla
PLINKSYS = plink.sys
VMCORE = vmcore.s
VMCOREBIN = vmcore.bin
VMCORECBIN = vmcorec.bin
LOADER = loader.pla
#
# Image filetypes for Virtual ][
#
PLATYPE = .\$$ED
BINTYPE = .BIN
SYSTYPE = .SYS
TXTTYPE = .TXT
#
# Image filetypes for CiderPress
#
#PLATYPE = \#ed0000
#BINTYPE = \#060000
#SYSTYPE = \#ff0000
#TXTTYPE = \#040000
all: $(RODSYS) $(FIRESYS) $(PLEDSYS) $(PLASMSYS) $(PLEXSYS) $(PLIDESYS) $(PLINKSYS) $(PLCOMP) $(BYTEDUMP) $(VMCOREBIN) $(VMCORECBIN) $(PLASMASYS)
$(PLCOMP): $(OBJS)
cc $(OBJS) -o $(PLCOMP)
$(BYTEDUMP): bytedump.c
cc bytedump.c -o $(BYTEDUMP)
$(RODSYS): $(PLCOMP) $(RODPLA)
./$(PLCOMP) < $(RODPLA) > rod.s
ca65 rod.s -o tmp.o
ld65 $(LFLAGS) tmp.o -o $(RODSYS)
rm tmp.o
cp $(RODSYS) rod\#ff0000
$(FIRESYS): $(PLCOMP) $(FIREPLA)
./$(PLCOMP) < $(FIREPLA) > fire.s
ca65 fire.s -o tmp.o
ld65 $(LFLAGS) tmp.o -o $(FIRESYS)
rm tmp.o
cp $(FIRESYS) fire\#ff0000
$(PLEDSYS): $(PLCOMP) $(PLEDPLA)
./$(PLCOMP) < $(PLEDPLA) > pled.s
ca65 pled.s -o tmp.o
ld65 $(LFLAGS) tmp.o -o $(PLEDSYS)
rm tmp.o
cp $(PLEDSYS) pled\#ff0000
$(PLASMSYS): $(PLCOMP) $(PLASMPLA)
./$(PLCOMP) < $(PLASMPLA) > plas.s
ca65 plas.s -o tmp.o
ld65 -C plide.cfg tmp.o -o $(PLASMSYS)
rm tmp.o
cp $(PLASMSYS) plas\#ff0000
$(PLEXSYS): $(PLCOMP) $(PLEXPLA)
./$(PLCOMP) < $(PLEXPLA) > plex.s
ca65 plex.s -o tmp.o
ld65 -C plide.cfg tmp.o -o $(PLEXSYS)
rm tmp.o
cp $(PLEXSYS) plex\#ff0000
$(CMDBYT): $(PLCOMP) $(CMDLDR) $(CMDPLA) $(BYTEDUMP)
./$(PLCOMP) $$ < $(CMDPLA) > cmd.s
ca65 $(CMDLDR) -o tmp.o
ld65 -C cmdloader.cfg tmp.o -o cmd.bin
./$(BYTEDUMP) cmd.bin > $(CMDBYT)
rm tmp.o
$(PLIDESYS): $(PLIDEPLA) $(PLCOMP)
./$(PLCOMP) < $(PLIDEPLA) > plide.s
ca65 plide.s -o tmp.o
ld65 -C plide.cfg tmp.o -o $(PLIDESYS)
rm tmp.o
cp $(PLIDESYS) plide\#ff0000
$(PLINKSYS): $(PLINKPLA) $(PLCOMP)
./$(PLCOMP) < $(PLINKPLA) > plink.s
ca65 plink.s -o tmp.o
ld65 $(LFLAGS) tmp.o -o $(PLINKSYS)
rm tmp.o
cp $(PLINKSYS) plink\#ff0000
$(VMCOREBIN): $(PLCOMP) $(VMCORE) $(CMDBYT) $(BYTEDUMP)
ca65 $(VMCORE) -D IS65C02=0 -o tmp.o
ld65 $(LFLAGS) tmp.o -o $(VMCOREBIN)
rm tmp.o
$(VMCORECBIN): $(PLCOMP) $(VMCORE) $(CMDBYTE) $(BYTEDUMP)
ca65 $(VMCORE) -D IS65C02=1 -o tmp.o
ld65 $(LFLAGS) tmp.o -o $(VMCORECBIN)
rm tmp.o
$(PLASMASYS): $(PLCOMP) $(VMLDR) $(VMCOREBIN) $(VMCORECBIN)
./$(BYTEDUMP) $(VMCOREBIN) > vmcore.byte
./$(BYTEDUMP) $(VMCORECBIN) > vmcorec.byte
ca65 $(VMLDR) -o tmp.o
ld65 $(LFLAGS) tmp.o -o $(PLASMASYS)
rm tmp.o
cp $(PLASMASYS) plasma.system#ff0000

213
plasma2/makesys.pla Executable file
View File

@ -0,0 +1,213 @@
BYTE INFOBUFF[20]
BYTE PERR
WORD FILESTR = $2006
;
; Defines for ASM routines
;
ASM EQUATES
TMP EQU $F0
TMPL EQU TMP
TMPH EQU TMP+1
SRC EQU TMP
SRCL EQU SRC
SRCH EQU SRC+1
DST EQU SRC+2
DSTL EQU DST
DSTH EQU DST+1
ESP EQU DST+2
JMPTMP: JMP (TMP)
END
;
; CALL 6502 ROUTINE
; ROMCALL(AREG, XREG, YREG, STATUS, ADDR)
;
ASM ROMCALL
PHP
LDA ESTKL,X
STA TMPL
LDA ESTKH,X
STA TMPH
INX
LDA ESTKL,X
PHA
INX
LDA ESTKL,X
TAY
INX
LDA ESTKL+1,X
PHA
LDA ESTKL,X
INX
STX ESP
TAX
PLA
BIT ROMIN
PLP
JSR JMPTMP
PHP
BIT LCBNK2
STA REGVALS+0
STX REGVALS+1
STY REGVALS+2
PLA
STA REGVALS+3
LDX ESP
LDA #<REGVALS
LDY #>REGVALS
STA ESTKL,X
STY ESTKH,X
PLP
RTS
REGVALS: DS 4
END
;
;
; CALL PRODOS
; SYSCALL(CMD, PARAMS)
;
ASM SYSCALL
LDA ESTKL,X
LDY ESTKH,X
STA PARAMS
STY PARAMS+1
INX
LDA ESTKL,X
STA CMD
STX ESP
BIT ROMIN
JSR $BF00
CMD: DB 00
PARAMS: DW 0000
BIT LCBNK2
LDX ESP
STA ESTKL,X
LDY #$00
STY ESTKH,X
END
;
; COPY MEMORY
; MEMCPY(SRCADDR, DSTADDR, SIZE)
;
ASM MEMCPY
LDY #$00
LDA ESTKL,X
BNE :+
LDA ESTKH,X
BEQ MEMEXIT
: LDA ESTKL+1,X
STA DSTL
LDA ESTKH+1,X
STA DSTH
LDA ESTKL+2,X
STA SRCL
LDA ESTKH+2,X
STA SRCH
CMP DSTH
BCC REVCPY
BNE FORCPY
LDA SRCL
CMP DSTL
BCS FORCPY
REVCPY: ; REVERSE DIRECTION COPY
; CLC
LDA ESTKL,X
ADC DSTL
STA DSTL
LDA ESTKH,X
ADC DSTH
STA DSTH
CLC
LDA ESTKL,X
ADC SRCL
STA SRCL
LDA ESTKH,X
ADC SRCH
STA SRCH
INC ESTKH,X
REVCPYLP:
LDA DSTL
BNE :+
DEC DSTH
: DEC DSTL
LDA SRCL
BNE :+
DEC SRCH
: DEC SRCL
LDA (SRC),Y
STA (DST),Y
DEC ESTKL,X
BNE REVCPYLP
DEC ESTKH,X
BNE REVCPYLP
BEQ MEMEXIT
FORCPY: INC ESTKH,X
FORCPYLP:
LDA (SRC),Y
STA (DST),Y
INC DSTL
BNE :+
INC DSTH
: INC SRCL
BNE :+
INC SRCH
: DEC ESTKL,X
BNE FORCPYLP
DEC ESTKH,X
BNE FORCPYLP
BEQ MEMEXIT
END
;
; READ STRING
; STR = RDSTR(PROMPTCHAR)
;
ASM RDSTR
LDA ESTKL,X
STA $33
STX ESP
BIT ROMIN
JSR $FD6A
BIT LCBNK2
STX $01FF
: LDA $01FF,X
AND #$7F
STA $01FF,X
DEX
BPL :-
LDX ESP
LDA #$FF
STA ESTKL,X
LDA #$01
STA ESTKH,X
END
DEF GETFILEINFO(PATH, INFOPTR)
BYTE PARAMS[18]
PARAMS.0 = 10
PARAMS:1 = PATH
PERR = SYSCALL($C4, @PARAMS)
IF NOT PERR
MEMCPY(@PARAMS.3, INFOPTR, 15)
FIN
RETURN PERR
END
DEF SETFILEINFO(PATH, INFOPTR)
BYTE PARAMS[14]
PARAMS.0 = 7
PARAMS:1 = PATH
MEMCPY(INFOPTR, @PARAMS.3, 11)
PERR = SYSCALL($C3, @PARAMS)
RETURN PERR
END
IF ^FILESTR == 0
FILESTR = RDSTR($BA)
FIN
IF GETFILEINFO(FILESTR, @INFOBUFF) == 0
INFOBUFF.1 = $FF
SETFILEINFO(FILESTR, @INFOBUFF)
FIN
DONE

1465
plasma2/parse.c Executable file

File diff suppressed because it is too large Load Diff

BIN
plasma2/parse.o Executable file

Binary file not shown.

2731
plasma2/plas.pla Executable file

File diff suppressed because it is too large Load Diff

9992
plasma2/plas.s Executable file

File diff suppressed because it is too large Load Diff

10
plasma2/plasma2.cfg Executable file
View File

@ -0,0 +1,10 @@
MEMORY {
RAM: start = $2000, size = $6000, file = %O;
}
SEGMENTS {
CODE: load = RAM, type = rw;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = rw;
}

2553
plasma2/plasma2.pla Executable file

File diff suppressed because it is too large Load Diff

BIN
plasma2/plc Executable file

Binary file not shown.

BIN
plasma2/pled#ff0000 Executable file

Binary file not shown.

1476
plasma2/pled.pla Executable file

File diff suppressed because it is too large Load Diff

5450
plasma2/pled.s Executable file

File diff suppressed because it is too large Load Diff

BIN
plasma2/pled.sys Executable file

Binary file not shown.

2850
plasma2/plex.pla Executable file

File diff suppressed because it is too large Load Diff

11246
plasma2/plex.s Executable file

File diff suppressed because it is too large Load Diff

64
plasma2/plib.s Executable file
View File

@ -0,0 +1,64 @@
.PC02
.DEFINE EQU =
.DEFINE DB .BYTE
.DEFINE DW .WORD
.DEFINE DS .RES
;*
;* LANGUAGE CARD CONTROL
;*
LCBNK2 EQU $C080
ROMIN EQU $C081
;*
;* LOAD VMCORE FILE
;*
;LOADVM:
LDA #$00
INC ; ONLY WORKS ON 65C02
CMP #$01
BEQ LDVMC02
LDVM02: LDA #<VMCORE
STA $06
LDA #>VMCORE
STA $07
BNE :+
LDVMC02: LDA #<VMCOREC
STA $06
LDA #>VMCOREC
STA $07
;*
;* MOVE VM INTO LANGUAGE CARD
;*
: LDA #$00
STA $08
LDA #$D0
STA $09
LDY #$00
BIT $C083 ; SELECT AND WE LC BANK 2
BIT $C083
MVVM: LDA ($06),Y
STA ($08),Y
INY
BNE MVVM
INC $07
INC $09
LDA $09
CMP #$E0
BNE MVVM
BIT ROMIN
;*
;* LOOK FOR STARTUP FILE
;*
;*
;* EXIT TO PRODOS
;*
EXIT: JSR $BF00
DB $65
DW EXITPARMS
EXITPARMS:
DB 4
DB 0
VMCORE:
.INCLUDE "vmcore.byte"
VMCOREC:
.INCLUDE "vmcorec.byte"

10
plasma2/plide.cfg Executable file
View File

@ -0,0 +1,10 @@
MEMORY {
RAM: start = $2000, size = $5000, file = %O;
}
SEGMENTS {
CODE: load = RAM, type = rw;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = rw;
}

3845
plasma2/plide.pla Executable file

File diff suppressed because it is too large Load Diff

14766
plasma2/plide.s Executable file

File diff suppressed because it is too large Load Diff

832
plasma2/plink.pla Executable file
View File

@ -0,0 +1,832 @@
CONST FALSE = 0
CONST TRUE = NOT FALSE
CONST OK = 0
CONST ERROR = -1
CONST INPUTSTR = $01FF
CONST INBUFF = $0800
CONST OUTBUFF = $0C00
CONST SYMTABLE = $1000
CONST SYMSIZE = $1000
CONST MODFILES = $7F00
CONST DATABUFF = $8000
WORD NEXTENTRY = SYMTABLE
BYTE PLASMASTR[] = "PLASMA LINKER 0.8"
BYTE NULLSTR[] = ""
BYTE BADMODSTR[] = "MODULE NOT FOUND"
BYTE ASMADR[] = "ASM ADDRESS: $"
BYTE LOADADR[] = "LOAD ADDRESS: $"
BYTE DATASZ[] = "DATA SIZE: $"
BYTE RELOFSTSTR[] = "REL OFFSET: $"
BYTE FIX16STR[] = "FIXUP 16-BIT ADDRESS: $"
BYTE FIX8STR[] = "FIXUP 8-BIT ADDRESS: $"
BYTE RLDLBL[] = "RELOCATION DIRECTORY:"
BYTE ESDLBL[] = "SYMBOL TABLE:"
BYTE MATCHEXTRNSTR = "MATCH EXTRN: "
BYTE INPUTFILESTR = "INPUT FILE"
BYTE OUTPUTFILESTR = "OUTPUT FILE"
BYTE BADEXT[] = "UNRESOLVED EXTERNAL SYMBOL: "
BYTE DUPSYMERR[] = "DUPLICATE EXTERNAL SYMBOL: "
BYTE ERROUTSTR = "ERROR CREATING OUTPUT FILE"
BYTE PRESSANYKEY[] = "PRESS ANY KEY TO CONTINUE..."
BYTE BINFILESTR[80]
BYTE MODCOUNT, MODI
BYTE BINREF, BINTYPE
WORD MODFILE,MODBUFF,MODLEN,MODADDR,LINKADDR
BYTE PERR
;
; Defines for ASM routines
;
ASM EQUATES
TMP EQU $F0
TMPL EQU TMP
TMPH EQU TMP+1
SRC EQU TMP
SRCL EQU SRC
SRCH EQU SRC+1
DST EQU SRC+2
DSTL EQU DST
DSTH EQU DST+1
ESP EQU DST+2
JMPTMP: JMP (TMP)
END
;
; CALL 6502 ROUTINE
; ROMCALL(AREG, XREG, YREG, STATUS, ADDR)
;
ASM ROMCALL
PHP
LDA ESTKL,X
STA TMPL
LDA ESTKH,X
STA TMPH
INX
LDA ESTKL,X
PHA
INX
LDA ESTKL,X
TAY
INX
LDA ESTKL+1,X
PHA
LDA ESTKL,X
INX
STX ESP
TAX
PLA
BIT ROMIN
PLP
JSR JMPTMP
PHP
BIT LCBNK2
STA REGVALS+0
STX REGVALS+1
STY REGVALS+2
PLA
STA REGVALS+3
LDX ESP
LDA #<REGVALS
LDY #>REGVALS
STA ESTKL,X
STY ESTKH,X
PLP
RTS
REGVALS: DS 4
END
;
; CALL PRODOS
; SYSCALL(CMD, PARAMS)
;
ASM SYSCALL
LDA ESTKL,X
LDY ESTKH,X
STA PARAMS
STY PARAMS+1
INX
LDA ESTKL,X
STA CMD
STX ESP
BIT ROMIN
JSR $BF00
CMD: DB 00
PARAMS: DW 0000
BIT LCBNK2
LDX ESP
STA ESTKL,X
LDY #$00
STY ESTKH,X
END
;
; SET MEMORY TO VALUE
; MEMSET(VALUE, ADDR, SIZE)
;
ASM MEMSET
LDY #$00
LDA ESTKL+1,X
STA DSTL
LDA ESTKH+1,X
STA DSTH
INC ESTKL,X
INC ESTKH,X
SETMEM: DEC ESTKL,X
BNE :+
DEC ESTKH,X
BEQ MEMEXIT
: LDA ESTKL+2,X
STA (DST),Y
INY
BNE :+
INC DSTH
: DEC ESTKL,X
BNE :+
DEC ESTKH,X
BEQ MEMEXIT
: LDA ESTKH+2,X
STA (DST),Y
INY
BNE SETMEM
INC DSTH
BNE SETMEM
MEMEXIT: INX
INX
INX
END
;
; COPY MEMORY
; MEMCPY(SRCADDR, DSTADDR, SIZE)
;
ASM MEMCPY
LDY #$00
LDA ESTKL,X
BNE :+
LDA ESTKH,X
BEQ MEMEXIT
: LDA ESTKL+1,X
STA DSTL
LDA ESTKH+1,X
STA DSTH
LDA ESTKL+2,X
STA SRCL
LDA ESTKH+2,X
STA SRCH
CMP DSTH
BCC REVCPY
BNE FORCPY
LDA SRCL
CMP DSTL
BCS FORCPY
REVCPY: ; REVERSE DIRECTION COPY
; CLC
LDA ESTKL,X
ADC DSTL
STA DSTL
LDA ESTKH,X
ADC DSTH
STA DSTH
CLC
LDA ESTKL,X
ADC SRCL
STA SRCL
LDA ESTKH,X
ADC SRCH
STA SRCH
INC ESTKH,X
REVCPYLP:
LDA DSTL
BNE :+
DEC DSTH
: DEC DSTL
LDA SRCL
BNE :+
DEC SRCH
: DEC SRCL
LDA (SRC),Y
STA (DST),Y
DEC ESTKL,X
BNE REVCPYLP
DEC ESTKH,X
BNE REVCPYLP
BEQ MEMEXIT
FORCPY: INC ESTKH,X
FORCPYLP:
LDA (SRC),Y
STA (DST),Y
INC DSTL
BNE :+
INC DSTH
: INC SRCL
BNE :+
INC SRCH
: DEC ESTKL,X
BNE FORCPYLP
DEC ESTKH,X
BNE FORCPYLP
BEQ MEMEXIT
END
;
; CHAR OUT
; COUT(CHAR)
;
ASM COUT
LDA ESTKL,X
INX
ORA #$80
BIT ROMIN
JSR $FDED
BIT LCBNK2
END
;
; CHAR IN
; RDKEY()
;
ASM CIN
BIT ROMIN
STX ESP
JSR $FD0C
LDX ESP
BIT LCBNK2
DEX
AND #$7F
STA ESTKL,X
LDY #$00
STY ESTKH,X
END
;
; PRINT STRING
; PRSTR(STR)
;
ASM PRSTR
LDY #$00
LDA ESTKL,X
STA SRCL
LDA ESTKH,X
STA SRCH
BIT ROMIN
LDA (SRC),Y
STA ESTKL,X
BEQ :+
_PRS1: INY
LDA (SRC),Y
ORA #$80
JSR $FDED
TYA
CMP ESTKL,X
BNE _PRS1
: INX
BIT LCBNK2
END
;
; READ STRING
; STR = RDSTR(PROMPTCHAR)
;
ASM RDSTR
LDA ESTKL,X
STA $33
STX ESP
BIT ROMIN
JSR $FD6A
BIT LCBNK2
STX $01FF
: LDA $01FF,X
AND #$7F
STA $01FF,X
DEX
BPL :-
LDX ESP
LDA #$FF
STA ESTKL,X
LDA #$01
STA ESTKH,X
END
;
; CONVERT CHARACTER TO UPPER CASE (AND STRIP MSB)
; CH = TOUPPER(CH)
;
ASM TOUPPER
LDA ESTKL,X
AND #$7F
CMP #'a'
BCC :+
CMP #'z'+1
BCS :+
; SEC
SBC #$1F ; SBC #$20
: STA ESTKL,X
END
DEF CROUT
COUT($0D)
END
DEF BADMOD
PRSTR(@BADMODSTR)
CROUT()
END
DEF PRBYTE(VAL)
DROP ROMCALL(VAL, 0, 0, 0, $FDDA)
END
DEF PRWORD(VAL)
DROP ROMCALL(VAL >> 8, VAL, 0, 0, $F941)
END
;
; BASIC FILE I/O
;
DEF GETFILEINFO(PATH, INFOPTR)
BYTE PARAMS[18]
PARAMS.0 = 10
PARAMS:1 = PATH
PERR = SYSCALL($C4, @PARAMS)
IF NOT PERR
MEMCPY(@PARAMS.3, INFOPTR, 15)
FIN
RETURN PERR
END
DEF DESTROY(PATH)
BYTE PARAMS[3]
PARAMS.0 = 1
PARAMS:1 = PATH
PERR = SYSCALL($C1, @PARAMS)
RETURN PERR
END
DEF CREATE(PATH, ACCESS, TYPE, AUX)
BYTE PARAMS[12]
PARAMS.0 = 7
PARAMS:1 = PATH
PARAMS.3 = ACCESS
PARAMS.4 = TYPE
PARAMS:5 = AUX
PARAMS.7 = $1
PARAMS:8 = 0
PARAMS:10 = 0
PERR = SYSCALL($C0, @PARAMS)
RETURN PERR
END
DEF OPEN(PATH, BUFF)
BYTE PARAMS[6]
PARAMS.0 = 3
PARAMS:1 = PATH
PARAMS:3 = BUFF
PARAMS.5 = 0
PERR = SYSCALL($C8, @PARAMS)
RETURN PARAMS.5
END
DEF CLOSE(REFNUM)
BYTE PARAMS[2]
PARAMS.0 = 1
PARAMS.1 = REFNUM
PERR = SYSCALL($CC, @PARAMS)
RETURN PERR
END
DEF READ(REFNUM, BUFF, LEN)
BYTE PARAMS[8]
PARAMS.0 = 4
PARAMS.1 = REFNUM
PARAMS:2 = BUFF
PARAMS:4 = LEN
PARAMS:6 = 0
PERR = SYSCALL($CA, @PARAMS)
RETURN PARAMS:6
END
DEF WRITE(REFNUM, BUFF, LEN)
BYTE PARAMS[8]
PARAMS.0 = 4
PARAMS.1 = REFNUM
PARAMS:2 = BUFF
PARAMS:4 = LEN
PARAMS:6 = 0
PERR = SYSCALL($CB, @PARAMS)
RETURN PARAMS:6
END
;
; REL MODULE FIXUPS
;
;DEF DUMPRLD(RLD)
; COUT('$')
; PRBYTE(^RLD)
; COUT(':')
; COUT(' ')
; COUT('$')
; PRWORD(*(RLD + 1))
; COUT(' ')
; COUT('$')
; PRBYTE(^(RLD + 3))
; CROUT
; RETURN RLD + 4
;END
;DEF DUMPESD(ESD)
; WHILE ^ESD & $80
; COUT(^ESD)
; ESD = ESD + 1
; LOOP
; COUT(^ESD)
; COUT(':')
; COUT(' ')
; COUT('$')
; PRBYTE(^(ESD + 1))
; COUT(' ')
; COUT('$')
; PRWORD(^(ESD + 2))
; CROUT
; RETURN ESD + 4
;END
DEF MATCHSTR(STR1, STR2)
BYTE I
IF ^STR1 == ^STR2
FOR I = ^STR1 DOWNTO 1
IF (STR1).[I] <> (STR2).[I]
RETURN FALSE
FIN
NEXT
RETURN TRUE
FIN
RETURN FALSE
END
;
; THE GLOBAL SYMBOL DICTIONARY HAS THE FORMAT OF:
; STRING: NAME (VARIABLE LENGTH)
; WORD: ADDRESS
;
DEF DUMPDICT
WORD DICTPTR
DICTPTR = SYMTABLE
CROUT()
WHILE ^DICTPTR
PRSTR(DICTPTR)
COUT(':')
COUT(' ')
COUT('$')
PRWORD(*(DICTPTR + ^DICTPTR + 1))
CROUT()
DICTPTR = DICTPTR + ^DICTPTR + 3 ; NEXT ENTRY
LOOP
END
DEF SEARCHDICT(SYMSTR)
WORD DICTPTR
DICTPTR = SYMTABLE
;
; SEARCH GLOBAL DICTIONARY LOOKING FOR MATCH
;
WHILE ^DICTPTR
IF MATCHSTR(DICTPTR, SYMSTR)
RETURN DICTPTR + ^DICTPTR + 1
FIN
DICTPTR = DICTPTR + ^DICTPTR + 3 ; NEXT ENTRY
LOOP
RETURN 0
END
DEF ADDSYM(SYMSTR, ADDR)
IF SEARCHDICT(SYMSTR)
PRSTR(@DUPSYMERR)
PRSTR(SYMSTR)
CROUT()
RETURN ERROR
FIN
MEMCPY(SYMSTR, NEXTENTRY, ^SYMSTR + 1)
NEXTENTRY = NEXTENTRY + ^NEXTENTRY
(NEXTENTRY):1 = ADDR
NEXTENTRY = NEXTENTRY + 3
RETURN OK
END
DEF MATCHEXTRN(INDEX, ESD)
BYTE SYMSTR[$81], I
WORD SYMPTR
;
; FIND MATCHING ESD INDEX
;
WHILE ^ESD
SYMPTR = ESD
I = 1
WHILE ^ESD & $80
SYMSTR[I] = TOUPPER(^ESD)
I = I + 1
ESD = ESD + 1
LOOP
SYMSTR[I] = TOUPPER(^ESD)
SYMSTR = I
IF ^(ESD + 1) & $10
IF ^(ESD + 2) == INDEX
RETURN SEARCHDICT(@SYMSTR)
FIN
FIN
ESD = ESD + 4
LOOP
RETURN 0
END
DEF PREXTRN(INDEX, ESD)
BYTE SYMSTR[$81], I
WORD SYMPTR
;
; FIND MATCHING ESD INDEX
;
WHILE ^ESD
SYMPTR = ESD
I = 1
WHILE ^ESD & $80
SYMSTR[I] = TOUPPER(^ESD)
I = I + 1
ESD = ESD + 1
LOOP
SYMSTR[I] = TOUPPER(^ESD)
SYMSTR = I
IF ^(ESD + 1) & $10
IF ^(ESD + 2) == INDEX
PRSTR(@SYMSTR)
FIN
FIN
ESD = ESD + 4
LOOP
END
;
; THE EXTENDED MODULE FORMAT CONTAINS:
; DATA_SIZE (WORD)
; IF DATA_SIZE <> 0
; DATA_SEGMENT (0..DATA_SIZE)
; ELSE
; DATA_SIZE (WORD)
; BYTECODE_SIZE (WORD)
; BYTECODE_FUNCTION_COUNT (BYTE)
; DATA_SEGMENT (1..DATA_SIZE)
; BYTECODE_SEGMENT (1..BYTECODE_SIZE)
; BYTECODE_FUNCTION_DICTIONARY (0..BYTECODE_FUNCTION_COUNT * 6)
; BYTE: FLAGS
; BIT 7: ENTRY DEF
; BIT 0..1: OPTIMIZATION LEVEL (0, 1, 2, 3)
; WORD: FUNC SIZE
; WORD: FUNC OFFSET
; BYTE: ESD INDEX IF ENTRY
; FIN
; RELOCATEABLE_DICTIONARY
; BYTE: FLAGS
; BIT 7: SIZE OF RELOC FIELD - 1 = WORD, 0 = BYTE
; BIT 6: MSB/LSB OF WORD - 1 = MSB, 0 = LSB
; BIT 5: ENDIANNESS OF WORD - 1 = BIG, 0 = LITTLE
; BIT 4: EXTRN REF - 1 = EXTRN, 0 = NOT EXTERN
; BIT 3: BYTCODE FUNC - 1 = FUNC, 0 NOT FUNC
; BIT 2: SEGMENT FIXUP - 1 = BYTECODE, 0 = DATA
; BIT 0: NOT END OF RLD - 1 = NOT END, 0 = END
; WORD: FIXUP_OFFSET
; BYTE: 8 BIT VALUE/ESD INDEX IF EXTERN/FUNC INDEX IF BYTECODE FUNC
; END_OF_RLD = $00 (BYTE)
; EXTERNAL_SYMBOL_DICTIONARY
; STRING: NAME
; BYTE: FLAGS
; BIT 4: EXTRN REF
; BIT 3: EXPORT DEF
; BIT 2: MODULE DEP (UNUSED MACRO-BIT)
; BIT 1: BYTECODE ENTRY
; BYTE: EXTRN SYMBOL INDEX/BYTECODE ENTRY INDEX/LSB OF EXPORT OFFSET
; BYTE: EXTERN SYMBOL MODULE INDEX/MSB OF EXPORT OFFSET
; END_OF_ESD = $00 (BYTE)
;
DEF FIXUP(DATASEGPTR, CODESEGPTR, BFD, RLD, OFST, ESD, PASS)
WORD FIXVAL, FIXADDR, EXTRNVAL
WHILE ^RLD
IF ^RLD & $04
FIXADDR = CODESEGPTR + *(RLD + 1)
ELSE
FIXADDR = DATASEGPTR + *(RLD + 1)
FIN
IF ^RLD & $08
;
; BYTCODE FUNC INDEX ADDRESS
;
FIXVAL = BFD + (^(RLD + 3) * 6)
ELSIF ^RLD & $10
;
; EXTERNAL SYMBOL
;
EXTRNVAL = MATCHEXTRN(^(RLD + 3), ESD)
IF EXTRNVAL
FIXVAL = *EXTRNVAL
ELSIF PASS == 2
PRSTR(@BADEXT)
PREXTRN(^(RLD + 3), ESD)
CROUT()
RETURN ERROR
FIN
ELSE
;
; DATA ADDRESS
;
IF ^RLD & $80
;
; 16 BIT OFFSET
;
FIXVAL = OFST
ELSE
;
; 8 BIT VALUE FROM RLD TABLE
;
FIXVAL = ^(RLD + 3) + OFST
FIN
FIN
IF ^RLD & $80
;
; 16 BIT FIXUP
;
IF ^RLD & $20 ; REVERSE HI AND LO BYTES
FIXVAL = FIXVAL + ((FIXADDR).1 ? ((FIXADDR).0 << 8))
*FIXADDR = ((FIXVAL >> 8) & $FF) ? (FIXVAL << 8)
ELSE
*FIXADDR = FIXVAL + *FIXADDR
FIN
ELSE
;
; 8 BIT FIXUP
;
IF ^RLD & $40
^FIXADDR = (FIXVAL >> 8) + ^FIXADDR
ELSE
^FIXADDR = FIXVAL + ^FIXADDR
FIN
FIN
RLD = RLD + 4
LOOP
RETURN OK
END
DEF LOADMOD(MODSTR, PASS)
BYTE REFNUM, I, INFO[15], SYMSTR[81]
WORD RELOFST, MODPTR, MODSYMTBL, MODSYMSZ, LEN
WORD DATASEG, CODESEG, DATALEN, CODELEN, NUMDEFS, BFD, RLD, ESD
WORD CODEOFST, BFDOFST
DROP GETFILEINFO(MODSTR, @INFO)
IF PERR OR INFO.1 <> $FE ; REL FILE TYPE
RETURN 0, 0
FIN
IF MODADDR
RELOFST = MODADDR - INFO:2
ELSE
MODADDR = INFO:2
LINKADDR = MODADDR
RELOFST = 0
FIN
MODADDR = MODADDR + DATALEN
;
; READ REL FILE
;
REFNUM = OPEN(MODSTR, INBUFF)
LEN = READ(REFNUM, DATABUFF, 16384)
DROP CLOSE(REFNUM)
;
; GET POINTERS TO IMPORTANT SECTIONS
;
DATALEN = *DATABUFF
IF DATALEN == 0
;
; EXTENDED FORMAT REL
;
MODPTR = DATABUFF + 2
DATALEN = (MODPTR):0
CODELEN = (MODPTR):2
NUMDEFS = (MODPTR).4
DATASEG = MODPTR + 5
CODESEG = DATASEG + DATALEN
CODEOFST = RELOFST + DATALEN
BFD = CODESEG + CODELEN
BFDOFST = CODEOFST + CODELEN
MODPTR = BFD
FOR I = 0 TO NUMDEFS
;
; REFORMAT BFD
;
(MODPTR).0 = $20 ; JSR
(MODPTR):1 = $03D6 ; INTERPX
(MODPTR):3 = (MODPTR):3 + CODEOFST ; FIXUP
(MODPTR).5 = $00 ; EXTERNAL BANK # (0 = MAIN MEM)
MODPTR = MODPTR + 6
NEXT
ELSE
;
; NORMAL FORMAT REL
;
CODELEN = 0
DATASEG = DATABUFF + 2
CODESEG = 0
BFD = 0
NUMDEFS = 0
MODPTR = DATASEG + DATALEN
FIN
RLD = MODPTR
ESD = RLD
WHILE ^ESD ; SKIP OVER RLD
ESD = ESD + 4
LOOP
ESD = ESD + 1
;
; RUN THROUGH DATA FIXUP TABLE
;
IF FIXUP(DATASEG, CODESEG, BFD, RLD, RELOFST, ESD, PASS)
RETURN 0, 0
FIN
;
; CHECK SYMBOL TABLE FOR EXPORTS/IMPORTS/MODULE DEPENDENCIES
;
IF PASS == 1
WHILE ^ESD
I = 1
WHILE ^ESD & $80
SYMSTR[I] = TOUPPER(^ESD)
I = I + 1
ESD = ESD + 1
LOOP
SYMSTR[I] = TOUPPER(^ESD)
SYMSTR = I
IF ^(ESD + 1) & $08 ; EXPORT SYMBOL
;
; ADD TO GLOBAL SYMBOL TABLE
;
IF ADDSYM(@SYMSTR, *(ESD + 2) + RELOFST)
RETURN 0, 0
FIN
ELSIF ^(ESD + 1) & $02 ; BYTECODE ENTRY SYMBOL
;
; ADD TO GLOBAL SYMBOL TABLE
;
IF ADDSYM(@SYMSTR, ^(ESD + 2) * 6 + BFDOFST)
RETURN 0, 0
FIN
ELSIF ^(ESD + 1) & $04 ; MODULE DEPENDENCY
;
; ADD MODULE DEPENDENCY TO MODFILE LIST
;
MEMCPY(@SYMSTR, MODFILE, I + 1)
MODFILE = MODFILE + I + 1
MODCOUNT = MODCOUNT + 1
FIN
ESD = ESD + 4
LOOP
FIN
RETURN DATASEG, DATALEN + CODELEN + NUMDEFS * 6
END
CROUT()
PRSTR(@PLASMASTR)
CROUT()
MEMSET(0, SYMTABLE, SYMSIZE)
MODCOUNT = 0
MODFILE = MODFILES
MODADDR = 0
PRSTR(@INPUTFILESTR)
WHILE ^(RDSTR($BA))
MEMCPY(INPUTSTR, MODFILE, ^INPUTSTR + 1)
MODFILE = MODFILE + ^MODFILE + 1
MODCOUNT = MODCOUNT + 1
LOOP
IF MODCOUNT
MODFILE = MODFILES
FOR MODI = 0 TO MODCOUNT - 1
IF NOT LOADMOD(MODFILE, 1)
PRSTR(MODFILE)
COUT('?')
COUT(7)
CROUT()
FIN
DROP
MODFILE = MODFILE + ^MODFILE + 1
NEXT
MODADDR = 0
MODFILE = MODFILES
IF LINKADDR == $2000
BINTYPE = $FF
ELSE
BINTYPE = $06
FIN
PRSTR(@OUTPUTFILESTR)
RDSTR($BA)
MEMCPY(INPUTSTR, BINFILESTR, ^INPUTSTR + 1)
DROP DESTROY(BINFILESTR)
DROP CREATE(BINFILESTR, $C3, BINTYPE, LINKADDR)
BINREF = OPEN(BINFILESTR, OUTBUFF)
IF BINREF == 0
PRSTR(@ERROUTSTR)
PRSTR(INPUTSTR)
ELSE
FOR MODI = 0 TO MODCOUNT - 1
MODBUFF =, MODLEN = LOADMOD(MODFILE, 2)
DROP WRITE(BINREF, MODBUFF, MODLEN)
PRSTR(MODFILE)
COUT('@')
COUT('$')
PRWORD(MODADDR - MODLEN)
CROUT()
MODFILE = MODFILE + ^MODFILE + 1
NEXT
DROP CLOSE(BINREF)
DUMPDICT()
FIN
CROUT()
PRSTR(@PRESSANYKEY)
WHILE ^$C000 < 128
LOOP
DROP ^$C010
FIN
DONE

1
plasma2/plinky.pla Executable file

File diff suppressed because one or more lines are too long

333
plasma2/plstub.s Executable file
View File

@ -0,0 +1,333 @@
.PC02
.DEFINE EQU =
.DEFINE DB .BYTE
.DEFINE DW .WORD
.DEFINE DS .RES
;*
;* LANGUAGE CARD CONTROL
;*
LCBNK2 EQU $C080
ROMIN EQU $C081
;**********************************************************
;*
;* VM ZERO PAGE LOCATIONS
;*
;**********************************************************
ESTKSZ EQU $20
ESTK EQU $C0
ESTKL EQU ESTK
ESTKH EQU ESTK+ESTKSZ/2
VMZP EQU ESTK+ESTKSZ
FRMP EQU VMZP+$00
FRMPL EQU FRMP
FRMPH EQU FRMP+1
PC EQU VMZP+$02
PCL EQU PC
PCH EQU PC+1
JSROP EQU VMZP+$0D
;*
;* PAGE 3 ENTRYPOINTS TO INTERNAL ROUTINES
;*
INTERP EQU $03D0
INTERPX EQU $03D6
LEAVE EQU $03DC
ENTER EQU $03E2
;*
;* INTERNAL OPCODE ADDRESS ADDRESSES (FROM OPTBL)
;*
_ZERO EQU $D000
_ADD EQU $D002
_SUB EQU $D004
_MUL EQU $D006
_DIV EQU $D008
_DIVMOD EQU $D00A
_INCR EQU $D00C
_DECR EQU $D00E
_NEG EQU $D010
_COMP EQU $D012
_BAND EQU $D014
_IOR EQU $D016
_XOR EQU $D018
_SHL EQU $D01A
_SHR EQU $D01C
_IDXW EQU $D01E
_NOT EQU $D020
_LOR EQU $D022
_LAND EQU $D024
_LA EQU $D026
_LLA EQU $D028
_CB EQU $D02A
_CW EQU $D02C
_SWAP EQU $D02E
_DROP EQU $D030
_DUP EQU $D032
_PUSH EQU $D034
_PULL EQU $D036
_SKPLT EQU $D038
_SKPGT EQU $D03A
_SKPEQ EQU $D03C
_SKPNE EQU $D03E
_ISEQ EQU $D040
_ISNE EQU $D042
_ISGT EQU $D044
_ISLT EQU $D046
_ISGE EQU $D048
_ISLE EQU $D04A
_SKPFLS EQU $D04C
_SKPTRU EQU $D04E
_SKIP EQU $D050
_ISKIP EQU $D052
_CALL EQU $D054
_ICAL EQU $D056
_ENTER EQU $D058
_LEAVE EQU $D05A
_RET EQU $D05C
_INT EQU $D05E
_LB EQU $D060
_LW EQU $D062
_LLB EQU $D064
_LLW EQU $D066
_LAB EQU $D068
_LAW EQU $D06A
_DLB EQU $D06C
_DLW EQU $D06E
_SB EQU $D070
_SW EQU $D072
_SLB EQU $D074
_SLW EQU $D076
_SAB EQU $D078
_SAW EQU $D07A
_DAB EQU $D07C
_DAW EQU $D07E
JMP _ENTRY
DB $EE,$EE
DB 65,00
DS 64
NOPLASMA: DB 39, " PLASMA VM NOT LOADED. PRESS ANY KEY..."
_ENTRY: BIT LCBNK2
LDA $D101
CMP #$B8 ; CLV
BEQ _JMPSTART
BIT ROMIN
LDY #$00
: INY
LDA NOPLASMA,Y
ORA #$80
JSR $FDED
CPY NOPLASMA
BNE :-
JSR $FD0C
JMP _EXIT
_JMPSTART: LDX #$FE ; LEAVE $1FF AVAIL FOR RDSTR()
TXS
LDX #$00
LDA #$BF
STX FRMPL
STA FRMPH
LDY #>START
LDA #<START
JSR $D104
;*
;* EXIT TO PRODOS
;*
_EXIT: JSR $BF00
DB $65
DW _EXITPARMS
_EXITPARMS:
DB 4
DB 0
;*
;* ENTER INTO INLINE BYTECODE
;* USING FAST INTERPRETER WITHOUT CHECKS
;*
_INTERP: BIT $C080
PLA
STA PCL
PLA
STA PCH
LDA #$00
INC
CMP #$01
BEQ NEXTOPC
LDY #$00
BEQ NEXTOP
FETCHOP:
LDA (PC),Y
STA JSROP+1
JSR JSROP
NEXTOP:
INC PCL
BNE FETCHOP
INC PCH
BNE FETCHOP
FETCHOPC:
LDA (PC)
STA JSROP+1
JSR JSROP
NEXTOPC:
INC PCL
BNE FETCHOPC
INC PCH
BNE FETCHOPC
;*
;* INDIRECT CALLS TO VM OPS
;*
;ZERO: JMP (_ZERO)
ADD: ;JMP (_ADD)
LDY #$02
BNE FIXUP
SUB: ;JMP (_SUB)
LDY #$04
BNE FIXUP
MUL: ;JMP (_MUL)
LDY #$06
BNE FIXUP
DIV: ;JMP (_DIV)
LDY #$08
BNE FIXUP
DIVMOD: ;JMP (_DIVMOD)
LDY #$0A
BNE FIXUP
;INCR: JMP (_INCR)
;DECR: JMP (_DECR)
NEG: ;JMP (_NEG)
LDY #$10
BNE FIXUP
COMP: ;JMP (_COMP)
LDY #$12
BNE FIXUP
BAND: ;JMP (_BAND)
LDY #$14
BNE FIXUP
IOR: ;JMP (_IOR)
LDY #$16
BNE FIXUP
XOR: ;JMP (_XOR)
LDY #$18
BNE FIXUP
SHL: ;JMP (_SHL)
LDY #$1A
BNE FIXUP
SHR: ;JMP (_SHR)
LDY #$1C
BNE FIXUP
IDXW: ;JMP (_IDXW)
LDY #$1E
BNE FIXUP
NOT: ;JMP (_NOT)
LDY #$20
BNE FIXUP
LOR: ;JMP (_LOR)
LDY #$22
BNE FIXUP
LAND: ;JMP (_LAND)
LDY #$24
BNE FIXUP
LA: ;JMP (_LA)
LDY #$26
BNE FIXUP
LLA: ;JMP (_LLA)
LDY #$28
BNE FIXUP
;CB: JMP (_CB)
;CW: JMP (_CW)
SWAP: ;JMP (_SWAP)
LDY #$2E
BNE FIXUP
;DROP: JMP (_DROP)
;DUP: JMP (_DUP)
;PUSH: JMP (_PUSH)
;PULL: JMP (_PULL)
;SKLT: JMP (_SKPLT)
;SKGT: JMP (_SKPGT)
;SKEQ: JMP (_SKPEQ)
;SKNE: JMP (_SKPNE)
ISEQ: ;JMP (_ISEQ)
LDY #$40
BNE FIXUP
ISNE: ;JMP (_ISNE)
LDY #$42
BNE FIXUP
ISGT: ;JMP (_ISGT)
LDY #$44
BNE FIXUP
ISLT: ;JMP (_ISLT)
LDY #$46
BNE FIXUP
ISGE: ;JMP (_ISGE)
LDY #$48
BNE FIXUP
ISLE: ;JMP (_ISLE)
LDY #$4A
BNE FIXUP
;SKFLS: JMP (_SKPFLS)
;SKTRU: JMP (_SKPTRU)
;SKIP: JMP (_SKPIP)
;ISKIP: JMP (_ISKIP)
;CALL: JMP (_CALL)
ICAL: ;JMP (_ICAL)
LDY #$56
BNE FIXUP
;ENTER: JMP (_ENTER)
;LEAVE: JMP (_LEAVE)
;RET: JMP (_RET)
;INT: ;JMP (_INT)
; LDY #$5E
; BNE FIXUP
LB: ;JMP (_LB)
LDY #$60
BNE FIXUP
LW: ;JMP (_LW)
LDY #$62
BNE FIXUP
;LLB: JMP (_LLB)
;LLW: JMP (_LLW)
;LAB: JMP (_LAB)
;LAW: JMP (_LAW)
;DLB: JMP (_DLB)
;DLW: JMP (_DLW)
SB: ;JMP (_SB)
LDY #$70
BNE FIXUP
SW: ;JMP (_SW)
LDY #$72
; BNE FIXUP
;SLB: JMP (_SLB)
;SLW: JMP (_SLW)
;SAB: JMP (_SAB)
;SAW: JMP (_SAW)
;DAB: JMP (_DAB)
;DAW: JMP (_DAW)
FIXUP: PLA
STA $06
SEC
SBC #$01
STA $08
PLA
STA $07
SBC #$00
STA $9
LDA $D000,Y
PHA
LDA $D001,Y
LDY #$01
STA ($08),Y
STA $0B
DEY
PLA
STA ($08),Y
STA $0A
LDA $07
PHA
LDA $06
PHA
JMP ($0A)

235
plasma2/pong.pla Executable file
View File

@ -0,0 +1,235 @@
CONST FALSE = 0
CONST TRUE = NOT FALSE
CONST SHOWLORES = $C056
CONST KEYBOARD = $C000
CONST KEYSTROBE = $C010
CONST SPEAKER = $C030
BYTE EXITMSG = "PRESS ANY KEY TO EXIT."
BYTE GOODBYE = "THAT'S ALL FOLKS!"
BYTE LEVEL = "1=HARD 2=MED 3=EASY ?"
BYTE YOURSCORE = "YOUR SCORE WAS "
BYTE AUTOPLAY = TRUE
BYTE PDLPOS, PDLSIZE, PDLMID, MISS
BYTE XSCRN, YSCRN
BYTE SCORE[3]
WORD XBALL, YBALL, XSPEED, YSPEED
FUNC INCSCORE
DEF BEEP(TONE, DURATION)
BYTE I, J
FOR J = DURATION DOWNTO 0
FOR I = TONE DOWNTO 0
NEXT
DROP ^SPEAKER
NEXT
END
DEF KEYPRESSED
RETURN ^KEYBOARD > 127
END
DEF GETKEY
BYTE KEY
REPEAT
KEY = ^KEYBOARD
UNTIL KEY > 127
DROP ^KEYSTROBE
RETURN KEY
END
DEF TEXTMODE
DROP ROMCALL(0, 0, 0, 0, $FB39)
END
DEF HOME
DROP ROMCALL(0, 0, 0, 0, $FC58)
END
DEF GOTOXY(X, Y)
^($24) = X
DROP ROMCALL(Y, 0, 0, 0, $FB5B)
END
DEF PRSTRXY(X, Y, STRPTR)
GOTOXY(X, Y)
PRSTR(STRPTR)
END
DEF GRMODE
DROP ROMCALL(0, 0, 0, 0, $FB40)
DROP ^SHOWLORES
END
DEF COLOR(CLR)
DROP ROMCALL(CLR, 0, 0, 0, $F864)
END
DEF PLOT(X, Y)
DROP ROMCALL(Y, 0, X, 0, $F800)
END
DEF HLIN(LEFT, RIGHT, VERT)
^($2C) = RIGHT
DROP ROMCALL(VERT, 0, LEFT, 0, $F819)
END
DEF VLIN(TOP, BOTTOM, HORZ)
^($2D) = BOTTOM
DROP ROMCALL(TOP, 0, HORZ, 0, $F828)
END
DEF PADDLE(NUM)
RETURN ROMCALL(0, NUM, 0, 0, $FB1E).2
END
DEF BUTTON(NUM)
RETURN ^($C060 + NUM) > 127
END
DEF UPDTPDL
IF AUTOPLAY
IF PDLPOS + PDLMID > XSCRN
IF PDLPOS > 0
PDLPOS = PDLPOS - 1
FIN
ELSIF PDLPOS + PDLMID + 1 < XSCRN
IF PDLPOS + PDLSIZE < 39
PDLPOS = PDLPOS + 1
FIN
FIN
ELSE
PDLPOS = PADDLE(0) / 5
FIN
IF PDLPOS + PDLSIZE > 39
PDLPOS = 39 - PDLSIZE
FIN
IF PDLPOS
COLOR(0)
HLIN(0, PDLPOS - 1, 39)
FIN
COLOR(1)
HLIN(PDLPOS, PDLPOS + PDLSIZE, 39)
IF PDLPOS + PDLSIZE < 38
COLOR(0)
HLIN(PDLPOS + PDLSIZE + 1, 39, 39)
FIN
END
DEF UPDTBALL
BYTE XNEW, YNEW
;
; UPDATE HORIZONTAL POSITION
;
XBALL = XBALL + XSPEED
IF XBALL > 623
XBALL = 623
XSPEED = -XSPEED
BEEP(4, 10)
ELSIF XBALL < 16
XBALL = 16
XSPEED = -XSPEED
BEEP(4, 10)
FIN
XNEW = XBALL >> 4
;
; UPDATE VERTICAL POSITION
;
YBALL = YBALL + YSPEED
IF YBALL > 623
;
; CHECK FOR PADDLE HIT
;
IF XNEW >= PDLPOS AND XNEW <= PDLPOS + PDLSIZE
YBALL = 623
YSPEED = -YSPEED - 2
XSPEED = XSPEED + (XNEW - (PDLPOS + PDLMID - 1))
IF XSPEED == 0
IF PDLPOS + PDLMID > 19
XSPEED = 1
ELSE
XSPEED = -1
FIN
FIN
INCSCORE
BEEP(4, 10)
ELSE
MISS = 1
BEEP(14, 40)
FIN
ELSIF YBALL < 16
YBALL = 16
YSPEED = -YSPEED
BEEP(4, 10)
FIN
YNEW = YBALL >> 4
;
; UPDATE ON-SCREEN BALL
;
IF XNEW <> XSCRN OR YNEW <> YSCRN
COLOR(8)
PLOT(XNEW, YNEW)
COLOR(0)
PLOT(XSCRN, YSCRN)
XSCRN = XNEW
YSCRN = YNEW
FIN
END
DEF PRSCORE
COUT(SCORE[2])
COUT(SCORE[1])
COUT(SCORE[0])
END
DEF INCSCORE
SCORE[0] = SCORE[0] + 1
IF SCORE[0] > '9'
SCORE[0] = '0'
SCORE[1] = SCORE[1] + 1
IF SCORE[1] > '9'
SCORE[1] = '0'
SCORE[2] = SCORE[2] + 1
FIN
FIN
GOTOXY(17, 22)
PRSCORE
END
DEF INITSCORE
SCORE[0] = '0'
SCORE[1] = '0'
SCORE[2] = '0'
GOTOXY(17, 22)
PRSCORE
END
PRSTR(@LEVEL)
PDLSIZE = (GETKEY - $B0) * 3
PDLMID = PDLSIZE >> 1
GRMODE
COLOR(15)
HLIN(0, 39, 0)
VLIN(1, 38, 0)
VLIN(1, 38, 39)
XBALL = PADDLE(0) + 16
YBALL = PADDLE(1) + 16
XSCRN = XBALL >> 4
YSCRN = YBALL >> 4
XSPEED = 1
YSPEED = 1
MISS = 0
INITSCORE
REPEAT
UPDTPDL
UPDTBALL
UNTIL KEYPRESSED OR MISS
TEXTMODE
HOME
PRSTR(@YOURSCORE)
PRSCORE
COUT($0D)
PRSTR(@GOODBYE)
DONE

162
plasma2/radar.pla Executable file
View File

@ -0,0 +1,162 @@
CONST SHOWGR = $C050
CONST SHOWFULL = $C052
CONST SHOWPG1 = $C054
CONST SHOWPG2 = $C055
CONST SHOWLORES = $C056
DEF TEXTMODE
DROP ^SHOWPG1
DROP ROMCALL(0, 0, 0, 0, $FB39)
END
DEF CPYBUF
; MEMCPY($0400, $0800, 1016)
END
DEF GRMODE
DROP ROMCALL(0, 0, 0, 0, $F832)
DROP ^SHOWGR
DROP ^SHOWFULL
CPYBUF
; DROP ^SHOWPG2
DROP ^SHOWLORES
END
DEF COLOR(CLR)
DROP ROMCALL(CLR, 0, 0, 0, $F864)
END
DEF PLOT(X, Y)
DROP ROMCALL(Y, 0, X, 0, $F800)
END
DEF HLIN(LEFT, RIGHT, VERT)
^$2C = RIGHT
DROP ROMCALL(VERT, 0, LEFT, 0, $F819)
END
DEF VLIN(TOP, BOTTOM, HORZ)
^$2D = BOTTOM
DROP ROMCALL(TOP, 0, HORZ, 0, $F828)
END
DEF LINE(X1, Y1, X2, Y2)
BYTE DX, DY, DX2, DY2, PP, S
WORD SX, SY, ERR, DXDY2
IF X1 < X2
SX = 1
DX = X2 - X1
ELSE
SX = -1
DX = X1 - X2
FIN
IF Y1 < Y2
SY = 1
DY = Y2 - Y1
ELSE
SY = -1
DY = Y1 - Y2
FIN
DX2 = DX << 1
DY2 = DY << 1
DXDY2 = DX2 - DY2
IF DX > DY
ERR = DX
PP = X1
IF SX < 0
FOR S = PP DOWNTO X2
IF ERR < 0
HLIN(S + 1, PP, Y1)
PP = S
ERR = ERR + DXDY2
Y1 = Y1 + SY
ELSE
ERR = ERR - DY2
FIN
NEXT
HLIN(X2, PP, Y2)
ELSE
FOR S = PP TO X2
IF ERR < 0
HLIN(PP, S - 1, Y1)
PP = S
ERR = ERR + DXDY2
Y1 = Y1 + SY
ELSE
ERR = ERR - DY2
FIN
NEXT
HLIN(PP, X2, Y2)
FIN
ELSE
ERR = -DY
PP = Y1
IF SY < 0
FOR S = PP DOWNTO Y2
IF ERR >= 0
VLIN(S + 1, PP, X1)
PP = S
ERR = ERR + DXDY2
X1 = X1 + SX
ELSE
ERR = ERR + DX2
FIN
NEXT
VLIN(Y2, PP, X2)
ELSE
FOR S = PP TO Y2
IF ERR >= 0
VLIN(PP, S - 1, X1)
PP = S
ERR = ERR + DXDY2
X1 = X1 + SX
ELSE
ERR = ERR + DX2
FIN
NEXT
VLIN(PP, Y2, X2)
FIN
FIN
END
DEF RADAR(C)
BYTE I
FOR I = 0 TO 38
COLOR(C)
LINE(20, 24, I, 0)
CPYBUF
COLOR(0)
LINE(20, 24, I, 0)
NEXT
FOR I = 0 TO 46
COLOR(C)
LINE(20, 24, 39, I)
CPYBUF
COLOR(0)
LINE(20, 24, 39, I)
NEXT
FOR I = 39 DOWNTO 1
COLOR(C)
LINE(20, 24, I, 47)
CPYBUF
COLOR(0)
LINE(20, 24, I, 47)
NEXT
FOR I = 47 DOWNTO 1
COLOR(C)
LINE(20, 24, 0, I)
CPYBUF
COLOR(0)
LINE(20, 24, 0, I)
NEXT
END
GRMODE
REPEAT
RADAR(15)
UNTIL ^$C000 > 127
DROP ^$C010
TEXTMODE
DONE

267
plasma2/read.me#040000 Executable file
View File

@ -0,0 +1,267 @@
WELCOME TO PLASMA ][!
FIRST THINGS FIRST:
YOU ARE INSIDE THE PLASMA TEXT EDITOR.
TO NAVIGATE, USE THE ARROW KEYS. ON THE
APPLE ][: CTRL-K = UP, CTRL-J = DOWN.
TO JUMP AROUND THE TEXT FILE USE:
CTRL-W = JUMP UP
CTRL-Z = JUMP DOWN
CTRL-A = JUMP LEFT
CTRL-S = JUMP RIGHT
CTRL-Q = JUMP BEGINNING
CTRL-E = JUMP END
THE 'ESCAPE' KEY WILL PUT YOU IN COMMAND
MODE. FROM THERE YOU CAN EXIT BY
ENTERING 'Q' AND 'RETURN'.
NOW THAT YOU CAN MOVE AROUND, LET'S
DESCRIBE WHAT PLASMA IS: PLASMA IS A
RUNTIME ENVIRONMENT AND TOOLSET USED TO
BUILD AND RUN A NEW CLASS OF PROGRAM ON
THE APPLE II SERIES OF COMPUTERS.
PLASMA ][ STANDS FOR PROTO LANGUAGE
ASSEMBLER FOR APPLE ][S.
PLASMA IS SIMILAR IN CONCEPT TO THE
APPLE PASCAL SYSTEM THAT WAS RELEASED
IN 1979. A VIRTUAL COMPUTER INSTRUCTION
SET WAS CREATED, DESIGNED SPECIFICALLY
FOR THE APPLE II AND 6502 PROCESSOR.
WITH A COMPILER CLOSELY MATCHED TO THE
VIRTUAL INSTRUCTION SET, FAST, EFFICIENT
AND COMPACT PROGRAMS CAN BE WRITTEN AND
RUN ON THE APPLE II. THE VIRTUAL
INSTRUCTIONS ARE EFFICIENTLY INTERPRETED
BY THE 6502 FROM CODE THAT RESIDES IN
THE LANGUAGE CARD. THE STANDARD PRODOS
'BYE' PROGRAM LAUNCHER HAS BEEN REPLACED
BY A COMMAND LINE LAUNCHER WRITTEN IN
PLASMA ITSELF. THIS LAUNCHER HAS A FEW
SIMPLE COMMANDS:
V = LIST ON-LINE VOLUMES
P = SET PREFIX
C = CATALOG
Q = QUIT (REBOOT)
- = LAUNCH PROGRAM NAME FOLLOWING '-'
THE LAUNCHER HAS THE ABILITY TO PASS
PARAMETERS TO A PROGRAM. FOR INSTANCE,
TYPING "-PLED READ.ME" WOULD TELL THE
PLASMA EDITOR, "PLED", TO READ THE FILE
"READ.ME" AT STARTUP. WHEN LISTING THE
CATALOG OF A DIRECTORY, FILES MARKED
WITH '*' ARE EXECUTABLE, '/' ARE
DIRECTORIES.
WHEN THE LAUNCHER IS FIRST LOADED, IT
LOOKS FOR A FILE CALLED AUTORUN. IF
IT EXISTS, THE FIRST LINE IN THE FILE IS
READ IN AND USED AS A COMMAND TO RUN.
FILES ON THIS DISK
==================
PLASMA.SYSTEM (PLASMA VM CORE, LAUNCHER)
PLED (PLASMA EDITOR, CURRENTLY RUNNING)
PLEX (PLASMA EXECUTIVE)
PLIDE (PLASMA IDE)
FIRE (FOREST FIRE SIMULATION)
ROD (ROD'S COLOR DEMO)
*.PLA (PLASMA SOURCE FILES)
PLED
----
THE PLASMA EDITOR IS A SIMPLE TEXT
EDITOR FOR ENTERING AND MANIPULATING
TEXT AND SOURCE CODE FILES. THE EDITOR
ONLY SUPPORTS 40 COLUMN TEXT ALTHOUGH
LINES CAN BE UP TO 79 CHARACTERS LONG.
THE SCREEN WILL SCROLL HORIZONTALLY
AS THE CURSOR
IT HAS TWO MODES, COMMAND AND EDIT.
EDIT COMMANDS:
LEFT ARROW = MOVE CHAR LEFT
RIGHT ARROW = MOVE CHAR RIGHT
UP ARROW = MOVE LINE UP
DOWN ARROW = MOVE LINE DOWN
CTRL-K = MOVE LINE UP
CTRL-J = MOVE LINE DOWN
CTRL-A = JUMP LEFT
CTRL-S = JUMP RIGHT
CTRL-W = JUMP UP
CTRL-Z = JUMP DOWN
CTRL-Q = JUMP BEGIN
CTRL-E = JUMP END
CTRL-D = DELETE CHAR
CTRL-X = DELETE LINE
CTRL-V = COPY DELETED LINE
CTRL-O = OPEN NEW LINE
CTRL-T = JOIN LINES
CTRL-I = TOGGLE INSERT/OVERWRITE
ESCAPE = SWITCH TO COMMAND MODE
APPLE ][ FEATURES:
SHIFT-M = ]
CTRL-N = [
CTRL-P = _
CTRL-B = \
CTRL-L = SHIFT LOCK
SHIFT-LEFT ARROW = DELETE (SHIFT-MOD)
WITH THE SHIFT-KEY MOD ON AN
APPLE ][, UPPER AND LOWER CASE
ENTRY WORKS AS EXPECTED.
CTRL-C = FORCE LOWER-CASE CHARS
IF YOU HAVE A LOWER-CASE CHARACTER
GENERATOR INSTALLED, YOU CAN FORCE
LOWER-CASE DISPLAY. OTHERWISE,
UPPER CASE WILL BE DISPLAYED NORMALLY
BUT lower-case will be displayed in
inverse. this is the default.
COMMAND MODE:
<REQUIRED PARAMETER>
[OPTIONAL PARAMETER]
Q = QUIT
R <FILENAME> = READ FILE
W [FILENAME] = WRITE FILE (OPTIONAL FILEADANAME)
A [FILENAME] = APPEND FILE
C <PREFIX> = CATALOG FILES
P [PREFIX] = SET PREFIX
H [SLOT] = HARDCOPY TO DEVICE IN SLOT (DEFAULT 1)
N = CLEAR TEXT IN MEMORY
E = EDIT MODE
'RETURN' = EDIT MODE
PLEX
----
THE PLASMA EXECUTIVE WILL LOAD A
PLASMA SOURCE FILE AND COMPILE IT INTO
A 16K BUFFER AND RUN THE PROGRAM IF
SUCCESSFULLY COMPILED. THE PROGRAM
WILL PREMATURELY END IF THERE IS A
PROGRAM BUG THAT CAUSES A STACK OVERFLOW
OR CTRL-C IS PRESSED. PLASMA PROGRAMS
THAT RUN IN THE EXECUTIVE ARE LIMITED
IN THEIR FEATURES OVER THOSE CROSS-
COMPILED. NO ASM DEFINED FUNCTIONS ARE
COMPILED BUT THERE ARE SOME BUILT-IN
ROUTINES FOR CALLING ROM ROUTINES AND
PRODOS.
PLIDE
-----
THE PLASMA INTEGRATED DEVELOPMENT
ENVIRONMENT COMBINES THE EDITOR AND
EXECUTIVE INTO ONE. AN ADDITIONAL
COMMAND IN COMMAND MODE IS ADDED:
X = EXECUTE PROGRAM IN MEMORY
PLIDE HAS A SMALLER EXECUTION BUFFER
THAN PLEX; ONLY 4K. THE SAMPLE PROGRAMS
ON THE DISK CAN BELOADED INTO PLIDE AND
RUN WITH THE EXCEPTION OF "FIRE.PLA"
WHICH IS TOO BIG FOR PLIDE AND MUST BE
RUN FROM PLEX.
THE PLASMA ][ LANGUAGE
======================
THE PLASMA LANGUAGE HAS EVOLVED A BIT
SINCE THE INITIAL PREVIEW. IN THE FIRST
ITERATION, PLASMA WAS STRUCTURED TO
KEEP THE CALLS TO FUNCTIONS, PARAMETERS
AND RESULTS, STRICTLY DEFINED AND NOT
VERY FLEXIBLE. EXPRESSIONS HAD TO MATCH
UP WITH RESULTS. THIS, VERY TRADITIONAL,
APPROACH, KEPT VALUES ON THE EXECUTION
STACK FROM GETTING LOST AND OVERFLOWING
THE STACK. BUT PLASMA HAS MUCH IN
COMMON WITH THE LANGUAGE 'FORTH' AND
WASN'T EFFECTIVELY USING THE POWER OF
THE STACK IN IT'S OPERATIONS. SO, THE
STRICT CONTROL OVER THE STACK WAS LOOSEND
TO ALLOW MULTIPLE VALUES TO BE SAVED,
STORED, AND MANIPULATED ON THE STACK.
THE COMMA OPERATOR SIMPLY LEAVES THE
CURRENTLY EVALUATED EXPRESSION ON THE
STACK AND MOVES TO THE NEXT ONE.
FUNCTIONS CAN RETURN MULTIPLE VALUES ON
THE STACK. AS AN EXAMPLE, HERE IS A
SIMPLE FUNCTION TO SWAP TO VALUES AROUND
DEF SWAP(A, B)
RETURN B, A
END
A NEW OPERATER, EQUAL LIST (=,), CAN BE
USED TO SET A LIST OF VARIABLES FROM THE
STACK. FUNCTIONS THAT RETURN MULTIPLE
VALUES CAN BE SET AS SUCH:
A =, B = SWAP(A, B)
COMBINING THESE CONCEPTS, YOU COULD USE:
A =, B = B, A
TO SWAP TWO VARIABLES WITH EACH OTHER.
THE DOWNSIDE OF SUCH FLEXIBILITY IS THE
EVALUATION STACK MUST BE TRACKED
CAREFULLY. ANY MISMATCH IN LOADING
OR SAVING VALUES FROM THE STACK WILL
RESULT IN AN OVERFLOW OR UNDERFLOW
CONDITION. ONE HUERISTIC TO HELP IS TO
APPEND A COUNT OF PARAMTERS AND RETURN
VALUES TO THE FUNCTION NAME. USING SUCH
NOMENCLATURE WOULD RESULT IN THE
DEFINITION OF SWAP AS SUCH:
DEF SWAP22(A, B)
RETURN B, A)
END
SOMETIMES THERE IS A NEED TO SIMPLY GET
RID OF THE VALUE ON THE STACK. 'DROP'
WILL DO THAT. IT CAN BE USED ALONG WITH
AN EXPRESSION OR BY ITSELF. TO READ A
SOFTSWITCH AND DISCARD THE VALUE WOULD
BE WRITTEN AS:
DROP ^$C010 ; CLEAR KEYBOARD STROBE
BY ALLOWING MULTIPLE VALUES TO BE LOADED
FROM THE EVALUATION STACK, THE MOD
OPERATOR (%) HAS BEEN MODIFIED INTO A
DIV-MOD OPERATOR. BOTH THE DIVIDE AND
REMAINDER RESULT ARE PRESENT ON THE
STACK AFTERWARD. OFTEN BOTH RESULTS ARE
USEFUL, BUT ONE OR THE OTHER CAN BE
EASILY DISCARDED WITH THE DROP KEYWORD.
DIV10 =, REM10 = I % 10
OTHER THAN THESE SMALL CHANGES, PLASMA
IS PRETTY MUCH THE SAME AS BEFORE.
MORE LANGUAGE SPECIFICATION WILL BE
WRITTEN IN THE FUTURE.

BIN
plasma2/rod#ff0000 Executable file

Binary file not shown.

182
plasma2/rod.pla Executable file
View File

@ -0,0 +1,182 @@
const speaker=$C030
const showgraphics=$C050
const showtext=$C051
const showfull=$C052
const showmix=$C053
const TRUE=$FFFF
const FALSE=$0000
const showpage1=$C054
const showpage2=$C055
const showlores=$C056
const showhires=$C057
const keyboard=$C000
const keystrobe=$C010
const hgr1=$2000
const hgr2=$4000
const page1=0
const page2=1
byte exitmsg[] = "PRESS ANY KEY TO EXIT."
byte goodbye[] = "THAT'S ALL FOLKS!"
byte rebootmsg[] = "PRESS ANY KEY TO REBOOT..."
byte i, j, k, w, fmi, fmk, color
;
; CALL 6502 ROUTINE
; ROMCALL(AREG, XREG, YREG, STATUS, ADDR)
;
asm romcall
TMP EQU $06
PHP
LDA ESTKL,X
STA TMP
LDA ESTKH,X
STA TMP+1
INX
LDA ESTKL,X
PHA
INX
LDA ESTKL,X
TAY
INX
LDA ESTKL+1,X
PHA
LDA ESTKL,X
INX
STX TMP+2
TAX
PLA
BIT ROMIN
PLP
JSR JMPTMP
PHP
BIT LCBNK2
STA REGVALS+0
STX REGVALS+1
STY REGVALS+2
PLA
STA REGVALS+3
LDX TMP+2
LDA #<REGVALS
LDY #>REGVALS
STA ESTKL,X
STY ESTKH,X
PLP
RTS
JMPTMP: JMP (TMP)
REGVALS: DS 4
end
;
; CHAR OUT
; COUT(CHAR)
;
asm cout
LDA ESTKL,X
INX
ORA #$80
BIT ROMIN
JSR $FDED
BIT LCBNK2
end
;
; PRINT STRING
; PRSTR(STR)
;
asm prstr
LDY #$00
LDA ESTKL,X
STA TMP
LDA ESTKH,X
STA TMP+1
BIT ROMIN
LDA (TMP),Y
STA ESTKL,X
BEQ :+
_PRS1: INY
LDA (TMP),Y
ORA #$80
JSR $FDED
TYA
CMP ESTKL,X
BNE _PRS1
: INX
BIT LCBNK2
end
def textmode
drop romcall(0, 0, 0, 0, $FB39)
end
def home
drop romcall(0, 0, 0, 0, $FC58)
end
def gotoxy(x, y)
^($24) = x
drop romcall(y, 0, 0, 0, $FB5B)
end
def crout
cout($0D)
end
def grmode
drop romcall(0, 0, 0, 0, $FB40)
drop ^showlores
end
; grcolor(color)
asm grcolor
LDA ESTKL,X
INX
STX TMP+2
BIT $C081
JSR $F864
BIT $C080
LDX TMP+2
end
; grplot(x, y)
asm grplot
LDA ESTKL,X
INX
LDY ESTKL,X
INX
STX TMP+2
BIT $C081
JSR $F800
BIT $C080
LDX TMP+2
end
defopt colors
while TRUE
for w = 3 to 50
for i = 1 to 19
for j = 0 to 19
k = i + j
color = (j * 3) / (i + 3) + i * w / 12
fmi = 40 - i
fmk = 40 - k
grcolor(color);
grplot(i, k);
grplot(k, i);
grplot(fmi, fmk);
grplot(fmk, fmi);
grplot(k, fmi);
grplot(fmi, k);
grplot(i, fmk);
grplot(fmk, i);
if ^keyboard >= 128
drop ^keystrobe
return
fin
next
next
next
loop
end
grmode()
home()
gotoxy(10,22)
prstr(@exitmsg)
colors()
textmode()
home()
prstr(@goodbye)
while ^keyboard < 128
loop
drop ^keystrobe
done

63
plasma2/rod.pla#040000 Executable file
View File

@ -0,0 +1,63 @@
const showlores = $C056
const keyboard = $C000
const keystrobe = $C010
byte exitmsg[] = "PRESS ANY KEY TO EXIT."
byte goodbye[] = "THAT'S ALL FOLKS!"
byte i, j, k, w, fmi, fmk, color
def textmode
drop romcall(0, 0, 0, 0, $FB39)
end
def home
drop romcall(0, 0, 0, 0, $FC58)
end
def gotoxy(x, y)
^($24) = x
drop romcall(y, 0, 0, 0, $FB5B)
end
def grmode
drop romcall(0, 0, 0, 0, $FB40)
^showlores
end
def colors
while 1
for w = 3 to 50
for i = 1 to 19
for j = 0 to 19
k = i + j
color = (j * 3) / (i + 3) + i * w / 12
fmi = 40 - i
fmk = 40 - k
drop romcall(color, 0, 0, 0, $F864) ;grcolor(color);
drop romcall(k, 0, i, 0, $F800) ;grplot(i, k);
drop romcall(i, 0, k, 0, $F800) ;grplot(k, i);
drop romcall(fmk, 0, fmi, 0, $F800) ;grplot(fmi, fmk);
drop romcall(fmi, 0, fmk, 0, $F800) ;grplot(fmk, fmi);
drop romcall(fmi, 0, k, 0, $F800) ;grplot(k, fmi);
drop romcall(k, 0, fmi, 0, $F800) ;grplot(fmi, k);
drop romcall(fmk, 0, i, 0, $F800) ;grplot(i, fmk);
drop romcall(i, 0, fmk, 0, $F800) ;grplot(fmk, i);
if ^keyboard >= 128
drop ^keystrobe
return
fin
next
next
next
loop
end
grmode
home
gotoxy(10,22)
prstr(@exitmsg)
colors
textmode
home
prstr(@goodbye)
done

670
plasma2/rod.s Executable file
View File

@ -0,0 +1,670 @@
.INCLUDE "plstub.s"
; 1: const speaker=$C030
; speaker = 49200
; 2: const showgraphics=$C050
; showgraphics = 49232
; 3: const showtext=$C051
; showtext = 49233
; 4: const showfull=$C052
; showfull = 49234
; 5: const showmix=$C053
; showmix = 49235
; 6: const TRUE=$FFFF
; TRUE = 65535
; 7: const FALSE=$0000
; FALSE = 0
; 8: const showpage1=$C054
; showpage1 = 49236
; 9: const showpage2=$C055
; showpage2 = 49237
; 10: const showlores=$C056
; showlores = 49238
; 11: const showhires=$C057
; showhires = 49239
; 12: const keyboard=$C000
; keyboard = 49152
; 13: const keystrobe=$C010
; keystrobe = 49168
; 14: const hgr1=$2000
; hgr1 = 8192
; 15: const hgr2=$4000
; hgr2 = 16384
; 16: const page1=0
; page1 = 0
; 17: const page2=1
; page2 = 1
; 18: byte exitmsg[] = "PRESS ANY KEY TO EXIT."
D0000: ; exitmsg
DB $16
DB $50,$52,$45,$53,$53,$20,$41,$4E
DB $59,$20,$4B,$45,$59,$20,$54,$4F
DB $20,$45,$58,$49,$54,$2E
; 19: byte goodbye[] = "THAT'S ALL FOLKS!"
D0023: ; goodbye
DB $11
DB $54,$48,$41,$54,$27,$53,$20,$41
DB $4C,$4C,$20,$46,$4F,$4C,$4B,$53
DB $21
; 20: byte rebootmsg[] = "PRESS ANY KEY TO REBOOT..."
D0041: ; rebootmsg
DB $1A
DB $50,$52,$45,$53,$53,$20,$41,$4E
DB $59,$20,$4B,$45,$59,$20,$54,$4F
DB $20,$52,$45,$42,$4F,$4F,$54,$2E
DB $2E,$2E
; 21: byte i, j, k, w, fmi, fmk, color
D0068: DS 1 ; i
D0069: DS 1 ; j
D0070: DS 1 ; k
D0071: DS 1 ; w
D0072: DS 1 ; fmi
D0073: DS 1 ; fmk
D0074: DS 1 ; color
; 22: ;
; 23: ; CALL 6502 ROUTINE
; 24: ; ROMCALL(AREG, XREG, YREG, STATUS, ADDR)
; 25: ;
; 26: asm romcall
C0000: ; romcall()
; 27: TMP EQU $06
TMP EQU $06
; 28:
; 29: PHP
PHP
; 30: LDA ESTKL,X
LDA ESTKL,X
; 31: STA TMP
STA TMP
; 32: LDA ESTKH,X
LDA ESTKH,X
; 33: STA TMP+1
STA TMP+1
; 34: INX
INX
; 35: LDA ESTKL,X
LDA ESTKL,X
; 36: PHA
PHA
; 37: INX
INX
; 38: LDA ESTKL,X
LDA ESTKL,X
; 39: TAY
TAY
; 40: INX
INX
; 41: LDA ESTKL+1,X
LDA ESTKL+1,X
; 42: PHA
PHA
; 43: LDA ESTKL,X
LDA ESTKL,X
; 44: INX
INX
; 45: STX TMP+2
STX TMP+2
; 46: TAX
TAX
; 47: PLA
PLA
; 48: BIT ROMIN
BIT ROMIN
; 49: PLP
PLP
; 50: JSR JMPTMP
JSR JMPTMP
; 51: PHP
PHP
; 52: BIT LCBNK2
BIT LCBNK2
; 53: STA REGVALS+0
STA REGVALS+0
; 54: STX REGVALS+1
STX REGVALS+1
; 55: STY REGVALS+2
STY REGVALS+2
; 56: PLA
PLA
; 57: STA REGVALS+3
STA REGVALS+3
; 58: LDX TMP+2
LDX TMP+2
; 59: LDA #<REGVALS
LDA #<REGVALS
; 60: LDY #>REGVALS
LDY #>REGVALS
; 61: STA ESTKL,X
STA ESTKL,X
; 62: STY ESTKH,X
STY ESTKH,X
; 63: PLP
PLP
; 64: RTS
RTS
; 65: JMPTMP: JMP (TMP)
JMPTMP: JMP (TMP)
; 66: REGVALS: DS 4
REGVALS: DS 4
; 67: end
RTS
; 68: ;
; 69: ; CHAR OUT
; 70: ; COUT(CHAR)
; 71: ;
; 72: asm cout
C0002: ; cout()
; 73: LDA ESTKL,X
LDA ESTKL,X
; 74: INX
INX
; 75: ORA #$80
ORA #$80
; 76: BIT ROMIN
BIT ROMIN
; 77: JSR $FDED
JSR $FDED
; 78: BIT LCBNK2
BIT LCBNK2
; 79: end
RTS
; 80: ;
; 81: ; PRINT STRING
; 82: ; PRSTR(STR)
; 83: ;
; 84: asm prstr
C0004: ; prstr()
; 85: LDY #$00
LDY #$00
; 86: LDA ESTKL,X
LDA ESTKL,X
; 87: STA TMP
STA TMP
; 88: LDA ESTKH,X
LDA ESTKH,X
; 89: STA TMP+1
STA TMP+1
; 90: BIT ROMIN
BIT ROMIN
; 91: LDA (TMP),Y
LDA (TMP),Y
; 92: STA ESTKL,X
STA ESTKL,X
; 93: BEQ :+
BEQ :+
; 94: _PRS1: INY
_PRS1: INY
; 95: LDA (TMP),Y
LDA (TMP),Y
; 96: ORA #$80
ORA #$80
; 97: JSR $FDED
JSR $FDED
; 98: TYA
TYA
; 99: CMP ESTKL,X
CMP ESTKL,X
; 100: BNE _PRS1
BNE _PRS1
; 101: : INX
: INX
; 102: BIT LCBNK2
BIT LCBNK2
; 103: end
RTS
; 104: def textmode
C0006: ; textmode()
; 105: drop romcall(0, 0, 0, 0, $FB39)
JSR _INTERP
DB $00 ; ZERO
DB $00 ; ZERO
DB $00 ; ZERO
DB $00 ; ZERO
DB $2C,$39,$FB ; CW 64313
DB $54,<C0000,>C0000 ; CALL C0000
DB $30 ; DROP
; 106: end
DB $5C ; RET
; 107: def home
C0008: ; home()
; 108: drop romcall(0, 0, 0, 0, $FC58)
JSR _INTERP
DB $00 ; ZERO
DB $00 ; ZERO
DB $00 ; ZERO
DB $00 ; ZERO
DB $2C,$58,$FC ; CW 64600
DB $54,<C0000,>C0000 ; CALL C0000
DB $30 ; DROP
; 109: end
DB $5C ; RET
; 110: def gotoxy(x, y)
C0010: ; gotoxy()
; x = 2
; y = 4
; 111: ^($24) = x
JSR _INTERP
DB $58,$06,$02 ; ENTER 6,2
DB $2A,$24 ; CB 36
DB $66,$02 ; LLW 2
DB $70 ; SB
; 112: drop romcall(y, 0, 0, 0, $FB5B)
DB $66,$04 ; LLW 4
DB $00 ; ZERO
DB $00 ; ZERO
DB $00 ; ZERO
DB $2C,$5B,$FB ; CW 64347
DB $54,<C0000,>C0000 ; CALL C0000
DB $30 ; DROP
; 113: end
DB $5A ; LEAVE
; 114: def crout
C0012: ; crout()
; 115: cout($0D)
JSR _INTERP
DB $2A,$0D ; CB 13
DB $54,<C0002,>C0002 ; CALL C0002
; 116: end
DB $5C ; RET
; 117: def grmode
C0014: ; grmode()
; 118: drop romcall(0, 0, 0, 0, $FB40)
JSR _INTERP
DB $00 ; ZERO
DB $00 ; ZERO
DB $00 ; ZERO
DB $00 ; ZERO
DB $2C,$40,$FB ; CW 64320
DB $54,<C0000,>C0000 ; CALL C0000
DB $30 ; DROP
; 119: drop ^showlores
DB $2C,$56,$C0 ; CW 49238
DB $60 ; LB
DB $30 ; DROP
; 120: end
DB $5C ; RET
; 121: ; grcolor(color)
; 122: asm grcolor
C0016: ; grcolor()
; 123: LDA ESTKL,X
LDA ESTKL,X
; 124: INX
INX
; 125: STX TMP+2
STX TMP+2
; 126: BIT $C081
BIT $C081
; 127: JSR $F864
JSR $F864
; 128: BIT $C080
BIT $C080
; 129: LDX TMP+2
LDX TMP+2
; 130: end
RTS
; 131: ; grplot(x, y)
; 132: asm grplot
C0018: ; grplot()
; 133: LDA ESTKL,X
LDA ESTKL,X
; 134: INX
INX
; 135: LDY ESTKL,X
LDY ESTKL,X
; 136: INX
INX
; 137: STX TMP+2
STX TMP+2
; 138: BIT $C081
BIT $C081
; 139: JSR $F800
JSR $F800
; 140: BIT $C080
BIT $C080
; 141: LDX TMP+2
LDX TMP+2
; 142: end
RTS
; 143: defopt colors
C0020: ; colors()
; 144: while TRUE
C0022:
DEX
LDA #$FF
STA ESTKL,X
STA ESTKH,X
INX
LDA ESTKL-1,X
ORA ESTKH-1,X
BNE :+
JMP C0023
:
; 145: for w = 3 to 50
DEX
LDA #$03
STA ESTKL,X
LDY #$00
STY ESTKH,X
C0025:
LDA ESTKL,X
STA D0071
DEX
LDA #$32
STA ESTKL,X
LDY #$00
STY ESTKH,X
INX
LDA ESTKL-1,X
CMP ESTKL,X
LDA ESTKH-1,X
SBC ESTKH,X
BPL :+
JMP C0024
:
INC ESTKL,X
BNE :+
INC ESTKH,X
:
; 146: for i = 1 to 19
DEX
LDA #$01
STA ESTKL,X
STY ESTKH,X
C0027:
LDA ESTKL,X
STA D0068
DEX
LDA #$13
STA ESTKL,X
LDY #$00
STY ESTKH,X
INX
LDA ESTKL-1,X
CMP ESTKL,X
LDA ESTKH-1,X
SBC ESTKH,X
BPL :+
JMP C0026
:
INC ESTKL,X
BNE :+
INC ESTKH,X
:
; 147: for j = 0 to 19
DEX
STY ESTKL,X
STY ESTKH,X
C0029:
LDA ESTKL,X
STA D0069
DEX
LDA #$13
STA ESTKL,X
LDY #$00
STY ESTKH,X
INX
LDA ESTKL-1,X
CMP ESTKL,X
LDA ESTKH-1,X
SBC ESTKH,X
BPL :+
JMP C0028
:
INC ESTKL,X
BNE :+
INC ESTKH,X
:
; 148: k = i + j
DEX
LDA D0068
STA ESTKL,X
STY ESTKH,X
DEX
LDA D0069
STA ESTKL,X
STY ESTKH,X
JSR ADD
LDA ESTKL,X
STA D0070
; 149: color = (j * 3) / (i + 3) + i * w / 12
LDA D0069
STA ESTKL,X
STY ESTKH,X
DEX
LDA #$03
STA ESTKL,X
STY ESTKH,X
JSR MUL
DEX
LDA D0068
STA ESTKL,X
STY ESTKH,X
DEX
LDA #$03
STA ESTKL,X
STY ESTKH,X
JSR ADD
JSR DIV
DEX
LDA D0068
STA ESTKL,X
LDY #$00
STY ESTKH,X
DEX
LDA D0071
STA ESTKL,X
STY ESTKH,X
JSR MUL
DEX
LDA #$0C
STA ESTKL,X
STY ESTKH,X
JSR DIV
JSR ADD
LDA ESTKL,X
STA D0074
; 150: fmi = 40 - i
LDA #$28
STA ESTKL,X
LDY #$00
STY ESTKH,X
DEX
LDA D0068
STA ESTKL,X
STY ESTKH,X
JSR SUB
LDA ESTKL,X
STA D0072
; 151: fmk = 40 - k
LDA #$28
STA ESTKL,X
STY ESTKH,X
DEX
LDA D0070
STA ESTKL,X
STY ESTKH,X
JSR SUB
LDA ESTKL,X
STA D0073
; 152: grcolor(color);
LDA D0074
STA ESTKL,X
STY ESTKH,X
JSR C0016
; 153: grplot(i, k);
DEX
LDA D0068
STA ESTKL,X
LDY #$00
STY ESTKH,X
DEX
LDA D0070
STA ESTKL,X
STY ESTKH,X
JSR C0018
; 154: grplot(k, i);
DEX
LDA D0070
STA ESTKL,X
LDY #$00
STY ESTKH,X
DEX
LDA D0068
STA ESTKL,X
STY ESTKH,X
JSR C0018
; 155: grplot(fmi, fmk);
DEX
LDA D0072
STA ESTKL,X
LDY #$00
STY ESTKH,X
DEX
LDA D0073
STA ESTKL,X
STY ESTKH,X
JSR C0018
; 156: grplot(fmk, fmi);
DEX
LDA D0073
STA ESTKL,X
LDY #$00
STY ESTKH,X
DEX
LDA D0072
STA ESTKL,X
STY ESTKH,X
JSR C0018
; 157: grplot(k, fmi);
DEX
LDA D0070
STA ESTKL,X
LDY #$00
STY ESTKH,X
DEX
LDA D0072
STA ESTKL,X
STY ESTKH,X
JSR C0018
; 158: grplot(fmi, k);
DEX
LDA D0072
STA ESTKL,X
LDY #$00
STY ESTKH,X
DEX
LDA D0070
STA ESTKL,X
STY ESTKH,X
JSR C0018
; 159: grplot(i, fmk);
DEX
LDA D0068
STA ESTKL,X
LDY #$00
STY ESTKH,X
DEX
LDA D0073
STA ESTKL,X
STY ESTKH,X
JSR C0018
; 160: grplot(fmk, i);
DEX
LDA D0073
STA ESTKL,X
LDY #$00
STY ESTKH,X
DEX
LDA D0068
STA ESTKL,X
STY ESTKH,X
JSR C0018
; 161: if ^keyboard >= 128
DEX
LDY #$00
STY ESTKL,X
LDA #$C0
STA ESTKH,X
JSR LB
DEX
LDA #$80
STA ESTKL,X
STY ESTKH,X
JSR ISGE
INX
LDA ESTKL-1,X
ORA ESTKH-1,X
BNE :+
JMP C0030
:
; 162: drop ^keystrobe
DEX
LDA #$10
STA ESTKL,X
LDA #$C0
STA ESTKH,X
LDY #$00
JSR LB
; 163: return
INX
INX
RTS
; 164: fin
INX
INX
C0030:
C0031:
; 165: next
JMP C0029
C0028:
; 166: next
INX
JMP C0027
C0026:
; 167: next
INX
JMP C0025
C0024:
; 168: loop
INX
JMP C0022
C0023:
; 169: end
RTS
; 170:
; 171: grmode()
START: ; JSR INTERP
DB $54,<C0014,>C0014 ; CALL C0014
; 172: home()
DB $54,<C0008,>C0008 ; CALL C0008
; 173: gotoxy(10,22)
DB $2A,$0A ; CB 10
DB $2A,$16 ; CB 22
DB $54,<C0010,>C0010 ; CALL C0010
; 174: prstr(@exitmsg)
DB $26,<D0000,>D0000 ; LA D0000
DB $54,<C0004,>C0004 ; CALL C0004
; 175: colors()
DB $54,<C0020,>C0020 ; CALL C0020
; 176: textmode()
DB $54,<C0006,>C0006 ; CALL C0006
; 177: home()
DB $54,<C0008,>C0008 ; CALL C0008
; 178: prstr(@goodbye)
DB $26,<D0023,>D0023 ; LA D0023
DB $54,<C0004,>C0004 ; CALL C0004
; 179: while ^keyboard < 128
C0032:
DB $2C,$00,$C0 ; CW 49152
DB $60 ; LB
DB $2A,$80 ; CB 128
DB $46 ; ISLT
DB $4C,<C0033,>C0033 ; SKPFLS C0033
; 180: loop
DB $50,<C0032,>C0032 ; SKIP C0032
C0033:
; 181: drop ^keystrobe
DB $2C,$10,$C0 ; CW 49168
DB $60 ; LB
DB $30 ; DROP
; 182: done
DB $5C ; RET

BIN
plasma2/rod.sys Executable file

Binary file not shown.

7
plasma2/teststack.pla Executable file
View File

@ -0,0 +1,7 @@
word a, b
defn test(parm1, parm2)
return 100 * parm1, 200 + parm2
end
a =, b = test(1, 2)
done

119
plasma2/tokens.h Executable file
View File

@ -0,0 +1,119 @@
#define TOKEN(c) (0x80|(c))
#define IS_TOKEN(c) (0x80&(c))
/*
* Identifier and constant tokens.
*/
#define ID_TOKEN TOKEN('V')
#define CHAR_TOKEN TOKEN('Y')
#define INT_TOKEN TOKEN('Z')
#define FLOAT_TOKEN TOKEN('F')
#define STRING_TOKEN TOKEN('S')
/*
* Keyword tokens.
*/
#define CONST_TOKEN TOKEN(1)
#define BYTE_TOKEN TOKEN(2)
#define WORD_TOKEN TOKEN(3)
#define IF_TOKEN TOKEN(4)
#define ELSEIF_TOKEN TOKEN(5)
#define ELSE_TOKEN TOKEN(6)
#define FIN_TOKEN TOKEN(7)
#define END_TOKEN TOKEN(8)
#define WHILE_TOKEN TOKEN(9)
#define LOOP_TOKEN TOKEN(10)
#define CASE_TOKEN TOKEN(11)
#define OF_TOKEN TOKEN(12)
#define DEFAULT_TOKEN TOKEN(13)
#define ENDCASE_TOKEN TOKEN(14)
#define FOR_TOKEN TOKEN(15)
#define TO_TOKEN TOKEN(16)
#define DOWNTO_TOKEN TOKEN(17)
#define STEP_TOKEN TOKEN(18)
#define NEXT_TOKEN TOKEN(19)
#define REPEAT_TOKEN TOKEN(20)
#define UNTIL_TOKEN TOKEN(21)
#define IFUNC_TOKEN TOKEN(22)
#define NFUNC_TOKEN TOKEN(23)
#define DROP_TOKEN TOKEN(24)
#define DONE_TOKEN TOKEN(25)
#define RETURN_TOKEN TOKEN(26)
#define BREAK_TOKEN TOKEN(27)
#define START_TOKEN TOKEN(28)
#define EXIT_TOKEN TOKEN(29)
#define EVAL_TOKEN TOKEN(30)
#define FUNC_TOKEN TOKEN(31)
#define ASM_TOKEN TOKEN(32)
/*
* Double operand operators.
*/
#define SET_TOKEN TOKEN('=')
#define ADD_TOKEN TOKEN('+')
#define ADD_SELF_TOKEN TOKEN('a')
#define SUB_TOKEN TOKEN('-')
#define SUB_SELF_TOKEN TOKEN('u')
#define MUL_TOKEN TOKEN('*')
#define MUL_SELF_TOKEN TOKEN('m')
#define DIV_TOKEN TOKEN('/')
#define DIV_SELF_TOKEN TOKEN('d')
#define DIVMOD_TOKEN TOKEN('%')
#define OR_TOKEN TOKEN('?')
#define OR_SELF_TOKEN TOKEN('o')
#define EOR_TOKEN TOKEN('^')
#define EOR_SELF_TOKEN TOKEN('x')
#define AND_TOKEN TOKEN('&')
#define AND_SELF_TOKEN TOKEN('n')
#define SHR_TOKEN TOKEN('R')
#define SHR_SELF_TOKEN TOKEN('r')
#define SHL_TOKEN TOKEN('L')
#define SHL_SELF_TOKEN TOKEN('l')
#define GT_TOKEN TOKEN('>')
#define GE_TOKEN TOKEN('H')
#define LT_TOKEN TOKEN('<')
#define LE_TOKEN TOKEN('B')
#define NE_TOKEN TOKEN('U')
#define EQ_TOKEN TOKEN('E')
#define LOGIC_AND_TOKEN TOKEN('N')
#define LOGIC_OR_TOKEN TOKEN('O')
/*
* Single operand operators.
*/
#define NEG_TOKEN TOKEN('-')
#define COMP_TOKEN TOKEN('#')
#define LOGIC_NOT_TOKEN TOKEN('!')
#define INC_TOKEN TOKEN('P')
#define DEC_TOKEN TOKEN('K')
#define BPTR_TOKEN TOKEN('^')
#define WPTR_TOKEN TOKEN('*')
#define POST_INC_TOKEN TOKEN('p')
#define POST_DEC_TOKEN TOKEN('k')
#define OPEN_PAREN_TOKEN TOKEN('(')
#define CLOSE_PAREN_TOKEN TOKEN(')')
#define OPEN_BRACKET_TOKEN TOKEN('[')
#define CLOSE_BRACKET_TOKEN TOKEN(']')
/*
* Misc. tokens.
*/
#define AT_TOKEN TOKEN('@')
#define DOT_TOKEN TOKEN('.')
#define COLON_TOKEN TOKEN(':')
#define COMMA_TOKEN TOKEN(',')
#define COMMENT_TOKEN TOKEN(';')
#define SETLIST_TOKEN TOKEN('i')
#define EOL_TOKEN TOKEN(0)
#define EOF_TOKEN TOKEN(0x7F)
typedef unsigned char t_token;
#define CONST_TYPE (1 << 0)
#define WORD_TYPE (1 << 1)
#define BYTE_TYPE (1 << 2)
#define VAR_TYPE (WORD_TYPE | BYTE_TYPE)
#define FUNC_TYPE (1 << 3)
#define LOCAL_TYPE (1 << 4)
#define ADDR_TYPE (VAR_TYPE | FUNC_TYPE)
#define BPTR_TYPE (1 << 5)
#define WPTR_TYPE (1 << 6)
#define PTR_TYPE (BPTR_TYPE | WPTR_TYPE)
#define STRING_TYPE (1 << 7)
#define TAG_TYPE (1 << 8)

1612
plasma2/vmcore.s Executable file

File diff suppressed because it is too large Load Diff

BIN
plasma3/a.out Executable file

Binary file not shown.

16
plasma3/acme Executable file
View File

@ -0,0 +1,16 @@
; ACME COMPATIBLE OUTPUT
; 1: byte a
D0000 !FILL 1 ; a
; 2:
; 3: def add(b)
C0000 ; add()
; b = 2
; 4: return a + b
DB $58,$04,$01 ; ENTER 4,1
DB $68,>D0000,<D0000 ; LAB D0000
DB $66,$02 ; LLW 2
DB $02 ; ADD
DB $5A ; LEAVE
; 5: end
; 6:
; 7: done

775
plasma3/codegen.c Executable file
View File

@ -0,0 +1,775 @@
#include <stdio.h>
#include "tokens.h"
#include "symbols.h"
#include "codegen.h"
/*
* Symbol table and fixup information.
*/
static int consts = 0;
static int externs = 0;
static int globals = 0;
static int locals = 0;
static int defs = 0;
static int codetags = 0;
static int fixups = 0;
static char idconst_name[1024][17];
static int idconst_value[1024];
static char idglobal_name[1024][17];
static int idglobal_type[1024];
static int idglobal_tag[1024];
static int localsize = 0;
static char idlocal_name[128][17];
static int idlocal_type[128];
static int idlocal_offset[128];
static char fixup_size[255];
static int fixup_type[255];
static int fixup_tag[255];
#define FIXUP_BYTE 0x00
#define FIXUP_WORD 0x80
int id_match(char *name, int len, char *id)
{
if (len == id[0])
{
if (len > 16) len = 16;
while (len--)
{
if (name[len] != id[1 + len])
return (0);
}
return (1);
}
return (0);
}
int idconst_lookup(char *name, int len)
{
int i;
for (i = 0; i < consts; i++)
if (id_match(name, len, &(idconst_name[i][0])))
return (i);
return (-1);
}
int idlocal_lookup(char *name, int len)
{
int i;
for (i = 0; i < locals; i++)
if (id_match(name, len, &(idlocal_name[i][0])))
return (i);
return (-1);
}
int idglobal_lookup(char *name, int len)
{
int i;
for (i = 0; i < globals; i++)
if (id_match(name, len, &(idglobal_name[i][0])))
return (i);
return (-1);
}
int idconst_add(char *name, int len, int value)
{
if (consts > 1024)
{
printf("Constant count overflow\n");
return (0);
}
char c = name[len];
name[len] = '\0';
emit_idconst(name, value);
name[len] = c;
idconst_name[consts][0] = len;
if (len > 16) len = 16;
while (len--)
idconst_name[consts][1 + len] = name[len];
idconst_value[consts] = value;
consts++;
return (1);
}
int idlocal_add(char *name, int len, int type, int size)
{
if (localsize > 255)
{
printf("Local variable size overflow\n");
return (0);
}
char c = name[len];
name[len] = '\0';
emit_idlocal(name, localsize);
name[len] = c;
idlocal_name[locals][0] = len;
if (len > 16) len = 16;
while (len--)
idlocal_name[locals][1 + len] = name[len];
idlocal_type[locals] = type | LOCAL_TYPE;
idlocal_offset[locals] = localsize;
localsize += size;
locals++;
return (1);
}
int idglobal_add(char *name, int len, int type, int size)
{
if (globals > 1024)
{
printf("Global variable count overflow\n");
return (0);
}
char c = name[len];
name[len] = '\0';
name[len] = c;
idglobal_name[globals][0] = len;
if (len > 16) len = 16;
while (len--)
idglobal_name[globals][1 + len] = name[len];
idglobal_type[globals] = type;
if (!(type & EXTERN_TYPE))
{
emit_idglobal(globals, size, name);
idglobal_tag[globals] = globals++;
}
else
{
printf("\t\t\t\t\t; %s -> X%03d\n", &idglobal_name[globals][1], externs);
idglobal_tag[globals++] = externs++;
}
return (1);
}
int id_add(char *name, int len, int type, int size)
{
return ((type & LOCAL_TYPE) ? idlocal_add(name, len, type, size) : idglobal_add(name, len, type, size));
}
int idfunc_add(char *name, int len, int type, int tag)
{
if (globals > 1024)
{
printf("Global variable count overflow\n");
return (0);
}
idglobal_name[globals][0] = len;
if (len > 16) len = 16;
while (len--)
idglobal_name[globals][1 + len] = name[len];
idglobal_type[globals] = type;
idglobal_tag[globals++] = tag;
if (type & EXTERN_TYPE)
printf("\t\t\t\t\t; %s -> X%03d\n", &idglobal_name[globals - 1][1], tag);
return (1);
}
int idfunc_set(char *name, int len, int type)
{
int i;
if (((i = idglobal_lookup(name, len)) >= 0) && (idglobal_type[i] & FUNC_TYPE))
{
idglobal_type[i] = type;
return (idglobal_type[i]);
}
parse_error("Undeclared identifier");
return (0);
}
void idglobal_size(int type, int size, int constsize)
{
if (size > constsize)
emit_data(0, 0, 0, size - constsize);
else if (size)
emit_data(0, 0, 0, size);
}
int idlocal_size(void)
{
return (localsize);
}
void idlocal_reset(void)
{
locals = 0;
localsize = 2;
}
int id_tag(char *name, int len)
{
int i;
if ((i = idlocal_lookup(name, len)) >= 0)
return (idlocal_offset[i]);
if ((i = idglobal_lookup(name, len)) >= 0)
return (idglobal_tag[i]);
parse_error("Undeclared identifier");
return (-1);
}
int id_const(char *name, int len)
{
int i;
if ((i = idconst_lookup(name, len)) >= 0)
return (idconst_value[i]);
parse_error("Undeclared constant");
return (0);
}
int id_type(char *name, int len)
{
int i;
if ((i = idconst_lookup(name, len)) >= 0)
return (CONST_TYPE);
if ((i = idlocal_lookup(name, len)) >= 0)
return (idlocal_type[i] | LOCAL_TYPE);
if ((i = idglobal_lookup(name, len)) >= 0)
return (idglobal_type[i]);
parse_error("Undeclared identifier");
return (0);
}
int tag_new(int type)
{
if (type & EXTERN_TYPE)
return (externs++);
if (type & ASM_TYPE)
return (globals);
if (type & DEF_TYPE)
return (defs++);
if (type & BRANCH_TYPE)
return (codetags++);
return globals++;
}
int fixup_new(int tag, int type, int size)
{
if (fixups > 255)
{
printf("External variable count overflow\n");
return (0);
}
fixup_tag[fixups] = tag;
fixup_type[fixups] = type;
fixup_size[fixups] = size;
return (fixups++);
}
/*
* Emit assembly code.
*/
#define BYTECODE_SEG 2
static int outflags = 0;
static char *DB = ".BYTE";
static char *DW = ".WORD";
static char *DS = ".RES";
static char LBL = ':';
char *tag_string(int tag, int type)
{
static char str[16];
char t;
if (type & EXTERN_TYPE)
t = 'X';
else if (type & DEF_TYPE)
t = 'C';
else if (type & ASM_TYPE)
t = 'A';
else if (type & BRANCH_TYPE)
t = 'B';
else
t = 'D';
sprintf(str, "_%c%03d", t, tag);
return str;
}
void emit_flags(int flags)
{
outflags = flags;
if (outflags & ACME)
{
DB = "!BYTE";
DW = "!WORD";
DS = "!FILL";
LBL = ' ';
}
}
void emit_header(void)
{
if (outflags & ACME)
printf("; ACME COMPATIBLE OUTPUT\n");
else
printf("; CA65 COMPATIBLE OUTPUT\n");
printf("_SEGBEGIN%c\n", LBL);
printf("\t%s\t_SEGEND-_SEGBEGIN\t; LENGTH OF HEADER + CODE/DATA + BYTECODE SEGMENT\n", DW);
printf("\t%s\t$DA7E\t\t\t; MAGIC #\n", DW);
printf("\t%s\t_SUBSEG\t\t\t; BYTECODE SUB-SEGMENT\n", DW);
}
void emit_trailer(void)
{
if (!(outflags & BYTECODE_SEG))
emit_bytecode_seg();
printf("_SEGEND%c\n", LBL);
}
char *supper(char *s)
{
static char su[80];
int i;
for (i = 0; s[i]; i++)
su[i] = toupper(s[i]);
su[i] = '\0';
return su;
}
void emit_dci(char *str, int len)
{
if (len--)
{
printf("\t; DCI STRING: %s\n", supper(str));
printf("\t%s\t$%02X", DB, toupper(*str++) | (len ? 0x80 : 0x00));
while (len--)
printf(",$%02X", toupper(*str++) | (len ? 0x80 : 0x00));
printf("\n");
}
}
void emit_moddep(char *name, int len)
{
if (name)
emit_dci(name, len);
else
printf("\t%s\t$00\t\t\t; END OF MODULE DEPENDENCIES\n", DB);
}
void emit_bytecode_seg(void)
{
if (!(outflags & BYTECODE_SEG))
printf("_SUBSEG%c\t\t\t\t; BYTECODE STARTS\n", LBL);
outflags |= BYTECODE_SEG;
}
void emit_comment(char *s)
{
printf("\t\t\t\t\t; %s\n", s);
}
void emit_asm(char *s)
{
printf("%s\n", s);
}
void emit_idlocal(char *name, int value)
{
printf("\t\t\t\t\t; %s -> [%d]\n", name, value);
}
void emit_idglobal(int tag, int size, char *name)
{
if (size == 0)
printf("_D%03d%c\t\t\t\t\t; %s\n", tag, LBL, name);
else
printf("_D%03d%c\t%s\t%d\t\t\t; %s\n", tag, LBL, DS, size, name);
}
void emit_idfunc(int tag, int type, char *name)
{
printf("%s%c\t\t\t\t\t; %s()\n", tag_string(tag, type), LBL, name);
}
void emit_idconst(char *name, int value)
{
printf("\t\t\t\t\t; %s = %d\n", name, value);
}
int emit_data(int vartype, int consttype, long constval, int constsize)
{
int datasize, i;
char *str;
if (consttype == 0)
{
datasize = constsize;
printf("\t%s\t$%02X\n", DS, constsize);
}
else if (consttype & STRING_TYPE)
{
datasize = constsize;
str = (char *)constval;
printf("\t%s\t$%02X\n", DB, --constsize);
while (constsize-- > 0)
{
printf("\t%s\t$%02X", DB, *str++);
for (i = 0; i < 7; i++)
{
if (constsize-- > 0)
printf(",$%02X", *str++);
else
break;
}
printf("\n");
}
}
else if (consttype & ADDR_TYPE)
{
if (vartype == WORD_TYPE)
{
int fixup = fixup_new(constval, consttype, FIXUP_WORD);
datasize = 2;
if (consttype & EXTERN_TYPE)
printf("_F%03d%c\t%s\t0\t\t\t; %s\n", fixup, LBL, DW, tag_string(constval, consttype));
else
printf("_F%03d%c\t%s\t%s\n", fixup, LBL, DW, tag_string(constval, consttype));
}
else
{
int fixup = fixup_new(constval, consttype, FIXUP_BYTE);
datasize = 1;
if (consttype & EXTERN_TYPE)
printf("_F%03d%c\t%s\t0\t\t\t; %s\n", fixup, LBL, DB, tag_string(constval, consttype));
else
printf("_F%03d%c\t%s\t%s\n", fixup, LBL, DB, tag_string(constval, consttype));
}
}
else
{
if (vartype == WORD_TYPE)
{
datasize = 2;
printf("\t%s\t$%04lX\n", DW, constval & 0xFFFF);
}
else
{
datasize = 1;
printf("\t%s\t$%02lX\n", DB, constval & 0xFF);
}
}
return (datasize);
}
void emit_codetag(int tag)
{
printf("_B%03d%c\n", tag, LBL);
}
void emit_const(int cval)
{
if (cval == 0)
printf("\t%s\t$00\t\t\t; ZERO\n", DB);
else if (cval > 0 && cval < 256)
printf("\t%s\t$2A,$%02X\t\t\t; CB\t%d\n", DB, cval, cval);
else
printf("\t%s\t$2C,$%02X,$%02X\t\t; CW\t%d\n", DB, cval&0xFF,(cval>>8)&0xFF, cval);
}
void emit_lb(void)
{
printf("\t%s\t$60\t\t\t; LB\n", DB);
}
void emit_lw(void)
{
printf("\t%s\t$62\t\t\t; LW\n", DB);
}
void emit_llb(int index)
{
printf("\t%s\t$64,$%02X\t\t\t; LLB\t[%d]\n", DB, index, index);
}
void emit_llw(int index)
{
printf("\t%s\t$66,$%02X\t\t\t; LLW\t[%d]\n", DB, index, index);
}
void emit_lab(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$68\t\t\t; LAB\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_law(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$6A\t\t\t; LAW\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_sb(void)
{
printf("\t%s\t$70\t\t\t; SB\n", DB);
}
void emit_sw(void)
{
printf("\t%s\t$72\t\t\t; SW\n", DB);
}
void emit_slb(int index)
{
printf("\t%s\t$74,$%02X\t\t\t; SLB\t[%d]\n", DB, index, index);
}
void emit_slw(int index)
{
printf("\t%s\t$76,$%02X\t\t\t; SLW\t[%d]\n", DB, index, index);
}
void emit_dlb(int index)
{
printf("\t%s\t$6C,$%02X\t\t\t; DLB\t[%d]\n", DB, index, index);
}
void emit_dlw(int index)
{
printf("\t%s\t$6E,$%02X\t\t\t; DLW\t[%d]\n", DB, index, index);
}
void emit_sab(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$78\t\t\t; SAB\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_saw(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$7A\t\t\t; SAW\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_dab(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$7C\t\t\t; DAB\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_daw(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$7E\t\t\t; DAW\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_localaddr(int index)
{
printf("\t%s\t$28,$%02X\t\t\t; LLA\t[%d]\n", DB, index, index);
}
void emit_globaladdr(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$26\t\t\t; LA\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_globaladdrofst(int tag, int ofst, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$26\t\t\t; LA\t%s+%d\n", DB, taglbl, ofst);
printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "" : taglbl, ofst);
}
void emit_indexbyte(void)
{
printf("\t%s\t$02\t\t\t; IDXB\n", DB);
}
void emit_indexword(void)
{
printf("\t%s\t$1E\t\t\t; IDXW\n", DB);
}
void emit_brfls(int tag)
{
printf("\t%s\t$4C\t\t\t; BRFLS\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_brtru(int tag)
{
printf("\t%s\t$4E\t\t\t; BRTRU\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_brnch(int tag)
{
printf("\t%s\t$50\t\t\t; BRNCH\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_breq(int tag)
{
printf("\t%s\t$3C\t\t\t; BREQ\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_brne(int tag)
{
printf("\t%s\t$3E\t\t\t; BRNE\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_brlt(int tag)
{
printf("\t%s\t$38\t\t\t; BRLT\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_brgt(int tag)
{
printf("\t%s\t$3A\t\t\t; BRGT\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_call(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$54\t\t\t; CALL\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_ical(void)
{
printf("\t%s\t$56\t\t\t; ICAL\n", DB);
}
void emit_leave(int framesize)
{
if (framesize > 2)
printf("\t%s\t$5A\t\t\t; LEAVE\n", DB);
else
printf("\t%s\t$5C\t\t\t; RET\n", DB);
}
void emit_ret(void)
{
printf("\t%s\t$5C\t\t\t; RET\n", DB);
}
void emit_def(int defopt)
{
}
void emit_enter(int framesize, int cparams)
{
if (framesize > 2)
printf("\t%s\t$58,$%02X,$%02X\t\t; ENTER\t%d,%d\n", DB, framesize, cparams, framesize, cparams);
}
void emit_start(void)
{
}
void emit_dup(void)
{
printf("\t%s\t$32\t\t\t; DUP\n", DB);
}
void emit_push(void)
{
printf("\t%s\t$34\t\t\t; PUSH\n", DB);
}
void emit_pull(void)
{
printf("\t%s\t$36\t\t\t; PULL\n", DB);
}
void emit_swap(void)
{
printf("\t%s\t$2E\t\t\t; SWAP\n", DB);
}
void emit_drop(void)
{
printf("\t%s\t$30\t\t\t; DROP\n", DB);
}
int emit_unaryop(int op)
{
switch (op)
{
case NEG_TOKEN:
printf("\t%s\t$10\t\t\t; NEG\n", DB);
break;
case COMP_TOKEN:
printf("\t%s\t$12\t\t\t; COMP\n", DB);
break;
case LOGIC_NOT_TOKEN:
printf("\t%s\t$20\t\t\t; NOT\n", DB);
break;
case INC_TOKEN:
printf("\t%s\t$0C\t\t\t; INCR\n", DB);
break;
case DEC_TOKEN:
printf("\t%s\t$0E\t\t\t; DECR\n", DB);
break;
case BPTR_TOKEN:
emit_lb();
break;
case WPTR_TOKEN:
emit_lw();
break;
default:
printf("emit_unaryop(%c) ???\n", op & 0x7F);
return (0);
}
return (1);
}
int emit_op(t_token op)
{
switch (op)
{
case MUL_TOKEN:
printf("\t%s\t$06\t\t\t; MUL\n", DB);
break;
case DIV_TOKEN:
printf("\t%s\t$08\t\t\t; DIV\n", DB);
break;
case MOD_TOKEN:
printf("\t%s\t$0A\t\t\t; MOD\n", DB);
break;
case ADD_TOKEN:
printf("\t%s\t$02\t\t\t; ADD\n", DB);
break;
case SUB_TOKEN:
printf("\t%s\t$04\t\t\t; SUB\n", DB);
break;
case SHL_TOKEN:
printf("\t%s\t$1A\t\t\t; SHL\n", DB);
break;
case SHR_TOKEN:
printf("\t%s\t$1C\t\t\t; SHR\n", DB);
break;
case AND_TOKEN:
printf("\t%s\t$14\t\t\t; AND\n", DB);
break;
case OR_TOKEN:
printf("\t%s\t$16\t\t\t; IOR\n", DB);
break;
case EOR_TOKEN:
printf("\t%s\t$18\t\t\t; XOR\n", DB);
break;
case EQ_TOKEN:
printf("\t%s\t$40\t\t\t; ISEQ\n", DB);
break;
case NE_TOKEN:
printf("\t%s\t$42\t\t\t; ISNE\n", DB);
break;
case GE_TOKEN:
printf("\t%s\t$48\t\t\t; ISGE\n", DB);
break;
case LT_TOKEN:
printf("\t%s\t$46\t\t\t; ISLT\n", DB);
break;
case GT_TOKEN:
printf("\t%s\t$44\t\t\t; ISGT\n", DB);
break;
case LE_TOKEN:
printf("\t%s\t$4A\t\t\t; ISLE\n", DB);
break;
case LOGIC_OR_TOKEN:
printf("\t%s\t$22\t\t\t; LOR\n", DB);
break;
case LOGIC_AND_TOKEN:
printf("\t%s\t$24\t\t\t; LAND\n", DB);
break;
case COMMA_TOKEN:
break;
default:
return (0);
}
return (1);
}
void emit_rld(void)
{
int i;
printf(";\n; RE-LOCATEABLE DICTIONARY\n;\n");
/*
* First emit the bytecode definition entrypoint information.
*/
for (i = 0; i < globals; i++)
if (!(idglobal_type[i] & EXTERN_TYPE) && (idglobal_type[i] & DEF_TYPE))
{
printf("\t%s\t$02\t\t\t; CODE TABLE FIXUP\n", DB);
printf("\t%s\t_C%03d\t\t\n", DW, idglobal_tag[i]);
printf("\t%s\t$00\n", DB);
}
/*
* Now emit the fixup table.
*/
for (i = 0; i < fixups; i++)
{
if (fixup_type[i] & EXTERN_TYPE)
{
printf("\t%s\t$%02X\t\t\t; EXTERNAL FIXUP\n", DB, 0x11 + fixup_size[i]);
printf("\t%s\t_F%03d\t\t\n", DW, i);
printf("\t%s\t%d\t\t\t; ESD INDEX\n", DB, fixup_tag[i]);
}
else
{
printf("\t%s\t$%02X\t\t\t; INTERNAL FIXUP\n", DB, 0x01 + fixup_size[i]);
printf("\t%s\t_F%03d\t\t\n", DW, i);
printf("\t%s\t$00\n", DB);
}
}
printf("\t%s\t$00\t\t\t; END OF RLD\n", DB);
}
void emit_esd(void)
{
int i;
printf(";\n; EXTERNAL/ENTRY SYMBOL DICTIONARY\n;\n");
for (i = 0; i < globals; i++)
{
if (idglobal_type[i] & EXTERN_TYPE)
{
emit_dci(&idglobal_name[i][1], idglobal_name[i][0]);
printf("\t%s\t$10\t\t\t; EXTERNAL SYMBOL FLAG\n", DB);
printf("\t%s\t%d\t\t\t; ESD INDEX\n", DW, idglobal_tag[i]);
}
else if (idglobal_type[i] & EXPORT_TYPE)
{
emit_dci(&idglobal_name[i][1], idglobal_name[i][0]);
printf("\t%s\t$08\t\t\t; ENTRY SYMBOL FLAG\n", DB);
printf("\t%s\t%s\t\t\n", DW, tag_string(idglobal_tag[i], idglobal_type[i]));
}
}
printf("\t%s\t$00\t\t\t; END OF ESD\n", DB);
}

775
plasma3/codegen.c~ Executable file
View File

@ -0,0 +1,775 @@
#include <stdio.h>
#include "tokens.h"
#include "symbols.h"
#include "codegen.h"
/*
* Symbol table and fixup information.
*/
static int consts = 0;
static int externs = 0;
static int globals = 0;
static int locals = 0;
static int defs = 0;
static int codetags = 0;
static int fixups = 0;
static char idconst_name[1024][17];
static int idconst_value[1024];
static char idglobal_name[1024][17];
static int idglobal_type[1024];
static int idglobal_tag[1024];
static int localsize = 0;
static char idlocal_name[128][17];
static int idlocal_type[128];
static int idlocal_offset[128];
static char fixup_size[255];
static int fixup_type[255];
static int fixup_tag[255];
#define FIXUP_BYTE 0x00
#define FIXUP_WORD 0x80
int id_match(char *name, int len, char *id)
{
if (len == id[0])
{
if (len > 16) len = 16;
while (len--)
{
if (name[len] != id[1 + len])
return (0);
}
return (1);
}
return (0);
}
int idconst_lookup(char *name, int len)
{
int i;
for (i = 0; i < consts; i++)
if (id_match(name, len, &(idconst_name[i][0])))
return (i);
return (-1);
}
int idlocal_lookup(char *name, int len)
{
int i;
for (i = 0; i < locals; i++)
if (id_match(name, len, &(idlocal_name[i][0])))
return (i);
return (-1);
}
int idglobal_lookup(char *name, int len)
{
int i;
for (i = 0; i < globals; i++)
if (id_match(name, len, &(idglobal_name[i][0])))
return (i);
return (-1);
}
int idconst_add(char *name, int len, int value)
{
if (consts > 1024)
{
printf("Constant count overflow\n");
return (0);
}
char c = name[len];
name[len] = '\0';
emit_idconst(name, value);
name[len] = c;
idconst_name[consts][0] = len;
if (len > 16) len = 16;
while (len--)
idconst_name[consts][1 + len] = name[len];
idconst_value[consts] = value;
consts++;
return (1);
}
int idlocal_add(char *name, int len, int type, int size)
{
if (localsize > 255)
{
printf("Local variable size overflow\n");
return (0);
}
char c = name[len];
name[len] = '\0';
emit_idlocal(name, localsize);
name[len] = c;
idlocal_name[locals][0] = len;
if (len > 16) len = 16;
while (len--)
idlocal_name[locals][1 + len] = name[len];
idlocal_type[locals] = type | LOCAL_TYPE;
idlocal_offset[locals] = localsize;
localsize += size;
locals++;
return (1);
}
int idglobal_add(char *name, int len, int type, int size)
{
if (globals > 1024)
{
printf("Global variable count overflow\n");
return (0);
}
char c = name[len];
name[len] = '\0';
name[len] = c;
idglobal_name[globals][0] = len;
if (len > 16) len = 16;
while (len--)
idglobal_name[globals][1 + len] = name[len];
idglobal_type[globals] = type;
if (!(type & EXTERN_TYPE))
{
emit_idglobal(globals, size, name);
idglobal_tag[globals] = globals++;
}
else
{
printf("\t\t\t\t\t; %s -> X%03d\n", &idglobal_name[globals][1], externs);
idglobal_tag[globals++] = externs++;
}
return (1);
}
int id_add(char *name, int len, int type, int size)
{
return ((type & LOCAL_TYPE) ? idlocal_add(name, len, type, size) : idglobal_add(name, len, type, size));
}
int idfunc_add(char *name, int len, int type, int tag)
{
if (globals > 1024)
{
printf("Global variable count overflow\n");
return (0);
}
idglobal_name[globals][0] = len;
if (len > 16) len = 16;
while (len--)
idglobal_name[globals][1 + len] = name[len];
idglobal_type[globals] = type;
idglobal_tag[globals++] = tag;
if (type & EXTERN_TYPE)
printf("\t\t\t\t\t; %s -> X%03d\n", &idglobal_name[globals - 1][1], tag);
return (1);
}
int idfunc_extern(char *name, int len)
{
int i;
if (((i = idglobal_lookup(name, len)) >= 0) && (idglobal_type[i] & FUNC_TYPE))
{
idglobal_type[i] |= EXTERN_TYPE;
return (idglobal_type[i]);
}
parse_error("Undeclared identifier");
return (0);
}
void idglobal_size(int type, int size, int constsize)
{
if (size > constsize)
emit_data(0, 0, 0, size - constsize);
else if (size)
emit_data(0, 0, 0, size);
}
int idlocal_size(void)
{
return (localsize);
}
void idlocal_reset(void)
{
locals = 0;
localsize = 2;
}
int id_tag(char *name, int len)
{
int i;
if ((i = idlocal_lookup(name, len)) >= 0)
return (idlocal_offset[i]);
if ((i = idglobal_lookup(name, len)) >= 0)
return (idglobal_tag[i]);
parse_error("Undeclared identifier");
return (-1);
}
int id_const(char *name, int len)
{
int i;
if ((i = idconst_lookup(name, len)) >= 0)
return (idconst_value[i]);
parse_error("Undeclared constant");
return (0);
}
int id_type(char *name, int len)
{
int i;
if ((i = idconst_lookup(name, len)) >= 0)
return (CONST_TYPE);
if ((i = idlocal_lookup(name, len)) >= 0)
return (idlocal_type[i] | LOCAL_TYPE);
if ((i = idglobal_lookup(name, len)) >= 0)
return (idglobal_type[i]);
parse_error("Undeclared identifier");
return (0);
}
int tag_new(int type)
{
if (type & EXTERN_TYPE)
return (externs++);
if (type & ASM_TYPE)
return (globals);
if (type & DEF_TYPE)
return (defs++);
if (type & BRANCH_TYPE)
return (codetags++);
return globals++;
}
int fixup_new(int tag, int type, int size)
{
if (fixups > 255)
{
printf("External variable count overflow\n");
return (0);
}
fixup_tag[fixups] = tag;
fixup_type[fixups] = type;
fixup_size[fixups] = size;
return (fixups++);
}
/*
* Emit assembly code.
*/
#define BYTECODE_SEG 2
static int outflags = 0;
static char *DB = ".BYTE";
static char *DW = ".WORD";
static char *DS = ".RES";
static char LBL = ':';
char *tag_string(int tag, int type)
{
static char str[16];
char t;
if (type & EXTERN_TYPE)
t = 'X';
else if (type & DEF_TYPE)
t = 'C';
else if (type & ASM_TYPE)
t = 'A';
else if (type & BRANCH_TYPE)
t = 'B';
else
t = 'D';
sprintf(str, "_%c%03d", t, tag);
return str;
}
void emit_flags(int flags)
{
outflags = flags;
if (outflags & ACME)
{
DB = "!BYTE";
DW = "!WORD";
DS = "!FILL";
LBL = ' ';
}
}
void emit_header(void)
{
if (outflags & ACME)
printf("; ACME COMPATIBLE OUTPUT\n");
else
printf("; CA65 COMPATIBLE OUTPUT\n");
printf("_SEGBEGIN%c\n", LBL);
printf("\t%s\t_SEGEND-_SEGBEGIN\t; LENGTH OF HEADER + CODE/DATA + BYTECODE SEGMENT\n", DW);
printf("\t%s\t$DA7E\t\t\t; MAGIC #\n", DW);
printf("\t%s\t_SUBSEG\t\t\t; BYTECODE SUB-SEGMENT\n", DW);
}
void emit_trailer(void)
{
if (!(outflags & BYTECODE_SEG))
emit_bytecode_seg();
printf("_SEGEND%c\n", LBL);
}
char *supper(char *s)
{
static char su[80];
int i;
for (i = 0; s[i]; i++)
su[i] = toupper(s[i]);
su[i] = '\0';
return su;
}
void emit_dci(char *str, int len)
{
if (len--)
{
printf("\t; DCI STRING: %s\n", supper(str));
printf("\t%s\t$%02X", DB, toupper(*str++) | (len ? 0x80 : 0x00));
while (len--)
printf(",$%02X", toupper(*str++) | (len ? 0x80 : 0x00));
printf("\n");
}
}
void emit_moddep(char *name, int len)
{
if (name)
emit_dci(name, len);
else
printf("\t%s\t$00\t\t\t; END OF MODULE DEPENDENCIES\n", DB);
}
void emit_bytecode_seg(void)
{
if (!(outflags & BYTECODE_SEG))
printf("_SUBSEG%c\t\t\t\t; BYTECODE STARTS\n", LBL);
outflags |= BYTECODE_SEG;
}
void emit_comment(char *s)
{
printf("\t\t\t\t\t; %s\n", s);
}
void emit_asm(char *s)
{
printf("%s\n", s);
}
void emit_idlocal(char *name, int value)
{
printf("\t\t\t\t\t; %s -> [%d]\n", name, value);
}
void emit_idglobal(int tag, int size, char *name)
{
if (size == 0)
printf("_D%03d%c\t\t\t\t\t; %s\n", tag, LBL, name);
else
printf("_D%03d%c\t%s\t%d\t\t\t; %s\n", tag, LBL, DS, size, name);
}
void emit_idfunc(int tag, int type, char *name)
{
printf("%s%c\t\t\t\t\t; %s()\n", tag_string(tag, type), LBL, name);
}
void emit_idconst(char *name, int value)
{
printf("\t\t\t\t\t; %s = %d\n", name, value);
}
int emit_data(int vartype, int consttype, long constval, int constsize)
{
int datasize, i;
char *str;
if (consttype == 0)
{
datasize = constsize;
printf("\t%s\t$%02X\n", DS, constsize);
}
else if (consttype & STRING_TYPE)
{
datasize = constsize;
str = (char *)constval;
printf("\t%s\t$%02X\n", DB, --constsize);
while (constsize-- > 0)
{
printf("\t%s\t$%02X", DB, *str++);
for (i = 0; i < 7; i++)
{
if (constsize-- > 0)
printf(",$%02X", *str++);
else
break;
}
printf("\n");
}
}
else if (consttype & ADDR_TYPE)
{
if (vartype == WORD_TYPE)
{
int fixup = fixup_new(constval, consttype, FIXUP_WORD);
datasize = 2;
if (consttype & EXTERN_TYPE)
printf("_F%03d%c\t%s\t0\t\t\t; %s\n", fixup, LBL, DW, tag_string(constval, consttype));
else
printf("_F%03d%c\t%s\t%s\n", fixup, LBL, DW, tag_string(constval, consttype));
}
else
{
int fixup = fixup_new(constval, consttype, FIXUP_BYTE);
datasize = 1;
if (consttype & EXTERN_TYPE)
printf("_F%03d%c\t%s\t0\t\t\t; %s\n", fixup, LBL, DB, tag_string(constval, consttype));
else
printf("_F%03d%c\t%s\t%s\n", fixup, LBL, DB, tag_string(constval, consttype));
}
}
else
{
if (vartype == WORD_TYPE)
{
datasize = 2;
printf("\t%s\t$%04lX\n", DW, constval & 0xFFFF);
}
else
{
datasize = 1;
printf("\t%s\t$%02lX\n", DB, constval & 0xFF);
}
}
return (datasize);
}
void emit_codetag(int tag)
{
printf("_B%03d%c\n", tag, LBL);
}
void emit_const(int cval)
{
if (cval == 0)
printf("\t%s\t$00\t\t\t; ZERO\n", DB);
else if (cval > 0 && cval < 256)
printf("\t%s\t$2A,$%02X\t\t\t; CB\t%d\n", DB, cval, cval);
else
printf("\t%s\t$2C,$%02X,$%02X\t\t; CW\t%d\n", DB, cval&0xFF,(cval>>8)&0xFF, cval);
}
void emit_lb(void)
{
printf("\t%s\t$60\t\t\t; LB\n", DB);
}
void emit_lw(void)
{
printf("\t%s\t$62\t\t\t; LW\n", DB);
}
void emit_llb(int index)
{
printf("\t%s\t$64,$%02X\t\t\t; LLB\t[%d]\n", DB, index, index);
}
void emit_llw(int index)
{
printf("\t%s\t$66,$%02X\t\t\t; LLW\t[%d]\n", DB, index, index);
}
void emit_lab(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$68\t\t\t; LAB\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_law(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$6A\t\t\t; LAW\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_sb(void)
{
printf("\t%s\t$70\t\t\t; SB\n", DB);
}
void emit_sw(void)
{
printf("\t%s\t$72\t\t\t; SW\n", DB);
}
void emit_slb(int index)
{
printf("\t%s\t$74,$%02X\t\t\t; SLB\t[%d]\n", DB, index, index);
}
void emit_slw(int index)
{
printf("\t%s\t$76,$%02X\t\t\t; SLW\t[%d]\n", DB, index, index);
}
void emit_dlb(int index)
{
printf("\t%s\t$6C,$%02X\t\t\t; DLB\t[%d]\n", DB, index, index);
}
void emit_dlw(int index)
{
printf("\t%s\t$6E,$%02X\t\t\t; DLW\t[%d]\n", DB, index, index);
}
void emit_sab(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$78\t\t\t; SAB\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_saw(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$7A\t\t\t; SAW\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_dab(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$7C\t\t\t; DAB\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_daw(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$7E\t\t\t; DAW\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_localaddr(int index)
{
printf("\t%s\t$28,$%02X\t\t\t; LLA\t[%d]\n", DB, index, index);
}
void emit_globaladdr(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$26\t\t\t; LA\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_globaladdrofst(int tag, int ofst, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$26\t\t\t; LA\t%s+%d\n", DB, taglbl, ofst);
printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "" : taglbl, ofst);
}
void emit_indexbyte(void)
{
printf("\t%s\t$02\t\t\t; IDXB\n", DB);
}
void emit_indexword(void)
{
printf("\t%s\t$1E\t\t\t; IDXW\n", DB);
}
void emit_brfls(int tag)
{
printf("\t%s\t$4C\t\t\t; BRFLS\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_brtru(int tag)
{
printf("\t%s\t$4E\t\t\t; BRTRU\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_brnch(int tag)
{
printf("\t%s\t$50\t\t\t; BRNCH\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_breq(int tag)
{
printf("\t%s\t$3C\t\t\t; BREQ\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_brne(int tag)
{
printf("\t%s\t$3E\t\t\t; BRNE\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_brlt(int tag)
{
printf("\t%s\t$38\t\t\t; BRLT\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_brgt(int tag)
{
printf("\t%s\t$3A\t\t\t; BRGT\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_call(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$54\t\t\t; CALL\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_ical(void)
{
printf("\t%s\t$56\t\t\t; ICAL\n", DB);
}
void emit_leave(int framesize)
{
if (framesize > 2)
printf("\t%s\t$5A\t\t\t; LEAVE\n", DB);
else
printf("\t%s\t$5C\t\t\t; RET\n", DB);
}
void emit_ret(void)
{
printf("\t%s\t$5C\t\t\t; RET\n", DB);
}
void emit_def(int defopt)
{
}
void emit_enter(int framesize, int cparams)
{
if (framesize > 2)
printf("\t%s\t$58,$%02X,$%02X\t\t; ENTER\t%d,%d\n", DB, framesize, cparams, framesize, cparams);
}
void emit_start(void)
{
}
void emit_dup(void)
{
printf("\t%s\t$32\t\t\t; DUP\n", DB);
}
void emit_push(void)
{
printf("\t%s\t$34\t\t\t; PUSH\n", DB);
}
void emit_pull(void)
{
printf("\t%s\t$36\t\t\t; PULL\n", DB);
}
void emit_swap(void)
{
printf("\t%s\t$2E\t\t\t; SWAP\n", DB);
}
void emit_drop(void)
{
printf("\t%s\t$30\t\t\t; DROP\n", DB);
}
int emit_unaryop(int op)
{
switch (op)
{
case NEG_TOKEN:
printf("\t%s\t$10\t\t\t; NEG\n", DB);
break;
case COMP_TOKEN:
printf("\t%s\t$12\t\t\t; COMP\n", DB);
break;
case LOGIC_NOT_TOKEN:
printf("\t%s\t$20\t\t\t; NOT\n", DB);
break;
case INC_TOKEN:
printf("\t%s\t$0C\t\t\t; INCR\n", DB);
break;
case DEC_TOKEN:
printf("\t%s\t$0E\t\t\t; DECR\n", DB);
break;
case BPTR_TOKEN:
emit_lb();
break;
case WPTR_TOKEN:
emit_lw();
break;
default:
printf("emit_unaryop(%c) ???\n", op & 0x7F);
return (0);
}
return (1);
}
int emit_op(t_token op)
{
switch (op)
{
case MUL_TOKEN:
printf("\t%s\t$06\t\t\t; MUL\n", DB);
break;
case DIV_TOKEN:
printf("\t%s\t$08\t\t\t; DIV\n", DB);
break;
case MOD_TOKEN:
printf("\t%s\t$0A\t\t\t; MOD\n", DB);
break;
case ADD_TOKEN:
printf("\t%s\t$02\t\t\t; ADD\n", DB);
break;
case SUB_TOKEN:
printf("\t%s\t$04\t\t\t; SUB\n", DB);
break;
case SHL_TOKEN:
printf("\t%s\t$1A\t\t\t; SHL\n", DB);
break;
case SHR_TOKEN:
printf("\t%s\t$1C\t\t\t; SHR\n", DB);
break;
case AND_TOKEN:
printf("\t%s\t$14\t\t\t; AND\n", DB);
break;
case OR_TOKEN:
printf("\t%s\t$16\t\t\t; IOR\n", DB);
break;
case EOR_TOKEN:
printf("\t%s\t$18\t\t\t; XOR\n", DB);
break;
case EQ_TOKEN:
printf("\t%s\t$40\t\t\t; ISEQ\n", DB);
break;
case NE_TOKEN:
printf("\t%s\t$42\t\t\t; ISNE\n", DB);
break;
case GE_TOKEN:
printf("\t%s\t$48\t\t\t; ISGE\n", DB);
break;
case LT_TOKEN:
printf("\t%s\t$46\t\t\t; ISLT\n", DB);
break;
case GT_TOKEN:
printf("\t%s\t$44\t\t\t; ISGT\n", DB);
break;
case LE_TOKEN:
printf("\t%s\t$4A\t\t\t; ISLE\n", DB);
break;
case LOGIC_OR_TOKEN:
printf("\t%s\t$22\t\t\t; LOR\n", DB);
break;
case LOGIC_AND_TOKEN:
printf("\t%s\t$24\t\t\t; LAND\n", DB);
break;
case COMMA_TOKEN:
break;
default:
return (0);
}
return (1);
}
void emit_rld(void)
{
int i;
printf(";\n; RE-LOCATEABLE DICTIONARY\n;\n");
/*
* First emit the bytecode definition entrypoint information.
*/
for (i = 0; i < globals; i++)
if (!(idglobal_type[i] & EXTERN_TYPE) && (idglobal_type[i] & DEF_TYPE))
{
printf("\t%s\t$02\t\t\t; CODE TABLE FIXUP\n", DB);
printf("\t%s\t_C%03d\t\t\n", DW, idglobal_tag[i]);
printf("\t%s\t$00\n", DB);
}
/*
* Now emit the fixup table.
*/
for (i = 0; i < fixups; i++)
{
if (fixup_type[i] & EXTERN_TYPE)
{
printf("\t%s\t$%02X\t\t\t; EXTERNAL FIXUP\n", DB, 0x11 + fixup_size[i]);
printf("\t%s\t_F%03d\t\t\n", DW, i);
printf("\t%s\t%d\t\t\t; ESD INDEX\n", DB, fixup_tag[i]);
}
else
{
printf("\t%s\t$%02X\t\t\t; INTERNAL FIXUP\n", DB, 0x01 + fixup_size[i]);
printf("\t%s\t_F%03d\t\t\n", DW, i);
printf("\t%s\t$00\n", DB);
}
}
printf("\t%s\t$00\t\t\t; END OF RLD\n", DB);
}
void emit_esd(void)
{
int i;
printf(";\n; EXTERNAL/ENTRY SYMBOL DICTIONARY\n;\n");
for (i = 0; i < globals; i++)
{
if (idglobal_type[i] & EXTERN_TYPE)
{
emit_dci(&idglobal_name[i][1], idglobal_name[i][0]);
printf("\t%s\t$10\t\t\t; EXTERNAL SYMBOL FLAG\n", DB);
printf("\t%s\t%d\t\t\t; ESD INDEX\n", DW, idglobal_tag[i]);
}
else if (idglobal_type[i] & EXPORT_TYPE)
{
emit_dci(&idglobal_name[i][1], idglobal_name[i][0]);
printf("\t%s\t$08\t\t\t; ENTRY SYMBOL FLAG\n", DB);
printf("\t%s\t%s\t\t\n", DW, tag_string(idglobal_tag[i], idglobal_type[i]));
}
}
printf("\t%s\t$00\t\t\t; END OF ESD\n", DB);
}

58
plasma3/codegen.h Executable file
View File

@ -0,0 +1,58 @@
#define ACME 1
void emit_flags(int flags);
void emit_header(void);
void emit_trailer(void);
void emit_moddep(char *name, int len);
void emit_bytecode_seg(void);
void emit_comment(char *s);
void emit_asm(char *s);
void emit_idlocal(char *name, int value);
void emit_idglobal(int value, int size, char *name);
void emit_idfunc(int tag, int type, char *name);
void emit_idconst(char *name, int value);
int emit_data(int vartype, int consttype, long constval, int constsize);
void emit_codetag(int tag);
void emit_const(int cval);
void emit_lb(void);
void emit_lw(void);
void emit_llb(int index);
void emit_llw(int index);
void emit_lab(int tag, int type);
void emit_law(int tag, int type);
void emit_sb(void);
void emit_sw(void);
void emit_slb(int index);
void emit_slw(int index);
void emit_dlb(int index);
void emit_dlw(int index);
void emit_sab(int tag, int type);
void emit_saw(int tag, int type);
void emit_dab(int tag, int type);
void emit_daw(int tag, int type);
void emit_call(int tag, int type);
void emit_ical(void);
void emit_localaddr(int index);
void emit_globaladdr(int tag, int type);
void emit_globaladdrofst(int tag, int offset, int type);
void emit_indexbyte(void);
void emit_indexword(void);
int emit_unaryop(int op);
int emit_op(t_token op);
void emit_brtru(int tag);
void emit_brfls(int tag);
void emit_brgt(int tag);
void emit_brlt(int tag);
void emit_brne(int tag);
void emit_brnch(int tag);
void emit_swap(void);
void emit_dup(void);
void emit_push(void);
void emit_pull(void);
void emit_drop(void);
void emit_leave(int framesize);
void emit_ret(void);
void emit_def(int defopt);
void emit_enter(int framesize, int cparams);
void emit_start(void);
void emit_rld(void);
void emit_esd(void);

BIN
plasma3/codegen.o Executable file

Binary file not shown.

182
plasma3/dict.c Executable file
View File

@ -0,0 +1,182 @@
/*
* Symbol table and fixup information.
*/
static int consts = 0;
static char idconst_name[1024][17];
static int idconst_value[1024];
static int globals = 0;
static int globalsize = 0;
static char idglobal_name[1024][17];
static int idglobal_type[1024];
static int idglobal_tag[1024];
static int locals = 0;
static int localsize = 0;
static char idlocal_name[128][17];
static int idlocal_type[128];
static int idlocal_offset[128];
static int codetag = 0;
static int fixup = 0;
int id_match(char *name, int len, char *id)
{
if (len == id[0])
{
if (len > 16) len = 16;
while (len--)
{
if (name[len] != id[1 + len])
return (0);
}
return (1);
}
return (0);
}
int idlocal_lookup(char *name, int len)
{
int i;
for (i = 0; i < locals; i++)
if (id_match(name, len, &(idlocal_name[i][0])))
return (i);
return (-1);
}
int idglobal_lookup(char *name, int len)
{
int i;
for (i = 0; i < globals; i++)
if (id_match(name, len, &(idglobal_name[i][0])))
return (i);
return (-1);
}
int idconst_lookup(char *name, int len)
{
int i;
for (i = 0; i < consts; i++)
if (id_match(name, len, &(idconst_name[i][0])))
return (i);
return (-1);
}
int idlocal_add(char *name, int len, int type, int size)
{
if (localsize > 255)
{
printf("Local variable size overflow\n");
return (0);
}
char c = name[len];
name[len] = '\0';
emit_idlocal(name, localsize);
name[len] = c;
idlocal_name[locals][0] = len;
if (len > 16) len = 16;
while (len--)
idlocal_name[locals][1 + len] = name[len];
idlocal_type[locals] = type;
idlocal_offset[locals] = localsize;
localsize += size;
locals++;
return (1);
}
int idglobal_add(char *name, int len, int type, int size)
{
if (globals > 1024)
{
printf("Global variable count overflow\n");
return (0);
}
char c = name[len];
name[len] = '\0';
emit_idglobal(globalsize, size, name);
name[len] = c;
idglobal_name[globals][0] = len;
if (len > 16) len = 16;
while (len--)
idglobal_name[globals][1 + len] = name[len];
idglobal_type[globals] = type;
idglobal_tag[globals] = globalsize;
globalsize += size;
globals++;
return (1);
}
void idglobal_size(int type, int size, int constsize)
{
if (size > constsize)
globalsize += emit_data(0, 0, 0, size - constsize);
else
globalsize += constsize;
}
int idfunc_add(char *name, int len, int tag)
{
if (globals > 1024)
{
printf("Global variable count overflow\n");
return (0);
}
idglobal_name[globals][0] = len;
if (len > 16) len = 16;
while (len--)
idglobal_name[globals][1 + len] = name[len];
idglobal_type[globals] = FUNC_TYPE;
idglobal_tag[globals] = tag;
globals++;
return (1);
}
int idconst_add(char *name, int len, int value)
{
if (consts > 1024)
{
printf("Constant count overflow\n");
return (0);
}
char c = name[len];
name[len] = '\0';
emit_idconst(name, value);
name[len] = c;
idconst_name[consts][0] = len;
if (len > 16) len = 16;
while (len--)
idconst_name[consts][1 + len] = name[len];
idconst_value[consts] = value;
consts++;
return (1);
}
int id_addr(char *name, int len)
{
int i;
if ((i = idlocal_lookup(name, len)) >= 0)
return (idlocal_offset[i]);
if ((i = idglobal_lookup(name, len)) >= 0)
return (idglobal_tag[i]);
parse_error("Undeclared identifier");
return (-1);
}
int id_const(char *name, int len)
{
int i;
if ((i = idconst_lookup(name, len)) >= 0)
return (idconst_value[i]);
parse_error("Undeclared constant");
return (0);
}
int id_type(char *name, int len)
{
int i;
if ((i = idconst_lookup(name, len)) >= 0)
return (CONST_TYPE);
if ((i = idlocal_lookup(name, len)) >= 0)
return (idlocal_type[i] | LOCAL_TYPE);
if ((i = idglobal_lookup(name, len)) >= 0)
return (idglobal_type[i]);
parse_error("Undeclared identifier");
return (0);
}
void idlocal_reset(void)
{
locals = localsize = 0;
}
int tag_new(void)
{
return (codetag++);
}
int add_fixup(tag)
{
return (fixup++);
}

1
plasma3/hi.ascii Executable file
View File

@ -0,0 +1 @@
€亗儎厗噲墛媽崕彁憭摂晼棙櫄洔潪煚、¥ウЖ┆<EFBFBD><EFBFBD><EFBFBD>辈炒刀犯购患骄坷谅媚牌侨墒颂臀闲岩釉罩棕仝圮蒉哙徕沅彐玷殛腱眍镳耱篝貊鼬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>€亗儎厗噲墛媽崕彁憭摂晼棙櫄洔潪煚、¥ウЖ┆<EFBFBD><EFBFBD><EFBFBD>辈炒刀犯购患骄坷谅媚牌侨墒颂臀闲岩釉罩棕仝圮蒉哙徕沅彐玷殛腱眍镳耱篝貊鼬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>

3
plasma3/hi.ascii.a Executable file
View File

@ -0,0 +1,3 @@
!to "hi.ascii", plain
*=0
!for i, 256 {!byte i-1 | $80}

363
plasma3/lex.c Executable file
View File

@ -0,0 +1,363 @@
#include <stdio.h>
#include <stdlib.h>
#include "tokens.h"
#include "symbols.h"
char *statement, *scanpos, *tokenstr;
t_token scantoken, prevtoken;
int tokenlen;
long constval;
int lineno = 0;
t_token keywords[] = {
IF_TOKEN, 'I', 'F',
ELSE_TOKEN, 'E', 'L', 'S', 'E',
ELSEIF_TOKEN, 'E', 'L', 'S', 'I', 'F',
FIN_TOKEN, 'F', 'I', 'N',
WHILE_TOKEN, 'W', 'H', 'I', 'L', 'E',
LOOP_TOKEN, 'L', 'O', 'O', 'P',
CASE_TOKEN, 'W', 'H', 'E', 'N',
OF_TOKEN, 'I', 'S',
DEFAULT_TOKEN, 'O', 'T', 'H', 'E', 'R', 'W', 'I', 'S', 'E',
ENDCASE_TOKEN, 'W', 'E', 'N', 'D',
FOR_TOKEN, 'F', 'O', 'R',
TO_TOKEN, 'T', 'O',
DOWNTO_TOKEN, 'D', 'O', 'W', 'N', 'T', 'O',
STEP_TOKEN, 'S', 'T', 'E', 'P',
NEXT_TOKEN, 'N', 'E', 'X', 'T',
REPEAT_TOKEN, 'R', 'E', 'P', 'E', 'A', 'T',
UNTIL_TOKEN, 'U', 'N', 'T', 'I', 'L',
BREAK_TOKEN, 'B', 'R', 'E', 'A', 'K',
ASM_TOKEN, 'A', 'S', 'M',
DEF_TOKEN, 'D', 'E', 'F',
EXPORT_TOKEN, 'E', 'X', 'P', 'O', 'R', 'T',
IMPORT_TOKEN, 'I', 'M', 'P', 'O', 'R', 'T',
RETURN_TOKEN, 'R', 'E', 'T', 'U', 'R', 'N',
END_TOKEN, 'E', 'N', 'D',
START_TOKEN, 'S', 'T', 'A', 'R', 'T',
EXIT_TOKEN, 'E', 'X', 'I', 'T',
DONE_TOKEN, 'D', 'O', 'N', 'E',
LOGIC_NOT_TOKEN, 'N', 'O', 'T',
LOGIC_AND_TOKEN, 'A', 'N', 'D',
LOGIC_OR_TOKEN, 'O', 'R',
BYTE_TOKEN, 'B', 'Y', 'T', 'E',
WORD_TOKEN, 'W', 'O', 'R', 'D',
CONST_TOKEN, 'C', 'O', 'N', 'S', 'T',
PREDEF_TOKEN, 'P', 'R', 'E', 'D', 'E', 'F',
EOL_TOKEN
};
void parse_error(char *errormsg)
{
char *error_carrot = statement;
fprintf(stderr, "\n%4d: %s\n ", lineno, statement);
for (error_carrot = statement; error_carrot != tokenstr; error_carrot++)
putc(*error_carrot == '\t' ? '\t' : ' ', stderr);
fprintf(stderr, "^\nError: %s\n", errormsg);
exit(1);
}
t_token scan(void)
{
prevtoken = scantoken;
/*
* Skip whitespace.
*/
while (*scanpos && (*scanpos == ' ' || *scanpos == '\t')) scanpos++;
tokenstr = scanpos;
/*
* Scan for token based on first character.
*/
if (*scanpos == '\0' || *scanpos == '\n' || *scanpos == ';')
scantoken = EOL_TOKEN;
else if ((scanpos[0] >= 'a' && scanpos[0] <= 'z')
|| (scanpos[0] >= 'A' && scanpos[0] <= 'Z')
|| (scanpos[0] == '_'))
{
/*
* ID, either variable name or reserved word.
*/
int keypos = 0, matchpos = 0;
do
{
scanpos++;
}
while ((*scanpos >= 'a' && *scanpos <= 'z')
|| (*scanpos >= 'A' && *scanpos <= 'Z')
|| (*scanpos == '_')
|| (*scanpos >= '0' && *scanpos <= '9'));
scantoken = ID_TOKEN;
tokenlen = scanpos - tokenstr;
/*
* Search for matching keyword.
*/
while (keywords[keypos] != EOL_TOKEN)
{
while (keywords[keypos + 1 + matchpos] == toupper(tokenstr[matchpos]))
matchpos++;
if (IS_TOKEN(keywords[keypos + 1 + matchpos]) && (matchpos == tokenlen))
{
/*
* A match.
*/
scantoken = keywords[keypos];
break;
}
else
{
/*
* Find next keyword.
*/
keypos += matchpos + 1;
matchpos = 0;
while (!IS_TOKEN(keywords[keypos])) keypos++;
}
}
}
else if (scanpos[0] >= '0' && scanpos[0] <= '9')
{
/*
* Number constant.
*/
for (constval = 0; *scanpos >= '0' && *scanpos <= '9'; scanpos++)
constval = constval * 10 + *scanpos - '0';
scantoken = INT_TOKEN;
}
else if (scanpos[0] == '$')
{
/*
* Hexadecimal constant.
*/
constval = 0;
while (scanpos++)
{
if (*scanpos >= '0' && *scanpos <= '9')
constval = constval * 16 + *scanpos - '0';
else if (*scanpos >= 'A' && *scanpos <= 'F')
constval = constval * 16 + *scanpos - 'A' + 10;
else if (*scanpos >= 'a' && *scanpos <= 'f')
constval = constval * 16 + *scanpos - 'a' + 10;
else
break;
}
scantoken = INT_TOKEN;
}
else if (scanpos[0] == '\'')
{
/*
* Character constant.
*/
scantoken = CHAR_TOKEN;
if (scanpos[1] != '\\')
{
constval = scanpos[1];
if (scanpos[2] != '\'')
{
parse_error("Bad character constant");
return (-1);
}
scanpos += 3;
}
else
{
switch (scanpos[2])
{
case 'n':
constval = '\n';
break;
case 'r':
constval = '\r';
break;
case 't':
constval = '\t';
break;
case '\'':
constval = '\'';
break;
case '\\':
constval = '\\';
break;
case '0':
constval = '\0';
break;
default:
parse_error("Bad character constant");
return (-1);
}
if (scanpos[3] != '\'')
{
parse_error("Bad character constant");
return (-1);
}
scanpos += 4;
}
}
else if (scanpos[0] == '\"')
{
char *scanshift;
/*
* String constant.
*/
scantoken = STRING_TOKEN;
constval = (long)++scanpos;
while (*scanpos && *scanpos != '\"')
{
if (*scanpos == '\\')
{
switch (scanpos[1])
{
case 'n':
*scanpos = '\n';
break;
case 'r':
*scanpos = '\r';
break;
case 't':
*scanpos = '\t';
break;
case '\'':
*scanpos = '\'';
break;
case '\\':
*scanpos = '\\';
break;
case '0':
*scanpos = '\0';
break;
default:
parse_error("Bad string constant");
return (-1);
}
for (scanshift = scanpos + 1; *scanshift; scanshift++)
scanshift[0] = scanshift[1];
}
else
scanpos++;
}
if (!*scanpos++)
{
parse_error("Unterminated string");
return (-1);
}
}
else
{
/*
* Potential two and three character tokens.
*/
switch (scanpos[0])
{
case '>':
if (scanpos[1] == '>')
{
scantoken = SHR_TOKEN;
scanpos += 2;
}
else if (scanpos[1] == '=')
{
scantoken = GE_TOKEN;
scanpos += 2;
}
else
{
scantoken = GT_TOKEN;
scanpos++;
}
break;
case '<':
if (scanpos[1] == '<')
{
scantoken = SHL_TOKEN;
scanpos += 2;
}
else if (scanpos[1] == '=')
{
scantoken = LE_TOKEN;
scanpos += 2;
}
else if (scanpos[1] == '>')
{
scantoken = NE_TOKEN;
scanpos += 2;
}
else
{
scantoken = LT_TOKEN;
scanpos++;
}
break;
case '=':
if (scanpos[1] == '=')
{
scantoken = EQ_TOKEN;
scanpos += 2;
}
else
{
scantoken = SET_TOKEN;
scanpos++;
}
break;
case '+':
if (scanpos[1] == '+')
{
scantoken = INC_TOKEN;
scanpos += 2;
}
else
{
scantoken = ADD_TOKEN;
scanpos++;
}
break;
case '-':
if (scanpos[1] == '-')
{
scantoken = DEC_TOKEN;
scanpos += 2;
}
else
{
scantoken = SUB_TOKEN;
scanpos++;
}
break;
default:
/*
* Simple single character tokens.
*/
scantoken = TOKEN(*scanpos++);
}
}
tokenlen = scanpos - tokenstr;
return (scantoken);
}
void scan_rewind(char *backptr)
{
scanpos = backptr;
}
int scan_lookahead(void)
{
char *backpos = scanpos;
char *backstr = tokenstr;
int prevtoken = scantoken;
int prevlen = tokenlen;
int look = scan();
scanpos = backpos;
tokenstr = backstr;
scantoken = prevtoken;
tokenlen = prevlen;
return (look);
}
char inputline[512];
int next_line(void)
{
gets(inputline);
lineno++;
statement = inputline;
scanpos = inputline;
scantoken = EOL_TOKEN;
scan();
printf("; %03d: %s\n", lineno, inputline);
return (1);
}

10
plasma3/lex.h Executable file
View File

@ -0,0 +1,10 @@
extern char *statement, *scanpos, *tokenstr;
extern t_token scantoken, prevtoken;
extern int tokenlen;
extern long constval;
extern char inputline[];
void parse_error(char *errormsg);
int next_line(void);
void scan_rewind(char *backptr);
int scan_lookahead(void);
t_token scan(void);

BIN
plasma3/lex.o Executable file

Binary file not shown.

39
plasma3/makefile Executable file
View File

@ -0,0 +1,39 @@
.SUFFIXES =
AFLAGS = -o $@
LFLAGS = -C default.cfg
PLVM = plvm
PLASM = plasm
INCS = tokens.h symbols.h lex.h parse.h codegen.h
OBJS = plasm.c parse.o lex.o codegen.o
#
# Image filetypes for Virtual ][
#
PLATYPE = .\$$ED
BINTYPE = .BIN
SYSTYPE = .SYS
TXTTYPE = .TXT
#
# Image filetypes for CiderPress
#
#PLATYPE = \#ed0000
#BINTYPE = \#060000
#SYSTYPE = \#ff0000
#TXTTYPE = \#040000
all: $(PLASM) $(PLVM)
$(PLASM): $(OBJS) $(INCS)
cc $(OBJS) -o $(PLASM)
$(PLVM): plvm.c
cc plvm.c -o $(PLVM)
test: test.pla $(PLVM) $(PLASM)
./$(PLASM) -A < test.pla > test.a
acme --setpc 4096 -o TEST.BIN test.a
./$(PLVM) TEST.BIN MAIN
debug: test.pla $(PLVM) $(PLASM)
./$(PLASM) -A < test.pla > test.a
acme --setpc 4096 -o TEST.BIN test.a
./$(PLVM) -s TEST.BIN MAIN

1294
plasma3/parse.c Executable file

File diff suppressed because it is too large Load Diff

1296
plasma3/parse.c~ Executable file

File diff suppressed because it is too large Load Diff

1
plasma3/parse.h Executable file
View File

@ -0,0 +1 @@
int parse_module(void);

BIN
plasma3/parse.o Executable file

Binary file not shown.

BIN
plasma3/plasm Executable file

Binary file not shown.

17
plasma3/plasm.c Executable file
View File

@ -0,0 +1,17 @@
#include <stdio.h>
#include "tokens.h"
#include "lex.h"
#include "codegen.h"
#include "parse.h"
int main(int argc, char **argv)
{
if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'A')
emit_flags(ACME);
if (parse_module())
{
fprintf(stderr, "Compilation complete.\n");
}
return (0);
}

3382
plasma3/pleaides.pla Executable file

File diff suppressed because it is too large Load Diff

BIN
plasma3/plvm Executable file

Binary file not shown.

895
plasma3/plvm.c Executable file
View File

@ -0,0 +1,895 @@
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
typedef unsigned char code;
typedef unsigned char byte;
typedef signed short word;
typedef unsigned short uword;
typedef unsigned short address;
/*
* Debug
*/
int show_state = 0;
/*
* Bytecode memory
*/
#define BYTE_PTR(bp) ((byte)(*bp++))
#define WORD_PTR(bp) ((word)(*bp++|(*++bp << 8)))
#define UWORD_PTR(bp) ((uword)(*bp++|(*++bp << 8)))
#define MOD_ADDR 0x1000
#define DEF_CALL 0x0800
#define DEF_CALLSZ 0x0800
#define DEF_ENTRYSZ 6
#define MEM_SIZE 65536
byte mem_data[MEM_SIZE], mem_code[MEM_SIZE];
byte *mem_bank[2] = {mem_data, mem_code};
uword sp = 0x01FE, fp = 0xBEFF, heap = 0x6000, xheap = 0x0800, deftbl = DEF_CALL, lastdef = DEF_CALL;
#define EVAL_STACKSZ 16
#define PUSH(v) (*(--esp))=(v)
#define POP (*(esp++))
#define UPOP ((uword)(*(esp++)))
#define TOS (esp[0])
word eval_stack[EVAL_STACKSZ];
word *esp = eval_stack + EVAL_STACKSZ;
#define SYMTBLSZ 1024
#define SYMSZ 16
#define MODTBLSZ 128
#define MODSZ 16
#define MODLSTSZ 32
byte symtbl[SYMTBLSZ];
byte *lastsym = symtbl;
byte modtbl[MODTBLSZ];
byte *lastmod = modtbl;
/*
* Utility routines.
*
* A DCI string is one that has the high bit set for every character except the last.
* More efficient than C or Pascal strings.
*/
int dcitos(byte *dci, char *str)
{
int len = 0;
do
str[len] = *dci & 0x7F;
while ((len++ < 15) && (*dci++ & 0x80));
str[len] = 0;
return len;
}
int stodci(char *str, byte *dci)
{
int len = 0;
do
dci[len] = toupper(*str) | 0x80;
while (*str++ && (len++ < 15));
dci[len - 1] &= 0x7F;
return len;
}
/*
* Heap routines.
*/
uword avail_heap(void)
{
return fp - heap;
}
uword alloc_heap(int size)
{
uword addr = heap;
heap += size;
if (heap >= fp)
{
printf("Error: heap/frame collision.\n");
exit (1);
}
return addr;
}
uword free_heap(int size)
{
heap -= size;
return fp - heap;
}
uword mark_heap(void)
{
return heap;
}
int release_heap(uword newheap)
{
heap = newheap;
return fp - heap;
}
uword avail_xheap(void)
{
return 0xC000 - xheap;
}
uword alloc_xheap(int size)
{
uword addr = xheap;
xheap += size;
if (xheap >= 0xC000)
{
printf("Error: xheap extinguished.\n");
exit (1);
}
return addr;
}
uword free_xheap(int size)
{
xheap -= size;
return 0xC000 - heap;
}
uword mark_xheap(void)
{
return xheap;
}
int release_xheap(uword newxheap)
{
xheap = newxheap;
return 0xC000 - xheap;
}
/*
* Copy from data mem to code mem.
*/
void xmemcpy(uword src, uword dst, uword size)
{
while (size--)
mem_code[dst + size] = mem_data[src + size];
}
/*
* Copy from code mem to data mem.
*/
void memxcpy(uword src, uword dst, uword size)
{
while (size--)
mem_data[dst + size] = mem_code[src + size];
}
/*
* DCI table routines,
*/
void dump_tbl(byte *tbl)
{
int len;
byte *entbl;
while (*tbl)
{
len = 0;
while (*tbl & 0x80)
{
putchar(*tbl++ & 0x7F);
len++;
}
putchar(*tbl++);
putchar(':');
while (len++ < 15)
putchar(' ');
printf("$%04X\n", tbl[0] | (tbl[1] << 8));
tbl += 2;
}
}
uword lookup_tbl(byte *dci, byte *tbl)
{
char str[20];
byte *match, *entry = tbl;
while (*entry)
{
match = dci;
while (*entry == *match)
{
if ((*entry & 0x80) == 0)
return entry[1] | (entry[2] << 8);
entry++;
match++;
}
while (*entry++ & 0x80);
entry += 2;
}
dcitos(dci, str);
return 0;
}
int add_tbl(byte *dci, int val, byte *tbl, byte **last)
{
while (*dci & 0x80)
*(*last)++ = *dci++;
*(*last)++ = *dci++;
*(*last)++ = val;
*(*last)++ = val >> 8;
}
/*
* Symbol table routines.
*/
void dump_sym(void)
{
printf("\nSystem Symbol Table:\n");
dump_tbl(symtbl);
}
uword lookup_sym(byte *sym)
{
return lookup_tbl(sym, symtbl);
}
int add_sym(byte *sym, int addr)
{
return add_tbl(sym, addr, symtbl, &lastsym);
}
/*
* Module routines.
*/
void dump_mod(void)
{
printf("\nSystem Module Table:\n");
dump_tbl(modtbl);
}
uword lookup_mod(byte *mod)
{
return lookup_tbl(mod, modtbl);
}
int add_mod(byte *mod, int addr)
{
return add_tbl(mod, addr, symtbl, &lastmod);
}
defcall_add(int bank, int addr)
{
mem_data[lastdef] = bank ? 2 : 1;
mem_data[lastdef + 1] = addr;
mem_data[lastdef + 2] = addr >> 8;
return lastdef++;
}
int def_lookup(byte *cdd, int defaddr)
{
int i, calldef = 0;
for (i = 0; cdd[i * 4] == 0x02; i++)
{
if ((cdd[i * 4 + 1] | (cdd[i * 4 + 2] << 8)) == defaddr)
{
calldef = cdd + i * 4 - mem_data;
break;
}
}
return calldef;
}
int extern_lookup(byte *esd, int index)
{
byte *sym;
char string[32];
while (*esd)
{
sym = esd;
esd += dcitos(esd, string);
if ((esd[0] & 0x10) && (esd[1] == index))
return lookup_sym(sym);
esd += 3;
}
printf("\nError: extern index %d not found in ESD.\n", index);
return 0;
}
int load_mod(byte *mod)
{
int len, size, end, magic, bytecode, fixup, addr, modaddr = mark_heap();
byte *moddep, *rld, *esd, *cdd, *sym;
byte header[128];
char filename[32], string[17];
dcitos(mod, filename);
printf("Load module %s\n");
int fd = open(filename, O_RDONLY, 0);
if ((fd > 0) && (len = read(fd, header, 128)) > 0)
{
magic = header[2] | (header[3] << 8);
if (magic == 0xDA7E)
{
/*
* This is a relocatable bytecode module.
*/
bytecode = header[4] | (header[5] << 8);
moddep = header + 6;
if (*moddep)
{
/*
* Load module dependencies.
*/
close(fd);
while (*moddep)
{
if (lookup_mod(moddep) == 0)
load_mod(moddep);
moddep += dcitos(moddep, string);
}
modaddr = mark_heap();
fd = open(filename, O_RDONLY, 0);
len = read(fd, mem_data + modaddr, 128);
}
else
memcpy(mem_data + modaddr, header, len);
}
addr = modaddr + len;
while ((len = read(fd, mem_data + addr, 4096)) > 0)
addr += len;
close(fd);
size = addr - modaddr;
len = mem_data[modaddr + 0] | (mem_data[modaddr + 1] << 8);
end = modaddr + len;
rld = mem_data + modaddr + len; // Re-Locatable Directory
esd = rld; // Extern+Entry Symbol Directory
bytecode += modaddr - MOD_ADDR;
while (*esd != 0x00) // Scan to end of RLD
esd += 4;
esd++;
cdd = rld;
if (show_state)
{
/*
* Dump different parts of module.
*/
printf("Module size: %d\n", size);
printf("Module code+data size: %d\n", len);
printf("Module magic: $%04X\n", magic);
printf("Module bytecode: $%04X\n", bytecode);
}
/*
* Print out the Re-Location Dictionary.
*/
if (show_state)
printf("\nRe-Location Dictionary:\n");
while (*rld)
{
if (rld[0] == 0x02)
{
if (show_state) printf("\tDEF CODE");
addr = rld[1] | (rld[2] << 8);
addr += modaddr - MOD_ADDR;
rld[1] = addr;
rld[2] = addr >> 8;
end = rld - mem_data + 4;
}
else
{
addr = rld[1] | (rld[2] << 8);
addr += modaddr - MOD_ADDR;
if (rld[0] & 0x80)
fixup = mem_data[addr] | (mem_data[addr + 1] << 8);
else
fixup = mem_data[addr];
if (rld[0] & 0x10)
{
if (show_state) printf("\tEXTERN[$%02X] ", rld[3]);
fixup += extern_lookup(esd, rld[3]);
}
else
{
if (show_state) printf("\tINTERN ");
fixup += modaddr - MOD_ADDR;
if (fixup >= bytecode)
/*
* Replace with call def dictionary.
*/
fixup = def_lookup(cdd, fixup);
}
if (rld[0] & 0x80)
{
if (show_state) printf("WORD");
mem_data[addr] = fixup;
mem_data[addr + 1] = fixup >> 8;
}
else
{
if (show_state) printf("BYTE");
mem_data[addr] = fixup;
}
}
if (show_state) printf("@$%04X\n", addr);
rld += 4;
}
if (show_state) printf("\nExternal/Entry Symbol Directory:\n");
while (*esd)
{
sym = esd;
esd += dcitos(esd, string);
if (esd[0] & 0x10)
{
if (show_state) printf("\tIMPORT %s[$%02X]\n", string, esd[1]);
}
else if (esd[0] & 0x08)
{
addr = esd[1] | (esd[2] << 8);
addr += modaddr - MOD_ADDR;
if (show_state) printf("\tEXPORT %s@$%04X\n", string, addr);
if (addr >= bytecode)
addr = def_lookup(cdd, addr);
add_sym(sym, addr);
}
esd += 3;
}
}
else
{
printf("Error: Unable to load module %s\n", filename);
exit (1);
}
/*
* Reserve heap space for relocated module.
*/
alloc_heap(end - modaddr);
return (fd > 0);
}
void interp(code *ip);
void call(word pc)
{
int i, s;
char sz[64];
switch (mem_data[pc++])
{
case 0: // NULL call
printf("NULL call code\n");
break;
case 1: // BYTECODE in mem_code
interp(mem_code + (mem_data[pc] + (mem_data[pc + 1] << 8)));
break;
case 2: // BYTECODE in mem_data
interp(mem_data + (mem_data[pc] + (mem_data[pc + 1] << 8)));
break;
case 3: // LIBRARY STDLIB::VIEWPORT
printf("Set Window %d, %d, %d, %n/n", POP, POP, POP, POP);
PUSH(0);
break;
case 4: // LIBRARY STDLIB::PUTC
putchar(POP);
PUSH(0);
break;
case 5: // LIBRARY STDLIB::PUTS
s = POP;
i = mem_data[s++];
PUSH(i);
while (i--)
putchar(mem_data[s++]);
break;
case 6: // LIBRARY STDLIB::PUTSZ
s = POP;
while (i = mem_data[s++])
{
if (i == '\r')
i = '\n';
putchar(i);
}
PUSH(0);
break;
case 7: // LIBRARY STDLIB::GETC
PUSH(getchar());
break;
case 8: // LIBRARY STDLIB::GETS
gets(sz);
i = 0;
while (sz[i])
mem_data[0x200 + i++] = sz[i];
mem_data[0x200 + i] = 0;
mem_data[0x1FF] = i;
PUSH(i);
break;
case 9: // LIBRARY STDLIB::CLS
puts("\033[2J");
fflush(stdout);
PUSH(0);
PUSH(0);
case 10: // LIBRARY STDLIB::GOTOXY
s = POP + 1;
i = POP + 1;
printf("\033[%d;%df", s, i);
fflush(stdout);
PUSH(0);
break;
default:
printf("Bad call code\n");
}
}
/*
* OPCODE TABLE
*
OPTBL: DW ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E
DW NEG,COMP,AND,IOR,XOR,SHL,SHR,IDXW ; 10 12 14 16 18 1A 1C 1E
DW NOT,LOR,LAND,LA,LLA,CB,CW,SWAP ; 20 22 24 26 28 2A 2C 2E
DW DROP,DUP,PUSH,PULL,BRGT,BRLT,BREQ,BRNE ; 30 32 34 36 38 3A 3C 3E
DW ISEQ,ISNE,ISGT,ISLT,ISGE,ISLE,BRFLS,BRTRU ; 40 42 44 46 48 4A 4C 4E
DW BRNCH,IBRNCH,CALL,ICAL,ENTER,LEAVE,RET,??? ; 50 52 54 56 58 5A 5C 5E
DW LB,LW,LLB,LLW,LAB,LAW,DLB,DLW ; 60 62 64 66 68 6A 6C 6E
DW SB,SW,SLB,SLW,SAB,SAW,DAB,DAW ; 70 72 74 76 78 7A 7C 7E
*/
void interp(code *ip)
{
word val, ea, frmsz, parmcnt;
while (1)
{
if (show_state)
{
word *dsp = &eval_stack[EVAL_STACKSZ - 1];
printf("$%04X: $%02X [ ", ip - mem_data, *ip);
while (dsp >= esp)
printf("$%04X ", (*dsp--) & 0xFFFF);
printf("]\n");
}
switch (*ip++)
{
/*
* 0x00-0x0F
*/
case 0x00: // ZERO : TOS = 0
PUSH(0);
break;
case 0x02: // ADD : TOS = TOS + TOS-1
val = POP;
ea = POP;
PUSH(ea + val);
break;
case 0x04: // SUB : TOS = TOS-1 - TOS
val = POP;
ea = POP;
PUSH(ea - val);
break;
case 0x06: // MUL : TOS = TOS * TOS-1
val = POP;
ea = POP;
PUSH(ea * val);
break;
case 0x08: // DIV : TOS = TOS-1 / TOS
val = POP;
ea = POP;
PUSH(ea / val);
break;
case 0x0A: // MOD : TOS = TOS-1 % TOS
val = POP;
ea = POP;
PUSH(ea % val);
break;
case 0x0C: // INCR : TOS = TOS + 1
TOS++;
break;
case 0x0E: // DECR : TOS = TOS - 1
TOS--;
break;
/*
* 0x10-0x1F
*/
case 0x10: // NEG : TOS = -TOS
TOS = -TOS;
break;
case 0x12: // COMP : TOS = ~TOS
TOS = ~TOS;
break;
case 0x14: // AND : TOS = TOS & TOS-1
val = POP;
ea = POP;
PUSH(ea & val);
break;
case 0x16: // IOR : TOS = TOS ! TOS-1
val = POP;
ea = POP;
PUSH(ea | val);
break;
case 0x18: // XOR : TOS = TOS ^ TOS-1
val = POP;
ea = POP;
PUSH(ea ^ val);
break;
case 0x1A: // SHL : TOS = TOS-1 << TOS
val = POP;
ea = POP;
PUSH(ea << val);
break;
case 0x1C: // SHR : TOS = TOS-1 >> TOS
val = POP;
ea = POP;
PUSH(ea >> val);
break;
case 0x1E: // IDXW : TOS = TOS * 2
TOS *= 2;
break;
/*
* 0x20-0x2F
*/
case 0x20: // NOT : TOS = !TOS
TOS = !TOS;
break;
case 0x22: // LOR : TOS = TOS || TOS-1
val = POP;
ea = POP;
PUSH(ea || val);
break;
case 0x24: // LAND : TOS = TOS && TOS-1
val = POP;
ea = POP;
PUSH(ea && val);
break;
case 0x26: // LA : TOS = @VAR ; equivalent to CW ADDRESSOF(VAR)
PUSH(WORD_PTR(ip));
break;
case 0x28: // LLA : TOS = @LOCALVAR ; equivalent to CW FRAMEPTR+OFFSET(LOCALVAR)
PUSH(fp + BYTE_PTR(ip));
break;
case 0x2A: // CB : TOS = CONSTANTBYTE (IP)
PUSH(BYTE_PTR(ip));
break;
case 0x2C: // CW : TOS = CONSTANTWORD (IP)
PUSH(WORD_PTR(ip));
break;
case 0x2E: // SWAP : TOS = TOS-1, TOS-1 = TOS
val = POP;
ea = POP;
PUSH(val);
PUSH(ea);
break;
/*
* 0x30-0x3F
*/
case 0x30: // DROP : TOS =
esp++;;
break;
case 0x32: // DUP : TOS = TOS
val = TOS;
PUSH(val);
break;
case 0x34: // PUSH : TOSP = TOS
val = POP;
mem_data[sp--] = val >> 8;
mem_data[sp--] = val;
break;
case 0x36: // PULL : TOS = TOSP
PUSH(mem_data[++sp] | (mem_data[++sp] << 8));
break;
case 0x38: // BRGT : TOS-1 > TOS ? IP += (IP)
val = POP;
ea = POP;
if (ea <= val)
ip += WORD_PTR(ip) - 2;
else
ip += 2;
break;
case 0x3A: // BRLT : TOS-1 < TOS ? IP += (IP)
val = POP;
ea = TOS;
if (ea >= val)
ip += WORD_PTR(ip) - 2;
else
ip += 2;
break;
case 0x3C: // BREQ : TOS == TOS-1 ? IP += (IP)
val = POP;
ea = TOS;
if (ea == val)
ip += WORD_PTR(ip) - 2;
else
ip += 2;
break;
case 0x3E: // BRNE : TOS != TOS-1 ? IP += (IP)
val = POP;
ea = TOS;
if (ea != val)
ip += WORD_PTR(ip) - 2;
else
ip += 2;
break;
/*
* 0x40-0x4F
*/
case 0x40: // ISEQ : TOS = TOS == TOS-1
val = POP;
ea = POP;
PUSH(ea == val);
break;
case 0x42: // ISNE : TOS = TOS != TOS-1
val = POP;
ea = POP;
PUSH(ea != val);
break;
case 0x44: // ISGT : TOS = TOS-1 > TOS
val = POP;
ea = POP;
PUSH(ea <= val);
break;
case 0x46: // ISLT : TOS = TOS-1 < TOS
val = POP;
ea = POP;
PUSH(ea >= val);
break;
case 0x48: // ISGE : TOS = TOS-1 >= TOS
val = POP;
ea = POP;
PUSH(ea < val);
break;
case 0x4A: // ISLE : TOS = TOS-1 <= TOS
val = POP;
ea = POP;
PUSH(ea > val);
break;
case 0x4C: // BRFLS : !TOS ? IP += (IP)
if (!POP)
ip += WORD_PTR(ip) - 2;
else
ip += 2;
break;
case 0x4E: // BRTRU : TOS ? IP += (IP)
if (POP)
ip += WORD_PTR(ip) - 2;
else
ip += 2;
break;
/*
* 0x50-0x5F
*/
case 0x50: // BRNCH : IP += (IP)
ip += WORD_PTR(ip) - 2;
break;
case 0x52: // IBRNCH : IP += TOS
ip += POP;
break;
case 0x54: // CALL : TOFP = IP, IP = (IP) ; call
call(UWORD_PTR(ip));
break;
case 0x56: // ICALL : TOFP = IP, IP = (TOS) ; indirect call
val = POP;
ea = mem_data[val] | (mem_data[val + 1] << 8);
call(ea);
break;
case 0x58: // ENTER : NEW FRAME, FOREACH PARAM LOCALVAR = TOS
frmsz = BYTE_PTR(ip);
mem_data[fp - frmsz] = fp;
mem_data[fp - frmsz + 1] = fp >> 8;
fp -= frmsz;
parmcnt = BYTE_PTR(ip);
while (parmcnt--)
{
val = POP;
mem_data[fp + parmcnt + 2] = val;
mem_data[fp + parmcnt + 3] = val >> 8;
}
break;
case 0x5A: // LEAVE : DEL FRAME, IP = TOFP
fp = mem_data[fp] | (mem_data[fp + 1] << 8);
case 0x5C: // RET : IP = TOFP
return;
case 0x5E: // ???
break;
/*
* 0x60-0x6F
*/
case 0x60: // LB : TOS = BYTE (TOS)
val = UPOP;
PUSH(mem_data[val]);
break;
case 0x62: // LW : TOS = WORD (TOS)
ea = POP;
PUSH(mem_data[ea] | (mem_data[ea + 1] << 8));
break;
case 0x64: // LLB : TOS = LOCALBYTE [IP]
PUSH(mem_data[fp + BYTE_PTR(ip)]);
break;
case 0x66: // LLW : TOS = LOCALWORD [IP]
ea = fp + BYTE_PTR(ip);
PUSH(mem_data[ea] | (mem_data[ea + 1] << 8));
break;
case 0x68: // LAB : TOS = BYTE (IP)
PUSH(mem_data[UWORD_PTR(ip)]);
break;
case 0x6A: // LAW : TOS = WORD (IP)
ea = UWORD_PTR(ip);
PUSH(mem_data[ea] | (mem_data[ea + 1] << 8));
break;
case 0x6C: // DLB : TOS = TOS, LOCALBYTE [IP] = TOS
mem_data[fp + BYTE_PTR(ip)] = TOS;
break;
case 0x6E: // DLW : TOS = TOS, LOCALWORD [IP] = TOS
ea = fp + BYTE_PTR(ip);
mem_data[ea] = TOS;
mem_data[ea + 1] = TOS >> 8;
break;
/*
* 0x70-0x7F
*/
case 0x70: // SB : BYTE (TOS) = TOS-1
val = POP;
ea = POP;
mem_data[ea] = val;
break;
case 0x72: // SW : WORD (TOS) = TOS-1
val = POP;
ea = POP;
mem_data[ea] = val;
mem_data[ea + 1] = val >> 8;
break;
case 0x74: // SLB : LOCALBYTE [TOS] = TOS-1
mem_data[fp + BYTE_PTR(ip)] = POP;
break;
case 0x76: // SLW : LOCALWORD [TOS] = TOS-1
ea = fp + BYTE_PTR(ip);
val = POP;
mem_data[ea] = val;
mem_data[ea + 1] = val >> 8;
break;
case 0x78: // SAB : BYTE (IP) = TOS
mem_data[WORD_PTR(ip)] = POP;
break;
case 0x7A: // SAW : WORD (IP) = TOS
ea = WORD_PTR(ip);
val = POP;
mem_data[ea] = val;
mem_data[ea + 1] = val >> 8;
break;
case 0x7C: // DAB : TOS = TOS, BYTE (IP) = TOS
mem_data[WORD_PTR(ip)] = TOS;
break;
case 0x7E: // DAW : TOS = TOS, WORD (IP) = TOS
ea = WORD_PTR(ip);
mem_data[ea] = TOS;
mem_data[ea + 1] = TOS >> 8;
break;
/*
* Odd codes and everything else are errors.
*/
default:
fprintf(stderr, "Illegal opcode 0x%02X @ 0x%04X\n", ip[-1], ip - mem_code);
}
}
}
char *stdlib_exp[] = {
"VIEWPORT",
"PUTC",
"PUTS",
"PUTSZ",
"GETC",
"GETS",
"CLS",
"GOTOXY"
};
byte stdlib[] = {
0x00
};
int main(int argc, char **argv)
{
byte dci[32];
int i;
if (--argc)
{
argv++;
if ((*argv)[0] == '-' && (*argv)[1] == 's')
{
show_state = 1;
argc--;
argv++;
}
/*
* Add default library.
*/
stodci("STDLIB", dci);
add_mod(dci, 0xFFFF);
for (i = 0; i < 8; i++)
{
mem_data[i] = i + 3;
stodci(stdlib_exp[i], dci);
add_sym(dci, i);
}
if (argc)
{
stodci(*argv, dci);
load_mod(dci);
if (show_state) dump_sym();
argc--;
argv++;
}
if (argc)
{
stodci(*argv, dci);
call(lookup_sym(dci));
}
}
return 0;
}

895
plasma3/plvm.c~ Executable file
View File

@ -0,0 +1,895 @@
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
typedef unsigned char code;
typedef unsigned char byte;
typedef signed short word;
typedef unsigned short uword;
typedef unsigned short address;
/*
* Debug
*/
int show_state = 0;
/*
* Bytecode memory
*/
#define BYTE_PTR(bp) ((byte)(*bp++))
#define WORD_PTR(bp) ((word)(*bp++|(*++bp << 8)))
#define UWORD_PTR(bp) ((uword)(*bp++|(*++bp << 8)))
#define MOD_ADDR 0x1000
#define DEF_CALL 0x0800
#define DEF_CALLSZ 0x0800
#define DEF_ENTRYSZ 6
#define MEM_SIZE 65536
byte mem_data[MEM_SIZE], mem_code[MEM_SIZE];
byte *mem_bank[2] = {mem_data, mem_code};
word sp = 0x01FE, fp = 0xBEFF, heap = 0x6000, xheap = 0x0800, deftbl = DEF_CALL, lastdef = DEF_CALL;
#define EVAL_STACKSZ 16
#define PUSH(v) (*(--esp))=(v)
#define POP (*(esp++))
#define UPOP ((uword)(*(esp++)))
#define TOS (esp[0])
word eval_stack[EVAL_STACKSZ];
word *esp = eval_stack + EVAL_STACKSZ;
#define SYMTBLSZ 1024
#define SYMSZ 16
#define MODTBLSZ 128
#define MODSZ 16
#define MODLSTSZ 32
byte symtbl[SYMTBLSZ];
byte *lastsym = symtbl;
byte modtbl[MODTBLSZ];
byte *lastmod = modtbl;
/*
* Utility routines.
*
* A DCI string is one that has the high bit set for every character except the last.
* More efficient than C or Pascal strings.
*/
int dcitos(byte *dci, char *str)
{
int len = 0;
do
str[len] = *dci & 0x7F;
while ((len++ < 15) && (*dci++ & 0x80));
str[len] = 0;
return len;
}
int stodci(char *str, byte *dci)
{
int len = 0;
do
dci[len] = toupper(*str) | 0x80;
while (*str++ && (len++ < 15));
dci[len - 1] &= 0x7F;
return len;
}
/*
* Heap routines.
*/
uword avail_heap(void)
{
return fp - heap;
}
uword alloc_heap(int size)
{
uword addr = heap;
heap += size;
if (heap >= fp)
{
printf("Error: heap/frame collision.\n");
exit (1);
}
return addr;
}
uword free_heap(int size)
{
heap -= size;
return fp - heap;
}
uword mark_heap(void)
{
return heap;
}
int release_heap(uword newheap)
{
heap = newheap;
return fp - heap;
}
uword avail_xheap(void)
{
return 0xC000 - xheap;
}
uword alloc_xheap(int size)
{
uword addr = xheap;
xheap += size;
if (xheap >= 0xC000)
{
printf("Error: xheap extinguished.\n");
exit (1);
}
return addr;
}
uword free_xheap(int size)
{
xheap -= size;
return 0xC000 - heap;
}
uword mark_xheap(void)
{
return xheap;
}
int release_xheap(uword newxheap)
{
xheap = newxheap;
return 0xC000 - xheap;
}
/*
* Copy from data mem to code mem.
*/
void xmemcpy(uword src, uword dst, uword size)
{
while (size--)
mem_code[dst + size] = mem_data[src + size];
}
/*
* Copy from code mem to data mem.
*/
void memxcpy(uword src, uword dst, uword size)
{
while (size--)
mem_data[dst + size] = mem_code[src + size];
}
/*
* DCI table routines,
*/
void dump_tbl(byte *tbl)
{
int len;
byte *entbl;
while (*tbl)
{
len = 0;
while (*tbl & 0x80)
{
putchar(*tbl++ & 0x7F);
len++;
}
putchar(*tbl++);
putchar(':');
while (len++ < 15)
putchar(' ');
printf("$%04X\n", tbl[0] | (tbl[1] << 8));
tbl += 2;
}
}
uword lookup_tbl(byte *dci, byte *tbl)
{
char str[20];
byte *match, *entry = tbl;
while (*entry)
{
match = dci;
while (*entry == *match)
{
if ((*entry & 0x80) == 0)
return entry[1] | (entry[2] << 8);
entry++;
match++;
}
while (*entry++ & 0x80);
entry += 2;
}
dcitos(dci, str);
return 0;
}
int add_tbl(byte *dci, int val, byte *tbl, byte **last)
{
while (*dci & 0x80)
*(*last)++ = *dci++;
*(*last)++ = *dci++;
*(*last)++ = val;
*(*last)++ = val >> 8;
}
/*
* Symbol table routines.
*/
void dump_sym(void)
{
printf("\nSystem Symbol Table:\n");
dump_tbl(symtbl);
}
uword lookup_sym(byte *sym)
{
return lookup_tbl(sym, symtbl);
}
int add_sym(byte *sym, int addr)
{
return add_tbl(sym, addr, symtbl, &lastsym);
}
/*
* Module routines.
*/
void dump_mod(void)
{
printf("\nSystem Module Table:\n");
dump_tbl(modtbl);
}
uword lookup_mod(byte *mod)
{
return lookup_tbl(mod, modtbl);
}
int add_mod(byte *mod, int addr)
{
return add_tbl(mod, addr, symtbl, &lastmod);
}
defcall_add(int bank, int addr)
{
mem_data[lastdef] = bank ? 2 : 1;
mem_data[lastdef + 1] = addr;
mem_data[lastdef + 2] = addr >> 8;
return lastdef++;
}
int def_lookup(byte *cdd, int defaddr)
{
int i, calldef = 0;
for (i = 0; cdd[i * 4] == 0x02; i++)
{
if ((cdd[i * 4 + 1] | (cdd[i * 4 + 2] << 8)) == defaddr)
{
calldef = cdd + i * 4 - mem_data;
break;
}
}
return calldef;
}
int extern_lookup(byte *esd, int index)
{
byte *sym;
char string[32];
while (*esd)
{
sym = esd;
esd += dcitos(esd, string);
if ((esd[0] & 0x10) && (esd[1] == index))
return lookup_sym(sym);
esd += 3;
}
printf("\nError: extern index %d not found in ESD.\n", index);
return 0;
}
int load_mod(byte *mod)
{
int len, size, end, magic, bytecode, fixup, addr, modaddr = mark_heap();
byte *moddep, *rld, *esd, *cdd, *sym;
byte header[128];
char filename[32], string[17];
dcitos(mod, filename);
printf("Load module %s\n");
int fd = open(filename, O_RDONLY, 0);
if ((fd > 0) && (len = read(fd, header, 128)) > 0)
{
magic = header[2] | (header[3] << 8);
if (magic == 0xDA7E)
{
/*
* This is a relocatable bytecode module.
*/
bytecode = header[4] | (header[5] << 8);
moddep = header + 6;
if (*moddep)
{
/*
* Load module dependencies.
*/
close(fd);
while (*moddep)
{
if (lookup_mod(moddep) == 0)
load_mod(moddep);
moddep += dcitos(moddep, string);
}
modaddr = mark_heap();
fd = open(filename, O_RDONLY, 0);
len = read(fd, mem_data + modaddr, 128);
}
else
memcpy(mem_data + modaddr, header, len);
}
addr = modaddr + len;
while ((len = read(fd, mem_data + addr, 4096)) > 0)
addr += len;
close(fd);
size = addr - modaddr;
len = mem_data[modaddr + 0] | (mem_data[modaddr + 1] << 8);
end = modaddr + len;
rld = mem_data + modaddr + len; // Re-Locatable Directory
esd = rld; // Extern+Entry Symbol Directory
bytecode += modaddr - MOD_ADDR;
while (*esd != 0x00) // Scan to end of RLD
esd += 4;
esd++;
cdd = rld;
if (show_state)
{
/*
* Dump different parts of module.
*/
printf("Module size: %d\n", size);
printf("Module code+data size: %d\n", len);
printf("Module magic: $%04X\n", magic);
printf("Module bytecode: $%04X\n", bytecode);
}
/*
* Print out the Re-Location Dictionary.
*/
if (show_state)
printf("\nRe-Location Dictionary:\n");
while (*rld)
{
if (rld[0] == 0x02)
{
if (show_state) printf("\tDEF CODE");
addr = rld[1] | (rld[2] << 8);
addr += modaddr - MOD_ADDR;
rld[1] = addr;
rld[2] = addr >> 8;
// end = rld - mem_data + 4;
}
else
{
addr = rld[1] | (rld[2] << 8);
addr += modaddr - MOD_ADDR;
if (rld[0] & 0x80)
fixup = mem_data[addr] | (mem_data[addr + 1] << 8);
else
fixup = mem_data[addr];
if (rld[0] & 0x10)
{
if (show_state) printf("\tEXTERN[$%02X] ", rld[3]);
fixup += extern_lookup(esd, rld[3]);
}
else
{
if (show_state) printf("\tINTERN ");
fixup += modaddr - MOD_ADDR;
if (fixup >= bytecode)
/*
* Replace with call def dictionary.
*/
fixup = def_lookup(cdd, fixup);
}
if (rld[0] & 0x80)
{
if (show_state) printf("WORD");
mem_data[addr] = fixup;
mem_data[addr + 1] = fixup >> 8;
}
else
{
if (show_state) printf("BYTE");
mem_data[addr] = fixup;
}
}
if (show_state) printf("@$%04X\n", addr);
rld += 4;
}
if (show_state) printf("\nExternal/Entry Symbol Directory:\n");
while (*esd)
{
sym = esd;
esd += dcitos(esd, string);
if (esd[0] & 0x10)
{
if (show_state) printf("\tIMPORT %s[$%02X]\n", string, esd[1]);
}
else if (esd[0] & 0x08)
{
addr = esd[1] | (esd[2] << 8);
addr += modaddr - MOD_ADDR;
if (show_state) printf("\tEXPORT %s@$%04X\n", string, addr);
if (addr >= bytecode)
addr = def_lookup(cdd, addr);
add_sym(sym, addr);
}
esd += 3;
}
}
else
{
printf("Error: Unable to load module %s\n", filename);
exit (1);
}
/*
* Reserve heap space for relocated module.
*/
alloc_heap(end - modaddr);
return (fd > 0);
}
void interp(code *ip);
void call(word pc)
{
int i, s;
char sz[64];
switch (mem_data[pc++])
{
case 0: // NULL call
printf("NULL call code\n");
break;
case 1: // BYTECODE in mem_code
interp(mem_code + (mem_data[pc] + (mem_data[pc + 1] << 8)));
break;
case 2: // BYTECODE in mem_data
interp(mem_data + (mem_data[pc] + (mem_data[pc + 1] << 8)));
break;
case 3: // LIBRARY STDLIB::VIEWPORT
printf("Set Window %d, %d, %d, %n/n", POP, POP, POP, POP);
PUSH(0);
break;
case 4: // LIBRARY STDLIB::PUTC
putchar(POP);
PUSH(0);
break;
case 5: // LIBRARY STDLIB::PUTS
s = POP;
i = mem_data[s++];
PUSH(i);
while (i--)
putchar(mem_data[s++]);
break;
case 6: // LIBRARY STDLIB::PUTSZ
s = POP;
while (i = mem_data[s++])
{
if (i == '\r')
i = '\n';
putchar(i);
}
PUSH(0);
break;
case 7: // LIBRARY STDLIB::GETC
PUSH(getchar());
break;
case 8: // LIBRARY STDLIB::GETS
gets(sz);
i = 0;
while (sz[i])
mem_data[0x200 + i++] = sz[i];
mem_data[0x200 + i] = 0;
mem_data[0x1FF] = i;
PUSH(i);
break;
case 9: // LIBRARY STDLIB::CLS
puts("\033[2J");
fflush(stdout);
PUSH(0);
PUSH(0);
case 10: // LIBRARY STDLIB::GOTOXY
s = POP + 1;
i = POP + 1;
printf("\033[%d;%df", s, i);
fflush(stdout);
PUSH(0);
break;
default:
printf("Bad call code\n");
}
}
/*
* OPCODE TABLE
*
OPTBL: DW ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E
DW NEG,COMP,AND,IOR,XOR,SHL,SHR,IDXW ; 10 12 14 16 18 1A 1C 1E
DW NOT,LOR,LAND,LA,LLA,CB,CW,SWAP ; 20 22 24 26 28 2A 2C 2E
DW DROP,DUP,PUSH,PULL,BRGT,BRLT,BREQ,BRNE ; 30 32 34 36 38 3A 3C 3E
DW ISEQ,ISNE,ISGT,ISLT,ISGE,ISLE,BRFLS,BRTRU ; 40 42 44 46 48 4A 4C 4E
DW BRNCH,IBRNCH,CALL,ICAL,ENTER,LEAVE,RET,??? ; 50 52 54 56 58 5A 5C 5E
DW LB,LW,LLB,LLW,LAB,LAW,DLB,DLW ; 60 62 64 66 68 6A 6C 6E
DW SB,SW,SLB,SLW,SAB,SAW,DAB,DAW ; 70 72 74 76 78 7A 7C 7E
*/
void interp(code *ip)
{
word val, ea, frmsz, parmcnt;
while (1)
{
if (show_state)
{
word *dsp = &eval_stack[EVAL_STACKSZ - 1];
printf("$%04X: $%02X [ ", ip - mem_data, *ip);
while (dsp >= esp)
printf("$%04X ", (*dsp--) & 0xFFFF);
printf("]\n");
}
switch (*ip++)
{
/*
* 0x00-0x0F
*/
case 0x00: // ZERO : TOS = 0
PUSH(0);
break;
case 0x02: // ADD : TOS = TOS + TOS-1
val = POP;
ea = POP;
PUSH(ea + val);
break;
case 0x04: // SUB : TOS = TOS-1 - TOS
val = POP;
ea = POP;
PUSH(ea - val);
break;
case 0x06: // MUL : TOS = TOS * TOS-1
val = POP;
ea = POP;
PUSH(ea * val);
break;
case 0x08: // DIV : TOS = TOS-1 / TOS
val = POP;
ea = POP;
PUSH(ea / val);
break;
case 0x0A: // MOD : TOS = TOS-1 % TOS
val = POP;
ea = POP;
PUSH(ea % val);
break;
case 0x0C: // INCR : TOS = TOS + 1
TOS++;
break;
case 0x0E: // DECR : TOS = TOS - 1
TOS--;
break;
/*
* 0x10-0x1F
*/
case 0x10: // NEG : TOS = -TOS
TOS = -TOS;
break;
case 0x12: // COMP : TOS = ~TOS
TOS = ~TOS;
break;
case 0x14: // AND : TOS = TOS & TOS-1
val = POP;
ea = POP;
PUSH(ea & val);
break;
case 0x16: // IOR : TOS = TOS ! TOS-1
val = POP;
ea = POP;
PUSH(ea | val);
break;
case 0x18: // XOR : TOS = TOS ^ TOS-1
val = POP;
ea = POP;
PUSH(ea ^ val);
break;
case 0x1A: // SHL : TOS = TOS-1 << TOS
val = POP;
ea = POP;
PUSH(ea << val);
break;
case 0x1C: // SHR : TOS = TOS-1 >> TOS
val = POP;
ea = POP;
PUSH(ea >> val);
break;
case 0x1E: // IDXW : TOS = TOS * 2
TOS *= 2;
break;
/*
* 0x20-0x2F
*/
case 0x20: // NOT : TOS = !TOS
TOS = !TOS;
break;
case 0x22: // LOR : TOS = TOS || TOS-1
val = POP;
ea = POP;
PUSH(ea || val);
break;
case 0x24: // LAND : TOS = TOS && TOS-1
val = POP;
ea = POP;
PUSH(ea && val);
break;
case 0x26: // LA : TOS = @VAR ; equivalent to CW ADDRESSOF(VAR)
PUSH(WORD_PTR(ip));
break;
case 0x28: // LLA : TOS = @LOCALVAR ; equivalent to CW FRAMEPTR+OFFSET(LOCALVAR)
PUSH(fp + BYTE_PTR(ip));
break;
case 0x2A: // CB : TOS = CONSTANTBYTE (IP)
PUSH(BYTE_PTR(ip));
break;
case 0x2C: // CW : TOS = CONSTANTWORD (IP)
PUSH(WORD_PTR(ip));
break;
case 0x2E: // SWAP : TOS = TOS-1, TOS-1 = TOS
val = POP;
ea = POP;
PUSH(val);
PUSH(ea);
break;
/*
* 0x30-0x3F
*/
case 0x30: // DROP : TOS =
esp++;;
break;
case 0x32: // DUP : TOS = TOS
val = TOS;
PUSH(val);
break;
case 0x34: // PUSH : TOSP = TOS
val = POP;
mem_data[sp--] = val >> 8;
mem_data[sp--] = val;
break;
case 0x36: // PULL : TOS = TOSP
PUSH(mem_data[++sp] | (mem_data[++sp] << 8));
break;
case 0x38: // BRGT : TOS-1 > TOS ? IP += (IP)
val = POP;
ea = POP;
if (ea <= val)
ip += WORD_PTR(ip) - 2;
else
ip += 2;
break;
case 0x3A: // BRLT : TOS-1 < TOS ? IP += (IP)
val = POP;
ea = TOS;
if (ea >= val)
ip += WORD_PTR(ip) - 2;
else
ip += 2;
break;
case 0x3C: // BREQ : TOS == TOS-1 ? IP += (IP)
val = POP;
ea = TOS;
if (ea == val)
ip += WORD_PTR(ip) - 2;
else
ip += 2;
break;
case 0x3E: // BRNE : TOS != TOS-1 ? IP += (IP)
val = POP;
ea = TOS;
if (ea != val)
ip += WORD_PTR(ip) - 2;
else
ip += 2;
break;
/*
* 0x40-0x4F
*/
case 0x40: // ISEQ : TOS = TOS == TOS-1
val = POP;
ea = POP;
PUSH(ea == val);
break;
case 0x42: // ISNE : TOS = TOS != TOS-1
val = POP;
ea = POP;
PUSH(ea != val);
break;
case 0x44: // ISGT : TOS = TOS-1 > TOS
val = POP;
ea = POP;
PUSH(ea <= val);
break;
case 0x46: // ISLT : TOS = TOS-1 < TOS
val = POP;
ea = POP;
PUSH(ea >= val);
break;
case 0x48: // ISGE : TOS = TOS-1 >= TOS
val = POP;
ea = POP;
PUSH(ea < val);
break;
case 0x4A: // ISLE : TOS = TOS-1 <= TOS
val = POP;
ea = POP;
PUSH(ea > val);
break;
case 0x4C: // BRFLS : !TOS ? IP += (IP)
if (!POP)
ip += WORD_PTR(ip) - 2;
else
ip += 2;
break;
case 0x4E: // BRTRU : TOS ? IP += (IP)
if (POP)
ip += WORD_PTR(ip) - 2;
else
ip += 2;
break;
/*
* 0x50-0x5F
*/
case 0x50: // BRNCH : IP += (IP)
ip += WORD_PTR(ip) - 2;
break;
case 0x52: // IBRNCH : IP += TOS
ip += POP;
break;
case 0x54: // CALL : TOFP = IP, IP = (IP) ; call
call(UWORD_PTR(ip));
break;
case 0x56: // ICALL : TOFP = IP, IP = (TOS) ; indirect call
val = POP;
ea = mem_data[val] | (mem_data[val + 1] << 8);
call(ea);
break;
case 0x58: // ENTER : NEW FRAME, FOREACH PARAM LOCALVAR = TOS
frmsz = BYTE_PTR(ip);
mem_data[fp - frmsz] = fp;
mem_data[fp - frmsz + 1] = fp >> 8;
fp -= frmsz;
parmcnt = BYTE_PTR(ip);
while (parmcnt--)
{
val = POP;
mem_data[fp + parmcnt + 2] = val;
mem_data[fp + parmcnt + 3] = val >> 8;
}
break;
case 0x5A: // LEAVE : DEL FRAME, IP = TOFP
fp = mem_data[fp] | (mem_data[fp + 1] << 8);
case 0x5C: // RET : IP = TOFP
return;
case 0x5E: // ???
break;
/*
* 0x60-0x6F
*/
case 0x60: // LB : TOS = BYTE (TOS)
val = UPOP;
PUSH(mem_data[val]);
break;
case 0x62: // LW : TOS = WORD (TOS)
ea = POP;
PUSH(mem_data[ea] | (mem_data[ea + 1] << 8));
break;
case 0x64: // LLB : TOS = LOCALBYTE [IP]
PUSH(mem_data[fp + BYTE_PTR(ip)]);
break;
case 0x66: // LLW : TOS = LOCALWORD [IP]
ea = fp + BYTE_PTR(ip);
PUSH(mem_data[ea] | (mem_data[ea + 1] << 8));
break;
case 0x68: // LAB : TOS = BYTE (IP)
PUSH(mem_data[UWORD_PTR(ip)]);
break;
case 0x6A: // LAW : TOS = WORD (IP)
ea = UWORD_PTR(ip);
PUSH(mem_data[ea] | (mem_data[ea + 1] << 8));
break;
case 0x6C: // DLB : TOS = TOS, LOCALBYTE [IP] = TOS
mem_data[fp + BYTE_PTR(ip)] = TOS;
break;
case 0x6E: // DLW : TOS = TOS, LOCALWORD [IP] = TOS
ea = fp + BYTE_PTR(ip);
mem_data[ea] = TOS;
mem_data[ea + 1] = TOS >> 8;
break;
/*
* 0x70-0x7F
*/
case 0x70: // SB : BYTE (TOS) = TOS-1
val = POP;
ea = POP;
mem_data[ea] = val;
break;
case 0x72: // SW : WORD (TOS) = TOS-1
val = POP;
ea = POP;
mem_data[ea] = val;
mem_data[ea + 1] = val >> 8;
break;
case 0x74: // SLB : LOCALBYTE [TOS] = TOS-1
mem_data[fp + BYTE_PTR(ip)] = POP;
break;
case 0x76: // SLW : LOCALWORD [TOS] = TOS-1
ea = fp + BYTE_PTR(ip);
val = POP;
mem_data[ea] = val;
mem_data[ea + 1] = val >> 8;
break;
case 0x78: // SAB : BYTE (IP) = TOS
mem_data[WORD_PTR(ip)] = POP;
break;
case 0x7A: // SAW : WORD (IP) = TOS
ea = WORD_PTR(ip);
val = POP;
mem_data[ea] = val;
mem_data[ea + 1] = val >> 8;
break;
case 0x7C: // DAB : TOS = TOS, BYTE (IP) = TOS
mem_data[WORD_PTR(ip)] = TOS;
break;
case 0x7E: // DAW : TOS = TOS, WORD (IP) = TOS
ea = WORD_PTR(ip);
mem_data[ea] = TOS;
mem_data[ea + 1] = TOS >> 8;
break;
/*
* Odd codes and everything else are errors.
*/
default:
fprintf(stderr, "Illegal opcode 0x%02X @ 0x%04X\n", ip[-1], ip - mem_code);
}
}
}
char *stdlib_exp[] = {
"VIEWPORT",
"PUTC",
"PUTS",
"PUTSZ",
"GETC",
"GETS",
"CLS",
"GOTOXY"
};
byte stdlib[] = {
0x00
};
int main(int argc, char **argv)
{
byte dci[32];
int i;
if (--argc)
{
argv++;
if ((*argv)[0] == '-' && (*argv)[1] == 's')
{
show_state = 1;
argc--;
argv++;
}
/*
* Add default library.
*/
stodci("STDLIB", dci);
add_mod(dci, 0xFFFF);
for (i = 0; i < 8; i++)
{
mem_data[i] = i + 3;
stodci(stdlib_exp[i], dci);
add_sym(dci, i);
}
if (argc)
{
stodci(*argv, dci);
load_mod(dci);
if (show_state) dump_sym();
argc--;
argv++;
}
if (argc)
{
stodci(*argv, dci);
call(lookup_sym(dci));
}
}
return 0;
}

1612
plasma3/plvm02.s Executable file

File diff suppressed because it is too large Load Diff

147
plasma3/samplib.s Executable file
View File

@ -0,0 +1,147 @@
;
; Sample PLASMA library.
;
!TO "samplib.bin", PLAIN
* = $1000
;
; DATA/CODE SEGMENT
;
_SEGBEGIN
!WORD _SEGEND-_SEGBEGIN ; LENGTH OF HEADER + CODE/DATA + BYTECODE SEGMENT
;
; MODULE HEADER
;
!WORD $DA7E ; MAGIC #
!WORD _SUBSEG ; BYTECODE SUB-SEGMENT
;
; MODULE DEPENDENCY LIST
; NOTE: DCI = PSUEDO OP FOR ASCII STRING WITH HI BIT SET EXCEPT LAST CHAR
;
;DCI "STDLIB"
!CT "hi.ascii"
!TX "STDLI"
!CT RAW
!TX 'B'
;DCI "FILEIO"
!CT "hi.ascii"
!TX "FILEI"
!CT RAW
!TX 'O'
!BYTE 0
;
; NATIVE CODE + GLOBAL DATA
;
COUNT !WORD 0
INCCNT
FIXUP1 INC COUNT
BNE XINIT
FIXUP2 INC COUNT+1
XINIT RTS
;
; BYTECODE SUB-SEGMENT
;
_SUBSEG
MYFUNC !BYTE $58, $01, $16 ; ENTER 1,16
!BYTE $66, $02 ; LLW 2
!BYTE $2A, $01 ; CB 1
!BYTE $54 ; CALL EXTERN(1) "OPEN"
FIXUP4 !WORD $0000
!BYTE $6E, $04 ; DLW 4
!BYTE $54 ; CALL EXTERN(3) "READ"
FIXUP5 !WORD $0000
!BYTE $30 ; DROP
!BYTE $66, $04 ; LLW 4
!BYTE $54 ; CALL EXTERN(2) ; "CLOSE"
FIXUP6 !WORD $0000
!BYTE $30 ; DROP
!BYTE $6A ; LAW COUNT
FIXUP7 !WORD $0000
!BYTE $54 ; CALL INCNT
FIXUP8 !WORD $0000
!BYTE $5A ; LEAVE
;
; END OF CODE/DATA + BYTECODE SEGMENT
;
_SEGEND
;
; BYTCODE FUNCTION DICTIONARY
;
!BYTE $A1 ; FIXUP FLAGS
!WORD MYFUNC ; FIXUP OFFSET
!BYTE $00 ; FIXUP LO BYTE (OF HI BYTE)/IMPORT INDEX
;
; RE-LOCATION DICTIONARY (FIXUP TABLE)
;
!BYTE $81 ; FIXUP FLAGS
!WORD FIXUP1+1 ; FIXUP OFFSET
!BYTE $00 ; FIXUP LO BYTE (OF HI BYTE)/IMPORT INDEX
!BYTE $81
!WORD FIXUP2+1
!BYTE $00
!BYTE $91 ; IMPORT FIXUP
!WORD FIXUP4
!BYTE $01 ; IMPORT INDEX 1
!BYTE $91
!WORD FIXUP5
!BYTE $03
!BYTE $91
!WORD FIXUP6
!BYTE $02
!BYTE $81
!WORD FIXUP7
!BYTE $00
!BYTE $81
!WORD FIXUP8
!BYTE $00
!BYTE 0 ; END OF RLD
;
; EXTERNAL/ENTRY SYMBOL DIRECTORY
;;
; IMPORT TABLE
;
IMPTBL ;DCI "OPEN" ; EXTERNAL SYMBOL NAME
!CT "hi.ascii"
!TX "OPE"
!CT RAW
!TX 'N'
!BYTE $10 ; EXTERNAL SYMBOL FLAG
!WORD 1 ; SYMBOL INDEX
;DCI "CLOSE"
!CT "hi.ascii"
!TX "CLOS"
!CT RAW
!TX 'E'
!BYTE $10
!WORD 2
;DCI "READ"
!CT "hi.ascii"
!TX "REA"
!CT RAW
!TX 'D'
!BYTE $10
!WORD 3
;DCI "MEMSET"
!CT "hi.ascii"
!TX "MEMSE"
!CT RAW
!TX 'T'
!BYTE $10
!WORD 4
;
; EXPORT TABLE
;
EXPTBL ;DCI "INCNT" ; ENTRY SYMBOL NAME
!CT "hi.ascii"
!TX "INCN"
!CT RAW
!TX 'T'
!BYTE $08 ; ENTRY SYMBOL FLAG
!WORD INCCNT ; OFFSET
;DCI "MYFUNC"
!CT "hi.ascii"
!TX "MYFUN"
!CT RAW
!TX 'C'
!BYTE $08
!WORD MYFUNC
!BYTE 0 ; END OF ESD

39
plasma3/symbols.h Executable file
View File

@ -0,0 +1,39 @@
/*
* Symbol table types.
*/
#define GLOBAL_TYPE (0)
#define CONST_TYPE (1 << 0)
#define WORD_TYPE (1 << 1)
#define BYTE_TYPE (1 << 2)
#define VAR_TYPE (WORD_TYPE | BYTE_TYPE)
#define ASM_TYPE (1 << 3)
#define DEF_TYPE (1 << 4)
#define BRANCH_TYPE (1 << 5)
#define FUNC_TYPE (ASM_TYPE | DEF_TYPE)
#define LOCAL_TYPE (1 << 6)
#define EXTERN_TYPE (1 << 7)
#define ADDR_TYPE (VAR_TYPE | FUNC_TYPE | EXTERN_TYPE)
#define WPTR_TYPE (1 << 8)
#define BPTR_TYPE (1 << 9)
#define PTR_TYPE (BPTR_TYPE | WPTR_TYPE)
#define STRING_TYPE (1 << 10)
#define TAG_TYPE (1 << 11)
#define EXPORT_TYPE (1 << 12)
int id_match(char *name, int len, char *id);
int idlocal_lookup(char *name, int len);
int idglobal_lookup(char *name, int len);
int idconst_lookup(char *name, int len);
int idlocal_add(char *name, int len, int type, int size);
int idglobal_add(char *name, int len, int type, int size);
int id_add(char *name, int len, int type, int size);
int idfunc_set(char *name, int len, int type);
int idfunc_add(char *name, int len, int type, int tag);
int idconst_add(char *name, int len, int value);
int id_tag(char *name, int len);
int id_const(char *name, int len);
int id_type(char *name, int len);
void idglobal_size(int type, int size, int constsize);
int idlocal_size(void);
void idlocal_reset(void);
int tag_new(int type);

39
plasma3/symbols.h~ Executable file
View File

@ -0,0 +1,39 @@
/*
* Symbol table types.
*/
#define GLOBAL_TYPE (0)
#define CONST_TYPE (1 << 0)
#define WORD_TYPE (1 << 1)
#define BYTE_TYPE (1 << 2)
#define VAR_TYPE (WORD_TYPE | BYTE_TYPE)
#define ASM_TYPE (1 << 3)
#define DEF_TYPE (1 << 4)
#define BRANCH_TYPE (1 << 5)
#define FUNC_TYPE (ASM_TYPE | DEF_TYPE)
#define LOCAL_TYPE (1 << 6)
#define EXTERN_TYPE (1 << 7)
#define ADDR_TYPE (VAR_TYPE | FUNC_TYPE | EXTERN_TYPE)
#define WPTR_TYPE (1 << 8)
#define BPTR_TYPE (1 << 9)
#define PTR_TYPE (BPTR_TYPE | WPTR_TYPE)
#define STRING_TYPE (1 << 10)
#define TAG_TYPE (1 << 11)
#define EXPORT_TYPE (1 << 12)
int id_match(char *name, int len, char *id);
int idlocal_lookup(char *name, int len);
int idglobal_lookup(char *name, int len);
int idconst_lookup(char *name, int len);
int idlocal_add(char *name, int len, int type, int size);
int idglobal_add(char *name, int len, int type, int size);
int id_add(char *name, int len, int type, int size);
int idfunc_extern(char *name, int len);
int idfunc_add(char *name, int len, int type, int tag);
int idconst_add(char *name, int len, int value);
int id_tag(char *name, int len);
int id_const(char *name, int len);
int id_type(char *name, int len);
void idglobal_size(int type, int size, int constsize);
int idlocal_size(void);
void idlocal_reset(void);
int tag_new(int type);

177
plasma3/test.a Executable file
View File

@ -0,0 +1,177 @@
; ACME COMPATIBLE OUTPUT
_SEGBEGIN
!WORD _SEGEND-_SEGBEGIN ; LENGTH OF HEADER + CODE/DATA + BYTECODE SEGMENT
!WORD $DA7E ; MAGIC #
!WORD _SUBSEG ; BYTECODE SUB-SEGMENT
; 001: ;
; 002: ; Declare all imported modules and their data/functions.
; 003: ;
; 004: import stdlib
; DCI STRING: STDLIB
!BYTE $D3,$D4,$C4,$CC,$C9,$42
; 005: predef cls, gotoxy, puts, putc
; cls -> X000
; gotoxy -> X001
; puts -> X002
; putc -> X003
; 006: end
; 007: ;
; 008: ; Predeclare and functions called before defined.
; 009: ;
; 010: predef main
!BYTE $00 ; END OF MODULE DEPENDENCIES
; 011: ;
; 012: ; Declare all global variables for this module.
; 013: ;
; 014: byte hello[] = "Hello, world.\n\n"
_D005 ; hello[] = "Hello, world.\n\n"
!BYTE $0F
!BYTE $48,$65,$6C,$6C,$6F,$2C,$20,$77
!BYTE $6F,$72,$6C,$64,$2E,$0A,$0A
; 015: word defptr = main
_D006 ; defptr = main
_F000 !WORD _C000
; 016: ;
; 017: ; Define functions.
; 018: ;
; 019:
; 020: export def ascii
_SUBSEG ; BYTECODE STARTS
_C001 ; ascii()
; 021: byte i
; i -> [2]
; 022: cls()
!BYTE $58,$03,$00 ; ENTER 3,0
!BYTE $54 ; CALL _X000
_F001 !WORD 0
!BYTE $30 ; DROP
; 023: for i = 32 to 127
!BYTE $2A,$20 ; CB 32
_B001
!BYTE $6C,$02 ; DLB [2]
!BYTE $2A,$7F ; CB 127
!BYTE $3A ; BRGT _B000
!WORD _B000-*
!BYTE $0C ; INCR
; 024: putc(i)
!BYTE $64,$02 ; LLB [2]
!BYTE $54 ; CALL _X003
_F002 !WORD 0
!BYTE $30 ; DROP
; 025: next
!BYTE $50 ; BRNCH _B001
!WORD _B001-*
_B000
!BYTE $30 ; DROP
; 026: end
!BYTE $00 ; ZERO
!BYTE $5A ; LEAVE
; 027:
; 028: export def main
_C000 ; main()
; 029: cls()
!BYTE $54 ; CALL _X000
_F003 !WORD 0
!BYTE $30 ; DROP
; 030: gotoxy(35,15)
!BYTE $2A,$23 ; CB 35
!BYTE $2A,$0F ; CB 15
!BYTE $54 ; CALL _X001
_F004 !WORD 0
!BYTE $30 ; DROP
; 031: return puts(@hello)
!BYTE $26 ; LA _D005
_F005 !WORD _D005
!BYTE $54 ; CALL _X002
_F006 !WORD 0
!BYTE $5C ; RET
; 032: end
; 033:
; 034: export def indirect
_C002 ; indirect()
; 035: word mainptr
; mainptr -> [2]
; 036: mainptr = @main
!BYTE $58,$04,$00 ; ENTER 4,0
!BYTE $26 ; LA _C000
_F007 !WORD _C000
!BYTE $76,$02 ; SLW [2]
; 037: mainptr()
!BYTE $28,$02 ; LLA [2]
!BYTE $56 ; ICAL
!BYTE $30 ; DROP
; 038: end
!BYTE $00 ; ZERO
!BYTE $5A ; LEAVE
; 039:
; 040: done
_SEGEND
;
; RE-LOCATEABLE DICTIONARY
;
!BYTE $02 ; CODE TABLE FIXUP
!WORD _C000
!BYTE $00
!BYTE $02 ; CODE TABLE FIXUP
!WORD _C001
!BYTE $00
!BYTE $02 ; CODE TABLE FIXUP
!WORD _C002
!BYTE $00
!BYTE $81 ; INTERNAL FIXUP
!WORD _F000
!BYTE $00
!BYTE $91 ; EXTERNAL FIXUP
!WORD _F001
!BYTE 0 ; ESD INDEX
!BYTE $91 ; EXTERNAL FIXUP
!WORD _F002
!BYTE 3 ; ESD INDEX
!BYTE $91 ; EXTERNAL FIXUP
!WORD _F003
!BYTE 0 ; ESD INDEX
!BYTE $91 ; EXTERNAL FIXUP
!WORD _F004
!BYTE 1 ; ESD INDEX
!BYTE $81 ; INTERNAL FIXUP
!WORD _F005
!BYTE $00
!BYTE $91 ; EXTERNAL FIXUP
!WORD _F006
!BYTE 2 ; ESD INDEX
!BYTE $81 ; INTERNAL FIXUP
!WORD _F007
!BYTE $00
!BYTE $00 ; END OF RLD
;
; EXTERNAL/ENTRY SYMBOL DICTIONARY
;
; DCI STRING: CLS
!BYTE $C3,$CC,$53
!BYTE $10 ; EXTERNAL SYMBOL FLAG
!WORD 0 ; ESD INDEX
; DCI STRING: GOTOXY
!BYTE $C7,$CF,$D4,$CF,$D8,$59
!BYTE $10 ; EXTERNAL SYMBOL FLAG
!WORD 1 ; ESD INDEX
; DCI STRING: PUTS
!BYTE $D0,$D5,$D4,$53
!BYTE $10 ; EXTERNAL SYMBOL FLAG
!WORD 2 ; ESD INDEX
; DCI STRING: PUTC
!BYTE $D0,$D5,$D4,$43
!BYTE $10 ; EXTERNAL SYMBOL FLAG
!WORD 3 ; ESD INDEX
; DCI STRING: MAIN
!BYTE $CD,$C1,$C9,$4E
!BYTE $08 ; ENTRY SYMBOL FLAG
!WORD _C000
; DCI STRING: ASCII
!BYTE $C1,$D3,$C3,$C9,$49
!BYTE $08 ; ENTRY SYMBOL FLAG
!WORD _C001
; DCI STRING: INDIRECT
!BYTE $C9,$CE,$C4,$C9,$D2,$C5,$C3,$54
!BYTE $08 ; ENTRY SYMBOL FLAG
!WORD _C002
!BYTE $00 ; END OF ESD

BIN
plasma3/test.bin Executable file

Binary file not shown.

40
plasma3/test.pla Executable file
View File

@ -0,0 +1,40 @@
;
; Declare all imported modules and their data/functions.
;
import stdlib
predef cls, gotoxy, puts, putc
end
;
; Predeclare and functions called before defined.
;
predef main
;
; Declare all global variables for this module.
;
byte hello[] = "Hello, world.\n\n"
word defptr = main
;
; Define functions.
;
export def ascii
byte i
cls()
for i = 32 to 127
putc(i)
next
end
export def main
cls()
gotoxy(35,15)
return puts(@hello)
end
export def indirect
word mainptr
mainptr = @main
mainptr()
end
done

40
plasma3/test.pla~ Executable file
View File

@ -0,0 +1,40 @@
;
; Declare all imported modules and their data/functions.
;
import stdlib
predef cls, gotoxy, puts, putc
end
;
; Predeclare and functions called before defined.
;
predef main
;
; Declare all global variables for this module.
;
byte hello[] = "Hello, world.\n\n"
word defptr = main
;
; Define functions.
;
export def ascii
byte i
cls()
for i = 32 to 127
putc(i)
next
end
export def main
cls()
gotoxy(35,15)
return puts(@hello)
end
export def indirect
word mainptr
mainptr = main
mainptr()
end
done

106
plasma3/tokens.h Executable file
View File

@ -0,0 +1,106 @@
#define TOKEN(c) (0x80|(c))
#define IS_TOKEN(c) (0x80&(c))
/*
* Identifier and constant tokens.
*/
#define ID_TOKEN TOKEN('V')
#define CHAR_TOKEN TOKEN('Y')
#define INT_TOKEN TOKEN('Z')
#define FLOAT_TOKEN TOKEN('F')
#define STRING_TOKEN TOKEN('S')
/*
* Keyword tokens.
*/
#define CONST_TOKEN TOKEN(1)
#define BYTE_TOKEN TOKEN(2)
#define WORD_TOKEN TOKEN(3)
#define IF_TOKEN TOKEN(4)
#define ELSEIF_TOKEN TOKEN(5)
#define ELSE_TOKEN TOKEN(6)
#define FIN_TOKEN TOKEN(7)
#define END_TOKEN TOKEN(8)
#define WHILE_TOKEN TOKEN(9)
#define LOOP_TOKEN TOKEN(10)
#define CASE_TOKEN TOKEN(11)
#define OF_TOKEN TOKEN(12)
#define DEFAULT_TOKEN TOKEN(13)
#define ENDCASE_TOKEN TOKEN(14)
#define FOR_TOKEN TOKEN(15)
#define TO_TOKEN TOKEN(16)
#define DOWNTO_TOKEN TOKEN(17)
#define STEP_TOKEN TOKEN(18)
#define NEXT_TOKEN TOKEN(19)
#define REPEAT_TOKEN TOKEN(20)
#define UNTIL_TOKEN TOKEN(21)
#define PREDEF_TOKEN TOKEN(22)
#define DEF_TOKEN TOKEN(23)
#define ASM_TOKEN TOKEN(24)
#define IMPORT_TOKEN TOKEN(25)
#define EXPORT_TOKEN TOKEN(26)
#define DONE_TOKEN TOKEN(27)
#define RETURN_TOKEN TOKEN(28)
#define BREAK_TOKEN TOKEN(29)
#define START_TOKEN TOKEN(30)
#define EXIT_TOKEN TOKEN(31)
#define EVAL_TOKEN TOKEN(32)
/*
* Double operand operators.
*/
#define SET_TOKEN TOKEN('=')
#define ADD_TOKEN TOKEN('+')
#define ADD_SELF_TOKEN TOKEN('a')
#define SUB_TOKEN TOKEN('-')
#define SUB_SELF_TOKEN TOKEN('u')
#define MUL_TOKEN TOKEN('*')
#define MUL_SELF_TOKEN TOKEN('m')
#define DIV_TOKEN TOKEN('/')
#define DIV_SELF_TOKEN TOKEN('d')
#define MOD_TOKEN TOKEN('%')
#define OR_TOKEN TOKEN('|')
#define OR_SELF_TOKEN TOKEN('o')
#define EOR_TOKEN TOKEN('^')
#define EOR_SELF_TOKEN TOKEN('x')
#define AND_TOKEN TOKEN('&')
#define AND_SELF_TOKEN TOKEN('n')
#define SHR_TOKEN TOKEN('R')
#define SHR_SELF_TOKEN TOKEN('r')
#define SHL_TOKEN TOKEN('L')
#define SHL_SELF_TOKEN TOKEN('l')
#define GT_TOKEN TOKEN('>')
#define GE_TOKEN TOKEN('H')
#define LT_TOKEN TOKEN('<')
#define LE_TOKEN TOKEN('B')
#define NE_TOKEN TOKEN('U')
#define EQ_TOKEN TOKEN('E')
#define LOGIC_AND_TOKEN TOKEN('N')
#define LOGIC_OR_TOKEN TOKEN('O')
/*
* Single operand operators.
*/
#define NEG_TOKEN TOKEN('-')
#define COMP_TOKEN TOKEN('~')
#define LOGIC_NOT_TOKEN TOKEN('!')
#define INC_TOKEN TOKEN('P')
#define DEC_TOKEN TOKEN('K')
#define BPTR_TOKEN TOKEN('^')
#define WPTR_TOKEN TOKEN('*')
#define POST_INC_TOKEN TOKEN('p')
#define POST_DEC_TOKEN TOKEN('k')
#define OPEN_PAREN_TOKEN TOKEN('(')
#define CLOSE_PAREN_TOKEN TOKEN(')')
#define OPEN_BRACKET_TOKEN TOKEN('[')
#define CLOSE_BRACKET_TOKEN TOKEN(']')
/*
* Misc. tokens.
*/
#define AT_TOKEN TOKEN('@')
#define DOT_TOKEN TOKEN('.')
#define COLON_TOKEN TOKEN(':')
#define POUND_TOKEN TOKEN('#')
#define COMMA_TOKEN TOKEN(',')
#define COMMENT_TOKEN TOKEN(';')
#define EOL_TOKEN TOKEN(0)
#define EOF_TOKEN TOKEN(0x7F)
typedef unsigned char t_token;

52
src/ArrayObj.s Executable file
View File

@ -0,0 +1,52 @@
;*
;* DUMMY CLASS FILE ARRAY OBJCT
;*
.BYTE $CA,$FE,$BA,$BE ; MAGIC
.BYTE $00,$00 ; MINOR 0
.BYTE $00,$31 ; MAJOR 49
;*
;* CONSTANT POOL
;*
.BYTE $00,$05 ; CONST POOL COUNT 5
;* CONST POOL INDEX 1
.BYTE 07 ; CLASS
.BYTE $00,$03 ; #3
;* CONST POOL INDEX 2
.BYTE 07 ; CLASS
.BYTE $00,$04 ; #4
;* CONST POOL INDEX 3
.BYTE $01 ; UTF8
.BYTE $00,$01 ; STRLEN
.BYTE "]"
;* CONST POOL INDEX 4
.BYTE $01 ; UTF8
.BYTE $00,$10 ; STRLEN
.BYTE "java/lang/Object"
;*
;* ACCESS FLAGS
;*
.BYTE $00,$21 ; 0x0021
;*
;* THIS CLASS
;*
.BYTE $00,$01 ; #1
;*
;* SUPER CLASS
;*
.BYTE $00,$02 ; #2
;*
;* INTERFACES
;*
.BYTE $00,$00 ; IFACE COUNT 0
;*
;* FIELDS
;*
.BYTE $00,$00 ; FIELD COUNT 0
;*
;* METHODS
;*
.BYTE $00,$00 ; METHOD COUNT 0
;*
;* GLOBAL ATTRIBUTES
;*
.BYTE $00,$00 ; ATTRIB COUNT 0

396
src/ObjectObj.s Executable file
View File

@ -0,0 +1,396 @@
;*
;* DUMMY JAVA OBJECT CLASSE FOR 6502
;*
;*
;* CLASS FILE Object.class
;*
.BYTE $CA,$FE,$BA,$BE ; MAGIC
.BYTE $00,$00 ; MINOR 0
.BYTE $00,$31 ; MAJOR 49
;*
;* CONSTANT POOL
;*
.BYTE $00,$1A ; CONST POOL COUNT 26
;* CONST POOL INDEX 1
.BYTE $0A ; METHODREF
.BYTE $00,$03 ; CLASS #3
.BYTE $00,$17 ; NAME AND TYPE #23
;* CONST POOL INDEX 2
.BYTE 07 ; CLASS
.BYTE $00,$19 ; #25
;* CONST POOL INDEX 3
.BYTE 07 ; CLASS
.BYTE $00,$00 ; #0
;* CONST POOL INDEX 4
.BYTE $01 ; UTF8
.BYTE $00,$06 ; STRLEN
.BYTE "<init>"
;* CONST POOL INDEX 5
.BYTE $01 ; UTF8
.BYTE $00,$03 ; STRLEN
.BYTE "()V"
;* CONST POOL INDEX 6
.BYTE $01 ; UTF8
.BYTE $00,$04 ; STRLEN
.BYTE "Code"
;* CONST POOL INDEX 7
.BYTE $01 ; UTF8
.BYTE $00,$05 ; STRLEN
.BYTE "clone"
;* CONST POOL INDEX 8
.BYTE $01 ; UTF8
.BYTE $00,$14 ; STRLEN
.BYTE "()Ljava/lang/Object;"
;* CONST POOL INDEX 9
.BYTE $01 ; UTF8
.BYTE $00,$06 ; STRLEN
.BYTE "equals"
;* CONST POOL INDEX 10
.BYTE $01 ; UTF8
.BYTE $00,$15 ; STRLEN
.BYTE "(Ljava/lang/Object;)Z"
;* CONST POOL INDEX 11
.BYTE $01 ; UTF8
.BYTE $00,$08 ; STRLEN
.BYTE "finalize"
;* CONST POOL INDEX 12
.BYTE $01 ; UTF8
.BYTE $00,$08 ; STRLEN
.BYTE "getClass"
;* CONST POOL INDEX 13
.BYTE $01 ; UTF8
.BYTE $00,$13 ; STRLEN
.BYTE "()Ljava/lang/Class;"
;* CONST POOL INDEX 14
.BYTE $01 ; UTF8
.BYTE $00,$08 ; STRLEN
.BYTE "hashCode"
;* CONST POOL INDEX 15
.BYTE $01 ; UTF8
.BYTE $00,$03 ; STRLEN
.BYTE "()I"
;* CONST POOL INDEX 16
.BYTE $01 ; UTF8
.BYTE $00,$06 ; STRLEN
.BYTE "notify"
;* CONST POOL INDEX 17
.BYTE $01 ; UTF8
.BYTE $00,$09 ; STRLEN
.BYTE "notifyAll"
;* CONST POOL INDEX 18
.BYTE $01 ; UTF8
.BYTE $00,$08 ; STRLEN
.BYTE "toString"
;* CONST POOL INDEX 19
.BYTE $01 ; UTF8
.BYTE $00,$14 ; STRLEN
.BYTE "()Ljava/lang/String;"
;* CONST POOL INDEX 20
.BYTE $01 ; UTF8
.BYTE $00,$04 ; STRLEN
.BYTE "wait"
;* CONST POOL INDEX 21
.BYTE $01 ; UTF8
.BYTE $00,$04 ; STRLEN
.BYTE "(J)V"
;* CONST POOL INDEX 22
.BYTE $01 ; UTF8
.BYTE $00,$05 ; STRLEN
.BYTE "(JI)V"
;* CONST POOL INDEX 23
.BYTE $0C ; NAME AND TYPE
.BYTE $00,$04 ; NAME #4
.BYTE $00,$05 ; DESC #5
;* CONST POOL INDEX 24
.BYTE $01 ; UTF8
.BYTE $00,$04 ; STRLEN
.BYTE "6502"
;* CONST POOL INDEX 25
.BYTE $01 ; UTF8
.BYTE $00,$10 ; STRLEN
.BYTE "java/lang/Object"
;*
;* ACCESS FLAGS
;*
.BYTE $00,$21 ; 0x0021
;*
;* THIS CLASS
;*
.BYTE $00,$02 ; #2
;*
;* SUPER CLASS
;*
.BYTE $00,$00 ; #0
;*
;* INTERFACES
;*
.BYTE $00,$00 ; IFACE COUNT 0
;*
;* FIELDS
;*
.BYTE $00,$00 ; FIELD COUNT 0
;*
;* METHODS
;*
.BYTE $00,$0C ; METHOD COUNT 12
;******* METHOD INDEX 0 ********
.BYTE $01,$01 ; ACCESS FLAGS 0x0101
.BYTE $00,$04 ; NAME #4
.BYTE $00,$05 ; DESC #5
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,24 ; NAME #24
.BYTE $00,$00,>(M0A0END-M0A0BGN),<(M0A0END-M0A0BGN)
M0A0BGN:
;* CODE:
.BYTE $00,$01 ; MAX STACK 1
.BYTE $00,$01 ; MAX LOCALS 1
.BYTE $00,$00,>(M0C0END-M0C0BGN),<(M0C0END-M0C0BGN)
M0C0BGN:
RTS
M0C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M0A0END:
;******* METHOD INDEX 1 ********
.BYTE $00,$04 ; ACCESS FLAGS 0x0004
.BYTE $00,$07 ; NAME #7
.BYTE $00,$08 ; DESC #8
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$06 ; NAME #6
.BYTE $00,$00,>(M1A0END-M1A0BGN),<(M1A0END-M1A0BGN)
M1A0BGN:
;* CODE:
.BYTE $00,$01 ; MAX STACK 1
.BYTE $00,$01 ; MAX LOCALS 1
.BYTE $00,$00,>(M1C0END-M1C0BGN),<(M1C0END-M1C0BGN)
M1C0BGN:
.BYTE $01 ; 00000: aconst_null
.BYTE $B0 ; 00001: areturn
M1C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M1A0END:
;******* METHOD INDEX 2 ********
.BYTE $00,$01 ; ACCESS FLAGS 0x0001
.BYTE $00,$09 ; NAME #9
.BYTE $00,$0A ; DESC #10
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$06 ; NAME #6
.BYTE $00,$00,>(M2A0END-M2A0BGN),<(M2A0END-M2A0BGN)
M2A0BGN:
;* CODE:
.BYTE $00,$01 ; MAX STACK 1
.BYTE $00,$02 ; MAX LOCALS 2
.BYTE $00,$00,>(M2C0END-M2C0BGN),<(M2C0END-M2C0BGN)
M2C0BGN:
.BYTE $04 ; 00000: iconst_1
.BYTE $AC ; 00001: ireturn
M2C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M2A0END:
;******* METHOD INDEX 3 - finalize ********
.BYTE $01,$04 ; ACCESS FLAGS 0x0104
.BYTE $00,$0B ; NAME #11
.BYTE $00,$05 ; DESC #5
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,24 ; NAME #24
.BYTE $00,$00,>(M3A0END-M3A0BGN),<(M3A0END-M3A0BGN)
M3A0BGN:
;* CODE:
.BYTE $00,$00 ; MAX STACK 0
.BYTE $00,$01 ; MAX LOCALS 1
.BYTE $00,$00,>(M3C0END-M3C0BGN),<(M3C0END-M3C0BGN)
M3C0BGN:
RTS
M3C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M3A0END:
;******* METHOD INDEX 4 ********
.BYTE $00,$11 ; ACCESS FLAGS 0x0011
.BYTE $00,$0C ; NAME #12
.BYTE $00,$0D ; DESC #13
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$06 ; NAME #6
.BYTE $00,$00,>(M4A0END-M4A0BGN),<(M4A0END-M4A0BGN)
M4A0BGN:
;* CODE:
.BYTE $00,$01 ; MAX STACK 1
.BYTE $00,$01 ; MAX LOCALS 1
.BYTE $00,$00,>(M4C0END-M4C0BGN),<(M4C0END-M4C0BGN)
M4C0BGN:
.BYTE $01 ; 00000: aconst_null
.BYTE $B0 ; 00001: areturn
M4C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M4A0END:
;******* METHOD INDEX 5 ********
.BYTE $00,$01 ; ACCESS FLAGS 0x0001
.BYTE $00,$0E ; NAME #14
.BYTE $00,$0F ; DESC #15
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$06 ; NAME #6
.BYTE $00,$00,>(M5A0END-M5A0BGN),<(M5A0END-M5A0BGN)
M5A0BGN:
;* CODE:
.BYTE $00,$01 ; MAX STACK 1
.BYTE $00,$01 ; MAX LOCALS 1
.BYTE $00,$00,>(M5C0END-M5C0BGN),<(M5C0END-M5C0BGN)
M5C0BGN:
.BYTE $03 ; 00000: iconst_0
.BYTE $AC ; 00001: ireturn
M5C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M5A0END:
;******* METHOD INDEX 6 ********
.BYTE $00,$11 ; ACCESS FLAGS 0x0011
.BYTE $00,$10 ; NAME #16
.BYTE $00,$05 ; DESC #5
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$06 ; NAME #6
.BYTE $00,$00,>(M6A0END-M6A0BGN),<(M6A0END-M6A0BGN)
M6A0BGN:
;* CODE:
.BYTE $00,$00 ; MAX STACK 0
.BYTE $00,$01 ; MAX LOCALS 1
.BYTE $00,$00,>(M6C0END-M6C0BGN),<(M6C0END-M6C0BGN)
M6C0BGN:
.BYTE $B1 ; 00000: return
M6C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M6A0END:
;******* METHOD INDEX 7 ********
.BYTE $00,$11 ; ACCESS FLAGS 0x0011
.BYTE $00,$11 ; NAME #17
.BYTE $00,$05 ; DESC #5
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$06 ; NAME #6
.BYTE $00,$00,>(M7A0END-M7A0BGN),<(M7A0END-M7A0BGN)
M7A0BGN:
;* CODE:
.BYTE $00,$00 ; MAX STACK 0
.BYTE $00,$01 ; MAX LOCALS 1
.BYTE $00,$00,>(M7C0END-M7C0BGN),<(M7C0END-M7C0BGN)
M7C0BGN:
.BYTE $B1 ; 00000: return
M7C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M7A0END:
;******* METHOD INDEX 8 ********
.BYTE $00,$01 ; ACCESS FLAGS 0x0001
.BYTE $00,$12 ; NAME #18
.BYTE $00,$13 ; DESC #19
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$06 ; NAME #6
.BYTE $00,$00,>(M8A0END-M8A0BGN),<(M8A0END-M8A0BGN)
M8A0BGN:
;* CODE:
.BYTE $00,$01 ; MAX STACK 1
.BYTE $00,$01 ; MAX LOCALS 1
.BYTE $00,$00,>(M8C0END-M8C0BGN),<(M8C0END-M8C0BGN)
M8C0BGN:
.BYTE $01 ; 00000: aconst_null
.BYTE $B0 ; 00001: areturn
M8C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M8A0END:
;******* METHOD INDEX 9 ********
.BYTE $00,$11 ; ACCESS FLAGS 0x0011
.BYTE $00,$14 ; NAME #20
.BYTE $00,$05 ; DESC #5
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$06 ; NAME #6
.BYTE $00,$00,>(M9A0END-M9A0BGN),<(M9A0END-M9A0BGN)
M9A0BGN:
;* CODE:
.BYTE $00,$00 ; MAX STACK 0
.BYTE $00,$01 ; MAX LOCALS 1
.BYTE $00,$00,>(M9C0END-M9C0BGN),<(M9C0END-M9C0BGN)
M9C0BGN:
.BYTE $B1 ; 00000: return
M9C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M9A0END:
;******* METHOD INDEX 10 ********
.BYTE $00,$11 ; ACCESS FLAGS 0x0011
.BYTE $00,$14 ; NAME #20
.BYTE $00,$15 ; DESC #21
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$06 ; NAME #6
.BYTE $00,$00,>(M10A0END-M10A0BGN),<(M10A0END-M10A0BGN)
M10A0BGN:
;* CODE:
.BYTE $00,$00 ; MAX STACK 0
.BYTE $00,$03 ; MAX LOCALS 3
.BYTE $00,$00,>(M10C0END-M10C0BGN),<(M10C0END-M10C0BGN)
M10C0BGN:
.BYTE $B1 ; 00000: return
M10C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M10A0END:
;******* METHOD INDEX 11 ********
.BYTE $00,$11 ; ACCESS FLAGS 0x0011
.BYTE $00,$14 ; NAME #20
.BYTE $00,$16 ; DESC #22
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$06 ; NAME #6
.BYTE $00,$00,>(M11A0END-M11A0BGN),<(M11A0END-M11A0BGN)
M11A0BGN:
;* CODE:
.BYTE $00,$00 ; MAX STACK 0
.BYTE $00,$04 ; MAX LOCALS 4
.BYTE $00,$00,>(M11C0END-M11C0BGN),<(M11C0END-M11C0BGN)
M11C0BGN:
.BYTE $B1 ; 00000: return
M11C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M11A0END:
;*
;* GLOBAL ATTRIBUTES
;*
.BYTE $00,$00 ; ATTRIB COUNT 0

1356
src/StringObj.s Executable file

File diff suppressed because it is too large Load Diff

16
src/_Object.java Executable file
View File

@ -0,0 +1,16 @@
public class _Object
{
public _Object(){};
protected Object clone(){return null;};
public boolean equals(Object obj){return true;};
protected void finalize(){};
public final Class _getClass(){return null;};
public int hashCode(){return 0;};
public final void _notify(){};
public final void _notifyAll(){};
public String toString(){return null;};
public final void _wait(){};
public final void _wait(long timeout){};
// public final void _wait(long timeout, int nanos){};
}

53
src/_String.java Executable file
View File

@ -0,0 +1,53 @@
public final class _String
{
private int hStrConst;
public _String(){}
public _String(byte ascii[], int hibyte){}
public _String(byte ascii[], int hibyte, int offset, int count){}
public _String(char value[]){}
public _String(char value[], int offset, int count){}
public _String(String value){}
public _String(StringBuffer buffer){}
public char charAt(int Index){return ' ';}
public int compareTo(String anotherString){return 0;}
public String concat(String str){return null;}
public static String copyValueOf(char data[]){return null;}
public static String copyValueOf(char data[], int offset, int count){return null;}
public boolean endsWith(String suffix){return true;}
public boolean equals(Object anObject){return true;}
public boolean equalsIgnoreCase(String anotherString){return true;}
public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstEnd){}
public void getChars(int srcBegin, int srcEnd, char dst[], int dstEnd){}
public int hashCode(){return 0;}
public int indexOf(int ch){return 0;}
public int indexOf(int ch, int fromIndex){return 0;}
public int indexOf(String str){return 0;}
public int indexOf(String str, int fromIndex){return 0;}
public String intern(){return null;}
public int lastIndexOf(int ch){return 0;}
public int lastIndexOf(int ch, int fromIndex){return 0;}
public int lastIndexOf(String str){return 0;}
public int lastIndexOf(String str, int fromIndex){return 0;}
public int length(){return 0;}
public boolean regionMathces(boolean ignoreCase, int toffset, String other, int ooffset, int len){return true;}
public boolean regionMathces(int toffset, String other, int ooffset, int len){return true;}
public String replace(char oldChar, char newChar){return null;}
public boolean startsWith(String prefix){return true;}
public boolean startWith(String prefix, int toffset){return true;}
public String subString(int beginIndex){return null;}
public String subString(int beginIndex, int endIndex){return null;}
public char[] toCharArray(){return null;}
public String toLowerCase(){return null;}
public String toString(){return null;}
public String toUpperCase(){return null;}
public String trim(){return null;}
public static String valueOf(boolean b){return null;}
public static String valueOf(char c){return null;}
public static String valueOf(char data[]){return null;}
public static String valueOf(char data[], int offset, int count){return null;}
public static String valueOf(float f){return null;}
public static String valueOf(int i){return null;}
public static String valueOf(Object obj){return null;}
}

910
src/apple2/AppleStuff.clasm Executable file
View File

@ -0,0 +1,910 @@
;*
;* CLASS FILE AppleStuff.class
;*
.ORG $1000 ; DUMMY ADDRESS
.BYTE $CA,$FE,$BA,$BE ; MAGIC
.BYTE $00,$00 ; MINOR 0
.BYTE $00,$31 ; MAJOR 49
;*
;* CONSTANT POOL
;*
.BYTE $00,$47 ; CONST POOL COUNT 71
;* CONST POOL INDEX 1
.BYTE $0A ; METHODREF
.BYTE $00,$17 ; CLASS #23
.BYTE $00,$37 ; NAME AND TYPE #55
;* CONST POOL INDEX 2
.BYTE $09 ; FIELDREF
.BYTE $00,$16 ; CLASS #22
.BYTE $00,$38 ; NAME AND TYPE #56
;* CONST POOL INDEX 3
.BYTE $03 ; INT
.BYTE $00,$00,$00,$0C ; 12
;* CONST POOL INDEX 4
.BYTE $0A ; METHODREF
.BYTE $00,$39 ; CLASS #57
.BYTE $00,$3A ; NAME AND TYPE #58
;* CONST POOL INDEX 5
.BYTE $03 ; INT
.BYTE $00,$00,$C0,$51 ; 49233
;* CONST POOL INDEX 6
.BYTE $0A ; METHODREF
.BYTE $00,$39 ; CLASS #57
.BYTE $00,$3B ; NAME AND TYPE #59
;* CONST POOL INDEX 7
.BYTE $03 ; INT
.BYTE $00,$00,$C0,$54 ; 49236
;* CONST POOL INDEX 8
.BYTE $0A ; METHODREF
.BYTE $00,$39 ; CLASS #57
.BYTE $00,$3C ; NAME AND TYPE #60
;* CONST POOL INDEX 9
.BYTE $03 ; INT
.BYTE $00,$00,$FC,$58 ; 64600
;* CONST POOL INDEX 10
.BYTE $03 ; INT
.BYTE $00,$00,$C0,$56 ; 49238
;* CONST POOL INDEX 11
.BYTE $03 ; INT
.BYTE $00,$00,$C0,$53 ; 49235
;* CONST POOL INDEX 12
.BYTE $03 ; INT
.BYTE $00,$00,$C0,$50 ; 49232
;* CONST POOL INDEX 13
.BYTE $03 ; INT
.BYTE $00,$00,$F8,$36 ; 63542
;* CONST POOL INDEX 14
.BYTE $03 ; INT
.BYTE $00,$00,$C0,$52 ; 49234
;* CONST POOL INDEX 15
.BYTE $03 ; INT
.BYTE $00,$00,$F8,$32 ; 63538
;* CONST POOL INDEX 16
.BYTE $03 ; INT
.BYTE $00,$01,$40,$20 ; 81952
;* CONST POOL INDEX 17
.BYTE $03 ; INT
.BYTE $01,$00,$00,$00 ; 16777216
;* CONST POOL INDEX 18
.BYTE $03 ; INT
.BYTE $00,$00,$FF,$FF ; 65535
;* CONST POOL INDEX 19
.BYTE $03 ; INT
.BYTE $00,$00,$C0,$57 ; 49239
;* CONST POOL INDEX 20
.BYTE $03 ; INT
.BYTE $00,$00,$C0,$55 ; 49237
;* CONST POOL INDEX 21
.BYTE $0A ; METHODREF
.BYTE $00,$16 ; CLASS #22
.BYTE $00,$3D ; NAME AND TYPE #61
;* CONST POOL INDEX 22
.BYTE 07 ; CLASS
.BYTE $00,$3E ; #62
;* CONST POOL INDEX 23
.BYTE 07 ; CLASS
.BYTE $00,$3F ; #63
;* CONST POOL INDEX 24
.BYTE $01 ; UTF8
.BYTE $00,$08 ; STRLEN
.BYTE "hrHandle"
;* CONST POOL INDEX 25
.BYTE $01 ; UTF8
.BYTE $00,$01 ; STRLEN
.BYTE "I"
;* CONST POOL INDEX 26
.BYTE $01 ; UTF8
.BYTE $00,$06 ; STRLEN
.BYTE "<init>"
;* CONST POOL INDEX 27
.BYTE $01 ; UTF8
.BYTE $00,$03 ; STRLEN
.BYTE "()V"
;* CONST POOL INDEX 28
.BYTE $01 ; UTF8
.BYTE $00,$04 ; STRLEN
.BYTE "Code"
;* CONST POOL INDEX 29
.BYTE $01 ; UTF8
.BYTE $00,$04 ; STRLEN
.BYTE "text"
;* CONST POOL INDEX 30
.BYTE $01 ; UTF8
.BYTE $00,$0A ; STRLEN
.BYTE "keyPressed"
;* CONST POOL INDEX 31
.BYTE $01 ; UTF8
.BYTE $00,$03 ; STRLEN
.BYTE "()Z"
;* CONST POOL INDEX 32
.BYTE $01 ; UTF8
.BYTE $00,$06 ; STRLEN
.BYTE "getKey"
;* CONST POOL INDEX 33
.BYTE $01 ; UTF8
.BYTE $00,$03 ; STRLEN
.BYTE "()C"
;* CONST POOL INDEX 34
.BYTE $01 ; UTF8
.BYTE $00,$08 ; STRLEN
.BYTE "loResMix"
;* CONST POOL INDEX 35
.BYTE $01 ; UTF8
.BYTE $00,$05 ; STRLEN
.BYTE "loRes"
;* CONST POOL INDEX 36
.BYTE $01 ; UTF8
.BYTE $00,$07 ; STRLEN
.BYTE "lrColor"
;* CONST POOL INDEX 37
.BYTE $01 ; UTF8
.BYTE $00,$04 ; STRLEN
.BYTE "(I)V"
;* CONST POOL INDEX 38
.BYTE $01 ; UTF8
.BYTE $00,$07 ; STRLEN
.BYTE "lrHLine"
;* CONST POOL INDEX 39
.BYTE $01 ; UTF8
.BYTE $00,$07 ; STRLEN
.BYTE "(IIII)V"
;* CONST POOL INDEX 40
.BYTE $01 ; UTF8
.BYTE $00,$06 ; STRLEN
.BYTE "(III)V"
;* CONST POOL INDEX 41
.BYTE $01 ; UTF8
.BYTE $00,$07 ; STRLEN
.BYTE "lrVLine"
;* CONST POOL INDEX 42
.BYTE $01 ; UTF8
.BYTE $00,$06 ; STRLEN
.BYTE "lrPlot"
;* CONST POOL INDEX 43
.BYTE $01 ; UTF8
.BYTE $00,$05 ; STRLEN
.BYTE "(II)V"
;* CONST POOL INDEX 44
.BYTE $01 ; UTF8
.BYTE $00,$05 ; STRLEN
.BYTE "hiRes"
;* CONST POOL INDEX 45
.BYTE $01 ; UTF8
.BYTE $00,$07 ; STRLEN
.BYTE "hrColor"
;* CONST POOL INDEX 46
.BYTE $01 ; UTF8
.BYTE $00,$06 ; STRLEN
.BYTE "hrPlot"
;* CONST POOL INDEX 47
.BYTE $01 ; UTF8
.BYTE $00,$06 ; STRLEN
.BYTE "hrLine"
;* CONST POOL INDEX 48
.BYTE $01 ; UTF8
.BYTE $00,$08 ; STRLEN
.BYTE "hrLineTo"
;* CONST POOL INDEX 49
.BYTE $01 ; UTF8
.BYTE $00,$06 ; STRLEN
.BYTE "paddle"
;* CONST POOL INDEX 50
.BYTE $01 ; UTF8
.BYTE $00,$04 ; STRLEN
.BYTE "(I)I"
;* CONST POOL INDEX 51
.BYTE $01 ; UTF8
.BYTE $00,$06 ; STRLEN
.BYTE "button"
;* CONST POOL INDEX 52
.BYTE $01 ; UTF8
.BYTE $00,$04 ; STRLEN
.BYTE "(I)Z"
;* CONST POOL INDEX 53
.BYTE $01 ; UTF8
.BYTE $00,$04 ; STRLEN
.BYTE "tone"
;* CONST POOL INDEX 54
.BYTE $01 ; UTF8
.BYTE $00,$08 ; STRLEN
.BYTE "<clinit>"
;* CONST POOL INDEX 55
.BYTE $0C ; NAME AND TYPE
.BYTE $00,$1A ; NAME #26
.BYTE $00,$1B ; DESC #27
;* CONST POOL INDEX 56
.BYTE $0C ; NAME AND TYPE
.BYTE $00,$18 ; NAME #24
.BYTE $00,$19 ; DESC #25
;* CONST POOL INDEX 57
.BYTE 07 ; CLASS
.BYTE $00,$40 ; #64
;* CONST POOL INDEX 58
.BYTE $0C ; NAME AND TYPE
.BYTE $00,$41 ; NAME #65
.BYTE $00,$42 ; DESC #66
;* CONST POOL INDEX 59
.BYTE $0C ; NAME AND TYPE
.BYTE $00,$43 ; NAME #67
.BYTE $00,$32 ; DESC #50
;* CONST POOL INDEX 60
.BYTE $0C ; NAME AND TYPE
.BYTE $00,$44 ; NAME #68
.BYTE $00,$45 ; DESC #69
;* CONST POOL INDEX 61
.BYTE $0C ; NAME AND TYPE
.BYTE $00,$35 ; NAME #53
.BYTE $00,$28 ; DESC #40
;* CONST POOL INDEX 62
.BYTE $01 ; UTF8
.BYTE $00,$11 ; STRLEN
.BYTE "apple2/AppleStuff"
;* CONST POOL INDEX 63
.BYTE $01 ; UTF8
.BYTE $00,$10 ; STRLEN
.BYTE "java/lang/Object"
;* CONST POOL INDEX 64
.BYTE $01 ; UTF8
.BYTE $00,$0B ; STRLEN
.BYTE "apple2/vm02"
;* CONST POOL INDEX 65
.BYTE $01 ; UTF8
.BYTE $00,$04 ; STRLEN
.BYTE "call"
;* CONST POOL INDEX 66
.BYTE $01 ; UTF8
.BYTE $00,$05 ; STRLEN
.BYTE "(II)I"
;* CONST POOL INDEX 67
.BYTE $01 ; UTF8
.BYTE $00,$08 ; STRLEN
.BYTE "peekByte"
;* CONST POOL INDEX 68
.BYTE $01 ; UTF8
.BYTE $00,$08 ; STRLEN
.BYTE "pokeByte"
;* CONST POOL INDEX 69
.BYTE $01 ; UTF8
.BYTE $00,$05 ; STRLEN
.BYTE "(IB)V"
;* CONST POOL INDEX 70
.BYTE $01 ; UTF8
.BYTE $00,$04 ; STRLEN
.BYTE "6502"
;*
;* ACCESS FLAGS
;*
.BYTE $00,$21 ; 0x0021
;*
;* THIS CLASS
;*
.BYTE $00,$16 ; #22
;*
;* SUPER CLASS
;*
.BYTE $00,$17 ; #23
;*
;* INTERFACES
;*
.BYTE $00,$00 ; IFACE COUNT 0
;*
;* FIELDS
;*
.BYTE $00,$01 ; FIELD COUNT 1
;******* FIELD INDEX 0 ********
.BYTE $00,$0A ; ACCESS FLAGS 0x000A
.BYTE $00,$18 ; NAME #24
.BYTE $00,$19 ; DESC #25
.BYTE $00,$00 ; ATTRIB COUNT 0
;*
;* METHODS
;*
.BYTE $00,$17 ; METHOD COUNT 23
;******* METHOD INDEX 0 ********
.BYTE $00,$01 ; ACCESS FLAGS 0x0001
.BYTE $00,$1A ; NAME #26
.BYTE $00,$1B ; DESC #27
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$1C ; NAME #28
.BYTE $00,$00,>(M0A0END-M0A0BGN),<(M0A0END-M0A0BGN)
M0A0BGN:
;* CODE:
.BYTE $00,$01 ; MAX STACK 1
.BYTE $00,$01 ; MAX LOCALS 1
.BYTE $00,$00,>(M0C0END-M0C0BGN),<(M0C0END-M0C0BGN)
M0C0BGN:
.BYTE $2A ; 00000: aload_0
.BYTE $B7,$00,$01 ; 00001: invokespecial #1
.BYTE $B1 ; 00004: return
M0C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M0A0END:
;******* METHOD INDEX 1 ********
.BYTE $00,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$1D ; NAME #29
.BYTE $00,$1B ; DESC #27
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$1C ; NAME #28
.BYTE $00,$00,>(M1A0END-M1A0BGN),<(M1A0END-M1A0BGN)
M1A0BGN:
;* CODE:
.BYTE $00,$02 ; MAX STACK 2
.BYTE $00,$00 ; MAX LOCALS 0
.BYTE $00,$00,>(M1C0END-M1C0BGN),<(M1C0END-M1C0BGN)
M1C0BGN:
.BYTE $B2,$00,$02 ; 00000: getstatic #2
.BYTE $99,$00,$10 ; 00003: ifeq +16 (000019)
.BYTE $B2,$00,$02 ; 00006: getstatic #2
.BYTE $12,$03 ; 00009: ldc #3
.BYTE $B8,$00,$04 ; 00011: invokestatic #4
.BYTE $57 ; 00014: pop
.BYTE $03 ; 00015: iconst_0
.BYTE $B3,$00,$02 ; 00016: putstatic #2
.BYTE $12,$05 ; 00019: ldc #5
.BYTE $B8,$00,$06 ; 00021: invokestatic #6
.BYTE $57 ; 00024: pop
.BYTE $12,$07 ; 00025: ldc #7
.BYTE $B8,$00,$06 ; 00027: invokestatic #6
.BYTE $57 ; 00030: pop
.BYTE $10,$22 ; 00031: bipush 34
.BYTE $03 ; 00033: iconst_0
.BYTE $B8,$00,$08 ; 00034: invokestatic #8
.BYTE $03 ; 00037: iconst_0
.BYTE $12,$09 ; 00038: ldc #9
.BYTE $B8,$00,$04 ; 00040: invokestatic #4
.BYTE $57 ; 00043: pop
.BYTE $B1 ; 00044: return
M1C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M1A0END:
;******* METHOD INDEX 2 ********
.BYTE $00,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$1E ; NAME #30
.BYTE $00,$1F ; DESC #31
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$1C ; NAME #28
.BYTE $00,$00,>(M2A0END-M2A0BGN),<(M2A0END-M2A0BGN)
M2A0BGN:
;* CODE:
.BYTE $00,$01 ; MAX STACK 1
.BYTE $00,$00 ; MAX LOCALS 0
.BYTE $00,$00,>(M2C0END-M2C0BGN),<(M2C0END-M2C0BGN)
M2C0BGN:
.BYTE $11,$02,$80 ; 00000: sipush 640
.BYTE $B8,$00,$06 ; 00003: invokestatic #6
.BYTE $9E,$00,$07 ; 00006: ifle +7 (000013)
.BYTE $04 ; 00009: iconst_1
.BYTE $A7,$00,$04 ; 00010: goto +4 (000014)
.BYTE $03 ; 00013: iconst_0
.BYTE $AC ; 00014: ireturn
M2C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M2A0END:
;******* METHOD INDEX 3 ********
.BYTE $00,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$20 ; NAME #32
.BYTE $00,$21 ; DESC #33
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$1C ; NAME #28
.BYTE $00,$00,>(M3A0END-M3A0BGN),<(M3A0END-M3A0BGN)
M3A0BGN:
;* CODE:
.BYTE $00,$02 ; MAX STACK 2
.BYTE $00,$01 ; MAX LOCALS 1
.BYTE $00,$00,>(M3C0END-M3C0BGN),<(M3C0END-M3C0BGN)
M3C0BGN:
.BYTE $03 ; 00000: iconst_0
.BYTE $10,$76 ; 00001: bipush $76
.BYTE $B8,$00,$04 ; 00003: invokestatic #4
.BYTE $3B ; 00006: istore_0
.BYTE $1A ; 00007: iload_0
.BYTE $10,$7F ; 00008: bipush 127
.BYTE $7E ; 00010: iand
.BYTE $92 ; 00011: i2c
.BYTE $AC ; 00012: ireturn
M3C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M3A0END:
;******* METHOD INDEX 4 ********
.BYTE $00,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$22 ; NAME #34
.BYTE $00,$1B ; DESC #27
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$1C ; NAME #28
.BYTE $00,$00,>(M4A0END-M4A0BGN),<(M4A0END-M4A0BGN)
M4A0BGN:
;* CODE:
.BYTE $00,$02 ; MAX STACK 2
.BYTE $00,$00 ; MAX LOCALS 0
.BYTE $00,$00,>(M4C0END-M4C0BGN),<(M4C0END-M4C0BGN)
M4C0BGN:
.BYTE $12,$0A ; 00000: ldc #10
.BYTE $B8,$00,$06 ; 00002: invokestatic #6
.BYTE $57 ; 00005: pop
.BYTE $12,$0B ; 00006: ldc #11
.BYTE $B8,$00,$06 ; 00008: invokestatic #6
.BYTE $57 ; 00011: pop
.BYTE $12,$0C ; 00012: ldc #12
.BYTE $B8,$00,$06 ; 00014: invokestatic #6
.BYTE $57 ; 00017: pop
.BYTE $03 ; 00018: iconst_0
.BYTE $12,$0D ; 00019: ldc #13
.BYTE $B8,$00,$04 ; 00021: invokestatic #4
.BYTE $57 ; 00024: pop
.BYTE $10,$22 ; 00025: bipush 34
.BYTE $10,$14 ; 00027: bipush 20
.BYTE $B8,$00,$08 ; 00029: invokestatic #8
.BYTE $03 ; 00032: iconst_0
.BYTE $12,$09 ; 00033: ldc #9
.BYTE $B8,$00,$04 ; 00035: invokestatic #4
.BYTE $57 ; 00038: pop
.BYTE $B1 ; 00039: return
M4C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M4A0END:
;******* METHOD INDEX 5 ********
.BYTE $00,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$23 ; NAME #35
.BYTE $00,$1B ; DESC #27
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$1C ; NAME #28
.BYTE $00,$00,>(M5A0END-M5A0BGN),<(M5A0END-M5A0BGN)
M5A0BGN:
;* CODE:
.BYTE $00,$02 ; MAX STACK 2
.BYTE $00,$00 ; MAX LOCALS 0
.BYTE $00,$00,>(M5C0END-M5C0BGN),<(M5C0END-M5C0BGN)
M5C0BGN:
.BYTE $12,$0A ; 00000: ldc #10
.BYTE $B8,$00,$06 ; 00002: invokestatic #6
.BYTE $57 ; 00005: pop
.BYTE $12,$0E ; 00006: ldc #14
.BYTE $B8,$00,$06 ; 00008: invokestatic #6
.BYTE $57 ; 00011: pop
.BYTE $12,$0C ; 00012: ldc #12
.BYTE $B8,$00,$06 ; 00014: invokestatic #6
.BYTE $57 ; 00017: pop
.BYTE $03 ; 00018: iconst_0
.BYTE $12,$0F ; 00019: ldc #15
.BYTE $B8,$00,$04 ; 00021: invokestatic #4
.BYTE $57 ; 00024: pop
.BYTE $B1 ; 00025: return
M5C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M5A0END:
;******* METHOD INDEX 6 - lrColor ********
.BYTE $01,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$24 ; NAME #36
.BYTE $00,$25 ; DESC #37
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,70 ; NAME #70
.BYTE $00,$00,>(M6A0END-M6A0BGN),<(M6A0END-M6A0BGN)
M6A0BGN:
;* CODE:
.BYTE $00,$00 ; MAX STACK 0
.BYTE $00,$01 ; MAX LOCALS 1
.BYTE $00,$00,>(M6C0END-M6C0BGN),<(M6C0END-M6C0BGN)
M6C0BGN:
.INCLUDE "apple2/lrColor.s"
M6C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M6A0END:
;******* METHOD INDEX 7 - lrHLine(x1, x2, y, c) ********
.BYTE $01,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$26 ; NAME #38
.BYTE $00,$27 ; DESC #39
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,70 ; NAME #70
.BYTE $00,$00,>(M7A0END-M7A0BGN),<(M7A0END-M7A0BGN)
M7A0BGN:
;* CODE:
.BYTE $00,$00 ; MAX STACK 0
.BYTE $00,$04 ; MAX LOCALS 4
.BYTE $00,$00,>(M7C0END-M7C0BGN),<(M7C0END-M7C0BGN)
M7C0BGN:
.INCLUDE "apple2/lrClrHLine.s"
M7C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M7A0END:
;******* METHOD INDEX 8 - lrHLine(x1, x2, y) ********
.BYTE $01,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$26 ; NAME #38
.BYTE $00,$28 ; DESC #40
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,70 ; NAME #70
.BYTE $00,$00,>(M8A0END-M8A0BGN),<(M8A0END-M8A0BGN)
M8A0BGN:
;* CODE:
.BYTE $00,$00 ; MAX STACK 0
.BYTE $00,$03 ; MAX LOCALS 3
.BYTE $00,$00,>(M8C0END-M8C0BGN),<(M8C0END-M8C0BGN)
M8C0BGN:
.INCLUDE "apple2/lrHLine.s"
M8C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M8A0END:
;******* METHOD INDEX 9 - lrVLine(x, y1, y2, c) ********
.BYTE $01,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$29 ; NAME #41
.BYTE $00,$27 ; DESC #39
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,70 ; NAME #70
.BYTE $00,$00,>(M9A0END-M9A0BGN),<(M9A0END-M9A0BGN)
M9A0BGN:
;* CODE:
.BYTE $00,$00 ; MAX STACK 0
.BYTE $00,$04 ; MAX LOCALS 4
.BYTE $00,$00,>(M9C0END-M9C0BGN),<(M9C0END-M9C0BGN)
M9C0BGN:
.INCLUDE "apple2/lrClrVLine.s"
M9C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M9A0END:
;******* METHOD INDEX 10 - lrVLine(x, y1, y2) ********
.BYTE $01,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$29 ; NAME #41
.BYTE $00,$28 ; DESC #40
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,70 ; NAME #70
.BYTE $00,$00,>(M10A0END-M10A0BGN),<(M10A0END-M10A0BGN)
M10A0BGN:
;* CODE:
.BYTE $00,$00 ; MAX STACK 0
.BYTE $00,$03 ; MAX LOCALS 3
.BYTE $00,$00,>(M10C0END-M10C0BGN),<(M10C0END-M10C0BGN)
M10C0BGN:
.INCLUDE "apple2/lrVLine.s"
M10C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M10A0END:
;******* METHOD INDEX 11 - lrPlot(x, y, c) ********
.BYTE $01,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$2A ; NAME #42
.BYTE $00,$28 ; DESC #40
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,70 ; NAME #70
.BYTE $00,$00,>(M11A0END-M11A0BGN),<(M11A0END-M11A0BGN)
M11A0BGN:
;* CODE:
.BYTE $00,$00 ; MAX STACK 0
.BYTE $00,$03 ; MAX LOCALS 3
.BYTE $00,$00,>(M11C0END-M11C0BGN),<(M11C0END-M11C0BGN)
M11C0BGN:
.INCLUDE "apple2/lrClrPlot.s"
M11C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M11A0END:
;******* METHOD INDEX 12 - lrPlot(x,y) ********
.BYTE $01,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$2A ; NAME #42
.BYTE $00,$2B ; DESC #43
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,70 ; NAME #70
.BYTE $00,$00,>(M12A0END-M12A0BGN),<(M12A0END-M12A0BGN)
M12A0BGN:
;* CODE:
.BYTE $00,$00 ; MAX STACK 0
.BYTE $00,$02 ; MAX LOCALS 2
.BYTE $00,$00,>(M12C0END-M12C0BGN),<(M12C0END-M12C0BGN)
M12C0BGN:
.INCLUDE "apple2/lrPlot.s"
M12C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M12A0END:
;******* METHOD INDEX 13 - hiRes ********
.BYTE $00,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$2C ; NAME #44
.BYTE $00,$1F ; DESC #31
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$1C ; NAME #28
.BYTE $00,$00,>(M13A0END-M13A0BGN),<(M13A0END-M13A0BGN)
M13A0BGN:
;* CODE:
.BYTE $00,$02 ; MAX STACK 2
.BYTE $00,$01 ; MAX LOCALS 1
.BYTE $00,$00,>(M13C0END-M13C0BGN),<(M13C0END-M13C0BGN)
M13C0BGN:
.BYTE $12,$10 ; 00000: ldc #16
.BYTE $10,$0A ; 00002: bipush 10
.BYTE $B8,$00,$04 ; 00004: invokestatic #4
.BYTE $3B ; 00007: istore_0
.BYTE $1A ; 00008: iload_0
.BYTE $12,$11 ; 00009: ldc #17
.BYTE $7E ; 00011: iand
.BYTE $9A,$00,$36 ; 00012: ifne +54 (000066)
.BYTE $1A ; 00015: iload_0
.BYTE $12,$12 ; 00016: ldc #18
.BYTE $7E ; 00018: iand
.BYTE $B3,$00,$02 ; 00019: putstatic #2
.BYTE $12,$0E ; 00022: ldc #14
.BYTE $B8,$00,$06 ; 00024: invokestatic #6
.BYTE $57 ; 00027: pop
.BYTE $12,$13 ; 00028: ldc #19
.BYTE $B8,$00,$06 ; 00030: invokestatic #6
.BYTE $57 ; 00033: pop
.BYTE $12,$14 ; 00034: ldc #20
.BYTE $B8,$00,$06 ; 00036: invokestatic #6
.BYTE $57 ; 00039: pop
.BYTE $12,$0C ; 00040: ldc #12
.BYTE $B8,$00,$06 ; 00042: invokestatic #6
.BYTE $57 ; 00045: pop
.BYTE $11,$40,$00 ; 00046: sipush 16384
.BYTE $10,$40 ; 00049: bipush 64
.BYTE $B8,$00,$04 ; 00051: invokestatic #4
.BYTE $57 ; 00054: pop
.BYTE $11,$20,$00 ; 00055: sipush 8192
.BYTE $10,$44 ; 00058: bipush 68
.BYTE $B8,$00,$04 ; 00060: invokestatic #4
.BYTE $57 ; 00063: pop
.BYTE $04 ; 00064: iconst_1
.BYTE $AC ; 00065: ireturn
.BYTE $10,$64 ; 00066: bipush 100
.BYTE $10,$64 ; 00068: bipush 100
.BYTE $B8,$00,$04 ; 00070: invokestatic #4
.BYTE $3B ; 00073: istore_0
.BYTE $1A ; 00074: iload_0
.BYTE $12,$11 ; 00075: ldc #17
.BYTE $7E ; 00077: iand
.BYTE $99,$FF,$B2 ; 00078: ifeq -78 (000000)
.BYTE $03 ; 00081: iconst_0
.BYTE $AC ; 00082: ireturn
M13C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M13A0END:
;******* METHOD INDEX 14 - hrColor ********
.BYTE $01,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$2D ; NAME #45
.BYTE $00,$25 ; DESC #37
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,70 ; NAME #70
.BYTE $00,$00,>(M14A0END-M14A0BGN),<(M14A0END-M14A0BGN)
M14A0BGN:
;* CODE:
.BYTE $00,$00 ; MAX STACK 0
.BYTE $00,$01 ; MAX LOCALS 1
.BYTE $00,$00,>(M14C0END-M14C0BGN),<(M14C0END-M14C0BGN)
M14C0BGN:
.INCLUDE "apple2/hrColor.s"
M14C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M14A0END:
;******* METHOD INDEX 15 - hrPlot ********
.BYTE $01,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$2E ; NAME #46
.BYTE $00,$2B ; DESC #43
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,70 ; NAME #70
.BYTE $00,$00,>(M15A0END-M15A0BGN),<(M15A0END-M15A0BGN)
M15A0BGN:
;* CODE:
.BYTE $00,$00 ; MAX STACK 0
.BYTE $00,$02 ; MAX LOCALS 2
.BYTE $00,$00,>(M15C0END-M15C0BGN),<(M15C0END-M15C0BGN)
M15C0BGN:
.INCLUDE "apple2/hrPlot.s"
M15C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M15A0END:
;******* METHOD INDEX 16 - hrLine ********
.BYTE $01,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$2F ; NAME #47
.BYTE $00,$27 ; DESC #39
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,70 ; NAME #70
.BYTE $00,$00,>(M16A0END-M16A0BGN),<(M16A0END-M16A0BGN)
M16A0BGN:
;* CODE:
.BYTE $00,$00 ; MAX STACK 0
.BYTE $00,$04 ; MAX LOCALS 4
.BYTE $00,$00,>(M16C0END-M16C0BGN),<(M16C0END-M16C0BGN)
M16C0BGN:
.INCLUDE "apple2/hrLine.s"
M16C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M16A0END:
;******* METHOD INDEX 17 - hrLineTo ********
.BYTE $01,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$30 ; NAME #48
.BYTE $00,$2B ; DESC #43
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,70 ; NAME #70
.BYTE $00,$00,>(M17A0END-M17A0BGN),<(M17A0END-M17A0BGN)
M17A0BGN:
;* CODE:
.BYTE $00,$00 ; MAX STACK 0
.BYTE $00,$02 ; MAX LOCALS 2
.BYTE $00,$00,>(M17C0END-M17C0BGN),<(M17C0END-M17C0BGN)
M17C0BGN:
.INCLUDE "apple2/hrLineTo.s"
M17C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M17A0END:
;******* METHOD INDEX 18 - paddle ********
.BYTE $01,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$31 ; NAME #49
.BYTE $00,$32 ; DESC #50
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,70 ; NAME #70
.BYTE $00,$00,>(M18A0END-M18A0BGN),<(M18A0END-M18A0BGN)
M18A0BGN:
;* CODE:
.BYTE $00,$01 ; MAX STACK 1
.BYTE $00,$01 ; MAX LOCALS 1
.BYTE $00,$00,>(M18C0END-M18C0BGN),<(M18C0END-M18C0BGN)
M18C0BGN:
.INCLUDE "apple2/paddle.s"
M18C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M18A0END:
;******* METHOD INDEX 19 24 - button ********
.BYTE $01,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$33 ; NAME #51
.BYTE $00,$34 ; DESC #52
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,70 ; NAME #70
.BYTE $00,$00,>(M19A0END-M19A0BGN),<(M19A0END-M19A0BGN)
M19A0BGN:
;* CODE:
.BYTE $00,$01 ; MAX STACK 1
.BYTE $00,$01 ; MAX LOCALS 1
.BYTE $00,$00,>(M19C0END-M19C0BGN),<(M19C0END-M19C0BGN)
M19C0BGN:
.INCLUDE "apple2/button.s"
M19C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M19A0END:
;******* METHOD INDEX 20 - tone(II) ********
.BYTE $00,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$35 ; NAME #53
.BYTE $00,$2B ; DESC #43
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$1C ; NAME #28
.BYTE $00,$00,>(M20A0END-M20A0BGN),<(M20A0END-M20A0BGN)
M20A0BGN:
;* CODE:
.BYTE $00,$03 ; MAX STACK 3
.BYTE $00,$02 ; MAX LOCALS 2
.BYTE $00,$00,>(M20C0END-M20C0BGN),<(M20C0END-M20C0BGN)
M20C0BGN:
.BYTE $1A ; 00000: iload_0
.BYTE $1A ; 00001: iload_0
.BYTE $04 ; 00002: iconst_1
.BYTE $7A ; 00003: ishr
.BYTE $1B ; 00004: iload_1
.BYTE $B8,$00,$15 ; 00005: invokestatic #21
.BYTE $B1 ; 00008: return
M20C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M20A0END:
;******* METHOD INDEX 21- tone(III) ********
.BYTE $01,$09 ; ACCESS FLAGS 0x0009
.BYTE $00,$35 ; NAME #53
.BYTE $00,$28 ; DESC #40
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,70 ; NAME #70
.BYTE $00,$00,>(M21A0END-M21A0BGN),<(M21A0END-M21A0BGN)
M21A0BGN:
;* CODE:
.BYTE $00,$00 ; MAX STACK 0
.BYTE $00,$03 ; MAX LOCALS 3
.BYTE $00,$00,>(M21C0END-M21C0BGN),<(M21C0END-M21C0BGN)
M21C0BGN:
.INCLUDE "apple2/tone.s"
M21C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M21A0END:
;******* METHOD INDEX 22 ********
.BYTE $00,$08 ; ACCESS FLAGS 0x0008
.BYTE $00,$36 ; NAME #54
.BYTE $00,$1B ; DESC #27
.BYTE $00,$01 ; ATTRIB COUNT 1
;* ATTRIB INDEX 0
.BYTE $00,$1C ; NAME #28
.BYTE $00,$00,>(M22A0END-M22A0BGN),<(M22A0END-M22A0BGN)
M22A0BGN:
;* CODE:
.BYTE $00,$01 ; MAX STACK 1
.BYTE $00,$00 ; MAX LOCALS 0
.BYTE $00,$00,>(M22C0END-M22C0BGN),<(M22C0END-M22C0BGN)
M22C0BGN:
.BYTE $03 ; 00000: iconst_0
.BYTE $B3,$00,$02 ; 00001: putstatic #2
.BYTE $B1 ; 00004: return
M22C0END:
;* EXCEPTION TABLE
.BYTE $00,$00 ; COUNT 0
;* CODE ATTRIB
.BYTE $00,$00 ; ATTRIB COUNT 0
M22A0END:
;*
;* GLOBAL ATTRIBUTES
;*
.BYTE $00,$00 ; ATTRIB COUNT 0

136
src/apple2/AppleStuff.java Executable file
View File

@ -0,0 +1,136 @@
package apple2;
public class AppleStuff {
private static int hrHandle = 0;
public static void text()
{
if (hrHandle != 0)
{
// Free hires memory
vm02.call(hrHandle, 0x0C);
hrHandle = 0;
}
vm02.peekByte(0xC051);
vm02.peekByte(0xC054);
vm02.pokeByte(0x22, (byte)0);
vm02.call(0, 0xFC58);
}
public static boolean keyPressed()
{
return (vm02.peekByte(0x0280) > 0);
}
public static char getKey()
{
int key = vm02.call(0, 0x76) & 0x7F; // CONSOLE READ
return ((char)key);
}
public static void loResMix()
{
vm02.peekByte(0xC056);
vm02.peekByte(0xC053);
vm02.peekByte(0xC050);
vm02.call(0, 0xF836);
vm02.pokeByte(0x22, (byte)20);
vm02.call(0, 0xFC58);
}
public static void loRes()
{
vm02.peekByte(0xC056);
vm02.peekByte(0xC052);
vm02.peekByte(0xC050);
vm02.call(0, 0xF832);
}
public static void lrColor(int color)
{
//vm02.call(color, 0xF864);
}
public static void lrHLine(int xLeft, int xRight, int y, int color)
{
//vm02.call(color, 0xF864);
//vm02.pokeByte(0x2C, (byte)xRight);
//vm02.call((xLeft << 16) | y, 0xF819);
}
public static void lrHLine(int xLeft, int xRight, int y)
{
//vm02.pokeByte(0x2C, (byte)xRight);
//vm02.call((xLeft << 16) | y, 0xF819);
}
public static void lrVLine(int x, int yTop, int yBottom, int color)
{
//vm02.call(color, 0xF864);
//vm02.pokeByte(0x2D, (byte)yBottom);
//vm02.call((x << 16) | yTop, 0xF828);
}
public static void lrVLine(int x, int yTop, int yBottom)
{
//vm02.pokeByte(0x2D, (byte)yBottom);
//vm02.call((x << 16) | yTop, 0xF828);
}
public static void lrPlot(int x, int y, int color)
{
//vm02.call(color, 0xF864);
//vm02.call((x << 16) | y, 0xF800);
}
public static void lrPlot(int x, int y)
{
//vm02.call((x << 16) | y, 0xF800);
}
public static boolean hiRes()
{
int result;
// Allocate hires page2 memory
do
{
result = vm02.call(0x014020, 0x0A); // HMEM_ALLOC_FIXED
if ((result & 0x01000000) == 0) // CARRY CLEAR == ALLOCED
{
hrHandle = result & 0xFFFF;
vm02.peekByte(0xC052);
vm02.peekByte(0xC057);
vm02.peekByte(0xC055);
vm02.peekByte(0xC050);
vm02.call(0x4000, 0x40); // SETDST
vm02.call(0x2000, 0x44); // MEMCLR
return true;
}
result = vm02.call(100, 0x64); // GC - MAX 100 ITERATIONS
} while ((result & 0x01000000) == 0);
return false;
}
public static void hrColor(int color)
{
//vm02.call(color << 8, 0xF6F0); // HCOLOR
}
public static void hrPlot(int x, int y)
{
//vm02.call((x << 8) | y, 0xF457); // HPLOT
}
public static void hrLine(int x1, int y1, int x2, int y2)
{
//vm02.call((x1 << 8) | y1, 0xF411); // HPOSN
//vm02.call(x2 | (y2 << 16), 0xF53A); // HLINE
}
public static void hrLineTo(int x, int y)
{
//vm02.call(x | (y << 16), 0xF53A); // HLINE
}
public static int paddle(int num)
{
//return ((vm02.call(num << 8, 0xFB1E) >> 16) & 0xFF);
return 0;
}
public static boolean button(int num)
{
//return (vm02.peekByte(0xC061+num) >= 128);
return false;
}
public static void tone(int pitch, int duration)
{
tone(pitch, pitch >> 1, duration);
}
public static void tone(int pitch, int timbre, int duration)
{
}
}

204
src/apple2/Ethernet.java Executable file
View File

@ -0,0 +1,204 @@
package apple2;
/*
* This class interfaces to the ethernet device.
*/
public class Ethernet extends java.net.NetworkDevice
{
static private int ethSlot, ethOutputBuff, ethInputBuff, ethRecvPacket, ethSendPacket, ethHeaderLen, ethPacketDone, ethCtrl, ethWrite, ethRead;
static private byte[] MAC = {(byte)0x00,(byte)0x0a,(byte)0x99,(byte)0x1e,(byte)0x02,(byte)0x00};
static final int MIN_DATA_SIZE = 46;
static final int MAX_DATA_SIZE = 1500;
private static void copyBytes(byte[] src, int srcOfst, byte[] dst, int dstOfst, int count)
{
while (count-- != 0)
dst[dstOfst++] = src[srcOfst++];
}
public static boolean enable()
{
//
// Search for ethernet card.
//
for (int slot = 1; slot < 8; slot++)
{
//
// ID device
//
if (((vm02.call((1 << 19), 0x90 + (slot << 1))) & 0x010000FF) == 0xE1) // CARRY clear == valid device IOCTL, 0xE1 == ethernet card ID
{
ethCtrl = 0x90 + (slot << 1);
ethWrite = 0x80 + (slot << 1);
ethRead = 0x70 + (slot << 1);
ethSlot = slot << 16;
ethInputBuff = ethSlot | ( 7 << 19);
ethOutputBuff = ethSlot | ( 9 << 19);
ethRecvPacket = ethSlot | (16 << 19);
ethSendPacket = ethSlot | (17 << 19);
ethPacketDone = ethSlot | (18 << 19);
ethHeaderLen = ethSlot | 14;
for (int oct = 0; oct < 3; oct++)
vm02.call(ethSlot
| ((19 + oct) << 19)
| ( MAC[oct*2] & 0x00FF)
| ((MAC[oct*2 + 1] << 8) & 0xFF00), ethCtrl); // set MAC address
if ((vm02.call(ethSlot | (3 << 19), ethCtrl) & 0x01000000) == 0) // open port
return true;
}
}
return false;
}
public static void disable()
{
vm02.call(ethSlot | 4, ethCtrl); // close port
}
public static byte[] localAddr()
{
return MAC;
}
public static byte[] broadcastAddr()
{
byte[] addr = new byte[6];
addr[0] = (byte)0xFF;
addr[1] = (byte)0xFF;
addr[2] = (byte)0xFF;
addr[3] = (byte)0xFF;
addr[4] = (byte)0xFF;
addr[5] = (byte)0xFF;
return addr;
}
public static byte[] newAddr()
{
return new byte[6];
}
public static boolean isEqualAddr(byte[] addr1, byte[] addr2)
{
return ((addr1[5] == addr2[5])
&& (addr1[4] == addr2[4])
&& (addr1[3] == addr2[3])
&& (addr1[2] == addr2[2])
&& (addr1[1] == addr2[1])
&& (addr1[0] == addr2[0]));
}
public static void copyAddr(byte[] src, byte[] dst)
{
copyBytes(src, 0, dst, 0, 6);
}
public static byte[] newHeader()
{
return new byte[14];
}
public static void setHeaderSrcAddr(byte[] header, byte[] addr)
{
copyBytes(addr, 0, header, 6, 6);
}
public static void setHeaderDstAddr(byte[] header, byte[] addr)
{
copyBytes(addr, 0, header, 0, 6);
}
public static void copyHeaderSrcAddr(byte[] header, byte[] addr)
{
copyBytes(header, 6, addr, 0, 6);
}
public static void copyHeaderDstAddr(byte[] header, byte[] addr)
{
copyBytes(header, 0, addr, 0, 6);
}
public static byte[] getHeaderSrcAddr(byte[] header)
{
byte[] addr = new byte[6];
copyBytes(header, 6, addr, 0, 6);
return addr;
}
public static byte[] getHeaderDstAddr(byte[] header)
{
byte[] addr = new byte[6];
copyBytes(header, 0, addr, 0, 6);
return addr;
}
public static int getHeaderType(byte[] header)
{
if (header == null || header.length < 14)
{
System.out.println("Bad header in getHeaderType!");
return 0;
}
return ((header[12] << 8) & 0xFF00) | (header[13] & 0x00FF);
}
public static void setHeaderType(byte[] header, int type)
{
header[12] = (byte)(type >> 8);
header[13] = (byte)type;
}
public static boolean sendHeader(byte[] header, int dataSize)
{
boolean success;
int hmem = vm02.refAsBits((Object)header) & 0xFFFF;
vm02.call(ethOutputBuff | (vm02.call(hmem, 0x0E) & 0xFFFF) + 2, ethCtrl); // HMEM_LOCK header IOCTL_OUTBUFF
success = (vm02.call(ethSendPacket | dataSize + 14, ethCtrl) & 0x01000000) == 0;
if (success) // prepare to write packet of length len
vm02.call(ethHeaderLen, ethWrite); // write 14 byte ethernet header
vm02.call(hmem, 0x10); // HMEM_UNLOCK header
return success;
}
public static boolean sendHeader(byte[] dst, int type, int dataSize)
{
byte[] header = new byte[14];
copyBytes(dst, 0, header, 0, 6);
copyBytes(MAC, 0, header, 6, 6);
header[12] = (byte)(type >> 8);
header[13] = (byte)type;
return sendHeader(header, dataSize);
}
public static void sendData(byte[] data, int offset, int size)
{
int hmem = vm02.refAsBits((Object)data) & 0xFFFF;
vm02.call(ethOutputBuff | (vm02.call(hmem, 0x0E) & 0xFFFF) + 2 + offset, ethCtrl); // HMEM_LOCK data IOCTL_OUTBUFF
vm02.call(ethSlot | size, ethWrite); // write data
vm02.call(hmem, 0x10); // HMEM_UNLOCK data
}
public static void sendData(byte[] data)
{
int hmem = vm02.refAsBits((Object)data) & 0xFFFF;
vm02.call(ethOutputBuff | (vm02.call(hmem, 0x0E) & 0xFFFF) + 2, ethCtrl); // HMEM_LOCK data IOCTL_OUTBUFF
vm02.call(ethSlot | data.length, ethWrite); // write data
vm02.call(hmem, 0x10); // HMEM_UNLOCK data
}
public static int recvHeader(byte[] header)
{
int len;
if (header == null || header.length < 14)
{
System.out.println("Bad header in recvHeader!");
return 0;
}
int hmem = vm02.refAsBits((Object)header) & 0xFFFF;
vm02.call(ethInputBuff | (vm02.call(hmem, 0x0E) & 0xFFFF) + 2, ethCtrl); // HMEM_LOCK header IOCTL_INBUFF
if ((len = vm02.call(ethRecvPacket, ethCtrl) & 0xFFFF) >= 14) // ETHRCTRL_RECVPKT
{
vm02.call(ethHeaderLen, ethRead); // read 14 byte ethernet header
vm02.call(hmem, 0x10); // HMEM_UNLOCK header
return len - 14;
}
vm02.call(hmem, 0x10); // HMEM_UNLOCK header
return 0;
}
public static void recvData(byte[] data, int offset, int size)
{
int hmem = vm02.refAsBits((Object)data) & 0xFFFF;
vm02.call(ethInputBuff | (vm02.call(hmem, 0x0E) & 0xFFFF) + 2 + offset, ethCtrl); // HMEM_LOCK data IOCTL_OUTBUFF
vm02.call(ethSlot | size, ethRead); // write data
vm02.call(hmem, 0x10); // HMEM_UNLOCK data
}
public static void recvData(byte[] data)
{
int hmem = vm02.refAsBits((Object)data) & 0xFFFF;
vm02.call(ethInputBuff | (vm02.call(hmem, 0x0E) & 0xFFFF) + 2, ethCtrl); // HMEM_LOCK data IOCTL_OUTBUFF
vm02.call(ethSlot | data.length, ethRead); // write data
vm02.call(hmem, 0x10); // HMEM_UNLOCK data
}
public static void xferComplete()
{
vm02.call(ethPacketDone, ethCtrl); // ETHRCRL_DONEPKT
}
}

Some files were not shown because too many files have changed in this diff Show More