**************************************** * MiniMemoryTester * * * * Dagen Brock * * 2015-09-16 * **************************************** org $2000 ; start at $2000 (all ProDOS8 system files) typ $ff ; set P8 type ($ff = "SYS") for output file dsk mtsystem ; tell compiler what name for output file put applerom Init sei ; disable interrupts clc xce ;enable full 65816 LDA #$A0 ;USE A BLANK SPACE TO JSR $C300 ;TURN ON THE VIDEO FIRMWARE lda $C034 ; save border color sta BorderColor jsr DetectRam lda BankExpansionLowest sta StartBank lda BankExpansionHighest sta EndBank lda #MainMenuDefs ldx #>MainMenuDefs jsr Menu_InitMenu * * Main Menu loop begin * Main :menuLoop jsr DrawMenuBackground jsr DrawRomMessage jsr DrawRamMessages jsr LogWelcomeMessage jsr LogRamMessages :menuDrawOptionsLoop jsr MenuUpdateWordSize ;always update this before draw in case of change lda #MainMenuDefs ldy #>MainMenuDefs jsr Menu_DrawOptions :menuNoDrawLoop jsr MenuCheckKeyColor bcc :menuNoDrawLoop ;hmm? :keyHit cmp #KEY_ENTER ;8D bne :check1 :enter jsr Menu_HandleSelection bra :menuDrawOptionsLoop ;because an option might have changed :check1 cmp #KEY_UPARROW ;8B beq :prevItem cmp #KEY_LTARROW ;88 beq :prevItem cmp #KEY_DNARROW ;8A beq :nextItem cmp #KEY_RTARROW ;95 beq :nextItem :unknownKey bra :menuNoDrawLoop :prevItem jsr Menu_PrevItem jsr Menu_UndrawSelectedAll ;hack for blinky cursor stz _ticker bra :menuNoDrawLoop :nextItem jsr Menu_NextItem jsr Menu_UndrawSelectedAll ;hack for blinky cursor stz _ticker bra :menuNoDrawLoop * * Main Menu loop end ^^^ * DrawMenuBackground jsr HOME lda #MainMenuStrs ldy #>MainMenuStrs ldx #00 ; horiz pos jsr PrintStringsX rts * Prints "Apple IIgs ROM 0x" DrawRomMessage PRINTXY #55;#06;Mesg_Rom lda GSROM jsr PRBYTE rts * Prints "Built-In RAM xxxK" * "Expansion RAM yyyyK" DrawRamMessages lda GSROM cmp #3 bne :rom0or1 :rom3 PRINTXY #55;#07;Mesg_InternalRam1024 bra :drawExpansionMessage :rom0or1 PRINTXY #55;#07;Mesg_InternalRam256 :drawExpansionMessage PRINTXY #55;#08;Mesg_ExpansionRam ldx #BankExpansionRamKB ldy #>BankExpansionRamKB jsr PrintInt lda #"K" jsr COUT rts LogWelcomeMessage jsr WinConsole LOG Mesg_Welcome jsr WinFull rts LogRamMessages jsr WinConsole LOG Mesg_DetectedBanks lda BankExpansionLowest jsr PRBYTE lda #Mesg_ToBank ldy #>Mesg_ToBank jsr PrintString lda BankExpansionHighest jsr PRBYTE jsr WinFull rts * * ####### ### ### ### * # ###### #### ##### ###### ##### ### ### ### * # # # # # # # ### ### ### * # ##### #### # ##### # # # # # * # # # # # ##### * # # # # # # # # ### ### ### * # ###### #### # ###### # # ### ### ### * * TestInit LOG Mesg_Starting stz _errorCounter stz _testIteration stz _testIteration+1 stz CurBank TestMasterLoop jsr TestGetNextBank ;sets initial bank when CurBank = 0 jsr TestPastFinalBank bcs :NextIteration :NextIteration inc _testIteration TestPastFinalBank lda TestDirection bne :descending :ascending lda EndBank cmp CurBank ;is EndBank < CurBank ? bcc :yes ;past final bank bcs :no :descending lda CurBank cmp StartBank ;is CurBank < StartBank ? bcc :yes bcs :no :yes sec rts :no clc rts TestGetNextBank lda TestDirection bne :descending :ascending lda CurBank bne :notInitialBank lda StartBank sta CurBank rts :notInitialBank inc CurBank rts :descending lda CurBank bne :notInitialBank2 lda EndBank sta CurBank rts :notInitialBank2 dec CurBank rts * * * ##### * # # # ##### * # # # # # * # # # # # * # # # # # * # # # # # * ##### ###### ##### * * BeginTest LOG Mesg_Starting stz _errorCounter stz _testIteration stz _testIteration+1 BeginTestPass PRINTXY #55;#10;Mesg_TestPass inc _testIteration bne :noroll inc _testIteration+1 :noroll lda _testIteration+1 ldx _testIteration jsr PRNTAX PRINTXY #55;#12;Mesg_Writing ; WRITE START clc xce rep $10 ; long x, short a lda StartBank sta CurBank ldy #0 ; update interval counter :bankloop lda CurBank sta :bankstore+3 ldx StartAddr lda HexPattern :bankstore stal $000000,x cpx EndAddr beq :donebank inx iny cpy #UpdateScanInterval bcc :bankstore jsr PrintTestCurrent bcc :noquit1 jmp :escpressed :noquit1 ldy #0 bra :bankstore :donebank ldy #0 ; because i'm anal.. this makes counter align inc CurBank lda EndBank cmp CurBank bcs :bankloop dec CurBank ; so many bad hacks jsr PrintTestCurrent ; print final score ;) bcc :noquit2 jmp :escpressed :noquit2 sep $10 ; WRITE END jsr Pauser ; PAUSE PRINTXY #55;#12;Mesg_Reading ; READ PREP ; READ START clc xce rep $10 ; long x, short a lda StartBank sta CurBank ldy #0 ; update interval counter :bankrloop lda CurBank sta :bankread+3 ldx StartAddr :bankread ldal $000000,x cmp HexPattern beq :testpass phx sta _stash ; = read value lda HexPattern sta _stash+1 ; = expected value stx _stash+2 jsr PrintTestError ; addr in X plx :testpass cpx EndAddr beq :donerbank inx iny cpy #UpdateScanInterval bcc :bankread jsr PrintTestCurrent ldy #0 bra :bankread :donerbank ldy #0 ; because i'm anal.. this makes counter align inc CurBank lda EndBank cmp CurBank bcs :bankrloop dec CurBank ; so many bad hacks jsr PrintTestCurrent ; print final score ;) sep $10 ; WRITE END jsr Pauser ; PAUSE lda BorderColor sta $C034 jmp BeginTestPass :escpressed sep $10 rts _testIteration ds 8 _errorCounter ds 8 UpdateScanInterval equ #$1000 Mesg_Welcome asc "Welcome to Mini Memory Tester v0.3 by Dagen Brock",$8D,00 Mesg_InternalRam256 asc "Built-In RAM 256K",00 Mesg_InternalRam1024 asc "Built-In RAM 1024K",00 Mesg_ExpansionRam asc "Expansion RAM ",00 Mesg_Rom asc "Apple IIgs ROM ",00 Mesg_UserManual asc "USE ARROW KEYS TO MOVE - USE ENTER TO SELECT/EDIT",00 Mesg_Starting asc $8D,"Starting Test",$8D,"Press P to pause, ESC to stop.",$8D,$8D,00 Mesg_Waiting asc "Waiting: ",00 Mesg_Writing asc "Writing: ",00 Mesg_Reading asc "Reading: ",00 Mesg_Errors asc " Errors: ",$00 Mesg_TestPass asc " Pass: ",00 Mesg_Blank asc " ",00 Mesg_DetectedBanks asc "Setting default start/end banks to detected memory expansion: $",00 Mesg_ToBank asc " to $",00 Mesg_ConsoleTop asc $1B,'ZLLLLLLLLLLLLLLL',$18,' Console Log ',$1B,'LLLLLLLLLLLLLLLLL_',$18,$8D,00 Mesg_ConsoleMid asc $1B,'Z'," ",'_',$18,$8D,00 Mesg_ConsoleBot asc $1B,'Z',"_____________________________________________",'_',$18,$8D,00 * Error message strings Mesg_E1 asc "Bad Read - Pass ",00 Mesg_E2 asc " Location: ",00 Mesg_E3 asc "Wrote: $",00 Mesg_E4 asc " ",$1B,'SU',$18," Read: $",00 Mesg_Arrow asc $1B,'SU',$18,00 mx %10 ;i think? * called with short M, long X PrintTestError sep $30 inc _errorCounter bne :noRoll inc _errorCounter+1 :noRoll PRINTXY #55;#11;Mesg_Errors ldx _errorCounter lda _errorCounter+1 jsr PRNTAX jsr WinConsole LOG Mesg_E1 ldx _testIteration lda _testIteration+1 jsr PRNTAX PRINTSTRING Mesg_E2 lda CurBank jsr PRBYTE lda #"/" jsr COUT lda _stash+3 ldx _stash+2 jsr PRNTAX lda #$8D jsr COUT LOG Mesg_E3 lda _stash+1 jsr PRBYTE lda #" " jsr COUT lda #"%" jsr COUT lda _stash+1 jsr PRBIN PRINTSTRING Mesg_E4 lda _stash jsr PRBYTE lda #" " jsr COUT lda #"%" jsr COUT lda _stash jsr PRBIN jsr WinFull clc xce rep $10 rts *Mesg_Error0 asc "Error: Bad Read Pass 0000 Location: 00/1234" *Mesg_Error0 asc "Wrote: $00 %12345678 Read: $00 %12345678" mx %01 PrintTestCurrent pha phy stx _stash ; save real X sep #$30 ;in case? there was a sec xce combo here GOXY #65;#12 lda CurBank sta :corruptme+3 jsr PRBYTE lda #"/" jsr COUT lda _stash+1 sta :corruptme+2 jsr PRBYTE lda _stash sta :corruptme+1 jsr PRBYTE * CORRUPTOR! :kloop lda KEY cmp #"c" ; REMOVE DEBUG beq :corruptor cmp #"C" beq :corruptor bra :nocorrupt :corruptor jsr GetRandTrash :corruptme stal $060000 ; addr gets overwritten inc $c034 sta STROBE ; we only clear if 'c' is hit inc _stash ; \ beq :noroll ; |- INX inc _stash+1 ; / :nocorrupt cmp #"p" ; check lower p * @TODO make tolower for the comparisons beq :pause cmp #"P" beq :pause bra :nopause :pause sta STROBE jsr WaitKey :nopause cmp #$9B bne :noquit clc xce rep $10 ldx _stash ply pla sec rts :noquit :noroll clc xce rep $10 ldx _stash ply pla clc rts mx %11 PRBIN pha phx ldx #8 :loop asl pha bcc :zero :one lda #"1" jsr COUT bra :ok :zero lda #"0" jsr COUT :ok pla dex bne :loop plx pla rts Pauser PRINTXY #55;#13;Mesg_Waiting ldy #60 ldx TestRefreshPause beq :donepause jsr PrintTimerVal ; inaugural print before waiting 1 sec :secondloop :wait ldal $e1c019 bpl :wait :wait2 ldal $e1c019 bmi :wait2 dey bne :secondloop dex beq :donepause jsr PrintTimerVal ldy #60 bra :secondloop :donepause PRINTXY #55;#13;Mesg_Blank rts PrintTimerVal phx phy txa GOXY #65;#13 ply plx txa jsr PRBYTE rts GetRandTrash ; USE ONLY WITH CORRUPTOR lda _randomTrashByte beq :doEor asl bcc :noEor :doEor eor #$1d :noEor sta _randomTrashByte rts _randomTrashByte db 0 * * #### ###### ##### ##### # # # #### #### * # # # # # ## # # # # * #### ##### # # # # # # # #### * # # # # # # # # # ### # * # # # # # # # ## # # # # * #### ###### # # # # # #### #### *@todo better defaults * 00 - Byte : Selected Value * 01 - Byte : Number of values * 02... - Words : Table of Addresses of possible values TestTypeTbl db 00 ; actual CONST val db 04 ; number of possible values da _TestType_0,_TestType_1,_TestType_2,_TestType_3,00,00 _TestType_0 asc "bit pattern",$00 _TestType_1 asc " bit walk 1",$00 _TestType_2 asc " bit walk 0",$00 _TestType_3 asc " random ",$00 TestDirectionTbl db 0 db 2 da _testDirectionUp,_testDirectionDown,00,00 _testDirectionUp asc "up",$00 _testDirectionDown asc "dn",$00 TestSizeTbl TestSize16Bit db 01 ;0=no ... 8bit, 1=yes ... 16 bit db 02 da _TestSize_0,_TestSize_1 _TestSize_0 asc " 8-bit",$00 _TestSize_1 asc "16-bit",$00 MenuStr_JSR da BeginTest ; MUST PRECEDE MENU STRING! Yes, it's magicly inferred. (-2) MenuStr_BeginTest asc " BEGIN TEST " MenuStr_BeginTestL equ #*-MenuStr_BeginTest MenuStr_BeginTestE db 00 StartBank db #$06 EndBank db #$1F CurBank db #0 StartAddr dw #$0000 EndAddr dw #$FFFF HexPattern dw #$0000 TestDirection dw #0 ; list TestTwoPass dw #0 ; bool is byte, but might change in future? :P TestAdjacentWrite dw #0 ; bool is byte, but might change in future? :P TestRefreshPause dw #$00 ; int TestReadRepeat dw #$01 ; int TestWriteRepeat dw #$01 ; int TestIterations dw #$00 ; int TestErrorPause dw #0 ;bool * * # # ###### # # # # * ## ## # ## # # # * # ## # ##### # # # # # * # # # # # # # # * # # # # ## # # * # # ###### # # #### MainMenuDefs :StartBank hex 19,05 ; x,y db Menu_TypeHex ; 1=hex input db 01 ; memory size (bytes) da StartBank ; variable storage :EndBank hex 22,05 ; x,y db Menu_TypeHex ; 1=hex input db 01 ; memory size (bytes) da EndBank ; variable storage :StartAddr hex 19,06 ; x,y db Menu_TypeHex ; 1=hex input db 02 ; memory size (bytes) da StartAddr ; variable storage :EndAddr hex 20,06 ; x,y db Menu_TypeHex ; 1=hex input db 02 ; memory size (bytes) da EndAddr ; variable storage :TestType hex 19,07 ; x,y db Menu_TypeList ; 3=list input db 11 ; max len size (bytes), 3=option list da TestTypeTbl ; params definition & storage :TestSize hex 28,07 ; x,y db Menu_TypeList ; 3=list input db 6 ; max len size (bytes), 3=option list da TestSizeTbl ; params definition & storage :HexPattern hex 19,08 ; x,y db Menu_TypeHex ; 3=list input _hexpatternsize db 02 ; max len size (bytes), 3=option list <- can change when 8 bit?? da HexPattern ; params definition & storage :BinPattern hex 19,09 ; x,y db Menu_TypeBin ; 5?=bin _binpatternsize db 02 ; max len size (bytes), 3=option list <- can change when 8 bit?? da HexPattern ; params definition & storage <- uses same space as above!! just different representation :Direction hex 12,0B db Menu_TypeList db 2 da TestDirectionTbl :TwoPass hex 28,0B db Menu_TypeBool db 2 ; could be 8-bit or 16-bit bool da TestTwoPass :AdjacentWrite hex 12,0C ; x,y db Menu_TypeBool ; 1=hex input db 01 ; memory size (bytes) da TestAdjacentWrite ; variable storage :TestErrorPause hex 28,0C ; x,y db Menu_TypeBool ; 1=hex input db 2 ; could be 8-bit or 16-bit bool da TestErrorPause ; variable storage :ReadRepeat hex 12,0D ; x,y db Menu_TypeInt ; 1=hex input db 03 ; display/entry width. ints are 16-bit internally da TestReadRepeat ; variable storage :WriteRepeat hex 28,0D ; x,y db Menu_TypeInt ; 1=hex input db 03 ; display/entry width. ints are 16-bit internally da TestWriteRepeat ; variable storage :TestIterations hex 12,0E ; x,y db Menu_TypeInt ; 1=hex input db 03 ; display/entry width. ints are 16-bit internally da TestIterations ; variable storage :TestRefreshPause hex 28,0E ; x,y db Menu_TypeInt ; 1=hex input db 03 ; display/entry width. ints are 16-bit internally da TestRefreshPause ; variable storage :BeginTest hex 1C,0F ; x,y db Menu_TypeAction ; 2=action db MenuStr_BeginTestL ; menu string length da MenuStr_BeginTest ; string storage MainMenuLen equ *-MainMenuDefs MainMenuItems equ MainMenuLen/6 MainMenuEnd dw 0000 Menu_ItemSelected db 0 * special helper functions to update some input sizes when * the user switches between 8 and 16 bit testing modes MenuUpdateWordSize lda TestSize16Bit bne :is16bit :is8bit jmp MenuSet8Bit :is16bit jmp MenuSet16Bit MenuSet16Bit lda #2 bra MenuSetBits MenuSet8Bit jsr MenuClearPatterns ;clear leftover chars because strings are shorter now lda #1 MenuSetBits sta _hexpatternsize sta _binpatternsize rts * hack to allow for smaller portion of screen to update MenuClearPatterns PRINTXY #$17;#$8;_clearstring PRINTXY #$17;#$9;_clearstring rts _clearstring asc " ",$00 MainMenuStrs asc " ______________________________________________________________________________",$8D,$00 asc $1B,'ZV_@ZVWVWVWV_',"Mini Memory Tester v0.3",'ZVWVWVWVWVWVWVWVWVWVW_',"UltimateMicro",'ZWVWVWVW_',$18,$00 asc $1B,'ZLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL_',$18,00 asc $1B,'ZZ \GGGGGGGGGGGGG_',"Test Settings",'ZGGGGGGGGGGGGG\ _'," ",'Z \GGGGGGGG_',"Info",'ZGGGGGGGG\ _'," ",'_',$18,00 asc $1B,'ZZ'," ",'_'," ",'Z'," ",'_'," ",'_',$18,00 asc $1B,'ZZ'," Start/End Bank : / ",'_'," ",'Z'," ",'_'," ",'_',$18,00 asc $1B,'ZZ'," Start/End Address : / ",'_'," ",'Z'," ",'_'," ",'_',$18,00 asc $1B,'ZZ'," Test Type : ",'_'," ",'Z'," ",'_'," ",'_',$18,00 asc $1B,'ZZ'," Hex Pattern : ",'_'," ",'Z'," ",'_'," ",'_',$18,00 asc $1B,'ZZ'," Bin Pattern : ",'_'," ",'Z'," ",'_'," ",'_',$18,00 asc $1B,'ZZ'," ",'_'," ",'Z'," ",'_'," ",'_',$18,00 asc $1B,'ZZ'," Direction Two-Pass R/W ",'_'," ",'Z'," ",'_'," ",'_',$18,00 asc $1B,'ZZ'," Adjacent Wr. Wait on Error ",'_'," ",'Z'," ",'_'," ",'_',$18,00 asc $1B,'ZZ'," Read Repeat Write Repeat ",'_'," ",'Z'," ",'_'," ",'_',$18,00 asc $1B,'ZZ'," Iterations Refresh Pause ",'_'," ",'Z'," ",'_'," ",'_',$18,00 asc $1B,'ZZ'," ( ) ",'_'," ",'Z'," ",'_'," ",'_',$18,00 asc $1B,'ZLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL_',$18,00 asc $1B,'Z'," ",'_',$18,00 asc $1B,'Z'," ",'_',$18,00 asc $1B,'Z'," ",'_',$18,00 asc $1B,'Z'," ",'_',$18,00 asc $1B,'Z'," ",'_',$18,00 asc $1B,'Z'," _",'_',$18,00 asc $1B,'Z',"_____________________________________________________________________________",'_',$18,00 hex 00,00 BorderColor db 0 ds \ _stash ds 255 ds \ * Creates a 256 byte map of each bank, "BankRam" * The map shows whether it's Built-in RAM, ROM, Expansion RAM, etc. DetectRam lda #BankRAMFastBuiltIn ;these are universal to all IIgs sta BankMap+$00 ;bank 00 sta BankMap+$01 ;bank 01 lda #BankRAMSlowBuiltIn ; sta BankMap+$e0 ;bank e0 sta BankMap+$e1 ;bank e1 lda #BankROMUsed sta BankMap+$FE ;bank FE sta BankMap+$FF ;bank FF lda GSROM cmp #3 ;check for ROM3 IIgs bne :rom0or1 :rom3 lda #BankRAMFastBuiltIn ldx #$02 ;bank 02 :builtinram sta BankMap,x ;bank 02 inx cpx #$10 ;stop after bank 0F bcc :builtinram lda #BankROMUsed ;ROM 3 is 256KB, so 4 banks (2 additional) sta BankMap+$FC ; sta BankMap+$FD ; ldx #$10 ;ROM3 starts scan at bank 10 bra :detectloop :rom0or1 ;no additional mappings lda #$FE ;ROM1 end bank FE sta :endbankscan+1 ;but change our max scan bank ldx #$02 ;ROM0/1 starts scan at bank 02 :detectloop txa ;we'll store the bank number sta :writer+3 ;overwrite bank address sta :reader+3 sta :compare+1 :writer stal $000000 ;should overwrite first byte :reader ldal $000000 :compare cmp #$00 bne :notused inc BankExpansionRam ;TotalMB++ lda #BankRAMFastExpansion ;store mapping sta BankMap,x :continue inx cpx #$E0 ;skip banks $E0-$EF bcc :endbankscan ; = F0 (>EF) ldx #$F0 ;skip to bank F0 bra :detectloop :endbankscan cpx #$FC ;ROM3 end bank (default) bcc :detectloop ;blt ;let's find low/high to simplify things ldx #$ff :lowloop lda BankMap,x cmp #BankRAMFastExpansion beq :isRam dex cpx #$ff bne :lowloop bra :checkhigh :isRam stx BankExpansionLowest dex bra :lowloop :checkhigh ldx #$00 :highloop lda BankMap,x cmp #BankRAMFastExpansion beq :isRam2 inx bne :highloop bra :done :isRam2 stx BankExpansionHighest inx bra :highloop :done bra :findKB :notused lda #BankNoRAM sta BankMap,x bra :continue :findKB lda BankExpansionRam ;number of banks clc xce rep #$30 mx %00 and #$00FF ;clear artifacts? can't remember state of B asl ;*2 asl ;*4 asl ;*8 asl ;*16 asl ;*32 asl ;*64 sta BankExpansionRamKB lda GSROM ;now check (hardcode really) build-in ram cmp #3 bne :notrom3 :rom3 lda #1024 sta BankBuiltInRamKB rts :notrom3 lda #256 sta BankBuiltInRamKB sep #$30 rts BankExpansionRamKB ds 2 BankBuiltInRamKB ds 2 BankExpansionRam ds 1 BankExpansionLowest ds 1 BankExpansionHighest ds 1 ds \ BankMap ds 256 ; BankROMUsed = 1 BankROMReserved = 2 BankRAMSlowBuiltIn = 3 BankRAMFastBuiltIn = 4 BankRAMFastExpansion = 5 BankNoRAM = 0 * Takes address in X/Y and prints out Int stored there PrintInt stx :loc+1 inx stx :loc2+1 sty :loc+2 sty :loc2+2 :loc ldx $2000 ;overwrite :loc2 ldy $2000 ;overwrite jsr BINtoBCD phx tya jsr PRBYTE pla jsr PRBYTE rts MLI equ $bf00 Quit jsr MLI ; first actual command, call ProDOS vector dfb $65 ; with "quit" request ($65) da QuitParm bcs Error brk $00 ; shouldn't ever here! QuitParm dfb 4 ; number of parameters dfb 0 ; standard quit type da $0000 ; not needed when using standard quit dfb 0 ; not used da $0000 ; not used Error brk $00 ; shouldn't be here either put misc put strings.s put menu.s