mirror of
https://github.com/zellyn/a2audit.git
synced 2024-11-23 20:31:50 +00:00
auxmem: lots of comments
This commit is contained in:
parent
5ceaf4f34e
commit
36212fb8df
1655
audit/audit.lst
1655
audit/audit.lst
File diff suppressed because it is too large
Load Diff
131
audit/auxmem.asm
131
audit/auxmem.asm
@ -3,21 +3,21 @@
|
|||||||
|
|
||||||
!zone auxmem {
|
!zone auxmem {
|
||||||
|
|
||||||
.MEM_1 = %00000000
|
;; Bitmask for whether ranges of Cxxx memory look like ROM or
|
||||||
.MEM_2 = %00000001
|
;; something else. 1 means it looks like ROM, 0 means it
|
||||||
.MEM_3 = %00000010
|
;; doesn't. How do we check whether a range looks like ROM?
|
||||||
.MEM_4 = %00000011
|
;; Check values at four different addresses, carefully chosen
|
||||||
.MEM_2_1_1_1 = (.MEM_2 << 0) + (.MEM_1 << 2) + (.MEM_1 << 4) + (.MEM_1 << 6)
|
;; to have consistent values in different ROM versions. The
|
||||||
.MEM_3_2_2_2 = (.MEM_3 << 0) + (.MEM_2 << 2) + (.MEM_2 << 4) + (.MEM_2 << 6)
|
;; check data is at .cxtestdata
|
||||||
|
|
||||||
.C_8f = %0001
|
.C_12 = %0010 ; Is C100-C2FF ROM or something else?
|
||||||
.C_12 = %0010
|
.C_47 = %0100 ; Is C400-C7FF ROM or something else?
|
||||||
.C_47 = %0100
|
.C_3 = %1000 ; Is C300-C3FF ROM or something else?
|
||||||
.C_3 = %1000
|
.C_8f = %0001 ; Is C800-CFFE ROM or something else?
|
||||||
.C_0 = %0000
|
.C_0 = %0000
|
||||||
.C_skip = $80
|
.C_skip = $80 ; Skip ROM checks.
|
||||||
.C_1348 = .C_12 | .C_3 | .C_47 | .C_8f
|
.C_1348 = .C_12 | .C_3 | .C_47 | .C_8f ; Everything is ROM
|
||||||
.C_38 = .C_3 | .C_8f
|
.C_38 = .C_3 | .C_8f ; C300-C3FF and C800-CFFE are ROM
|
||||||
|
|
||||||
.checkdata = tmp1
|
.checkdata = tmp1
|
||||||
.ismain = tmp3
|
.ismain = tmp3
|
||||||
@ -26,9 +26,18 @@
|
|||||||
.desired = tmp2
|
.desired = tmp2
|
||||||
|
|
||||||
|
|
||||||
|
;;; Auxmem tests. First, we try the language card test again, but in
|
||||||
|
;;; auxmem. (If the language card test failed the first time, we skip
|
||||||
|
;;; this part.)
|
||||||
|
;;;
|
||||||
|
;;; Then, we try data-driven tests.
|
||||||
|
;;;
|
||||||
|
;;; On success, carry will be clear; on failure, set.
|
||||||
AUXMEMTESTS
|
AUXMEMTESTS
|
||||||
lda #0
|
lda #0
|
||||||
sta AUXRESULT
|
sta AUXRESULT
|
||||||
|
|
||||||
|
;; If we have 64k or less, skip this test.
|
||||||
lda MEMORY
|
lda MEMORY
|
||||||
cmp #65
|
cmp #65
|
||||||
bcs +
|
bcs +
|
||||||
@ -42,6 +51,8 @@ AUXMEMTESTS
|
|||||||
!text "TESTING AUX MEM",$8D
|
!text "TESTING AUX MEM",$8D
|
||||||
+printed
|
+printed
|
||||||
|
|
||||||
|
;; If we failed the Language Card test already, there's no
|
||||||
|
;; point in trying the auxmem version of it.
|
||||||
lda LCRESULT
|
lda LCRESULT
|
||||||
bne .auxlc
|
bne .auxlc
|
||||||
+print
|
+print
|
||||||
@ -56,7 +67,11 @@ AUXMEMTESTS
|
|||||||
lda #0
|
lda #0
|
||||||
sta LCRESULT
|
sta LCRESULT
|
||||||
|
|
||||||
;; Store distinct values in RAM areas, to see if they stay safe.
|
;; Store distinct values in RAM areas overwritten by the
|
||||||
|
;; language card test, to see if they stay safe. The language
|
||||||
|
;; card tests should leave non-auxmem memory and language card
|
||||||
|
;; bank alone. These $44 bytes will act as canaries.
|
||||||
|
|
||||||
lda $C08B ; Read and write bank 1
|
lda $C08B ; Read and write bank 1
|
||||||
lda $C08B
|
lda $C08B
|
||||||
lda #$44
|
lda #$44
|
||||||
@ -109,7 +124,7 @@ AUXMEMTESTS
|
|||||||
+
|
+
|
||||||
lda $FE1F
|
lda $FE1F
|
||||||
cmp #$44
|
cmp #$44
|
||||||
beq .datadriventests
|
beq .datadriventests ; all three canaries were OK. Jump to main data-driven tests.
|
||||||
pha
|
pha
|
||||||
+print
|
+print
|
||||||
!text "WANT RAM $FE1F"
|
!text "WANT RAM $FE1F"
|
||||||
@ -148,7 +163,7 @@ AUXMEMTESTS
|
|||||||
sta PCH
|
sta PCH
|
||||||
;;; Main data-drive-test loop.
|
;;; Main data-drive-test loop.
|
||||||
.ddloop
|
.ddloop
|
||||||
ldy #0
|
ldy #0 ; data-driven tests are null-terminated.
|
||||||
lda (PCL),Y
|
lda (PCL),Y
|
||||||
beq .success
|
beq .success
|
||||||
|
|
||||||
@ -158,6 +173,10 @@ AUXMEMTESTS
|
|||||||
sta SET_RAMRD
|
sta SET_RAMRD
|
||||||
|
|
||||||
.initloop ; Loop twice: initialize aux to $3 and main to $1.
|
.initloop ; Loop twice: initialize aux to $3 and main to $1.
|
||||||
|
|
||||||
|
;; Store current value of A (first $3, then $1) into all
|
||||||
|
;; locations in [.memorylocs:.memorylocs+.memorylen]. (This
|
||||||
|
;; will store A in $00 several times, but that's ok.
|
||||||
ldy #.memorylen
|
ldy #.memorylen
|
||||||
- ldx .memorylocs,y
|
- ldx .memorylocs,y
|
||||||
stx + +1
|
stx + +1
|
||||||
@ -205,10 +224,11 @@ AUXMEMTESTS
|
|||||||
sta .checkdata+1
|
sta .checkdata+1
|
||||||
|
|
||||||
;; First checkdata byte is for Cxxx tests.
|
;; First checkdata byte is for Cxxx tests.
|
||||||
jsr NEXTCHECK
|
jsr NEXTCHECK ; grab the next byte of check data in A, use it to set flags.
|
||||||
bmi +
|
bmi +
|
||||||
jsr .checkCxxx
|
jsr .checkCxxx
|
||||||
|
|
||||||
|
;; Save checkdata address in XY. Reset all softswitches. Then restore checkdata.
|
||||||
+ ldx .checkdata
|
+ ldx .checkdata
|
||||||
ldy .checkdata+1
|
ldy .checkdata+1
|
||||||
jsr RESETALL
|
jsr RESETALL
|
||||||
@ -493,6 +513,48 @@ zpfromaux
|
|||||||
bne -
|
bne -
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
;;; These are the main auxmem tests. Their format is:
|
||||||
|
;;;
|
||||||
|
;;; lda TEST_NUMBER
|
||||||
|
;;; ; (do whatever you want in normal assembly)
|
||||||
|
;;; jsr .check
|
||||||
|
;;; !byte ROM_CHECK_WANT, ZP_WANT, MAIN_WANT, TEXT_WANT, HIRES_WANT, ZP_AUX_WANT, MAIN_AUX_WANT, TEXT_AUX_WANT, HIRES_AUX_WANT
|
||||||
|
;;;
|
||||||
|
;;;
|
||||||
|
;;; The tests work like so:
|
||||||
|
;;;
|
||||||
|
;;; 1) The harness code stores $1 into all the test addresses in
|
||||||
|
;;; normal memory, and $3 into all the test locations in aux
|
||||||
|
;;; memory.
|
||||||
|
;;;
|
||||||
|
;;; 2) The test-specific piece of custom assembly code does whatever
|
||||||
|
;;; it wants to do to softswitches.
|
||||||
|
;;;
|
||||||
|
;;; 3) The harness code increments each of the test addresses
|
||||||
|
;;; once. Some will be in normal memory, some in aux memory,
|
||||||
|
;;; depending on what the custom code did.
|
||||||
|
;;;
|
||||||
|
;;; 4) If the ROM_CHECK_WANT byte is not .C_skip, then the harness
|
||||||
|
;;; calculates which portions of Cxxx memory are reading as ROMs,
|
||||||
|
;;; and validates that using the routine .checkCxxx
|
||||||
|
;;;
|
||||||
|
;;; 5) The harness code runs through the test addresses, one region at
|
||||||
|
;;; a time, checking that the values are what the test expects.
|
||||||
|
;;;
|
||||||
|
;;; The regions and their test addresses (stored at .memorylocs),
|
||||||
|
;;; which correspond to the segments that can be independently
|
||||||
|
;;; pointed at main memory or aux memory, are:
|
||||||
|
;;;
|
||||||
|
;;; - zero page: $ff, $100
|
||||||
|
;;; - main memory: $200, $3ff, $800, $1fff, $4000, $5fff, $bfff
|
||||||
|
;;; - text: $427, $7ff
|
||||||
|
;;; - hires: $2000, $3fff
|
||||||
|
;;;
|
||||||
|
;;; The harness checks that the zero page main memory test
|
||||||
|
;;; addresses hold ZP_WANT, and that the zero page main memory test
|
||||||
|
;;; addresses hold ZP_AUX_WANT. Similarly for the other three
|
||||||
|
;;; regions.
|
||||||
|
|
||||||
.auxtests
|
.auxtests
|
||||||
|
|
||||||
;; Our four basic tests --------------------------------------
|
;; Our four basic tests --------------------------------------
|
||||||
@ -738,28 +800,31 @@ zpfromaux
|
|||||||
.memorylen = * - .memorylocs - 2
|
.memorylen = * - .memorylocs - 2
|
||||||
!word 0
|
!word 0
|
||||||
|
|
||||||
|
;;; Bytes to check to see whether ranges of memory contain ROM or not.
|
||||||
|
;;; If I recall correctly, these were chosen to be bytes that remain
|
||||||
|
;;; the same in different ROM versions.
|
||||||
.cxtestdata
|
.cxtestdata
|
||||||
;; C800-Cffe
|
;; C800-Cffe
|
||||||
!byte $00, $c8, $4c
|
!byte $00, $c8, $4c ; CB00: 4C
|
||||||
!byte $21, $ca, $8d
|
!byte $21, $ca, $8d ; CA21: 8D
|
||||||
!byte $43, $cc, $f0
|
!byte $43, $cc, $f0 ; CC43: F0
|
||||||
!byte $b5, $ce, $7b
|
!byte $b5, $ce, $7b ; CEB5: 7B
|
||||||
|
|
||||||
;; C100-C2ff
|
;; C100-C2ff
|
||||||
!byte $4d, $c1, $a5
|
!byte $4d, $c1, $a5 ; C14D: A5
|
||||||
!byte $6c, $c1, $2a
|
!byte $6c, $c1, $2a ; C16C: 2A
|
||||||
!byte $b5, $c2, $ad
|
!byte $b5, $c2, $ad ; C2B5: AD
|
||||||
!byte $ff, $c2, $00
|
!byte $ff, $c2, $00 ; C2FF: 00
|
||||||
|
|
||||||
;; C400-C7ff
|
;; C400-C7ff
|
||||||
!byte $36, $c4, $8d
|
!byte $36, $c4, $8d ; C436: 8D
|
||||||
!byte $48, $c5, $18
|
!byte $48, $c5, $18 ; C548: 18
|
||||||
!byte $80, $c6, $8b
|
!byte $80, $c6, $8b ; C680: 8B
|
||||||
!byte $6e, $c7, $cb
|
!byte $6e, $c7, $cb ; C76E: CB
|
||||||
|
|
||||||
;; C300-C3ff
|
;; C300-C3ff
|
||||||
!byte $00, $c3, $2c
|
!byte $00, $c3, $2c ; C300: 2C
|
||||||
!byte $0a, $c3, $0c
|
!byte $0a, $c3, $0c ; C30A: 0C
|
||||||
!byte $2b, $c3, $04
|
!byte $2b, $c3, $04 ; C32B: 04
|
||||||
!byte $e2, $c3, $ed
|
!byte $e2, $c3, $ed ; C3E2: ED
|
||||||
} ;auxmem
|
} ;auxmem
|
||||||
|
@ -13,19 +13,56 @@
|
|||||||
* = TEMP
|
* = TEMP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
;; print/printed prints the string between them.
|
||||||
|
;;
|
||||||
|
;; `+print` does a `jsr LASTSTRING`, jumping to the position
|
||||||
|
;; of the next string, LASTSTRING, as if it were a
|
||||||
|
;; subroutine. Then, setting the current address to
|
||||||
|
;; LASTSTRING, it lays down a `jsr print`, so that first `jsr`
|
||||||
|
;; will jump straight to another jump to `print`. That serves
|
||||||
|
;; to get the address of the following string onto the stack.
|
||||||
|
;;
|
||||||
|
;; After that, you lay down the text you want to print, and a
|
||||||
|
;; final `+printed` lays down a trailing zero byte and fixes
|
||||||
|
;; up LASTSTRING ready for the next string, and puts the
|
||||||
|
;; current position back after that `jsr` that started this
|
||||||
|
;; dance.
|
||||||
|
;;
|
||||||
|
;; So, if you write:
|
||||||
|
;;
|
||||||
|
;; lda #42
|
||||||
|
;; +print
|
||||||
|
;; !text "HELLO, WORLD",$8D
|
||||||
|
;; +printed
|
||||||
|
;; sta $17
|
||||||
|
;;
|
||||||
|
;; what you get is this:
|
||||||
|
;;
|
||||||
|
;;
|
||||||
|
;; lda #42
|
||||||
|
;; jsr LASTSTRING(orig) ------------> LASTSTRING(orig): jsr print
|
||||||
|
;; ; `print` returns here "HELLO, WORLD",$8D,$0
|
||||||
|
;; sta $17 LASTSTRING(new): ; next string or jsr print goes here
|
||||||
|
;;
|
||||||
|
;;
|
||||||
|
;; Why this dance? Well, the alternative would be either a
|
||||||
|
;; version of `print` that expects the string directly after
|
||||||
|
;; the `jsr` instruction in memory, or code that saves A, then
|
||||||
|
;; pushes the HI and LO of LASTSTRING before calling `print`.
|
||||||
!macro print {
|
!macro print {
|
||||||
jsr LASTSTRING
|
jsr LASTSTRING
|
||||||
!set TEMP = *
|
!set TEMP = *
|
||||||
* = LASTSTRING
|
* = LASTSTRING
|
||||||
jsr print
|
jsr print
|
||||||
}
|
}
|
||||||
|
|
||||||
!macro printed {
|
!macro printed {
|
||||||
!byte 0
|
!byte 0
|
||||||
!set LASTSTRING=*
|
!set LASTSTRING=*
|
||||||
* = TEMP
|
* = TEMP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
;; +prerr/+prerred is like +print/+printed, but prints an
|
||||||
|
;; error number and message.
|
||||||
!macro prerr NUM {
|
!macro prerr NUM {
|
||||||
ldy #>NUM
|
ldy #>NUM
|
||||||
ldx #<NUM
|
ldx #<NUM
|
||||||
@ -39,7 +76,8 @@
|
|||||||
+printed
|
+printed
|
||||||
}
|
}
|
||||||
|
|
||||||
;; A version of prerr that also displays the current value of A.
|
;; +prerra/+printed is a version of prerr that also displays
|
||||||
|
;; the current value of A.
|
||||||
!macro prerra NUM {
|
!macro prerra NUM {
|
||||||
ldy #>NUM
|
ldy #>NUM
|
||||||
ldx #<NUM
|
ldx #<NUM
|
||||||
|
Loading…
Reference in New Issue
Block a user