Merge branch 'master' into pfont

This commit is contained in:
Martin Haye 2015-06-06 14:23:08 -07:00
commit e70280df73
7 changed files with 550 additions and 415 deletions

View File

@ -4,7 +4,7 @@
;
; See detailed description in mem.i
* = $800
* = $2000 ; PLASMA loader loads us initially at $2000
; Use hi-bit ASCII for Apple II
!convtab "../include/hiBitAscii.ct"
@ -46,36 +46,391 @@ headerBuf = $4C00 ; len $1400
prodosMemMap = $BF58
;------------------------------------------------------------------------------
; Initial vectors - these have to start at $800
codeBegin:
clc
bcc locationCheck
jmp main_dispatch
jmp aux_dispatch
jmp __asmPlasm
locationCheck:
jsr monrts
tsx
lda $100,x
cmp #>*
bne +
jmp init
+ sta pSrc+1
lda #>*
sta pDst+1
; Relocate all the pieces to their correct locations
relocate:
; first our lo memory piece goes to $800 (two pages should be plenty)
ldy #0
sty pSrc
sty pDst
ldx #>(tableEnd-codeBegin+$100)
- lda (pSrc),y
sta (pDst),y
- lda loMemBegin,y
sta $800,y
lda loMemBegin+$100,y
sta $900,y
iny
bne -
inc pSrc+1
inc pDst+1
dex
bne -
jmp codeBegin
; copy the ProDOS code from main memory to aux
bit setLcRW+lcBank1 ; only copy bank 1, because bank 2 is PLASMA runtime
bit setLcRW+lcBank1 ; write to it
ldy #0
ldx #$D0
.pglup stx .ld+2
stx .st+2
.bylup sta clrAuxZP ; get byte from main LC
.ld lda $D000,y
sta setAuxZP ; temporarily turn on aux LC
.st sta $D000,y
iny
bne .bylup
inx ; all pages until we hit $00
bne .pglup
sta clrAuxZP ; ...back to main LC
; patch into the main ProDOS MLI entry point
lda #$4C ; jmp
sta $BFBB
lda #<enterProDOS1
sta $BFBC
lda #>enterProDOS1
sta $BFBD
; patch into the interrupt handler
lda #$4C ; jmp
sta $BFEB
lda #<enterProDOS2
sta $BFEC
lda #>enterProDOS2
sta $BFED
; patch into the shared MLI/IRQ exit routine
lda #$4C ; jmp
sta $BFA0
lda #<exitProDOS
sta $BFA1
lda #>exitProDOS
sta $BFA2
; now blow away the main RAM LC area as a check
ldx #$D0
lda #0
tay
.clrlup stx .st2+2
.st2 sta $D000,Y
iny
bne .st2
inx
cpx #$F8
bne .clrlup
; it's very convenient to have the monitor in the LC for debugging
bit setLcWr+lcBank1 ; read from ROM, write to LC RAM
.cpmon stx .ld3+2
stx .st3+2
.ld3 lda $F800,Y
.st3 sta $F800,Y
iny
bne .ld3
inx
bne .cpmon
; Place the bulk of the memory manager code into the newly cleared LC
ldx #>hiMemBegin
.cpmm stx .ld4+2
.ld4 lda hiMemBegin,y
.st4 sta $D000,y
iny
bne .ld4
inc .st4+2
inx
cpx #>(hiMemEnd+$100)
bne .cpmm
; Ready to actually init the memory manager in its final location.
; fall through to j_init...
;------------------------------------------------------------------------------
; Vectors and debug support code - these go in low memory at $800
loMemBegin: !pseudopc $800 {
jmp j_init
jmp j_main_dispatch
jmp j_aux_dispatch
jmp __asmPlasm
; Vectors for debug macros
jmp __writeStr
jmp __prByte
jmp __prSpace
jmp __prWord
jmp __prA
jmp __prX
jmp __prY
jmp __crout
jmp __waitKey
j_init:
bit setLcRW+lcBank1 ; switch in mem mgr
bit setLcRW+lcBank1
jsr init
bit setLcRW+lcBank2 ; back to PLASMA
rts
j_main_dispatch:
bit setLcRW+lcBank1 ; switch in mem mgr
bit setLcRW+lcBank1
jsr main_dispatch
bit setLcRW+lcBank2 ; back to PLASMA
rts
j_aux_dispatch:
bit setLcRW+lcBank1 ; switch in mem mgr
bit setLcRW+lcBank1
jsr aux_dispatch
bit setLcRW+lcBank2 ; back to PLASMA
rts
;------------------------------------------------------------------------------
; Normal entry point for ProDOS MLI calls. This patches the code at $BFBB.
enterProDOS1: !zone
pla ; saved A reg
sta .ld2+1
pla ; lo byte of ret addr
sta .ld1+1
pla ; hi byte of ret addr
sta setAuxZP ; switch to aux stack/ZP/LC
pha ; hi byte of ret addr
.ld1 lda #11 ; self-modified earlier
pha ; lo byte of ret addr
.ld2 lda #11 ; saved A reg
pha
lda $E000 ; this is what the original code at $BFBB did
jmp $BFBE ; jump back in where ProDOS enter left off
;------------------------------------------------------------------------------
; Entry point for ProDOS interrupt handler. This patches the code at $BFEB.
enterProDOS2: !zone
pla ; saved P reg
sta .ld2+1
pla ; ret addr lo
sta .ld1+1
pla ; ret addr hi
sta setAuxZP ; switch to aux stack/ZP/LC
pha
.ld1 lda #11 ; self-modified earlier
pha
.ld2 lda #11 ; ditto
pha
bit $C08B ; this is what the original code at $BFEB did
jmp $BFEE ; back to where ProDOS left off
;------------------------------------------------------------------------------
; Shared exit point for ProDOS MLI and IRQ handlers. This patches the code
; at $BFA0.
exitProDOS: !zone
pla ; saved A reg
sta .ld3+1
pla ; P-reg for RTI
sta .ld2+1
pla ; hi byte of ret addr
sta .ld1+1
pla ; lo byte of ret addr
sta clrAuxZP ; back to main stack/ZP/LC
pha ; lo byte of ret addr
.ld1 lda #11 ; self-modified earlier
pha ; hi byte of ret addr
.ld2 lda #11 ; ditto
pha ; P-reg for RTI
.ld3 lda #11 ; self-modified earlier (the saved A reg)
; Note! We leave LC bank 1 enabled, since that's where the memory
; manager lives, and it's the only code that calls ProDOS.
rti ; RTI pops P-reg and *exact* return addr (not adding 1)
;------------------------------------------------------------------------------
; Utility routine for convenient assembly routines in PLASMA code.
; Params: Y=number of parameters passed from PLASMA routine
; 1. Save PLASMA's X register index to evalStk
; 2. Verify X register is in the range 0-$10
; 3. Load the *last* parameter into A=lo, Y=hi
; 4. Run the calling routine (X still points into evalStk for add'l params if needed)
; 5. Restore PLASMA's X register, and advance it over the parameter(s)
; 6. Store A=lo/Y=hi into PLASMA return value
; 7. Return to PLASMA
__asmPlasm: !zone
pla ; save address of calling routine, so we can call it
clc
adc #1
sta .jsr+1
pla
adc #0
sta .jsr+2
; adjust PLASMA stack pointer to skip over params
dey
sty tmp
txa
cpx #$11
bcs .badx ; X must be in range 0..$10
.add adc tmp ; carry cleared by cpx above
pha ; and save that
cmp #$11 ; again, X must be in range 0..$10
bcs .badx
lda evalStkL,x ; get last param to A=lo
ldy evalStkH,x ; ...Y=hi
.jsr jsr $1111 ; call the routine to do work
sta tmp ; stash return value lo
pla
tax ; restore adjusted PLASMA stack pointer
lda tmp
sta evalStkL,x ; store return value
tya
sta evalStkH,x
rts ; and return to PLASMA interpreter
.badx ; X reg ran outside valid range. Print and abort.
+prStr : !text $8D,"X=",0
+prX
ldx #<+
ldy #>+
jmp fatalError
+ !text $8D, "PLASMA x-reg out of range", 0
;------------------------------------------------------------------------------
; Debug code to support macros
; Fetch a byte pointed to by the first entry on the stack, and advance that entry.
_getStackByte !zone {
inc $101,x
bne +
inc $102,x
+ lda $101,x
sta .ld+1
lda $102,x
sta .ld+2
.ld: lda $2000
rts
}
; Support to print a string following the JSR, in high or low bit ASCII,
; terminated by zero. If the string has a period "." it will be followed
; automatically by a carriage return. Preserves all registers.
__writeStr: !zone {
jsr iosave
tsx
.loop: jsr _getStackByte
beq .done
jsr cout
cmp #$AE ; "."
bne .loop
jsr crout
jmp .loop
.done: jmp iorest
}
__prByte: !zone {
jsr iosave
ldy #0
; fall through to _prShared...
}
_prShared: !zone {
tsx
jsr _getStackByte
sta .ld+1
jsr _getStackByte
sta .ld+2
.ld: lda $2000,y
jsr prbyte
dey
bpl .ld
+prSpace
jmp iorest
}
__prSpace: !zone {
php
pha
lda #$A0
jsr cout
pla
plp
rts
}
__prWord: !zone {
jsr iosave
ldy #1
bne _prShared ; always taken
}
__prA: !zone {
php
pha
jsr prbyte
pla
plp
rts
}
__prX: !zone {
php
pha
txa
jsr prbyte
pla
plp
rts
}
__prY: !zone {
php
pha
tya
jsr prbyte
pla
plp
rts
}
__crout: !zone {
php
pha
jsr crout
pla
plp
rts
}
__waitKey: !zone {
jsr iosave
jsr rdkey
jmp iorest
}
!macro callMLI cmd, parms {
lda #cmd
ldx #<parms
ldy #>parms
jsr _callMLI
}
; Call MLI from main memory rather than LC, since it lives in aux LC.
_callMLI: sta .cmd
stx .params
sty .params+1
jsr mli
.cmd !byte 0
.params !word 0
rts
; Out ProDOS param blocks can't be in LC ram
openParams: !byte 3 ; param count
!word filename ; pointer to file name
!word fileBuf ; pointer to buffer
openFileRef: !byte 0 ; returned file number
filename: !byte 15 ; length
!raw "/LL/GAME.PART." ; TODO: Figure out how to avoid specifying full path. "raw" for ProDOS
; If I leave it out, ProDOS complains with error $40.
partNumChar: !raw "x" ; "x" replaced by partition number
readParams: !byte 4 ; param count
readFileRef: !byte 0 ; file ref to read
readAddr: !word 0
readLen: !word 0
readGot: !word 0
setMarkParams: !byte 2 ; param count
setMarkFileRef: !byte 0 ; file reference to set mark in
setMarkPos: !byte 0 ; mark position (3 byte integer)
!byte 0
!byte 0
closeParams: !byte 1 ; param count
closeFileRef: !byte 0 ; file ref to close
paramsEnd = *
} ; end of !pseodupc $800
loMemEnd = *
;------------------------------------------------------------------------------
; The remainder of the code gets relocated up into the Language Card, bank 1.
hiMemBegin: !pseudopc $D000 {
;------------------------------------------------------------------------------
; Variables
@ -88,9 +443,6 @@ curPartition: !byte 0
partFileRef: !byte 0
fixupHint: !word 0
;------------------------------------------------------------------------------
!if DEBUG { !source "../include/debug.i" }
;------------------------------------------------------------------------------
grabSegment: !zone
; Input: None
@ -314,10 +666,12 @@ saneCheck: !zone {
lda $BF00
cmp #$4C
beq +
+prChr 'S'
brk
+ lda $E1
cmp #$BE
bcc +
+prChr 's'
brk
+ rts
}
@ -413,13 +767,7 @@ fatalError: !zone
init: !zone
; put something interesting on the screen :)
jsr home
ldx #0
- lda .welcomeStr,x
beq +
jsr cout
inx
bne -
+
+prStr : !text "Welcome to Mythos.",0
; close all files
lda #0
jsr closeFile
@ -429,6 +777,7 @@ init: !zone
.clr: sta prodosMemMap-1,x
dex
bne .clr
; clear the segment tables
- sta tSegLink,x
sta tSegAdrLo,x
@ -463,8 +812,10 @@ init: !zone
; 3: aux $C000 -> 0, active + locked
; 4: main $0xxx -> 5, inactive (xxx = end of mem mgr tables)
; 5: main $2000 -> 6, active + locked
; 6: main $6000 -> 3, inactive
; 7: main $BF00 -> 0, active + locked
; 6: main $6000 -> 7, inactive
; 7: main $BF00 -> 8, active + locked
; 8: main $E000 -> 9, inactive
; 9: main $F800 -> 0, active + locked
; First, the flags
lda #$C0 ; flags for active + locked (with no resource)
sta tSegType+0
@ -472,6 +823,7 @@ init: !zone
sta tSegType+3
sta tSegType+5
sta tSegType+7
sta tSegType+9
; Next the links
ldx #2
stx tSegLink+1
@ -485,6 +837,10 @@ init: !zone
stx tSegLink+5
inx
stx tSegLink+6
inx
stx tSegLink+7
inx
stx tSegLink+8
; Then the addresses
lda #2
sta tSegAdrHi+2
@ -492,18 +848,22 @@ init: !zone
sty tSegAdrHi+3
dey
sty tSegAdrHi+7
lda #<tableEnd
lda #<paramsEnd
sta tSegAdrLo+4
lda #>tableEnd
lda #>paramsEnd
sta tSegAdrHi+4
lda #$40
sta tSegAdrHi+5
lda #$60
sta tSegAdrHi+6
lda #$E0
sta tSegAdrHi+8
lda #$F8
sta tSegAdrHi+9
; Finally, form a long list of the remaining unused segments.
ldx #8
ldx #10
stx unusedSeg ; that's the first unused seg
ldy #9
ldy #11
.loop: tya
sta tSegLink,x
inx
@ -514,11 +874,11 @@ init: !zone
!if SANITY_CHECK {
lda #$20
sta framePtr+1 ; because sanity check verifies it's not $BE or $BF
}
}
ldx #0
ldy #2 ; 2 pages
lda #REQUEST_MEMORY
jsr mainLoader
jsr main_dispatch
stx framePtr
stx outerFramePtr
iny ; twice for 2 pages: initial pointer at top of new space
@ -528,25 +888,33 @@ init: !zone
dey
dey
lda #LOCK_MEMORY ; lock it in place forever
jsr mainLoader
jsr main_dispatch
; Reserve hi-res page 1
lda #SET_MEM_TARGET
ldx #0
ldy #$20 ; at $2000
jsr main_dispatch
lda #REQUEST_MEMORY
ldx #0
ldy #$20 ; length $2000
jsr main_dispatch
; Load PLASMA module #1
ldx #0
lda #START_LOAD
jsr mainLoader
jsr main_dispatch
ldx #RES_TYPE_MODULE
ldy #1
lda #QUEUE_LOAD
jsr mainLoader
jsr main_dispatch
stx .gomod+1
sty .gomod+2
lda #LOCK_MEMORY ; lock it in forever
jsr mainLoader
jsr main_dispatch
ldx #1 ; keep open for efficiency's sake
lda #FINISH_LOAD
jsr mainLoader
jsr main_dispatch
ldx #$10 ; initial eval stack index
.gomod: jmp $1111 ; jump to module for further bootstrapping
.welcomeStr !text "Welcome to MythOS.",$8D,0
;------------------------------------------------------------------------------
!if DEBUG {
@ -631,7 +999,7 @@ reservedErr: !zone
ldx #<+
ldy #>+
jmp fatalError
+ !text "Mem reserved", 0
+ !text "Mem already alloc'd", 0
;------------------------------------------------------------------------------
main_request: !zone
@ -1063,14 +1431,12 @@ openPartition: !zone
lda curPartition
clc
adc #'0' ; assume partition numbers range from 0..9 for now
sta .partNumChar
sta partNumChar
; open the file
jsr mli
!byte MLI_OPEN
!word .openParams
+callMLI MLI_OPEN, openParams
bcs prodosError
; grab the file number, since we're going to keep it open
lda .openFileRef
lda openFileRef
sta partFileRef
sta readFileRef
; Read the first two bytes, which tells us how long the header is.
@ -1092,21 +1458,6 @@ openPartition: !zone
sta readAddr
jmp readToMain ; finish by reading the rest of the header
.openParams: !byte 3 ; number of params
!word .filename ; pointer to file name
!word fileBuf ; pointer to buffer
.openFileRef: !byte 0 ; returned file number
.filename: !byte 15 ; length
!raw "/LL/GAME.PART." ; TODO: Figure out how to avoid specifying full path. "raw" for ProDOS
; If I leave it out, ProDOS complains with error $40.
.partNumChar: !raw "x" ; "x" replaced by partition number
readParams: !byte 4 ; number of params
readFileRef: !byte 0
readAddr: !word 0
readLen: !word 0
readGot: !word 0
;------------------------------------------------------------------------------
prodosError: !zone
pha
@ -1231,16 +1582,15 @@ disk_finishLoad: !zone
lda partFileRef ; see if we actually queued anything (and opened the file)
bne + ; non-zero means we have work to do
rts ; nothing to do - return immediately
+ sta .setMarkFileRef ; copy the file ref number to our MLI param blocks
+ sta setMarkFileRef ; copy the file ref number to our MLI param blocks
sta readFileRef
lda headerBuf ; grab # header bytes
sta .setMarkPos ; set to start reading at first non-header byte in file
sta setMarkPos ; set to start reading at first non-header byte in file
lda headerBuf+1 ; hi byte too
sta .setMarkPos+1
sta setMarkPos+1
lda #0
sta .setMarkPos+2
sta setMarkPos+2
sta .nFixups
jsr setupDecomp ; one-time init for decompression code
jsr startHeaderScan ; start scanning the partition header
.scan: lda (pTmp),y ; get resource type byte
bne .notEnd ; non-zero = not end of header
@ -1304,9 +1654,7 @@ disk_finishLoad: !zone
lda tSegAdrHi,x ; hi byte too
sta pDst+1
!if DEBUG { jsr .debug2 }
jsr mli ; move the file pointer to the current block
!byte MLI_SET_MARK
!word .setMarkParams
+callMLI MLI_SET_MARK, setMarkParams ; move the file pointer to the current block
bcs .prodosErr
!if DEBUG >= 2 { +prStr : !text "Deco.",0 }
jsr lz4Decompress ; decompress (or copy if uncompressed)
@ -1314,18 +1662,18 @@ disk_finishLoad: !zone
.resume ldy .ysave
.next lda (pTmp),y ; lo byte of length
clc
adc .setMarkPos ; advance mark position exactly that far
sta .setMarkPos
adc setMarkPos ; advance mark position exactly that far
sta setMarkPos
iny
lda (pTmp),y ; hi byte of length
bpl + ; if hi bit is clear, resource is uncompressed
iny ; skip compressed size
iny
and #$7F ; mask off the flag
+ adc .setMarkPos+1 ; bump the high byte of the file mark pos
sta .setMarkPos+1
+ adc setMarkPos+1 ; bump the high byte of the file mark pos
sta setMarkPos+1
bcc +
inc .setMarkPos+2 ; account for partitions > 64K
inc setMarkPos+2 ; account for partitions > 64K
+ iny ; increment to next entry
bpl + ; if Y index is is small, no need to adjust
jsr adjYpTmp ; adjust pTmp and Y to make it small again
@ -1335,11 +1683,6 @@ disk_finishLoad: !zone
.addrErr:
jmp invalAddr
.setMarkParams: !byte 2 ; param count
.setMarkFileRef:!byte 0 ; file reference
.setMarkPos: !byte 0 ; mark position (3 byte integer)
!byte 0
!byte 0
.ysave: !byte 0
.nFixups: !byte 0
@ -1383,24 +1726,16 @@ adjYpTmp: !zone
;------------------------------------------------------------------------------
closeFile: !zone
sta .closeFileRef
jsr mli ; now that we're done loading, we can close the partition file
!byte MLI_CLOSE
!word .closeParams
sta closeFileRef
+callMLI MLI_CLOSE, closeParams
bcs .prodosErr
rts
.prodosErr:
jmp prodosError
.closeParams:
!byte 1 ; param count
.closeFileRef:
!byte 0 ; file ref to close
;------------------------------------------------------------------------------
readToMain: !zone
jsr mli
!byte MLI_READ
!word readParams
+callMLI MLI_READ, readParams
bcs .err
rts
.err: jmp prodosError
@ -1567,18 +1902,6 @@ lz4Decompress: !zone
!if DEBUG_DECOMP { sta ucLen : jsr .debug4 }
tay ; ...to count bytes
.auxWr2 sta setAuxWr ; self-modified earlier, based on isAuxCmd
; Subroutine does the work. Runs in stack area so it can write *and* read aux mem
jsr .matchCopy ; copy match bytes (aux->aux, or main->main)
sta clrAuxWr ; back to writing main mem
inc ucLen+1 ; to make it zero for the next match decode
+ ldy tmp ; restore index to source pointer
jmp .getToken ; go on to the next token in the compressed stream
; Subroutine to copy bytes, either main->main or aux->aux. We put it down in the
; stack space ($100) so it can access either area. The stack doesn't get bank-switched
; by setAuxRd/clrAuxRd.
.matchShadow_beg = *
!pseudopc $100 {
.matchCopy:
.auxRd1 sta setAuxRd ; self-modified based on isAuxCmd
.srcLoad:
lda $1100,x ; self-modified earlier for offsetted source
@ -1598,9 +1921,10 @@ lz4Decompress: !zone
dec ucLen+1 ; count pages
bpl .srcLoad ; loop for more. NOTE: this would fail if we had blocks >= 32K
sta clrAuxRd ; back to reading main mem, for mem mgr code
+ rts ; done copying bytes
}
.matchShadow_end = *
sta clrAuxWr ; back to writing main mem
inc ucLen+1 ; to make it zero for the next match decode
+ ldy tmp ; restore index to source pointer
jmp .getToken ; go on to the next token in the compressed stream
; Subroutine called when length token = $F, to extend the length by additional bytes
.longLen:
- sta ucLen ; save what we got so far
@ -1658,17 +1982,6 @@ nextSrcPage:
.auxWr4 sta setAuxWr ; go back to writing aux mem (self-modified for aux or main)
rts
; Copy the match shadow down to the stack area so it can copy from aux to aux.
; This needs to be called once before any decompression is done. We shouldn't
; rely on it being preserved across calls to the memory manager.
setupDecomp:
ldx #.matchShadow_end - .matchShadow_beg - 1
- lda .matchShadow_beg,x ; get the copy from main RAM
sta .matchCopy,x ; and put it down in stack space where it can access both main and aux
dex ; next byte
bpl - ; loop until we grab them all (including byte 0)
rts
!if DEBUG_DECOMP {
.debug1 +prStr : !text "Decompressing: isComp=",0
+prByte isCompressed
@ -1733,12 +2046,6 @@ setupDecomp:
; resources from memory.
doAllFixups: !zone
!if DEBUG >= 2 { +prStr : !text "Doing all fixups.",0 }
; copy the shadow code down to $100, so we can read aux mem bytes
ldx #.fixupShadow_end - .fixupShadow - 1
- lda .fixupShadow,x
sta .getFixupByte,x
dex
bpl -
; Now scan aux mem for fixup segments
ldx #1 ; start at first aux mem segment (0=main mem, 1=aux)
.loop: lda tSegType,x ; grab flags & type
@ -1826,7 +2133,9 @@ doAllFixups: !zone
jsr .adAux ; recalc and store hi byte
sta clrAuxWr
bne .proc ; always taken
.adAux jsr .getBytecode ; get num to add to offset
.adAux sta setAuxRd
lda (pDst),y ; get num to add to offset
sta clrAuxRd
adc .mainBase,y ; add the offset
sta (pDst),y ; *STORE* back the result
rts
@ -1873,26 +2182,13 @@ doAllFixups: !zone
.fetchFixup:
ldy #0
jsr .getFixupByte ; get a byte from aux mem
sta setAuxRd
lda (pSrc),y
sta clrAuxRd
inc pSrc ; and advance the pointer
bne +
inc pSrc+1 ; hi byte too, if necessary
+ rts
.fixupShadow:
!pseudopc $100 {
.getFixupByte:
sta setAuxRd
lda (pSrc),y
sta clrAuxRd
rts
.getBytecode:
sta setAuxRd
lda (pDst),y
sta clrAuxRd
rts
}
.fixupShadow_end = *
!if DEBUG >= 2 {
.debug1 +prStr : !text "Found fixup, res=",0
+prByte resNum
@ -1918,60 +2214,6 @@ doAllFixups: !zone
.mainBase !word 0
.auxBase !word 0
;------------------------------------------------------------------------------
; Utility routine for convenient assembly routines in PLASMA code.
; Params: Y=number of parameters passed from PLASMA routine
; 1. Save PLASMA's X register index to evalStk
; 2. Verify X register is in the range 0-$10
; 3. Switch to ROM
; 4. Load the *last* parameter into A=lo, Y=hi
; 5. Run the calling routine (X still points into evalStk for add'l params if needed)
; 6. Switch back to LC RAM
; 7. Restore PLASMA's X register, and advance it over the parameter(s)
; 8. Store A=lo/Y=hi into PLASMA return value
; 9. Return to PLASMA
__asmPlasm: !zone
bit setROM ; switch to ROM
pla ; save address of calling routine, so we can call it
clc
adc #1
sta .jsr+1
pla
adc #0
sta .jsr+2
; adjust PLASMA stack pointer to skip over params
dey
sty tmp
txa
cpx #$11
bcs .badx ; X must be in range 0..$10
.add adc tmp ; carry cleared by cpx above
pha ; and save that
cmp #$11 ; again, X must be in range 0..$10
bcs .badx
lda evalStkL,x ; get last param to A=lo
ldy evalStkH,x ; ...Y=hi
.jsr jsr $1111 ; call the routine to do work
bit setLcRW+lcBank2 ; read from language card (where PLASMA runtime lives)
sta tmp ; stash return value lo
pla
tax ; restore adjusted PLASMA stack pointer
lda tmp
sta evalStkL,x ; store return value
tya
sta evalStkH,x
rts ; and return to PLASMA interpreter
.badx jsr crout ; X reg ran outside valid range. Print and abort.
lda #'X'
jsr cout
txa
jsr prbyte
jsr crout
ldx #<+
ldy #>+
jmp fatalError
+ !text $8D, "PLASMA x-reg out of range", 0
;------------------------------------------------------------------------------
; Segment tables
@ -1986,3 +2228,6 @@ tSegAdrHi = * : !fill MAX_SEGS
;------------------------------------------------------------------------------
; Marker for end of the tables, so we can compute its length
tableEnd = *
} ; end of !pseudopc $D000
hiMemEnd = *

View File

@ -1,197 +0,0 @@
; Debug macros
!macro prStr {
jsr _writeStr
}
!macro prByte addr {
jsr _prByte
!word addr
}
!macro prSpace {
jsr _prSpace
}
!macro prChr chr {
jsr _writeStr
!byte chr, 0
}
!macro prA {
jsr _prA
jsr _prSpace
}
!macro prX {
jsr _prX
jsr _prSpace
}
!macro prY {
jsr _prY
jsr _prSpace
}
!macro prXA {
jsr _prX
jsr _prA
jsr _prSpace
}
!macro prAX {
jsr _prA
jsr _prX
jsr _prSpace
}
!macro prYA {
jsr _prY
jsr _prA
jsr _prSpace
}
!macro prAY {
jsr _prA
jsr _prY
jsr _prSpace
}
!macro prXY {
jsr _prX
jsr _prY
jsr _prSpace
}
!macro prYX {
jsr _prY
jsr _prX
jsr _prSpace
}
!macro prWord addr {
jsr _prWord
!word addr
}
!macro crout {
jsr _crout
}
!macro waitKey {
jsr _waitKey
}
; Debug code to support macros
jmp _afterDebug
; Fetch a byte pointed to by the first entry on the stack, and advance that entry.
_getStackByte !zone {
inc $101,x
bne +
inc $102,x
+ lda $101,x
sta .ld+1
lda $102,x
sta .ld+2
.ld: lda $2000
rts
}
; Support to print a string following the JSR, in high or low bit ASCII,
; terminated by zero. If the string has a period "." it will be followed
; automatically by a carriage return. Preserves all registers.
_writeStr: !zone {
jsr iosave
tsx
.loop: jsr _getStackByte
beq .done
jsr cout
cmp #$AE ; "."
bne .loop
jsr crout
jmp .loop
.done: jmp iorest
}
_prByte: !zone {
jsr iosave
ldy #0
; fall through to _prShared...
}
_prShared: !zone {
tsx
jsr _getStackByte
sta .ld+1
jsr _getStackByte
sta .ld+2
.ld: lda $2000,y
jsr prbyte
dey
bpl .ld
+prSpace
jmp iorest
}
_prSpace: !zone {
php
pha
lda #$A0
jsr cout
pla
plp
rts
}
_prWord: !zone {
jsr iosave
ldy #1
bne _prShared ; always taken
}
_prA: !zone {
php
pha
jsr prbyte
pla
plp
rts
}
_prX: !zone {
php
pha
txa
jsr prbyte
pla
plp
rts
}
_prY: !zone {
php
pha
tya
jsr prbyte
pla
plp
rts
}
_crout: !zone {
php
pha
jsr crout
pla
plp
rts
}
_waitKey: !zone {
jsr iosave
jsr rdkey
jmp iorest
}
_afterDebug:

View File

@ -102,3 +102,4 @@ iorest = $FF3F
monrts = $FF58
monitor = $FF69
getnum = $FFA7

View File

@ -292,3 +292,97 @@ FATAL_ERROR = $1F
jsr _asmPlasm
}
_asmPlasm = $809
; Debug support routines (defined in core/mem.s)
_writeStr = $80C
_prByte = _writeStr+3
_prSpace = _prByte+3
_prWord = _prSpace+3
_prA = _prWord+3
_prX = _prA+3
_prY = _prX+3
_crout = _prY+3
_waitKey = _crout+3
; Debug macros
!macro prStr {
jsr _writeStr
}
!macro prByte addr {
jsr _prByte
!word addr
}
!macro prSpace {
jsr _prSpace
}
!macro prChr chr {
jsr _writeStr
!byte chr, 0
}
!macro prA {
jsr _prA
jsr _prSpace
}
!macro prX {
jsr _prX
jsr _prSpace
}
!macro prY {
jsr _prY
jsr _prSpace
}
!macro prXA {
jsr _prX
jsr _prA
jsr _prSpace
}
!macro prAX {
jsr _prA
jsr _prX
jsr _prSpace
}
!macro prYA {
jsr _prY
jsr _prA
jsr _prSpace
}
!macro prAY {
jsr _prA
jsr _prY
jsr _prSpace
}
!macro prXY {
jsr _prX
jsr _prY
jsr _prSpace
}
!macro prYX {
jsr _prY
jsr _prX
jsr _prSpace
}
!macro prWord addr {
jsr _prWord
!word addr
}
!macro crout {
jsr _crout
}
!macro waitKey {
jsr _waitKey
}

View File

@ -120,8 +120,7 @@ asm __defs
!source "../../include/fontEngine.i"
; Optional debug printing support
DEBUG = 1
!if DEBUG { !source "../../include/debug.i" }
DEBUG = 0
; General use
tmp = $2
@ -479,7 +478,6 @@ end
// Jump straight to the system monitor
// Params: None
asm goMon
bit setROM
jmp $FF69
end
@ -487,7 +485,6 @@ end
// Execute a monitor breakpoint
// Params: None
asm brk
bit setROM
bit setText
bit page1
brk
@ -812,6 +809,7 @@ def fakeChars()
rawDisplayStr("Blak Bart 12 4 ")
rawDisplayStr("Wyld Bill 8 2 ")
rawDisplayStr("LucyLwls 9 6")
setWindow2()
end
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -1251,6 +1249,8 @@ def loadTitle()
puts("Loading Lawless Legends.\n")
// Load the title screen
loader(UNLOCK_MEMORY, MAIN_MEM, $2000)
loader(FREE_MEMORY, MAIN_MEM, $2000)
loader(SET_MEM_TARGET, MAIN_MEM, $2000)
loader(QUEUE_LOAD, MAIN_MEM, 1<<8 | RES_TYPE_SCREEN) // title screen is fixed at #1
loader(LOCK_MEMORY, MAIN_MEM, $2000)

View File

@ -28,8 +28,6 @@ DEBUG_COLUMN = -1
; Shared constants, zero page, buffer locations, etc.
!source "render.i"
; Debug macros and support functions
!source "../include/debug.i"
; Memory manager
!source "../include/mem.i"
; Font engine
@ -1617,9 +1615,7 @@ loadTextures: !zone
; finally, init the scripts.
!if DEBUG { +prStr : !text "Calling script init ",0 : +prWord .scInit+1 : +crout }
ldx plasmaStk
bit setLcRW+lcBank2 ; switch PLASMA runtime back in
.scInit jsr $1111 ; self-modified earlier
bit setROM ; back to ROM so we can work normally
!if DEBUG { +prStr : !text "Back from script init. ",0 }
rts
.get: lda $1111
@ -1764,6 +1760,7 @@ pl_render: !zone
cmp $4001
beq ++
+ jsr copyScreen ; if it was, restore by copying hgr1 to hgr2
jsr makeLines
++ jmp renderFrame ; then go ahead and render
;-------------------------------------------------------------------------------

View File

@ -104,9 +104,6 @@ next_zp = $AB
JMP pl_setColor ; params: slot (0=sky/1=ground), color (0-15); return: nothing
jmp pl_render ; params: none
; Debug support -- must come after jump vectors, since it's not just macros.
!source "../include/debug.i"
;----------------------------------------------------------------------
; >> START LOADING MAP SECTIONS
START_MAP_LOAD
@ -321,9 +318,7 @@ LOAD_SCRIPTS_NO_CALC:
+finishLoad 0 ; all done
!if DEBUG { +prStr : !text "Calling init script.",0 }
LDX PLASMA_X
BIT setLcRW+lcBank2 ; switch PLASMA runtime back in
JSR .callit ; perform script init
BIT setROM ; switch out PLASMA so we're ready to render
!if DEBUG { +prStr : !text "Back from init script.",0 }
RTS
.callit JMP (SCRIPTS_LOC) ; the init function is always first in the script module