mirror of
https://github.com/elliotnunn/boot3.git
synced 2024-12-31 23:29:50 +00:00
5b0f0cc134
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
453 lines
17 KiB
Plaintext
453 lines
17 KiB
Plaintext
;
|
|
; File: MemoryMgrExtensions.a
|
|
;
|
|
; Contains: New routines for the Memory Mgr.
|
|
;
|
|
; Written by: A bunch of people. Merged into this file by Tim Nichols
|
|
;
|
|
; Copyright: © 1990-1993 by Apple Computer, Inc., all rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <SM4> 6/14/93 kc Roll in Ludwig.
|
|
; <LW2> 5/11/93 chp MoveHLow was depending on the CCR to indicate error conditions
|
|
; reported by _RecoverHandle. This weirdass trap only returns its
|
|
; result in MemErr, so insert an explicit test to avoid crashing
|
|
; in the subsequent _HGetState. Partial fix for RADAR #1081681.
|
|
; <SM3> 10/22/92 CSS Change some branch short instructions to word branches.
|
|
; <SM2> 7/10/92 RLM add CycloneTranslate24To32
|
|
; <1> 4/8/92 tcn New today. Code from MemoryMgrPatches.a
|
|
;
|
|
|
|
|
|
load 'StandardEqu.d'
|
|
|
|
MACHINE MC68020 ;<SM2> RLM
|
|
|
|
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
;
|
|
; MoveHLow
|
|
;
|
|
; entry:
|
|
; A0 - handle requested
|
|
; exit:
|
|
; D0 - error (word)
|
|
; internal:
|
|
; A4 - (long) handle to original block
|
|
; A3 - (long) pointer to new block
|
|
; D3 - (long) size of block
|
|
; D4 - (long) offset to block tags (24 = -8; 32 = -12)
|
|
; info:
|
|
; This code does the opposite in principle to MoveHHi. The handle input
|
|
; is moved as low as possible in the heap that it belongs. This call works
|
|
; with 24 and 32 bit zones.
|
|
; to do:
|
|
; ¥ roving pointer point at newly freed block (is this good?)
|
|
|
|
myError EQU nsStackErr ;QuickDraw error meaning not enough stack
|
|
blkSize EQU -8 ;note that this offset is the same for 24/32 bit zones
|
|
StackSlop EQU (3*1024) ;3k slop for interupts and our minimal buffer
|
|
BlockTagBits EQU $C0 ;
|
|
|
|
MakeBlocksNonPurgeableStack record {a6Link},decr
|
|
startParams equ *
|
|
paramSize equ startParams-*
|
|
return ds.l 1
|
|
a6Link ds.l 1
|
|
HPurgeAddress ds.l 1 ;trap address for HPurge
|
|
hNoPurgeAddress ds.l 1 ;trap address for HNoPurge
|
|
RecoverHAddress ds.l 1 ;trap address for RecoverHandle
|
|
HGetStateAddress ds.l 1 ;trap address for HGetState
|
|
largestFreeSpace ds.l 1 ;size of largest free space available
|
|
freeSpaceAccumulator ds.l 1 ;a place to add up free space
|
|
keepCheckingFreeSpace ds.w 1 ;should we keep checking free space?
|
|
passedOurBlock ds.w 1 ;are we past our block yet?
|
|
localSize equ * ;size of all the local variables
|
|
endR
|
|
|
|
MoveHLow Proc Export
|
|
|
|
@Regs REG a3-a6/d3-d7
|
|
|
|
movem.l @Regs,-(sp) ;save regs
|
|
move.l theZone,-(sp) ;save theZone
|
|
move.l a0,a4 ;save callers A0,
|
|
; original MoveHHi did this
|
|
|
|
;check for nil master pointer
|
|
move.w #nilHandleErr,MemErr ;
|
|
move.l (a0),d0 ;check for nil MP
|
|
beq @RestoreZoneStateAndExit ;
|
|
|
|
;check for locked handle passed in, and save the state of the handle
|
|
;move.l a4,a0 ;get handle to original block
|
|
_HGetState ;
|
|
move.b d0,d2 ;save handle state of original block
|
|
move.w #memLockedErr,MemErr ;
|
|
btst #lock,d0 ;
|
|
bne @RestoreZoneStateAndExit ; <SM3> CSS
|
|
|
|
;set theZone to zone that this handle lives in
|
|
move.l a4,a0 ;get handle to original block
|
|
_HandleZone ;
|
|
tst.w d0 ;
|
|
bne @RestoreZoneStateAndExit ; <SM3> CSS
|
|
move.l a0,theZone ;temporarily set theZone to contain block
|
|
|
|
;set up offset in d4 to MemMgr Block tags (be 24/32 bit zone friendly)
|
|
moveq #-8,d4 ;-8 offset MemMgr Block tags in 24 zone
|
|
move.l Lo3Bytes,d6 ;setup mask for MakeBlocksNonPurgeable
|
|
tst.b maxNRel(a0) ;check if 32 zone
|
|
beq.s @not32bitzone ;
|
|
add.l #-4,d4 ;-12 offset MemMgr Block tags in 32 zone
|
|
moveq #-1,d6 ;setup mask for MakeBlocksNonPurgeable
|
|
@not32bitzone
|
|
|
|
;mark all purgeable blocks as non-purgeable when/if we call Newptr
|
|
|
|
;mark our block as non-purgeable
|
|
move.l a4,a0 ;get handle to original block
|
|
_HNoPurge
|
|
|
|
;always allocate a buffer on the stack
|
|
link A6,#MakeBlocksNonPurgeableStack.localSize ;Unlk A6 happens in RestorePurgeableBlocks
|
|
clr.l -(sp) ;ensure end of handle list is a nil
|
|
bsr MakeBlocksNonPurgeable ; <SM3> CSS
|
|
bne.s @DoCommonExit ;condition codes are set for failure
|
|
|
|
;allocate block of same size in lower in this heap. (first get size of handle)
|
|
move.l a4,a0 ;get handle to original block
|
|
_GetHandleSize ;
|
|
move.l d0,d3 ;save size of block and check for error
|
|
bmi.s @DoCommonExit ;
|
|
_NewPtr ;d0 from _GetHandleSize
|
|
bne.s @DoCommonExit ;check for error
|
|
move.l a0,a3 ;save pointer to new block
|
|
|
|
;the result from NewPtr may actually be higher in memory than Handle passed in
|
|
;check for this and leave handle where it is
|
|
move.l (a4),d0 ;get pointer to old block
|
|
_StripAddress ;in 24 bit world, this call needed
|
|
cmp.l a0,d0 ;is new block higher in memory than old?
|
|
blt.s @DisposeBlock ;yes, go dispose the new block
|
|
|
|
;copy junk from old handle to new pointer
|
|
move.l a0,a1 ;set up destination for blockmove
|
|
move.l (a4),a0 ;set up source for blockmove
|
|
move.l d3,d0 ;set up size for blockmove
|
|
_BlockMove
|
|
|
|
;make the handle point at the new block, and make the old block a pointer block
|
|
;fix relhandle
|
|
;move.l (a4),a0 ;point a0 at old block
|
|
move.l -(a0),-4(a3) ;fix relhandle for new block
|
|
move.l theZone,(a0)+ ;change relhandle to pointer block info
|
|
|
|
;change master pointer to point at new
|
|
move.l a3,(a4) ;no more references to old block
|
|
|
|
;mark old block as pointer block, and new block as relocateable
|
|
eori.b #BlockTagBits,(a3,d4) ;toggle new block from nonrel to rel
|
|
eori.b #BlockTagBits,(a0,d4) ;toggle old block from rel to nonrel
|
|
|
|
;Dispose of the old block (this frees the block)
|
|
@DisposeBlock
|
|
_DisposePtr
|
|
;fall through to exit code (ResoreHandleStateAndExit)
|
|
|
|
@DoCommonExit ;
|
|
;walk the heap to restore Purgeable Blocks and cleanup the stack
|
|
bsr RestorePurgeableBlocks ;
|
|
move.l (sp)+,d0 ;remove the nil marker
|
|
unlk a6 ;distroy stack buffer
|
|
|
|
;restore the master pointer flags
|
|
move.w MemErr,d3 ;preserve MemErr across _HSetState call
|
|
move.l a4,a0 ;get handle to new block
|
|
move.b d2,d0 ;restore handle state of original block
|
|
_HSetState ;
|
|
move.w d3,MemErr ;restore MemErr after _HSetState call
|
|
;set up D0, fall through to exit code (RemoveStackBuffer)
|
|
moveq #0,d0 ;
|
|
|
|
@RestoreZoneStateAndExit
|
|
move.l (sp)+,theZone ;restore theZone
|
|
move.l a4,a0 ;preserve handle across MoveHHi
|
|
move.w MemErr,d0 ;make d0 agree with MemErr
|
|
movem.l (sp)+,@Regs ;restore regs, leave cc's unchanged
|
|
rts ;return without calling through
|
|
|
|
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
;
|
|
; MakeBlocksNonPurgeable
|
|
;
|
|
; entry:
|
|
; theZone - the zone we will walk
|
|
; d4 - negative size of heapblock header.
|
|
; exit :
|
|
; a0-a1 - trashed
|
|
; a2-a3 - unchanged
|
|
; a4 - unchanged; handle of block passed to MoveHLow
|
|
; a5 - trashed, used to jump through as return address
|
|
; a6 - should be used to unlink buffer on stack
|
|
; a7,sp - points to buffer on stack (first long is number of entries)
|
|
; d0 - error (long) (0 means no error, else bail; leave buffer on stack)
|
|
; d1 - trashed
|
|
; d2 - unchanged
|
|
; d3 - address of block passed to MoveHLow
|
|
; d4-d6 - unchanged
|
|
; d7 - trashed
|
|
;
|
|
; info:
|
|
; Walk the heap and mark purgeable blocks Non-purgeable. The problem is that
|
|
; the original MoveHHi did not purge any blocks. We need to save all purgeable
|
|
; handles, make a NewPtr call, and then restore them. Remember which
|
|
; blocks we change by putting the master pointers in a buffer on the stack.
|
|
; Warning! This routine leaves a buffer on the stack, which will be
|
|
; removed by calling RestorePurgeableBlocks. That means this routine
|
|
; canÕt save anything on the stack except master pointers.
|
|
;
|
|
; todo:
|
|
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
with MakeBlocksNonPurgeableStack
|
|
MakeBlocksNonPurgeable
|
|
move.l a3,d1 ;preserve a3 across call
|
|
move.l (sp)+,a5 ;get return address
|
|
|
|
|
|
;see if we can make a buffer with storage for at least entry
|
|
_StackSpace ;
|
|
sub.l #StackSlop,d0 ;need some slop on stack for interupts
|
|
bmi @ErrorExit ;
|
|
|
|
;initialize regs for @loop
|
|
;clear free space counters
|
|
;clear flags to see if we should check free space and if weÕve passed our block
|
|
;set up our block address for free space counter
|
|
;A1 points at end of stack buffer
|
|
;A3 points at first block in heap
|
|
;D7 points at end of heap
|
|
clr.l largestFreeSpace(a6) ;start with zero as the largest free space
|
|
clr.l freeSpaceAccumulator(a6) ;and the accumulator starts out empty, too
|
|
clr.w keepCheckingFreeSpace(a6) ;clear the flag for free space checks
|
|
clr.w passedOurBlock(a6) ;clear the flag for our block in the heap
|
|
move.l sp,a1 ;pointer to stack buffer
|
|
sub.l d0,a1 ;point to the end of the stack buffer
|
|
move.l (a4),d0 ;get address of our block
|
|
_StripAddress ;shave off nasty bits, Õcause weÕre gonna compare against it
|
|
move.l d0,d3 ;keep block address in d3
|
|
move.l theZone,a3 ;get pointer to start of this zone
|
|
move.l bkLim(a3),d7 ;save end of heap
|
|
add.l #heapData,a3 ;skip past zone header
|
|
sub.l d4,a3 ;skip past heap block header
|
|
;this loop walks the heap, and marks all purgeable blocks non-purgeable
|
|
@loop
|
|
cmp.l a1,sp ;check if stack buffer is full
|
|
ble @ErrorExit ;no more room in buffer, signal error
|
|
cmp.l a3,d7 ;check if end of heap
|
|
blt @NormalExit ;successfull, exit loop
|
|
cmp.l a3,d3 ;check if weÕre to our block
|
|
bgt.s @pastCheckForOurBlock ;if weÕre not there, then move on
|
|
move.w #-1, passedOurBlock(a6) ;otherwise, set the flag that says weÕre past our block
|
|
;now treat block passed in as a special case terminator for free space checks
|
|
cmp.l a3,d3
|
|
beq.s @resetFreeSpaceAccumulator
|
|
@pastCheckForOurBlock
|
|
|
|
;low two bits in d0 will be the block type
|
|
move.b (a3,d4),d0 ;get the blocktype
|
|
lsr.b #6,d0 ;only use the tag bits
|
|
|
|
;if free d0 = 0
|
|
beq.s @addToFreeSpaceAccumulator
|
|
|
|
@notFreeBlock
|
|
;bail if pointer block
|
|
cmp.b #tybkNRel,d0 ;check if pointer block
|
|
beq.s @resetFreeSpaceAccumulator ;advance to next block
|
|
|
|
;we are sure it is a relocateable block now, but check just in case.
|
|
cmp.b #tybkRel,d0 ;check if relocateable block
|
|
bne.s @resetFreeSpaceAccumulator ;if not relocatateable, error, go next?
|
|
|
|
;we have a pointer to the relocatable block, we need a handle to mark it non-purgeable
|
|
move.l a3,a0 ;set up pointer to block
|
|
_RecoverHandle ;if this fails, then this block is
|
|
;orphaned, and we can move it at will
|
|
tst.w MemErr ;(RecoverHandle result in MemErr only!) <LW2>
|
|
bmi.s @pastFreeSpaceChecks ;
|
|
|
|
;if already locked, we donÕt need to change its state
|
|
_HGetState ;
|
|
btst #lock,d0 ;check if handle is locked
|
|
bne.s @resetFreeSpaceAccumulator ;is locked, go to nextBlock
|
|
|
|
;last test, is it a purgeable block?
|
|
btst #purge,d0 ;check if handle is purgeable
|
|
beq.s @pastFreeSpaceChecks ;if not purgable go to nextBlock
|
|
|
|
;change its state, and save a handle to this block in our buffer.
|
|
_HNoPurge ;keep this block from purgeing
|
|
move.l a0,-(sp) ;save handle to this block on stack
|
|
bra.s @pastFreeSpaceChecks
|
|
|
|
;we found a relocatable or free block, so add this block to the possible space for our ptr
|
|
@addToFreeSpaceAccumulator
|
|
move.l blkSize(a3),d0 ;get size of this block
|
|
and.l d6,d0 ;strip off tags 24 bit world (32 is ok)
|
|
tst.w keepCheckingFreeSpace(a6) ;should we bother (have we passed our block)
|
|
bmi.s @endOfLoop ;donÕt bother if weÕve passed our block
|
|
add.l d0, freeSpaceAccumulator(a6) ;and add the size to the free space for this island
|
|
bra.s @endOfLoop
|
|
|
|
;we ran across an immovable block, so reset our counter and update the largest free area weÕve found
|
|
@resetFreeSpaceAccumulator
|
|
tst.w keepCheckingFreeSpace(a6) ;should we bother with this? (past our block?)
|
|
bmi.s @pastFreeSpaceChecks ;if the flag is set, skip the free space stuff
|
|
tst.w passedOurBlock(a6) ;have we (just now) passed our block in the heap
|
|
beq.s @pastPreflightCheck ;if the flag is not set, keep checking free spaces
|
|
;now comes the good part... should we bail out early because there isnÕt sufficient free space
|
|
;lower that our block in the heap?
|
|
move.l a3, -(sp) ;save block pointer, Õcause we need an address register
|
|
move.l d3,a3 ;put block passed in here
|
|
move.l blkSize(a3),d0 ;get size of our block
|
|
and.l d6,d0 ;strip off tags 24 bit world (32 is ok)
|
|
cmp.l largestFreeSpace(a6),d0 ;do we have room for our block lower in the heap?
|
|
move.l (sp)+, a3 ;put old block pointer back, donÕt affect cc
|
|
bgt.s @ErrorExit ;no room in heap, bail out!
|
|
move.w #-1,keepCheckingFreeSpace(a6) ;now that we have good news, stop checking free space
|
|
bra.s @pastFreeSpaceChecks
|
|
@pastPreflightCheck
|
|
move.l freeSpaceAccumulator(a6), d0 ;get the space we counted this time
|
|
cmp.l largestFreeSpace(a6), d0 ;see if the largest is still king of the hill
|
|
ble.s @pastFreeSpaceChecks ;if so, move on
|
|
move.l d0, largestFreeSpace(a6) ;else make a new king
|
|
clr.l freeSpaceAccumulator(a6) ;and clear the accumulator
|
|
@pastFreeSpaceChecks
|
|
move.l blkSize(a3),d0 ;get size of this block
|
|
and.l d6,d0 ;strip off tags 24 bit world (32 is ok)
|
|
|
|
;end of @loop, bump a3 to point at next block
|
|
@endOfLoop
|
|
add.l d0,a3 ;point at next block
|
|
bra @loop ;loop back for more
|
|
|
|
|
|
;if error occured, we must signal error by putting a zero count into stack buffer
|
|
@ErrorExit
|
|
move.w #myError,d0 ;signal an error to the main routine
|
|
move.w d0,MemErr ;set MemErr
|
|
bra.s @CommonExit ;exit through CommonExit
|
|
|
|
@NormalExit
|
|
moveq #0,d0 ;signal no error to the main routine
|
|
|
|
@CommonExit
|
|
;condition codes must be set at this point, caller depends on this
|
|
movea.l d1,a3 ;preserve a3 across call
|
|
jmp (a5) ;rts
|
|
endwith
|
|
|
|
|
|
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
;
|
|
; RestorePurgeableBlocks
|
|
;
|
|
; entry:
|
|
; A6 - should be used to unlink buffer on stack
|
|
; exit :
|
|
; D1 - trashed
|
|
; A5 - trashed
|
|
; A6 - restored
|
|
;
|
|
; info:
|
|
; Traverse the stack buffer and restore the saved handles to their purgeable
|
|
; state. Deallocate the stack buffer.
|
|
; Warning! This routine removes the buffer on the stack. This buffer was
|
|
; allocated by MakeBlocksNonPurgeable.
|
|
; todo:
|
|
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
RestorePurgeableBlocks
|
|
move.l (sp)+,a5 ;get return address
|
|
|
|
@loop
|
|
tst.l (sp) ;check for end of list
|
|
beq.s @ExitRestorePurgeableBlocks ;nil meant end of list
|
|
move.l (sp)+,a0 ;get handle
|
|
_HPurge ;mark as purgeable, ignore any error
|
|
bra.s @loop ;check if anymore
|
|
|
|
@ExitRestorePurgeableBlocks
|
|
jmp (a5) ;return to caller
|
|
EndProc
|
|
|
|
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
; ¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥ Patch for CycloneTranslate24To32 ¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥ <P8> RMP
|
|
;
|
|
; FUNCTION CycloneTranslate24To32(Addr24: long): Addr32;
|
|
;
|
|
; Translate an Cyclone 24-bit address to a valid Cyclone 32-bit address.
|
|
;
|
|
; INPUT D0=Addr24;
|
|
; OUTPUT D0=Addr32;
|
|
;
|
|
; All other registers preserved
|
|
;
|
|
; Translation algorithm from Cyclone Hardware ERS:
|
|
;
|
|
; Old first 3 nibbles New first 3 nibbles
|
|
; ------------------- -------------------
|
|
; xx0 000
|
|
; : :
|
|
; xx7 007
|
|
; xx8 400-->408 for safety in 24 bit mode; also since the emulator doesn't alias
|
|
; xx9 409 second meg of ROM is in tradional slot 9 space.
|
|
; xxA FA0
|
|
; : :
|
|
; xxE FE0
|
|
; xxF 500
|
|
;
|
|
;
|
|
;
|
|
; NOTE: Unlike _StripAddress, this routine does not necessarily
|
|
; return an address which can also be used in 24 bit mode.
|
|
; Furthermore, Translate24To32 can not be called meaningfully
|
|
; with the result of a previous translation.
|
|
;
|
|
;
|
|
;
|
|
|
|
CycloneTranslate24To32 Proc Export
|
|
|
|
AND.L Lo3Bytes,D0 ;Clean high byte for fast exit
|
|
BCLR #23,D0 ;Is the address in RAM?
|
|
BNE.S @NotRam ;no, go patch up address
|
|
RTS ;quick exit
|
|
|
|
@NotRam MOVE.W D1,-(SP) ;save a work register
|
|
SWAP D0 ;get relevant nibbles into low word
|
|
MOVE.W D0,D1 ;...and into index register
|
|
LSR.W #4,D1 ;move nibble 3 to use as index
|
|
AND.W (@TABLE+2,PC,D1.W*4),D0 ;mask off bits that will be added.
|
|
ADD.W (@TABLE,PC,D1.W*4),D0 ;translate by adding table value
|
|
SWAP D0 ;move translated nibbles back to high word
|
|
MOVE.W (SP)+,D1 ;restore work register
|
|
RTS
|
|
|
|
@TABLE
|
|
DC.W $4080,$FFFF ; 008x -> 408x
|
|
Dc.w $4080,$FFFF ; 009x -> 409x
|
|
Dc.w $FA00,$000F ; 00Ax -> FA0x
|
|
Dc.w $FB00,$000F ; 00Bx -> FB0x
|
|
Dc.w $FC00,$000F ; 00Cx -> FC0x
|
|
Dc.w $FD00,$000F ; 00Dx -> FD0x
|
|
Dc.w $FE00,$000F ; 00Ex -> FE0x
|
|
Dc.w $5000,$000F ; 00Fx -> 500x
|
|
|
|
ENDPROC
|
|
|
|
|
|
end |