mirror of
https://github.com/badvision/lawless-legends.git
synced 2024-11-15 04:08:04 +00:00
Centralized some zero-page, I/O, and ROM defines. More memory manager code written.
This commit is contained in:
parent
7bc7c94f8b
commit
afaca91d28
@ -6,9 +6,9 @@
|
||||
; if any, are used there as well as usage flags to mark free, used, or reserved memory.
|
||||
;
|
||||
; Memory is marked as used as it is loaded by the loader, but the caller program
|
||||
; should mark memory as free as soon as the memory is no longer in use. It is
|
||||
; very possible that the memory will not be reclaimed right away and could be
|
||||
; reinstated as in-use without a loading penalty.
|
||||
; should free it as soon as the memory is no longer in use. It is very possible that
|
||||
; the memory will not be reclaimed right away and could be reinstated as in-use without
|
||||
; a loading penalty.
|
||||
;
|
||||
; Another scenario is that free memory will be relocated to auxiliary banks
|
||||
; and potentially later restored to active memory at a later time. Depending on the
|
||||
@ -34,11 +34,9 @@
|
||||
; FFFFtttt nnnnnnnn
|
||||
; F = Flags
|
||||
; 7 - Active/Inactive
|
||||
; 6 - Locked (Cannot reclaim for any reason)
|
||||
; 5 - Primary (1) or Secondary (0)
|
||||
; 6 - Primary (1) or Secondary (0)
|
||||
; Memory pages are allocated in chunks, the first page is always primary
|
||||
; So detecting primary pages means we can clear more than one page at a time
|
||||
; 4 - Loaded (Memory contains copy of disk-based resource identified below)
|
||||
; t = Type of resource (1-15, 0 is invalid)
|
||||
; n = Resource number (1-255, 0 is invalid)
|
||||
;
|
||||
@ -58,12 +56,6 @@
|
||||
mainLoader = $800
|
||||
auxLoader = $803
|
||||
|
||||
; Monitor routines
|
||||
setNorm = $FE84
|
||||
monInit = $FB2F
|
||||
setVid = $FE93
|
||||
setKbd = $FE89
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; Command codes
|
||||
|
||||
@ -90,32 +82,36 @@ RESET_MEMORY = $10
|
||||
; This command is acted upon and then passed on to chained loaders.
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
LOCK_MEMORY = $11
|
||||
; Input: X-reg - page address for start of reservation
|
||||
; Y-reg - number of pages to reserve
|
||||
;
|
||||
; Output: None
|
||||
;
|
||||
; Reserve a specific area of memory. If it cannot be reserved for any reason,
|
||||
; a FATAL_ERROR is triggered.
|
||||
;
|
||||
; This command is acted upon immediately and chained loaders are not called.
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
REQUEST_MEMORY = $12
|
||||
REQUEST_MEMORY = $11
|
||||
; Input: X-reg - number of pages to allocate
|
||||
;
|
||||
; Output: X-reg - starting memory page that was allocated
|
||||
; Output: A-reg - starting memory page that was allocated
|
||||
;
|
||||
; Allocate a number of blocks in the memory space of this loader. If there
|
||||
; isn't a large enough continguous memory segment available, the system
|
||||
; will be halted immediately with HALT_MEMORY.
|
||||
;
|
||||
; Normally this command chooses the location of the memory area; if you
|
||||
; want to force it to use a particular location, use SET_MEM_TARGET first.
|
||||
;
|
||||
; To allocate main memory, call the main memory loader. To allocate aux
|
||||
; mem, call that loader instead.
|
||||
;
|
||||
; This command is acted upon immediately and chained loaders are not called.
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
SET_MEM_TARGET = $12
|
||||
; Input: X-reg - page number target
|
||||
;
|
||||
; Output: None
|
||||
;
|
||||
; Sets the target page in memory for the next REQUEST_MEMORY or QUEUE_LOAD
|
||||
; command. This will force allocation at a specific location instead
|
||||
; allowing the loader to choose.
|
||||
;
|
||||
; This is a one-shot command, i.e. as soon as an allocation is performed,
|
||||
; subsequent allocations will revert to their normal behavior.
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
START_LOAD = $13
|
||||
; Input: X-reg - disk partition number (0 for boot disk, 1-15 for others)
|
||||
@ -133,12 +129,15 @@ QUEUE_LOAD = $14
|
||||
; Input: X-reg - resource type
|
||||
; Y-reg - resource number
|
||||
;
|
||||
; Output: X-reg - memory page the load will occur at
|
||||
; Output: A-reg - memory page the load will occur at
|
||||
;
|
||||
; This is the main entry for loading resources from disk. It queues a load
|
||||
; request, allocating main memory to hold the entire resource. Note that
|
||||
; the load is only queued; it will be completed by FINISH_LOAD.
|
||||
;
|
||||
; Normally this command chooses the location of the memory area; if you
|
||||
; want to force it to use a particular location, use SET_MEM_TARGET first.
|
||||
;
|
||||
; Note that if the data is already in memory, its former location will
|
||||
; be returned and no disk access will be queued.
|
||||
;
|
||||
@ -168,7 +167,22 @@ FREE_MEMORY = $16
|
||||
; reused. This also clears the lock bit!
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
FATAL_ERROR = $17
|
||||
CHAIN_LOADER = $17
|
||||
; Input: X-reg / Y-reg - pointer to loader (X=lo, Y=hi) to add to chain
|
||||
;
|
||||
; Output: None
|
||||
;
|
||||
; Add a loader to the chain just after this loader. The current next
|
||||
; loader (if there is one) will be passed to the new loader with another
|
||||
; CHAIN_LOADER command.
|
||||
;
|
||||
; The purpose of a loader chain is to insert faster devices between the
|
||||
; main/aux loader (fastest) and the disk loader (slowest). Note that the
|
||||
; main mem and aux mem loaders are conceptually one; a chained loader will
|
||||
; always be inserted after them, not between them.
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
FATAL_ERROR = $18
|
||||
; Input: X-reg / Y-reg: message number or pointer (see below)
|
||||
;
|
||||
; Output: Never returns
|
||||
@ -193,103 +207,136 @@ FATAL_ERROR = $17
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; code begins here
|
||||
* = $800
|
||||
jmp mainLoader
|
||||
jmp auxLoader
|
||||
.org $800
|
||||
|
||||
nextLoaderVec: jmp diskLoader
|
||||
.include "../include/global.i"
|
||||
|
||||
mainLoader:
|
||||
lda #0 ; incremented after init
|
||||
bne :+
|
||||
jmp init
|
||||
: cmp #RESET_MEMORY
|
||||
bne :+
|
||||
jmp main_reset
|
||||
: cmp #LOCK_MEMORY
|
||||
bne :+
|
||||
jmp main_lock
|
||||
; zero page
|
||||
pPageTbl1 = $6 ; length 2
|
||||
pPageTbl2 = $8 ; length 2
|
||||
|
||||
; Initial vectors
|
||||
jmp main_dispatch
|
||||
jmp aux_dispatch
|
||||
|
||||
; Page tables
|
||||
main_pageTbl1: .res $C0
|
||||
main_pageTbl2: .res $C0
|
||||
aux_pageTbl1: .res $C0
|
||||
aux_pageTbl2: .res $C0
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; Variables
|
||||
isInitted:
|
||||
.byte 0
|
||||
targetPage:
|
||||
.byte 0
|
||||
nextLoaderVec:
|
||||
jmp diskLoader
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
main_dispatch:
|
||||
bit isInitted ; check if initted yet
|
||||
bmi :+
|
||||
jsr init ; init once only
|
||||
: cmp #REQUEST_MEMORY
|
||||
bne :+
|
||||
jmp main_req
|
||||
jmp main_request
|
||||
: cmp #QUEUE_LOAD
|
||||
bne shared_dispatch
|
||||
jmp main_queueLoad
|
||||
shared_dispatch:
|
||||
cmp #RESET_MEMORY
|
||||
bne :+
|
||||
jmp main_reset
|
||||
: cmp #SET_MEM_TARGET
|
||||
bne :+
|
||||
stx targetPage
|
||||
rts
|
||||
: cmp #FATAL_ERROR
|
||||
bne :+
|
||||
jmp fatalError
|
||||
: cmp #START_LOAD
|
||||
bcc cmdError
|
||||
cmp #FINISH_LOAD+1
|
||||
bcs cmdError
|
||||
; Found a command that needs to be chained to next loader
|
||||
; Pass command to next chained loader
|
||||
jmp nextLoaderVec
|
||||
|
||||
cmdError:
|
||||
ldx #LOAD_ERR_INVALID_COMMAND
|
||||
ldy #0
|
||||
;------------------------------------------------------------------------------
|
||||
aux_dispatch:
|
||||
cmp #REQUEST_MEMORY
|
||||
bne :+
|
||||
jmp aux_request
|
||||
: cmp #QUEUE_LOAD
|
||||
bne shared_dispatch
|
||||
jmp aux_queueLoad
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; Print fatal error message (custom or predefined) and print the
|
||||
; call stack, then halt.
|
||||
fatalError:
|
||||
tya
|
||||
bne customErr
|
||||
predefErr:
|
||||
lda #0 ; default start index
|
||||
cpy #0 ; custom message?
|
||||
bne printErr ; yes, don't do predef scan
|
||||
; note, y is now conveniently 0
|
||||
; Find a predefined error message in the table of messages
|
||||
scanPredef:
|
||||
dex
|
||||
beq foundErrMsg
|
||||
beq foundPredef
|
||||
: iny
|
||||
lda errorText,y
|
||||
bne :-
|
||||
beq predefErr
|
||||
foundErrMsg:
|
||||
beq scanPredef
|
||||
foundPredef:
|
||||
tya
|
||||
clc
|
||||
adc #<errorText
|
||||
tax
|
||||
ldy #>errorText
|
||||
bcc customErr
|
||||
iny
|
||||
customErr:
|
||||
sty pTmp+1
|
||||
stx pTmp
|
||||
; Set up text mode, print message
|
||||
ldx #<errorText
|
||||
printErr:
|
||||
jsr setNorm
|
||||
jsr monInit
|
||||
jsr setVid
|
||||
jsr setKbd
|
||||
; Set up text mode, print message
|
||||
pha ; save index
|
||||
sty pTmp+1 ; save message ptr hi...
|
||||
stx pTmp ; ...and lo
|
||||
jsr setnorm ; set up text mode and vectors
|
||||
jsr textinit
|
||||
jsr setvid
|
||||
jsr setkbd
|
||||
jsr crout ; a couple newlines
|
||||
jsr crout
|
||||
jsr crout
|
||||
ldy #0
|
||||
pla ; restore message pointer
|
||||
tay
|
||||
: lda (pTmp),y
|
||||
beq :+
|
||||
jsr cout
|
||||
iny
|
||||
bne :-
|
||||
; Print call stack
|
||||
jsr crout
|
||||
tsx
|
||||
: cpx #$FF
|
||||
beq :+
|
||||
inx
|
||||
lda 100,x
|
||||
: jsr crout
|
||||
tsx ; start at current stack pointer
|
||||
@stackLoop:
|
||||
lda 101,x ; JSR increments PC twice before pushing it
|
||||
sec
|
||||
sbc #2
|
||||
sta pTmp
|
||||
lda 101,x
|
||||
tay
|
||||
lda 102,x
|
||||
sbc #0
|
||||
sta pTmp+1
|
||||
and #$C0
|
||||
sta @load+2
|
||||
and #$C0 ; avoid accidentally grabbing data from the IO area
|
||||
cmp #$C0
|
||||
beq :-
|
||||
ldy #0
|
||||
lda (pTmp),y
|
||||
@load:
|
||||
lda $1000,y ; is there a JSR there?
|
||||
cmp #$20
|
||||
bne :-
|
||||
lda pTmp+1
|
||||
jsr prByte
|
||||
lda pTmp
|
||||
jsr prByte
|
||||
lda @load+2
|
||||
jsr prbyte
|
||||
tya
|
||||
jsr prbyte
|
||||
lda #$A0
|
||||
jsr cout
|
||||
jmp :-
|
||||
inx ; work up to...
|
||||
cpx #$FF ; ...top of stack
|
||||
bcc @stackLoop
|
||||
; Beep, and loop forever
|
||||
: jsr bell
|
||||
loopForever: jmp loopForever
|
||||
jsr bell
|
||||
loopForever:
|
||||
jmp loopForever
|
||||
|
||||
errorText:
|
||||
.byte "Invalid command", 0
|
||||
@ -297,3 +344,166 @@ errorText:
|
||||
.byte "Reserved memory", 0
|
||||
.byte "Unknown error", 0
|
||||
.byte 0
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
init:
|
||||
; clear the page tables
|
||||
ldy #0
|
||||
tya
|
||||
: sta main_pageTbl1,y
|
||||
sta main_pageTbl2,y
|
||||
sta aux_pageTbl1,y
|
||||
sta aux_pageTbl2,y
|
||||
iny
|
||||
cpy #$C0
|
||||
bne :-
|
||||
; make sure init won't get called next time
|
||||
sty isInitted
|
||||
rts
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
main_setup:
|
||||
lda #<main_pageTbl1
|
||||
sta pPageTbl1
|
||||
lda #>main_pageTbl1
|
||||
sta pPageTbl1+1
|
||||
lda #<main_pageTbl2
|
||||
sta pPageTbl2
|
||||
lda #>main_pageTbl2
|
||||
sta pPageTbl2+1
|
||||
rts
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
aux_setup:
|
||||
lda #<aux_pageTbl1
|
||||
sta pPageTbl1
|
||||
lda #>aux_pageTbl1
|
||||
sta pPageTbl1+1
|
||||
lda #<aux_pageTbl2
|
||||
sta pPageTbl2
|
||||
lda #>aux_pageTbl2
|
||||
sta pPageTbl2+1
|
||||
rts
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
main_reset:
|
||||
; Set all pages from end of memory manager up to (but not including) ProDOS
|
||||
; system page as "inactive".
|
||||
ldy #>codeEnd
|
||||
iny
|
||||
: lda main_pageTbl1,y
|
||||
and #$7F ; strip the "active" bit
|
||||
sta main_pageTbl1,y
|
||||
iny
|
||||
cpy #$BF ; stop just before ProDOS sys page
|
||||
bne :-
|
||||
aux_reset:
|
||||
; Set all pages except zero page and stack to "inactive"
|
||||
ldy #2
|
||||
: lda aux_pageTbl1,y
|
||||
and #$7F ; strip the "active" bit
|
||||
sta aux_pageTbl1,y
|
||||
iny
|
||||
cpy #$C0 ; stop at end of 48K mem bank
|
||||
bne :-
|
||||
jmp nextLoaderVec ; allow chained loaders to reset also
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
main_request:
|
||||
jsr main_setup
|
||||
shared_request:
|
||||
lda targetPage ; see if SET_MEM_TARGET was called
|
||||
ldy #0
|
||||
sty targetPage ; clear it for next time
|
||||
tay
|
||||
bne @gotPage ; if SET_MEM_TARGET was called, don't scan
|
||||
; need to scan for a block that has enough pages
|
||||
stx tmp ; save number of pages
|
||||
ldy #1 ; begin scan at page 2 (1+1)
|
||||
@blockLoop:
|
||||
iny ; try next page
|
||||
sty tmp+1 ; remember starting page of area
|
||||
ldx #0 ; initialize count of free pages found
|
||||
@pageLoop:
|
||||
cpy #$C0 ; stop at end of mem
|
||||
bcs outOfMemErr
|
||||
lda (pPageTbl1),y ; is page active?
|
||||
bmi @blockLoop ; yes active, skip it
|
||||
iny
|
||||
inx ; got one more inactive page
|
||||
cpx tmp ; is it enough?
|
||||
bcc @pageLoop ; no, keep going
|
||||
@foundBlock: ; yes, got enough
|
||||
ldy tmp+1 ; recall starting page
|
||||
@gotPage:
|
||||
lda #$C0 ; mark first page as $80 (active) + $40 (primary)
|
||||
: cpy #$C0 ; all pages from $C0.FF are reserved
|
||||
bcs reservedErr
|
||||
pha
|
||||
lda (pPageTbl1),y ; don't want to reserve same area twice
|
||||
bne reservedErr
|
||||
pla
|
||||
sta (pPageTbl1),y
|
||||
lda #$80 ; mark subsequent pages as $80 (active) but not primary
|
||||
iny
|
||||
dex
|
||||
bne :-
|
||||
lda tmp+1 ; return starting page
|
||||
rts
|
||||
reservedErr:
|
||||
ldx #LOAD_ERR_RESERVED_MEM
|
||||
produceErr:
|
||||
ldy #0
|
||||
lda #FATAL_ERROR
|
||||
jmp mainLoader
|
||||
outOfMemErr:
|
||||
ldx #LOAD_ERR_OUT_OF_MEMORY
|
||||
bne produceErr ; always taken
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
aux_request:
|
||||
jsr aux_setup
|
||||
jmp shared_request
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
main_queueLoad:
|
||||
jsr main_setup
|
||||
shared_queueLoad:
|
||||
stx tmp ; save resource type
|
||||
sty tmp+1 ; save resource number
|
||||
; Scan to see if we already have this resource in memory
|
||||
ldy #0
|
||||
@scanLoop:
|
||||
lda (pPageTbl1),y
|
||||
and #$40 ; primary? that is, start of an area?
|
||||
bcc @skip ; no, skip it
|
||||
lda (pPageTbl1),y
|
||||
and #$F ; extract resource type
|
||||
cmp tmp ; is it the type we're looking for?
|
||||
bne @skip ; no, skip it
|
||||
lda (pPageTbl2),y ; get resource number
|
||||
cmp tmp+1 ; is it the resource # we're looking for?
|
||||
beq @found ; yes! found what we want.
|
||||
@skip:
|
||||
iny ; next page
|
||||
cpy #$C0 ; end of memory?
|
||||
bne @scanLoop ; no, keep scanning
|
||||
ldx tmp ; yes, end of memory. Recall type parameter
|
||||
ldy tmp+1 ; recall resource number
|
||||
jmp nextLoaderVec ; call next loader so it can load the resource
|
||||
@found:
|
||||
lda (pPageTbl1),y
|
||||
ora #$80 ; mark this area as active now
|
||||
sta (pPageTbl1),y
|
||||
tya ; transfer page num to A-reg for API return
|
||||
rts
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
aux_queueLoad:
|
||||
jsr aux_setup
|
||||
jmp shared_queueLoad
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; Marker for end of the code, so we can compute its length
|
||||
codeEnd:
|
||||
|
||||
|
47
Platform/Apple/virtual/src/include/global.i
Normal file
47
Platform/Apple/virtual/src/include/global.i
Normal file
@ -0,0 +1,47 @@
|
||||
; Shared definitions for all modules
|
||||
|
||||
; Zero page temps
|
||||
tmp = $2 ; len 2
|
||||
pTmp = $4 ; len 2
|
||||
|
||||
; Zero page monitor locations
|
||||
a2l = $3E
|
||||
a2h = $3F
|
||||
|
||||
; Other monitor locations
|
||||
resetVec = $3F2
|
||||
|
||||
; I/O locations
|
||||
kbd = $C000
|
||||
clrAuxRd = $C002
|
||||
setAuxRd = $C003
|
||||
clrAuxWr = $C004
|
||||
setAuxWr = $C005
|
||||
clrAuxZP = $C008
|
||||
setAuxZP = $C009
|
||||
kbdStrobe = $C010
|
||||
clrText = $C050
|
||||
setText = $C051
|
||||
clrMixed = $C052
|
||||
setMixed = $C053
|
||||
page1 = $C054
|
||||
page2 = $C055
|
||||
clrHires = $C056
|
||||
setHires = $C057
|
||||
|
||||
; ROM routines
|
||||
prntax = $F941
|
||||
textinit = $FB2F
|
||||
rdkey = $FD0C
|
||||
getln1 = $FD6F
|
||||
crout = $FD8E
|
||||
prbyte = $FDDA
|
||||
cout = $FDED
|
||||
setnorm = $FE84
|
||||
setkbd = $FE89
|
||||
setvid = $FE93
|
||||
prerr = $FF2D
|
||||
bell = $FF3A
|
||||
monitor = $FF69
|
||||
getnum = $FFA7
|
||||
|
@ -1,5 +1,7 @@
|
||||
; Shared definitions for the rendering code
|
||||
|
||||
.include "../include/global.i"
|
||||
|
||||
; Constants
|
||||
TOP_LINE = $2180 ; 24 lines down from top
|
||||
NLINES = 128
|
||||
@ -21,15 +23,10 @@ BLIT_OFF6 = 24
|
||||
BLIT_STRIDE = 29
|
||||
|
||||
; Renderer zero page
|
||||
playerDir = $3 ; len 1
|
||||
playerX = $4 ; len 2 (hi=integer, lo=fraction)
|
||||
playerY = $6 ; len 2 (hi=integer, lo=fraction)
|
||||
pDst = $8 ; len 2
|
||||
pTex = $A ; len 2
|
||||
pixNum = $C ; len 1
|
||||
byteNum = $D ; len 1
|
||||
pTmp = $E ; len 2
|
||||
tmp = $10 ; len 2
|
||||
mapWidth = $12 ; len 1
|
||||
mapHeight = $13 ; len 1
|
||||
pRayData = $14 ; len 2
|
||||
@ -56,11 +53,9 @@ maxX = $5D ; len 1
|
||||
minY = $5E ; len 1
|
||||
maxY = $5F ; len 1
|
||||
screenCol = $60 ; len 1
|
||||
|
||||
; Other monitor locations
|
||||
a2l = $3E
|
||||
a2h = $3F
|
||||
resetVec = $3F2
|
||||
playerDir = $61 ; len 1
|
||||
playerX = $62 ; len 2 (hi=integer, lo=fraction)
|
||||
playerY = $64 ; len 2 (hi=integer, lo=fraction)
|
||||
|
||||
;---------------------------------
|
||||
; The following are all in aux mem...
|
||||
@ -85,35 +80,6 @@ blitRoll = $B000 ; Unrolled blitting code. Size 29*128 = $E80, plus 1 for
|
||||
MLI = $BF00 ; Entry point for ProDOS MLI
|
||||
memMap = $BF58 ; ProDOS memory map
|
||||
|
||||
; I/O locations
|
||||
kbd = $C000
|
||||
clrAuxRd = $C002
|
||||
setAuxRd = $C003
|
||||
clrAuxWr = $C004
|
||||
setAuxWr = $C005
|
||||
clrAuxZP = $C008
|
||||
setAuxZP = $C009
|
||||
kbdStrobe = $C010
|
||||
clrText = $C050
|
||||
setText = $C051
|
||||
clrMixed = $C052
|
||||
setMixed = $C053
|
||||
page1 = $C054
|
||||
page2 = $C055
|
||||
clrHires = $C056
|
||||
setHires = $C057
|
||||
|
||||
; ROM routines
|
||||
prntax = $F941
|
||||
rdkey = $FD0C
|
||||
getln1 = $FD6F
|
||||
crout = $FD8E
|
||||
prbyte = $FDDA
|
||||
cout = $FDED
|
||||
prerr = $FF2D
|
||||
monitor = $FF69
|
||||
getnum = $FFA7
|
||||
|
||||
; mipmap level offsets
|
||||
MIP_OFFSET_0 = 0
|
||||
MIP_OFFSET_1 = $400 ; 32*32
|
||||
|
Loading…
Reference in New Issue
Block a user