mirror of
https://github.com/dschmenk/VM02.git
synced 2024-11-25 23:49:19 +00:00
Initial import
This commit is contained in:
commit
1066a69950
13
BUILD.TXT
Executable file
13
BUILD.TXT
Executable 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
317
DESIGN.TXT
Executable 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
280
LICENSE.TXT
Executable 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
88
README.TXT
Executable 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
126
plasma2/FIRE.PLA#040000
Executable 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
1
plasma2/autorun#040000
Executable file
@ -0,0 +1 @@
|
||||
PLED READ.ME
|
BIN
plasma2/bytedump
Executable file
BIN
plasma2/bytedump
Executable file
Binary file not shown.
29
plasma2/bytedump.c
Executable file
29
plasma2/bytedump.c
Executable 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
492
plasma2/cmd.pla
Executable 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
1372
plasma2/cmd.s
Executable file
File diff suppressed because it is too large
Load Diff
10
plasma2/cmdloader.cfg
Executable file
10
plasma2/cmdloader.cfg
Executable 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
1098
plasma2/codegen.c
Executable file
File diff suppressed because it is too large
Load Diff
55
plasma2/codegen.h
Executable file
55
plasma2/codegen.h
Executable 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
BIN
plasma2/codegen.o
Executable file
Binary file not shown.
10
plasma2/default.cfg
Executable file
10
plasma2/default.cfg
Executable 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
189
plasma2/dumprel.pla
Executable 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
BIN
plasma2/fire#ff0000
Executable file
Binary file not shown.
269
plasma2/fire.pla
Executable file
269
plasma2/fire.pla
Executable 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
1375
plasma2/fire.s
Executable file
File diff suppressed because it is too large
Load Diff
BIN
plasma2/fire.sys
Executable file
BIN
plasma2/fire.sys
Executable file
Binary file not shown.
1023
plasma2/interp6502.s
Executable file
1023
plasma2/interp6502.s
Executable file
File diff suppressed because it is too large
Load Diff
314
plasma2/lex.c
Executable file
314
plasma2/lex.c
Executable 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
9
plasma2/lex.h
Executable 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
BIN
plasma2/lex.o
Executable file
Binary file not shown.
92
plasma2/loadcmd.s
Executable file
92
plasma2/loadcmd.s
Executable 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
811
plasma2/loadrel.pla
Executable 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
117
plasma2/loadvm.s
Executable 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
127
plasma2/makefile
Executable 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
213
plasma2/makesys.pla
Executable 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
1465
plasma2/parse.c
Executable file
File diff suppressed because it is too large
Load Diff
BIN
plasma2/parse.o
Executable file
BIN
plasma2/parse.o
Executable file
Binary file not shown.
2731
plasma2/plas.pla
Executable file
2731
plasma2/plas.pla
Executable file
File diff suppressed because it is too large
Load Diff
9992
plasma2/plas.s
Executable file
9992
plasma2/plas.s
Executable file
File diff suppressed because it is too large
Load Diff
10
plasma2/plasma2.cfg
Executable file
10
plasma2/plasma2.cfg
Executable 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
2553
plasma2/plasma2.pla
Executable file
File diff suppressed because it is too large
Load Diff
BIN
plasma2/plc
Executable file
BIN
plasma2/plc
Executable file
Binary file not shown.
BIN
plasma2/pled#ff0000
Executable file
BIN
plasma2/pled#ff0000
Executable file
Binary file not shown.
1476
plasma2/pled.pla
Executable file
1476
plasma2/pled.pla
Executable file
File diff suppressed because it is too large
Load Diff
5450
plasma2/pled.s
Executable file
5450
plasma2/pled.s
Executable file
File diff suppressed because it is too large
Load Diff
BIN
plasma2/pled.sys
Executable file
BIN
plasma2/pled.sys
Executable file
Binary file not shown.
2850
plasma2/plex.pla
Executable file
2850
plasma2/plex.pla
Executable file
File diff suppressed because it is too large
Load Diff
11246
plasma2/plex.s
Executable file
11246
plasma2/plex.s
Executable file
File diff suppressed because it is too large
Load Diff
64
plasma2/plib.s
Executable file
64
plasma2/plib.s
Executable 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
10
plasma2/plide.cfg
Executable 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
3845
plasma2/plide.pla
Executable file
File diff suppressed because it is too large
Load Diff
14766
plasma2/plide.s
Executable file
14766
plasma2/plide.s
Executable file
File diff suppressed because it is too large
Load Diff
832
plasma2/plink.pla
Executable file
832
plasma2/plink.pla
Executable 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
1
plasma2/plinky.pla
Executable file
File diff suppressed because one or more lines are too long
333
plasma2/plstub.s
Executable file
333
plasma2/plstub.s
Executable 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
235
plasma2/pong.pla
Executable 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
162
plasma2/radar.pla
Executable 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
267
plasma2/read.me#040000
Executable 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
BIN
plasma2/rod#ff0000
Executable file
Binary file not shown.
182
plasma2/rod.pla
Executable file
182
plasma2/rod.pla
Executable 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
63
plasma2/rod.pla#040000
Executable 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
670
plasma2/rod.s
Executable 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
BIN
plasma2/rod.sys
Executable file
Binary file not shown.
7
plasma2/teststack.pla
Executable file
7
plasma2/teststack.pla
Executable 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
119
plasma2/tokens.h
Executable 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
1612
plasma2/vmcore.s
Executable file
File diff suppressed because it is too large
Load Diff
BIN
plasma3/a.out
Executable file
BIN
plasma3/a.out
Executable file
Binary file not shown.
16
plasma3/acme
Executable file
16
plasma3/acme
Executable 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
775
plasma3/codegen.c
Executable 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
775
plasma3/codegen.c~
Executable 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
58
plasma3/codegen.h
Executable 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
BIN
plasma3/codegen.o
Executable file
Binary file not shown.
182
plasma3/dict.c
Executable file
182
plasma3/dict.c
Executable 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
1
plasma3/hi.ascii
Executable 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
3
plasma3/hi.ascii.a
Executable file
@ -0,0 +1,3 @@
|
||||
!to "hi.ascii", plain
|
||||
*=0
|
||||
!for i, 256 {!byte i-1 | $80}
|
363
plasma3/lex.c
Executable file
363
plasma3/lex.c
Executable 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
10
plasma3/lex.h
Executable 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
BIN
plasma3/lex.o
Executable file
Binary file not shown.
39
plasma3/makefile
Executable file
39
plasma3/makefile
Executable 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
1294
plasma3/parse.c
Executable file
File diff suppressed because it is too large
Load Diff
1296
plasma3/parse.c~
Executable file
1296
plasma3/parse.c~
Executable file
File diff suppressed because it is too large
Load Diff
1
plasma3/parse.h
Executable file
1
plasma3/parse.h
Executable file
@ -0,0 +1 @@
|
||||
int parse_module(void);
|
BIN
plasma3/parse.o
Executable file
BIN
plasma3/parse.o
Executable file
Binary file not shown.
BIN
plasma3/plasm
Executable file
BIN
plasma3/plasm
Executable file
Binary file not shown.
17
plasma3/plasm.c
Executable file
17
plasma3/plasm.c
Executable 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
3382
plasma3/pleaides.pla
Executable file
File diff suppressed because it is too large
Load Diff
BIN
plasma3/plvm
Executable file
BIN
plasma3/plvm
Executable file
Binary file not shown.
895
plasma3/plvm.c
Executable file
895
plasma3/plvm.c
Executable 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
895
plasma3/plvm.c~
Executable 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
1612
plasma3/plvm02.s
Executable file
File diff suppressed because it is too large
Load Diff
147
plasma3/samplib.s
Executable file
147
plasma3/samplib.s
Executable 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
39
plasma3/symbols.h
Executable 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
39
plasma3/symbols.h~
Executable 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
177
plasma3/test.a
Executable 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
BIN
plasma3/test.bin
Executable file
Binary file not shown.
40
plasma3/test.pla
Executable file
40
plasma3/test.pla
Executable 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
40
plasma3/test.pla~
Executable 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
106
plasma3/tokens.h
Executable 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
52
src/ArrayObj.s
Executable 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
396
src/ObjectObj.s
Executable 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
1356
src/StringObj.s
Executable file
File diff suppressed because it is too large
Load Diff
16
src/_Object.java
Executable file
16
src/_Object.java
Executable 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
53
src/_String.java
Executable 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
910
src/apple2/AppleStuff.clasm
Executable 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
136
src/apple2/AppleStuff.java
Executable 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
204
src/apple2/Ethernet.java
Executable 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
Loading…
Reference in New Issue
Block a user