mirror of
https://github.com/badvision/lawless-legends.git
synced 2024-12-25 13:29:59 +00:00
Working Apple II loader
This commit is contained in:
parent
97529baec3
commit
bb5eb20141
@ -1,11 +1,96 @@
|
||||
const iobuffer = $0800
|
||||
const databuff = $0C00
|
||||
const MOD_ADDR = $1000
|
||||
const MODADDR = $1000
|
||||
|
||||
predef home, gotoxy, viewport, crout, cout, prstr, cin, rdstr
|
||||
predef syscall, romcall
|
||||
predef markheap, allocheap, releaseheap, availheap
|
||||
predef memclr, memset, memcpy
|
||||
predef uword_isgt, uword_isge, uword_islt, uword_isle
|
||||
predef getpfx, setpfx, newline, online, open, close, read, write, create, destroy
|
||||
byte version[] = "PLASMA VERSION 0.9"
|
||||
byte errorstr[] = "ERROR: $"
|
||||
byte okstr[] = "OK"
|
||||
byte heaperr[] = "ERR: HEAP/FRAME COLLISION.\n"
|
||||
byte prefix[32] = ""
|
||||
byte readerrstr = "ERROR READING FILE"
|
||||
byte davestr[] = "Relocateble PLASMA module:"
|
||||
byte modsizestr[] = "Module size: $"
|
||||
byte modlenstr[] = "Module len: $"
|
||||
byte modcodestr[] = "Module code: $"
|
||||
byte modinitstr[] = "Module init: $"
|
||||
byte adddefstr[] = "Add def call: $"
|
||||
byte defstr[] = "DEF "
|
||||
byte externstr[] = "EXTERN[$"
|
||||
byte internstr[] = "INTERN "
|
||||
byte wordstr[] = " WORD"
|
||||
byte bytestr[] = " BYTE"
|
||||
byte addrstr[] = "@$"
|
||||
byte luerrstr[] = "Lookup fail: "
|
||||
byte stdlibstr[] = "STDLIB"
|
||||
byte clsstr[] = "CLS"
|
||||
byte gotoxystr[] = "GOTOXY"
|
||||
byte viewstr[] = "VIEWPORT"
|
||||
byte putnlstr[] = "PUTNL"
|
||||
byte putcstr[] = "PUTC"
|
||||
byte putsstr[] = "PUTS"
|
||||
byte getcstr[] = "GETC"
|
||||
byte getsstr[] = "GETS"
|
||||
byte sysstr[] = "SYSCALL"
|
||||
byte romstr[] = "ROMCALL"
|
||||
byte getpfxstr[] = "GETPREFIX"
|
||||
byte setpfxstr[] = "SETPREFIX"
|
||||
byte newlinestr[] = "SETNEWLINE"
|
||||
byte onlinestr[] = "ONLINE"
|
||||
byte openstr[] = "OPEN"
|
||||
byte closestr[] = "CLOSE"
|
||||
byte readstr[] = "READ"
|
||||
byte writestr[] = "WRITE"
|
||||
byte creatstr[] = "CREATE"
|
||||
byte destroystr[] = "DESTROY"
|
||||
byte hpmarkstr[] = "HEAPMARK"
|
||||
byte hpallocstr[] = "HEAPALLOC"
|
||||
byte hprelstr[] = "HEAPRELEASE"
|
||||
byte hpavailstr[] = "HEAPAVAIL"
|
||||
byte memclrstr[] = "MEMCLR"
|
||||
byte memsetstr[] = "MEMSET"
|
||||
byte memcpystr[] = "MEMCPY"
|
||||
byte uisgtstr[] = "ISUGT"
|
||||
byte uisgestr[] = "ISUGE"
|
||||
byte uisltstr[] = "ISULT"
|
||||
byte uislestr[] = "ISULE"
|
||||
word exports[] = @clsstr, @home
|
||||
word = @gotoxystr, @gotoxy
|
||||
word = @viewstr, @viewport
|
||||
word = @putnlstr, @crout
|
||||
word = @putcstr, @cout
|
||||
word = @putsstr, @prstr
|
||||
word = @getcstr, @cin
|
||||
word = @getsstr, @rdstr
|
||||
word = @sysstr, @syscall
|
||||
word = @romstr, @romcall
|
||||
word = @hpmarkstr, @markheap
|
||||
word = @hpallocstr,@allocheap
|
||||
word = @hprelstr, @releaseheap
|
||||
word = @hpavailstr,@availheap
|
||||
word = @memclrstr, @memclr
|
||||
word = @memsetstr, @memset
|
||||
word = @memcpystr, @memcpy
|
||||
word = @uisgtstr, @uword_isgt
|
||||
word = @uisgestr, @uword_isge
|
||||
word = @uisltstr, @uword_islt
|
||||
word = @uislestr, @uword_isle
|
||||
word = @getpfxstr, @getpfx
|
||||
word = @setpfxstr, @setpfx
|
||||
word = @newlinestr,@newline
|
||||
word = @onlinestr, @online
|
||||
word = @openstr, @open
|
||||
word = @closestr, @close
|
||||
word = @readstr, @read
|
||||
word = @writestr, @write
|
||||
word = @creatstr, @create
|
||||
word = @destroystr,@destroy
|
||||
word = 0
|
||||
word heap = $6000
|
||||
byte modtbl[256]
|
||||
word lastmod = @modtbl
|
||||
@ -13,7 +98,7 @@ byte symtbl[1024]
|
||||
word lastsym = @symtbl
|
||||
byte deftbl[2048]
|
||||
word lastdef = @deftbl
|
||||
byte perr
|
||||
word perr
|
||||
word cmdptr
|
||||
;
|
||||
; Utility functions
|
||||
@ -35,10 +120,54 @@ LCBNK1 = $08
|
||||
ESP !BYTE 0
|
||||
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 ROMEN
|
||||
PLP
|
||||
JSR JMPTMP
|
||||
PHP
|
||||
BIT LCRDEN+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 !FILL 4
|
||||
JMPTMP JMP (TMP)
|
||||
end
|
||||
;
|
||||
; CALL PRODOS
|
||||
; SYSCALL(CMD, PARAMS)
|
||||
;
|
||||
asm prodos
|
||||
asm syscall
|
||||
LDA ESTKL,X
|
||||
LDY ESTKH,X
|
||||
STA PARAMS
|
||||
@ -92,19 +221,54 @@ asm memclr
|
||||
INC ESTKL,X
|
||||
INC ESTKH,X
|
||||
TYA
|
||||
SETMLP DEC ESTKL,X
|
||||
CLRMLP DEC ESTKL,X
|
||||
BNE +
|
||||
DEC ESTKH,X
|
||||
BEQ ++
|
||||
+ STA (DST),Y
|
||||
INY
|
||||
BNE SETMLP
|
||||
BNE CLRMLP
|
||||
INC DSTH
|
||||
BNE SETMLP
|
||||
BNE CLRMLP
|
||||
++ INX
|
||||
RTS
|
||||
end
|
||||
;
|
||||
; SET MEMORY TO VALUE
|
||||
; MEMSET(ADDR, SIZE, VALUE)
|
||||
;
|
||||
asm memset
|
||||
LDY #$00
|
||||
LDA ESTKL+2,X
|
||||
STA DSTL
|
||||
LDA ESTKH+2,X
|
||||
STA DSTH
|
||||
INC ESTKL+1,X
|
||||
INC ESTKH+1,X
|
||||
SETMLP DEC ESTKL+1,X
|
||||
BNE +
|
||||
DEC ESTKH+1,X
|
||||
BEQ SETMEX
|
||||
+ LDA ESTKL,X
|
||||
STA (DST),Y
|
||||
INY
|
||||
BNE +
|
||||
INC DSTH
|
||||
+ DEC ESTKL+1,X
|
||||
BNE +
|
||||
DEC ESTKH+1,X
|
||||
BEQ SETMEX
|
||||
+ LDA ESTKH,X
|
||||
STA (DST),Y
|
||||
INY
|
||||
BNE SETMLP
|
||||
INC DSTH
|
||||
BNE SETMLP
|
||||
SETMEX INX
|
||||
INX
|
||||
RTS
|
||||
end
|
||||
;
|
||||
; COPY MEMORY
|
||||
; MEMCPY(DSTADDR, SRCADDR, SIZE)
|
||||
;
|
||||
@ -113,7 +277,7 @@ asm memcpy
|
||||
LDA ESTKL,X
|
||||
BNE +
|
||||
LDA ESTKH,X
|
||||
BEQ MEMEXIT
|
||||
BEQ CPYMEX
|
||||
+ LDA ESTKL+2,X
|
||||
STA DSTL
|
||||
LDA ESTKH+2,X
|
||||
@ -159,7 +323,7 @@ REVCPYLP
|
||||
BNE REVCPYLP
|
||||
DEC ESTKH,X
|
||||
BNE REVCPYLP
|
||||
BEQ MEMEXIT
|
||||
BEQ CPYMEX
|
||||
FORCPY INC ESTKH,X
|
||||
FORCPYLP
|
||||
LDA (SRC),Y
|
||||
@ -174,7 +338,32 @@ FORCPYLP
|
||||
BNE FORCPYLP
|
||||
DEC ESTKH,X
|
||||
BNE FORCPYLP
|
||||
MEMEXIT INX
|
||||
CPYMEX INX
|
||||
INX
|
||||
RTS
|
||||
end
|
||||
;
|
||||
; HOME
|
||||
;
|
||||
asm home
|
||||
DEX
|
||||
RTS
|
||||
end
|
||||
;
|
||||
; SET CURSOR POSITION
|
||||
; GOTOXY(X,Y)
|
||||
;
|
||||
asm gotoxy
|
||||
INX
|
||||
RTS
|
||||
end
|
||||
;
|
||||
; SET VIEWPORT
|
||||
; VIEWPORT(LEFT, TOP, RIGHT, BOTTOM)
|
||||
;
|
||||
asm viewport
|
||||
INX
|
||||
INX
|
||||
INX
|
||||
RTS
|
||||
end
|
||||
@ -216,10 +405,11 @@ asm prstr
|
||||
STA SRCL
|
||||
LDA ESTKH,X
|
||||
STA SRCH
|
||||
BIT ROMEN
|
||||
STY ESTKH,X
|
||||
LDA (SRC),Y
|
||||
STA ESTKL,X
|
||||
BEQ +
|
||||
BIT ROMEN
|
||||
- INY
|
||||
LDA (SRC),Y
|
||||
ORA #$80
|
||||
@ -227,8 +417,8 @@ asm prstr
|
||||
TYA
|
||||
CMP ESTKL,X
|
||||
BNE -
|
||||
+ BIT LCRDEN+LCBNK2
|
||||
RTS
|
||||
BIT LCRDEN+LCBNK2
|
||||
+ RTS
|
||||
end
|
||||
;
|
||||
; PRINT BYTE
|
||||
@ -365,7 +555,7 @@ def getpfx(path)
|
||||
^path = 0
|
||||
params.0 = 1
|
||||
params:1 = path
|
||||
perr = prodos($C7, @params)
|
||||
perr = syscall($C7, @params)
|
||||
return path
|
||||
end
|
||||
def setpfx(path)
|
||||
@ -373,7 +563,7 @@ def setpfx(path)
|
||||
|
||||
params.0 = 1
|
||||
params:1 = path
|
||||
perr = prodos($C6, @params)
|
||||
perr = syscall($C6, @params)
|
||||
return path
|
||||
end
|
||||
def online
|
||||
@ -382,7 +572,7 @@ def online
|
||||
params.0 = 2
|
||||
params.1 = 0
|
||||
params:2 = databuff
|
||||
perr = prodos($C5, @params)
|
||||
perr = syscall($C5, @params)
|
||||
return databuff
|
||||
end
|
||||
def open(path, buff)
|
||||
@ -392,7 +582,7 @@ def open(path, buff)
|
||||
params:1 = path
|
||||
params:3 = buff
|
||||
params.5 = 0
|
||||
perr = prodos($C8, @params)
|
||||
perr = syscall($C8, @params)
|
||||
return params.5
|
||||
end
|
||||
def close(refnum)
|
||||
@ -400,7 +590,7 @@ def close(refnum)
|
||||
|
||||
params.0 = 1
|
||||
params.1 = refnum
|
||||
perr = prodos($CC, @params)
|
||||
perr = syscall($CC, @params)
|
||||
return perr
|
||||
end
|
||||
def read(refnum, buff, len)
|
||||
@ -411,9 +601,52 @@ def read(refnum, buff, len)
|
||||
params:2 = buff
|
||||
params:4 = len
|
||||
params:6 = 0
|
||||
perr = prodos($CA, @params)
|
||||
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
|
||||
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 destroy(path)
|
||||
byte params[12]
|
||||
|
||||
params.0 = 1
|
||||
params:1 = path
|
||||
perr = syscall($C1, @params)
|
||||
return perr
|
||||
end
|
||||
def newline(refnum, emask, nlchar)
|
||||
byte params[4]
|
||||
|
||||
params.0 = 3
|
||||
params.1 = refnum
|
||||
params.2 = emask
|
||||
params.3 = nlchar
|
||||
perr = syscall($C9, @params)
|
||||
return perr
|
||||
end
|
||||
|
||||
;
|
||||
; Utility routines.
|
||||
@ -422,33 +655,40 @@ end
|
||||
; More efficient than C or Pascal strings.
|
||||
;
|
||||
def dcitos(dci, str)
|
||||
byte len
|
||||
byte len, c
|
||||
len = 0
|
||||
repeat
|
||||
str.[len] = dci.[len] & $7F
|
||||
c = (dci).[len]
|
||||
len = len + 1
|
||||
until len > 15 or !(dci.[len - 1] & $80)
|
||||
str.[len] = 0
|
||||
(str).[len] = c & $7F
|
||||
until !(c & $80)
|
||||
^str = len
|
||||
return len
|
||||
end
|
||||
def stodci(str, dci)
|
||||
byte len
|
||||
len = 0
|
||||
while len < 16 and str.[len]
|
||||
dci.[len] = toupper(str.[len]) | $80
|
||||
len = len + 1
|
||||
byte len, c
|
||||
len = ^str
|
||||
if len == 0
|
||||
return
|
||||
fin
|
||||
c = toupper((str).[len]) & $7F
|
||||
len = len - 1
|
||||
(dci).[len] = c
|
||||
while len
|
||||
c = toupper((str).[len]) | $80
|
||||
len = len - 1
|
||||
(dci).[len] = c
|
||||
loop
|
||||
dci.[len - 1] = dci.[len - 1] & $7F;
|
||||
return len;
|
||||
return ^str
|
||||
end
|
||||
;
|
||||
; Heap routines.
|
||||
;
|
||||
def avail_heap
|
||||
def availheap
|
||||
byte fp
|
||||
return @fp - heap
|
||||
end
|
||||
def alloc_heap(size)
|
||||
def allocheap(size)
|
||||
word addr
|
||||
addr = heap
|
||||
heap = heap + size
|
||||
@ -458,21 +698,21 @@ def alloc_heap(size)
|
||||
; fin
|
||||
return addr
|
||||
end
|
||||
def free_heap(size)
|
||||
def freeheap(size)
|
||||
heap = heap - size;
|
||||
return @size - heap;
|
||||
end
|
||||
def mark_heap
|
||||
def markheap
|
||||
return heap;
|
||||
end
|
||||
def release_heap(newheap)
|
||||
def releaseheap(newheap)
|
||||
heap = newheap;
|
||||
return @newheap - heap;
|
||||
end
|
||||
;def avail_xheap(void)
|
||||
;def availxheap(void)
|
||||
; return 0xC000 - xheap;
|
||||
;end
|
||||
;def alloc_xheap(int size)
|
||||
;def allocxheap(int size)
|
||||
; uword addr = xheap;
|
||||
; xheap += size;
|
||||
; if (xheap >= 0xC000)
|
||||
@ -482,14 +722,14 @@ end
|
||||
; }
|
||||
; return addr;
|
||||
;end
|
||||
;def free_xheap(int size)
|
||||
;def freexheap(int size)
|
||||
; xheap -= size;
|
||||
; return 0xC000 - heap;
|
||||
;end
|
||||
;def mark_xheap(void)
|
||||
;def markxheap(void)
|
||||
; return xheap;
|
||||
;end
|
||||
;def release_xheap(uword newxheap)
|
||||
;def releasexheap(uword newxheap)
|
||||
; xheap = newxheap;
|
||||
; return 0xC000 - xheap;
|
||||
;end
|
||||
@ -510,13 +750,13 @@ end
|
||||
;
|
||||
; DCI table routines,
|
||||
;
|
||||
def dump_tbl(tbl)
|
||||
def dumptbl(tbl)
|
||||
byte len
|
||||
word entbl
|
||||
|
||||
while ^tbl
|
||||
len = 0
|
||||
while ^tbl & $80
|
||||
cout(^tbl & $7F)
|
||||
cout(^tbl)
|
||||
tbl = tbl + 1
|
||||
len = len + 1
|
||||
loop
|
||||
@ -528,118 +768,139 @@ def dump_tbl(tbl)
|
||||
len = len + 1
|
||||
loop
|
||||
cout('$')
|
||||
prbyte((tbl).1)
|
||||
prbyte((tbl).0)
|
||||
prword(*tbl)
|
||||
crout
|
||||
tbl = tbl + 2
|
||||
loop
|
||||
end
|
||||
def lookup_tbl(dci, tbl)
|
||||
def lookuptbl(dci, tbl)
|
||||
byte str[20]
|
||||
word match, entry
|
||||
entry = tbl
|
||||
while ^entry
|
||||
word match
|
||||
|
||||
while ^tbl
|
||||
dcitos(tbl, @str)
|
||||
prstr(@str)
|
||||
crout
|
||||
match = dci
|
||||
while ^entry == ^match
|
||||
if !(^entry & $80)
|
||||
return (entry):1
|
||||
while ^tbl == ^match
|
||||
if !(^tbl & $80)
|
||||
return (tbl):1
|
||||
fin
|
||||
entry = entry + 1
|
||||
tbl = tbl + 1
|
||||
match = match + 1
|
||||
loop
|
||||
while ^entry & $80
|
||||
entry = entry + 1
|
||||
while ^tbl & $80
|
||||
tbl = tbl + 1
|
||||
loop
|
||||
entry = entry + 2
|
||||
tbl = tbl + 3
|
||||
loop
|
||||
prstr(@luerrstr)
|
||||
dcitos(dci, @str)
|
||||
prstr(@str)
|
||||
crout
|
||||
return 0
|
||||
end
|
||||
def add_tbl(dci, val, last)
|
||||
def addtbl(dci, val, last)
|
||||
while ^dci & $80
|
||||
^(*last) = ^dci
|
||||
*last = *last + 1
|
||||
dci = dci + 1
|
||||
^*last = ^dci
|
||||
*last = *last + 1
|
||||
dci = dci + 1
|
||||
loop
|
||||
^(*last) = ^dci
|
||||
*last = *last + 1
|
||||
dci = dci + 1
|
||||
^(*last) = val
|
||||
*last = *last + 2
|
||||
^*last = ^dci
|
||||
*last = *last + 1
|
||||
**last = val
|
||||
*last = *last + 2
|
||||
end
|
||||
;
|
||||
; Symbol table routines.
|
||||
;
|
||||
def dump_sym
|
||||
def dumpsym
|
||||
;printf("\nSystem Symbol Table:\n");
|
||||
dump_tbl(symtbl)
|
||||
dumptbl(@symtbl)
|
||||
end
|
||||
def lookup_sym(sym)
|
||||
return lookup_tbl(sym, symtbl)
|
||||
def lookupsym(sym)
|
||||
return lookuptbl(sym, @symtbl)
|
||||
end
|
||||
def add_sym(sym, addr)
|
||||
return add_tbl(sym, addr, @lastsym);
|
||||
def addsym(sym, addr)
|
||||
return addtbl(sym, addr, @lastsym);
|
||||
end
|
||||
;
|
||||
; Module routines.
|
||||
;
|
||||
def dump_mod
|
||||
def dumpmod
|
||||
;printf("\nSystem Module Table:\n");
|
||||
dump_tbl(modtbl)
|
||||
dumptbl(@modtbl)
|
||||
end
|
||||
def lookup_mod(mod)
|
||||
return lookup_tbl(mod, modtbl)
|
||||
def lookupmod(mod)
|
||||
return lookuptbl(mod, @modtbl)
|
||||
end
|
||||
def add_mod(mod, addr)
|
||||
return add_tbl(mod, addr, @lastmod)
|
||||
def addmod(mod)
|
||||
return addtbl(mod, @lastmod)
|
||||
end
|
||||
def defcall_add(bank, addr)
|
||||
def adddef(bank, addr)
|
||||
(lastdef).0 = $20 ; JSR $03D6
|
||||
(lastdef):1 = $03D6
|
||||
(lastdef).3 = bank
|
||||
(lastdef):4 = addr
|
||||
prstr(@adddefstr)
|
||||
prword(lastdef)
|
||||
crout
|
||||
lastdef = lastdef + 6
|
||||
return lastdef - 6
|
||||
end
|
||||
def def_lookup(cdd, defaddr)
|
||||
word i
|
||||
i = 0
|
||||
while (cdd).[i] == $02
|
||||
if (cdd):[i + 1] == defaddr)
|
||||
return cdd + i
|
||||
def lookupdef(bank, addr)
|
||||
word entry
|
||||
|
||||
entry = @deftbl
|
||||
while ^entry == $20
|
||||
if (entry):4 == addr
|
||||
if (entry).3 == bank
|
||||
return entry
|
||||
fin
|
||||
fin
|
||||
i = i + 4
|
||||
entry = entry + 6
|
||||
loop
|
||||
return 0
|
||||
end
|
||||
def extern_lookup(esd, index)
|
||||
def lookupextern(esd, index)
|
||||
word sym
|
||||
byte str[17]
|
||||
byte str[16]
|
||||
while ^esd
|
||||
sym = esd;
|
||||
esd = esd + dcitos(esd, str)
|
||||
sym = esd
|
||||
esd = esd + dcitos(esd, @str)
|
||||
if (esd).0 & $10 and (esd).1 == index
|
||||
return lookup_sym(sym)
|
||||
return lookupsym(sym)
|
||||
fin
|
||||
esd = esd + 3
|
||||
loop
|
||||
return 0
|
||||
end
|
||||
def load_mod(mod)
|
||||
def loadmod(mod)
|
||||
word refnum, len, size,modend, bytecode, fixup, addr, init, modaddr, modfix
|
||||
word moddep, rld, esd, cdd, sym;
|
||||
byte str[16]
|
||||
byte filename[64]
|
||||
byte header[128]
|
||||
byte filename[32]
|
||||
byte str[17]
|
||||
|
||||
init = 0
|
||||
modaddr = mark_heap
|
||||
dcitos(mod, filename)
|
||||
;printf("Load module %s\n", filename)
|
||||
refnum = open(filename)
|
||||
dcitos(mod, @filename)
|
||||
prbyte(filename)
|
||||
cout(' ')
|
||||
prstr(@filename)
|
||||
crout
|
||||
refnum = open(@filename, iobuffer)
|
||||
if refnum > 0
|
||||
modaddr = markheap
|
||||
init = 0
|
||||
len = read(refnum, @header, 128)
|
||||
prstr(@modlenstr)
|
||||
prword(len)
|
||||
crout
|
||||
if len > 4 and header:2 == $DA7E ; DAVE
|
||||
;
|
||||
; This is a relocatable bytecode module.
|
||||
;
|
||||
prstr(@davestr)
|
||||
crout
|
||||
bytecode = header:4
|
||||
init = header:6
|
||||
moddep = @header + 8
|
||||
@ -649,28 +910,34 @@ def load_mod(mod)
|
||||
;
|
||||
close(refnum)
|
||||
while ^moddep
|
||||
if lookup_mod(moddep) == 0
|
||||
load_mod(moddep)
|
||||
if lookupmod(moddep) == 0
|
||||
dumpmod
|
||||
if loadmod(moddep) <> 0
|
||||
dumpmod
|
||||
return perr
|
||||
fin
|
||||
fin
|
||||
moddep = moddep + dcitos(moddep, str)
|
||||
moddep = moddep + dcitos(moddep, @str)
|
||||
prstr(@str)
|
||||
crout
|
||||
loop
|
||||
modaddr = mark_heap
|
||||
refnum = open(filename)
|
||||
modaddr = markheap
|
||||
refnum = open(@filename, iobuffer)
|
||||
len = read(refnum, modaddr, 128)
|
||||
fin
|
||||
else
|
||||
memcpy(modaddr, header, len)
|
||||
memcpy(modaddr, @header, len)
|
||||
fin
|
||||
addr = modaddr + len;
|
||||
repeat
|
||||
len = read(refnum, addr, 4096)
|
||||
addr = addr + len
|
||||
until len > 0
|
||||
until len <= 0
|
||||
close(refnum)
|
||||
size = addr - modaddr
|
||||
len = *modaddr
|
||||
modend = modaddr + len
|
||||
modfix = modaddr - MOD_ADDR
|
||||
modfix = modaddr - MODADDR
|
||||
bytecode = bytecode + modfix
|
||||
rld = modaddr + len ; Re-Locatable Directory
|
||||
cdd = rld ; Code Definition Directory
|
||||
@ -679,88 +946,107 @@ def load_mod(mod)
|
||||
esd = esd + 4
|
||||
loop
|
||||
esd = esd + 1
|
||||
;if show_state
|
||||
;if showstate
|
||||
;
|
||||
; Dump different parts of module.
|
||||
;
|
||||
;printf("Module size: %d\n", size);
|
||||
prstr(@modsizestr)
|
||||
prword(size)
|
||||
crout
|
||||
;printf("Module code+data size: %d\n", len);
|
||||
;printf("Module magic: $%04X\n", magic);
|
||||
prstr(@modlenstr)
|
||||
prword(len)
|
||||
crout
|
||||
;printf("Module bytecode: $%04X\n", bytecode);
|
||||
prstr(@modcodestr)
|
||||
prword(bytecode)
|
||||
crout
|
||||
;printf("Module init: $%04X\n", init);
|
||||
prstr(@modinitstr)
|
||||
prword(init)
|
||||
crout
|
||||
;fin
|
||||
;
|
||||
; Print out the Re-Location Dictionary.
|
||||
;
|
||||
;if show_state
|
||||
;if showstate
|
||||
;printf("\nRe-Location Dictionary:\n")
|
||||
;fin
|
||||
while ^rld
|
||||
if ^rld == $02
|
||||
;if show_state prstr("\tDEF CODE")
|
||||
(rld):1 = (rld):1 + modfix
|
||||
modend = rld + 4
|
||||
addr = (rld):1 + modfix
|
||||
(rld):1 = addr
|
||||
adddef(0, addr)
|
||||
prstr(@defstr)
|
||||
else
|
||||
addr = (rld):1 + modfix
|
||||
if (rld).0 & $80
|
||||
if ^rld & $80
|
||||
fixup = *addr
|
||||
else
|
||||
fixup = ^addr
|
||||
fin
|
||||
if (^rld & $10)
|
||||
;if show_state printf("\tEXTERN[$%02X] ", rld[3]);
|
||||
fixup = fixup + extern_lookup(esd, rld[3]);
|
||||
if ^rld & $10
|
||||
prstr(@externstr)
|
||||
prbyte((rld).3);"\tEXTERN[$%02X] ", rld[3]);
|
||||
cout(']')
|
||||
fixup = fixup + lookupextern(esd, (rld).3);
|
||||
else
|
||||
;if (show_state) printf("\tINTERN ")
|
||||
prstr(@internstr);printf("\tINTERN ")
|
||||
fixup = fixup + modfix
|
||||
if uword_isge(fixup, bytecode)
|
||||
;
|
||||
; Replace with call def dictionary.
|
||||
;
|
||||
fixup = def_lookup(cdd, fixup)
|
||||
fixup = lookupdef(0, fixup)
|
||||
fin
|
||||
fin
|
||||
if ^rld & $80
|
||||
;if show_state printf("WORD")
|
||||
prstr(@wordstr);printf("WORD")
|
||||
*addr = fixup
|
||||
else
|
||||
;if show_state printf("BYTE")
|
||||
prstr(@bytestr);printf("BYTE")
|
||||
^addr = fixup
|
||||
fin
|
||||
|
||||
fin
|
||||
;if show_state printf("@$%04X\n", addr)
|
||||
rld = rld + 4;
|
||||
prstr(@addrstr)
|
||||
prword(addr)
|
||||
crout;printf("@$%04X\n", addr)
|
||||
rld = rld + 4
|
||||
loop
|
||||
;if show_state printf("\nExternal/Entry Symbol Directory:\n")
|
||||
;if showstate printf("\nExternal/Entry Symbol Directory:\n")
|
||||
while ^esd
|
||||
sym = esd
|
||||
esd = esd + dcitos(esd, str)
|
||||
esd = esd + dcitos(esd, @str)
|
||||
if ^esd & $10
|
||||
;if show_state printf("\tIMPORT %s[$%02X]\n", string, esd[1])
|
||||
;if showstate printf("\tIMPORT %s[$%02X]\n", string, esd[1])
|
||||
elsif ^esd & $08
|
||||
addr = (esd):1 + modfix
|
||||
;if show_state printf("\tEXPORT %s@$%04X\n", string, addr)
|
||||
;if showstate printf("\tEXPORT %s@$%04X\n", string, addr)
|
||||
if uword_isge(addr, bytecode)
|
||||
addr = def_lookup(cdd, addr)
|
||||
addr = lookupdef(0, addr)
|
||||
fin
|
||||
add_sym(sym, addr)
|
||||
addsym(sym, addr)
|
||||
fin
|
||||
esd = esd + 3
|
||||
loop
|
||||
else
|
||||
;printf("Error: Unable to load module %s\n", filename);
|
||||
return -1
|
||||
prstr(@readerrstr)
|
||||
crout
|
||||
perr = 0x100
|
||||
return perr
|
||||
fin
|
||||
;
|
||||
; Reserve heap space for relocated module.
|
||||
;
|
||||
alloc_heap(modend - modaddr)
|
||||
allocheap(modend - modaddr)
|
||||
;
|
||||
; Call init routine.
|
||||
;
|
||||
if init
|
||||
return (init + modfix)()
|
||||
init = adddef(0, init + modfix)
|
||||
cin
|
||||
return init()
|
||||
fin
|
||||
return 0
|
||||
end
|
||||
@ -797,7 +1083,7 @@ def catalog(optpath)
|
||||
prstr(@path)
|
||||
crout()
|
||||
fin
|
||||
refnum = open(@path, iobuffer);
|
||||
refnum = open(@path, iobuffer)
|
||||
if perr
|
||||
return perr
|
||||
fin
|
||||
@ -917,50 +1203,45 @@ def execsys(sysfile)
|
||||
fin
|
||||
fin
|
||||
end
|
||||
def execmod(modfile)
|
||||
byte dci[17]
|
||||
word saveheap, savemod, savesym, savedef
|
||||
|
||||
if stodci(modfile, @dci)
|
||||
saveheap = heap
|
||||
savemod = lastmod
|
||||
savesym = lastsym
|
||||
savedef = lastdef
|
||||
loadmod(@dci)
|
||||
heap = saveheap
|
||||
lastmod = savemod
|
||||
lastsym = savesym
|
||||
lastdef = savedef
|
||||
^heap = 0
|
||||
^lastmod = 0
|
||||
^lastsym = 0
|
||||
^lastdef = 0
|
||||
fin
|
||||
end
|
||||
def initsyms
|
||||
byte dci[17]
|
||||
word globals
|
||||
|
||||
def prucomp(a, b)
|
||||
if uword_isgt(a, b)
|
||||
prword(a)
|
||||
cout('>')
|
||||
prword(b)
|
||||
crout
|
||||
fin
|
||||
if uword_isge(a, b)
|
||||
prword(a)
|
||||
cout('>')
|
||||
cout('=')
|
||||
prword(b)
|
||||
crout
|
||||
fin
|
||||
if uword_islt(a, b)
|
||||
prword(a)
|
||||
cout('<')
|
||||
prword(b)
|
||||
crout
|
||||
fin
|
||||
if uword_isle(a, b)
|
||||
prword(a)
|
||||
cout('<')
|
||||
cout('=')
|
||||
prword(b)
|
||||
crout
|
||||
fin
|
||||
stodci(@stdlibstr, @dci)
|
||||
addmod(@dci, 1)
|
||||
globals = @exports
|
||||
while *globals
|
||||
stodci(*globals, @dci)
|
||||
globals = globals + 2
|
||||
addsym(@dci, *globals)
|
||||
globals = globals + 2
|
||||
loop
|
||||
end
|
||||
|
||||
resetmemfiles()
|
||||
prstr(@version)
|
||||
crout()
|
||||
prucomp($1, $2)
|
||||
prucomp($2, $1)
|
||||
prucomp($100, $200)
|
||||
prucomp($200, $100)
|
||||
prucomp($9000, $A000)
|
||||
prucomp($A000, $9000)
|
||||
prucomp($E000, $E000)
|
||||
prucomp($E001, $E000)
|
||||
prucomp($E000, $E001)
|
||||
prucomp($FFFF, $FFFE)
|
||||
prucomp($FFFE, $FFFF)
|
||||
initsyms
|
||||
while 1
|
||||
prstr(getpfx(@prefix))
|
||||
cmdptr = rdstr($BA)
|
||||
@ -976,10 +1257,13 @@ while 1
|
||||
is '-'
|
||||
execsys(cmdptr)
|
||||
perr = $46
|
||||
is '+'
|
||||
execmod(cmdptr)
|
||||
wend
|
||||
if perr
|
||||
prstr(@errorstr)
|
||||
prbyte(perr)
|
||||
perr = 0
|
||||
else
|
||||
prstr(@okstr)
|
||||
fin
|
||||
|
@ -11,7 +11,9 @@ static int consts = 0;
|
||||
static int externs = 0;
|
||||
static int globals = 0;
|
||||
static int locals = 0;
|
||||
static int predefs = 0;
|
||||
static int defs = 0;
|
||||
static int asmdefs = 0;
|
||||
static int codetags = 0;
|
||||
static int fixups = 0;
|
||||
static char idconst_name[1024][17];
|
||||
@ -23,9 +25,9 @@ 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];
|
||||
static char fixup_size[1024];
|
||||
static int fixup_type[1024];
|
||||
static int fixup_tag[1024];
|
||||
#define FIXUP_BYTE 0x00
|
||||
#define FIXUP_WORD 0x80
|
||||
int id_match(char *name, int len, char *id)
|
||||
@ -155,13 +157,14 @@ int idfunc_add(char *name, int len, int type, int tag)
|
||||
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 idfunc_set(char *name, int len, int type, int tag)
|
||||
{
|
||||
int i;
|
||||
if (((i = idglobal_lookup(name, len)) >= 0) && (idglobal_type[i] & FUNC_TYPE))
|
||||
{
|
||||
idglobal_tag[i] = tag;
|
||||
idglobal_type[i] = type;
|
||||
return (idglobal_type[i]);
|
||||
return (type);
|
||||
}
|
||||
parse_error("Undeclared identifier");
|
||||
return (0);
|
||||
@ -215,9 +218,15 @@ int id_type(char *name, int len)
|
||||
int tag_new(int type)
|
||||
{
|
||||
if (type & EXTERN_TYPE)
|
||||
{
|
||||
if (externs > 254)
|
||||
parse_error("External variable count overflow\n");
|
||||
return (externs++);
|
||||
}
|
||||
if (type & PREDEF_TYPE)
|
||||
return (predefs++);
|
||||
if (type & ASM_TYPE)
|
||||
return (globals);
|
||||
return (asmdefs++);
|
||||
if (type & DEF_TYPE)
|
||||
return (defs++);
|
||||
if (type & BRANCH_TYPE)
|
||||
@ -226,11 +235,6 @@ int tag_new(int type)
|
||||
}
|
||||
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;
|
||||
@ -268,6 +272,8 @@ char *tag_string(int tag, int type)
|
||||
t = 'A';
|
||||
else if (type & BRANCH_TYPE)
|
||||
t = 'B';
|
||||
else if (type & PREDEF_TYPE)
|
||||
t = 'P';
|
||||
else
|
||||
t = 'D';
|
||||
sprintf(str, "_%c%03d", t, tag);
|
||||
@ -418,7 +424,7 @@ void emit_idglobal(int tag, int size, char *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);
|
||||
printf("%s%c\t\t\t\t\t; %s()\n", tag_string(tag, type), LBL, name);
|
||||
}
|
||||
void emit_idconst(char *name, int value)
|
||||
{
|
||||
|
8
PLASMA/src/hello.pla
Normal file
8
PLASMA/src/hello.pla
Normal file
@ -0,0 +1,8 @@
|
||||
import STDLIB
|
||||
predef puts
|
||||
end
|
||||
|
||||
byte hellostr[] = "Hello, world.\n"
|
||||
|
||||
puts(@hellostr)
|
||||
done
|
@ -163,7 +163,7 @@ t_token scan(void)
|
||||
switch (scanpos[2])
|
||||
{
|
||||
case 'n':
|
||||
constval = '\n';
|
||||
constval = 0x0D;
|
||||
break;
|
||||
case 'r':
|
||||
constval = '\r';
|
||||
@ -207,7 +207,7 @@ t_token scan(void)
|
||||
switch (scanpos[1])
|
||||
{
|
||||
case 'n':
|
||||
*scanpos = '\n';
|
||||
*scanpos = 0x0D;
|
||||
break;
|
||||
case 'r':
|
||||
*scanpos = '\r';
|
||||
|
@ -840,8 +840,9 @@ int parse_stmnt(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
parse_error("RETURN outside of function");
|
||||
return (0);
|
||||
if (!parse_expr())
|
||||
emit_const(0);
|
||||
emit_ret();
|
||||
}
|
||||
break;
|
||||
case EOL_TOKEN:
|
||||
@ -1077,7 +1078,7 @@ int parse_vars(int type)
|
||||
*/
|
||||
if (scan() == ID_TOKEN)
|
||||
{
|
||||
type |= DEF_TYPE;
|
||||
type |= PREDEF_TYPE;
|
||||
idstr = tokenstr;
|
||||
idlen = tokenlen;
|
||||
idfunc_add(tokenstr, tokenlen, type, tag_new(type));
|
||||
@ -1165,13 +1166,14 @@ int parse_defs(void)
|
||||
type |= DEF_TYPE;
|
||||
if (idglobal_lookup(tokenstr, tokenlen) >= 0)
|
||||
{
|
||||
if (!(id_type(tokenstr, tokenlen) & DEF_TYPE))
|
||||
if (!(id_type(tokenstr, tokenlen) & PREDEF_TYPE))
|
||||
{
|
||||
parse_error("Mismatch function type");
|
||||
return (0);
|
||||
}
|
||||
idfunc_set(tokenstr, tokenlen, type); // Override any predef type
|
||||
func_tag = id_tag(tokenstr, tokenlen);
|
||||
emit_idfunc(id_tag(tokenstr, tokenlen), PREDEF_TYPE, tokenstr);
|
||||
func_tag = tag_new(type);
|
||||
idfunc_set(tokenstr, tokenlen, type, func_tag); // Override any predef type & tag
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1241,8 +1243,14 @@ int parse_defs(void)
|
||||
type |= ASM_TYPE;
|
||||
if (idglobal_lookup(tokenstr, tokenlen) >= 0)
|
||||
{
|
||||
idfunc_set(tokenstr, tokenlen, type); // Override any predef type
|
||||
func_tag = id_tag(tokenstr, tokenlen);
|
||||
if (!(id_type(tokenstr, tokenlen) & PREDEF_TYPE))
|
||||
{
|
||||
parse_error("Mismatch function type");
|
||||
return (0);
|
||||
}
|
||||
emit_idfunc(id_tag(tokenstr, tokenlen), PREDEF_TYPE, tokenstr);
|
||||
func_tag = tag_new(type);
|
||||
idfunc_set(tokenstr, tokenlen, type, func_tag); // Override any predef type & tag
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1300,14 +1308,18 @@ int parse_module(void)
|
||||
while (parse_defs()) next_line();
|
||||
if (scantoken != DONE_TOKEN && scantoken != EOF_TOKEN)
|
||||
{
|
||||
emit_bytecode_seg();
|
||||
emit_start();
|
||||
emit_def("_INIT", 1);
|
||||
prevstmnt = 0;
|
||||
while (parse_stmnt()) next_line();
|
||||
if (scantoken != DONE_TOKEN)
|
||||
parse_error("Missing DONE statement");
|
||||
emit_const(0);
|
||||
emit_ret();
|
||||
if (prevstmnt != RETURN_TOKEN)
|
||||
{
|
||||
emit_const(0);
|
||||
emit_ret();
|
||||
}
|
||||
}
|
||||
}
|
||||
emit_trailer();
|
||||
|
@ -435,7 +435,7 @@ void interp(code *ip);
|
||||
void call(uword pc)
|
||||
{
|
||||
unsigned int i, s;
|
||||
char sz[64];
|
||||
char c, sz[64];
|
||||
|
||||
switch (mem_data[pc++])
|
||||
{
|
||||
@ -453,7 +453,10 @@ void call(uword pc)
|
||||
PUSH(0);
|
||||
break;
|
||||
case 4: // LIBRARY STDLIB::PUTC
|
||||
putchar(POP);
|
||||
c = POP;
|
||||
if (c == 0x0D)
|
||||
c = '\n';
|
||||
putchar(c);
|
||||
PUSH(0);
|
||||
break;
|
||||
case 5: // LIBRARY STDLIB::PUTS
|
||||
@ -461,15 +464,20 @@ void call(uword pc)
|
||||
i = mem_data[s++];
|
||||
PUSH(i);
|
||||
while (i--)
|
||||
putchar(mem_data[s++]);
|
||||
{
|
||||
c = mem_data[s++];
|
||||
if (c == 0x0D)
|
||||
c = '\n';
|
||||
putchar(c);
|
||||
}
|
||||
break;
|
||||
case 6: // LIBRARY STDLIB::PUTSZ
|
||||
s = POP;
|
||||
while (i = mem_data[s++])
|
||||
while (c = mem_data[s++])
|
||||
{
|
||||
if (i == '\r')
|
||||
i = '\n';
|
||||
putchar(i);
|
||||
if (c == 0x0D)
|
||||
c = '\n';
|
||||
putchar(c);
|
||||
}
|
||||
PUSH(0);
|
||||
break;
|
||||
|
@ -9,7 +9,6 @@
|
||||
#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)
|
||||
@ -19,7 +18,8 @@
|
||||
#define STRING_TYPE (1 << 10)
|
||||
#define TAG_TYPE (1 << 11)
|
||||
#define EXPORT_TYPE (1 << 12)
|
||||
|
||||
#define PREDEF_TYPE (1 << 13)
|
||||
#define FUNC_TYPE (ASM_TYPE | DEF_TYPE | PREDEF_TYPE)
|
||||
int id_match(char *name, int len, char *id);
|
||||
int idlocal_lookup(char *name, int len);
|
||||
int idglobal_lookup(char *name, int len);
|
||||
@ -27,7 +27,7 @@ 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_set(char *name, int len, int type, int tag);
|
||||
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);
|
||||
|
@ -49,5 +49,5 @@ export def indirect
|
||||
mainptr()
|
||||
end
|
||||
|
||||
ascii
|
||||
indirect
|
||||
done
|
||||
|
Loading…
Reference in New Issue
Block a user