我试图从顶部和底部打印一些字符行,第一行结果如预期,但下一行没有打印。我在";Currentline";让程序打印下一行,好吧——这就是我认为可行的。它不会打印,但如果我设置";Currentline";从开始到40,它打印在下一行。
我做错了什么?
/*
****************************************
* Really awesome code by Cri33e - 2022 *
****************************************
*/
*=$2000 // Startas med sys8192
.var ScreenCTop_Adress = $d7ff
.var ScreenCBottom_Adress = $dbbf
.var ScreenTop_Adress = $03ff
.var ScreenBottom_Adress = $07bf
.var Currentline = 0
.var Char_color = 3
.var HowManyRows = 4
Next_row:
lda #Char_color
ldy #20
ldx #40
loop1:
sta ScreenCTop_Adress+Currentline,x
sta ScreenCBottom_Adress-Currentline,x
tya
sta ScreenTop_Adress+Currentline,x
sta ScreenBottom_Adress-Currentline,x
lda #Char_color
dex
bne loop1
lda Currentline + 40
sta Currentline
ldx HowManyRows
dex
stx HowManyRows
bne Next_row
rts
enter code here
我看到以下问题:
.var
指令不会执行您认为它会执行的操作(至少对于Currentline
和HowManyRows
(。我认为这只是一个预处理指令,类似于C中的#define
。您应该将.DB
指令与内存标签一起使用- 您不能在同一操作中进行加法和加载,因此(假设您进行了第1点中建议的更正(
lda Currentline + 40
不会执行您认为会执行的操作。它用Currentline
指定的存储器地址的值加载累加器,偏移40字节 - 类似地,您不能在同一操作中进行加法和存储,所以,所以(假设您在第1点中进行了建议的更正(像
sta ScreenCTop_Adress+Currentline,x
这样的行将不起作用。它将把值存储在累加器中等于ScreenCTop_Adress
的地址+Currentline
的地址加上X中的值
您的代码需要大量重写才能正常工作,而且由于屏幕RAM和彩色RAM各大于256字节,如果不在零页中使用指针和间接寻址,就无法正确地完成。然而,为了好玩,我将尝试重写不使用零页面,因为我不知道零页面的哪一部分对您可用。我也会尽量让它与您的代码相似,但有很多地方需要更改。我警告你,结果将是丑陋的,决不是正确的解决方案。此外,我并没有对此进行测试。
; Color RAM base addresses for groups of six character rows
; (i.e. what can be fully addressed with an 8-bit index)
.VAR ScreenC_Address_0_5 = $D800 ; rows 0-5
.VAR ScreenC_Address_6_11 = $D8F0 ; rows 6-11
.VAR ScreenC_Address_12_17 = $D9E0 ; rows 12-17
.VAR ScreenC_Address_18_23 = $DAD0 ; rows 18-23
.VAR ScreenC_Address_24 = $DBC0 ; row 24
; Screen RAM base addresses for groups of six character rows
; (i.e. what can be fully addressed with an 8-bit index)
.VAR Screen_Address_0_5 = $0400 ; rows 0-5
.VAR Screen_Address_6_11 = $04F0 ; rows 6-11
.VAR Screen_Address_12_17 = $05E0 ; rows 12-17
.VAR Screen_Address_18_23 = $06D0 ; rows 18-23
.VAR Screen_Address_24 = $07C0 ; row 24
; this is what you are filling your line with
; these are constants - you need to reassemble to change them
; an alternative is to store these in memory and set then set
; them in code before calling the function
.VAR Char_color = 3 ; color constant (cyan)
.VAR CharVal = $20 ; fill character display code (space)
CurrentLine: .DB 0 ; first row number to fill
HowManyRows: .DB 4 ; count of rows to fill at top and bottom
MirrorCount: .DB ; so code doesn't have to be duplicated for top/bottom halves
Next_row: LDA #2
STA MirrorCount ; two line fills per row (one at the top, one at the bottom)
MirrorWrite: LDA CurrentLine ; get the row number to fill next
LDX #$FF
FindBankLoop: INX
SEC
SBC #6
BCS FindBankLoop ; find which bank of 6 rows the target row resides in
ADC #6
TAY ; calculate the row number relative to the start of the bank
CLC
RowIdxLoop: ADC #40
DEY
BPL RowIdxLoop
TAY ; get an index to the end of the row (actually start of subsequent row)
FillLine: DEX
BPL TryBank1 ; continue if row is not in first bank
TAX ; get index to the end of the row
LDA #Char_color
LineColorBank0: DEX
STA ScreenC_Address_0_5,X ; set a character colour
BNE LineColorBank0 ; fill the line with the desired colour
LDA #CharVal
LineTextBank0: DEY
STA Screen_Address_0_5,Y ; write the screen code to screen RAM
BNE LineTextBank0 ; fill the line with the character
BEQ EndLineFill ; absolute branch - finish with the current line
; same thing but in the second bank of six character rows
TryBank1: DEX
BPL TryBank2
TAX
LDA #Char_color
LineColorBank1: DEX
STA ScreenC_Address_6_11,X
BNE LineColorBank1
LDA #CharVal
LineTextBank1: DEY
STA Screen_Address_6_11,Y
BNE LineTextBank1
BEQ EndLineFill
; same thing but in the third bank of six character rows
TryBank2: DEX
BPL TryBank3
TAX
LDA #Char_color
LineColorBank2: DEX
STA ScreenC_Address_12_17,X
BNE LineColorBank2
LDA #CharVal
LineTextBank2: DEY
STA Screen_Address_12_17,Y
BNE LineTextBank2
BEQ EndLineFill
; same thing but in the fourth bank of six character rows
TryBank3: DEX
BPL DoLine24
TAX
LDA #Char_color
LineColorBank3: DEX
STA ScreenC_Address_18_23,X
BNE LineColorBank3
LDA #CharVal
LineTextBank3: DEY
STA Screen_Address_18_23,Y
BNE LineTextBank3
BEQ EndLineFill
; same thing but in the fifth bank of six character rows
DoLine24: TAX
LDA #Char_color
Line24Color: DEX
STA ScreenC_Address_24,X
BNE Line24Color
LDA #CharVal
Line24Text: DEY
STA Screen_Address_24,Y
BNE Line24Text
EndLineFill: SEC
LDA #24
SBC CurrentLine
STA CurrentLine ; mirror the current line in the bottom half of the screen (or switch back to the top half)
DEC MirrorCount
BEQ Cont1
JMP MirrorWrite ; fill the line in the bottom half of the screen
Cont1: INC CurrentLine ; move to the next row
DEC HowManyRows
BEQ Cont2
JMP Next_row ; fill the specified number of rows
Cont2: RTS
编辑:在发布这个答案30秒后,我想到了一种更干净的方法,仍然不使用零页面。我意识到我可以在屏幕RAM和彩色RAM中使用行开头的内联指针。这大大缩短了代码。
.VAR ScreenC_Address = $D8 ; color RAM base page
.VAR Screen_Address = $04 ; screen RAM base page
; this is what you are filling your line with
; these are constants - you need to reassemble to change them
; an alternative is to store these in memory and set then set
; them in code before calling the function
.VAR Char_color = 3 ; color constant (cyan)
.VAR CharVal = $20 ; fill character display code (space)
; set these values to whatever you want before calling the function
CurrentLine: .DB 0 ; first row number to fill (0 – 24)
HowManyRows: .DB 4 ; count of rows to fill at top and bottom
MirrorCount: .DB ; so code doesn't have to be duplicated for top/bottom halves
Next_row: LDA #2
STA MirrorCount ; two line fills per row (one at the top, one at the bottom)
MirrorWrite: LDA #0
TAY
LDX CurrentLine
CLC
BEQ SetPointers
PtrAdjLoop: ADC #40
BCC SkipHigh
INY
CLC
SkipHigh: DEX
BNE PtrAdjLoop ; calculate 16-bit index to start of row in YA
SetPointers: STA InlPtrColor+1
STY InlPtrColor+2
STA InlPtrScreen+1
STY InlPtrScreen+2
LDA #ScreenC_Address
ADC InlPtrColor+2
STA InlPtrColor+2 ; set inline color RAM pointer to start of row
LDA #Screen_Address
ADC InlPtrScreen+2
STA InlPtrScreen+2 ; set inline screen RAM pointer to start of row
LDA #Char_color
LDY #39
InlPtrColor: STA $FFFF,Y ; $FFFF is arbitrary default value for color RAM pointer
DEY
BPL InlPtrColor
LDA #CharVal
LDY #39
InlPtrScreen: STA $FFFF,Y ; $FFFF is arbitrary default value for screen RAM pointer
DEY
BPL InlPtrScreen
SEC
LDA #24
SBC CurrentLine
STA CurrentLine ; mirror the current line in the bottom half of the screen (or switch back to the top half)
DEC MirrorCount
BNE MirrorWrite ; fill the line in the bottom half of the screen
INC CurrentLine ; move to the next row
DEC HowManyRows
BNE Next_row ; fill the specified number of rows
RTS