Unexpanded VIC 20 Memory
Moderator: Moderators
- Kweepa
- Vic 20 Scientist
- Posts: 1315
- Joined: Fri Jan 04, 2008 5:11 pm
- Location: Austin, Texas
- Occupation: Game maker
So I was digging through the Whack source code and I notice that Aleksi stores some nybbles at $9400-$95FF on the unexpanded VIC.
Is it common knowledge that there's a whole spare 512x4bit block? I'd assumed that the hardware rerouted memory access when you insert an 8k expansion. Does anyone know why the hardware is designed this way? It seems ludicrously wasteful! But I'm loving the info. Extra memory! Yay!
Is it common knowledge that there's a whole spare 512x4bit block? I'd assumed that the hardware rerouted memory access when you insert an 8k expansion. Does anyone know why the hardware is designed this way? It seems ludicrously wasteful! But I'm loving the info. Extra memory! Yay!
Yes, it is rather well known. I'm using those 512 bytes quite frequently in my games when I want to store colour-ish data not visible to the player.
Also remember you may expand the screen to cover more than 512 bytes. In that case the 1K of nybbles comes handy. Generally PAL screens can grow bigger than NTSC ones can.
Also remember you may expand the screen to cover more than 512 bytes. In that case the 1K of nybbles comes handy. Generally PAL screens can grow bigger than NTSC ones can.
Anders Carlsson
In an unexpanded VIC 20 the 512 locations in memory from $9600-$97ff are used as the colour RAM, whereas if an *K expansion RAM is fitted, the block $9400-$95ff is used instead. In either case the locations used are only four bits in size instead of the usual eight bits in size.
The different locations are used to hold the appropriate foreground colour
for each character area of the display on the TV screen. There is, therefore,
a direct correspondence between the locations of the video RAM, the character table and the colour RAM.
taken from
Lance Ewing (PAL user)
http://www.fpgaarcade.com/resources/6561.txt
The different locations are used to hold the appropriate foreground colour
for each character area of the display on the TV screen. There is, therefore,
a direct correspondence between the locations of the video RAM, the character table and the colour RAM.
taken from
Lance Ewing (PAL user)
http://www.fpgaarcade.com/resources/6561.txt
Code: Select all
1 rem for pal systems, for ntsc use 4 instead of 12
10 fori=12to77step.5
20 poke36864,i
30 fort=1to 25:next
40 next
50 fori=77to12step-.5
60 poke36864,i
70 fort=1to25:next
80 next i
run
I think the screen matrix and colour memory addressing both read the "lowest" bit from 36866:
$1000 = $9400, $1200 = $9600
$1400 = $9400, $1600 = $9600
$1800 = $9400, $1A00 = $9600
$1C00 = $9400, $1E00 = $9600
It means even on an unexpanded machine, if you move the screen back to start at $1C00 = 7168, the colour memory will follow back to $9400.
$1000 = $9400, $1200 = $9600
$1400 = $9400, $1600 = $9600
$1800 = $9400, $1A00 = $9600
$1C00 = $9400, $1E00 = $9600
It means even on an unexpanded machine, if you move the screen back to start at $1C00 = 7168, the colour memory will follow back to $9400.
Anders Carlsson
I believe I have a better understanding of this program now, it is written with BASIC Tokens and executed from memory byte 864. From just looking at it I can see there is some PRINT tokens and some STEP tokens.Legacy wrote:Ok so back to the 1.3 demo:
1 REM VIC VERSION
800 FOR AD=864TO885:READDA:POKEAD,DA:NEXTAD
805 PRINT"SYS 864 TO ACTIVATE"
810 DATA 160, 0, 169, 1, 153, 0
820 DATA 30, 153, 0, 31, 169, 6
830 DATA 153, 0, 150, 153, 0, 151
840 DATA 200, 208, 237, 96
I recall seeing a program online where COMMODORE + IBM = pi (symbol) . It was a brain teaser and there was also a contest to see who could create the most innovative clear screen routine and another article on creating a 3d star field, and now I never bookmarked the page and I've forgotten where it can be found. Can anyone assist me on finding this web page, I believe it may have Jim Brain on it as well, but not sure about that. Thank you
- Kweepa
- Vic 20 Scientist
- Posts: 1315
- Joined: Fri Jan 04, 2008 5:11 pm
- Location: Austin, Texas
- Occupation: Game maker
Not quite...Legacy wrote: I believe I have a better understanding of this program now, it is written with BASIC Tokens and executed from memory byte 864. From just looking at it I can see there is some PRINT tokens and some STEP tokens.
It's a machine code program which can be readily hand disassembled:
Code: Select all
LDY #0
LDA #1
STA $1E00,Y ; write 1 to the upper and lower pages of the screen memory
STA $1F00,Y
LDA #6
STA $9600,Y ; write 6 (blue) to the upper and lower pages of the color memory
STA $9700,Y
INY
BNE -19
RTS
I have put that code through dasm and there seems to be an error:
It seems like the instructions are one byte too long for it's intended purpose. The initial listing says it should goto 885 , the branch is not functional. I don't know how to fix this
d0 8a is actualy 208, 138 not 208,238 d0.... ED = 238 which means the BNE statement is wrong. The accumulator will never reach -19, is that added for a loop? I recompiled with -18 and -17 and everytime the branch is still out of range even though it falls within the specified bytes in memory (885 for -18)How did you find out the assembly code, this is what i tried doing :
It didnt do what I thought it would
Code: Select all
------- FILE basicasm.asm LEVEL 1 PASS 1
1 0000 processor 6502
2 0000 ????
3 034e org $034e
4 034e
5 034e a0 00 LDY #0
6 0350 a9 01 LDA #1
7 0352 99 00 1e STA $1E00,Y ; write 1 to the upper and lower pages of the screen memory
8 0355 99 00 1f STA $1F00,Y
9 0358 a9 06 LDA #6
10 035a 99 00 96 STA $9600,Y ; write 6 (blue) to the upper and lower pages of the color memory
11 035d 99 00 97 STA $9700,Y
12 0360 c8 INY
basicasm.asm (13): error: Branch out of range (-886 bytes).
13 0361 d0 8a BNE -19
14 0363 60 rts
d0 8a is actualy 208, 138 not 208,238 d0.... ED = 238 which means the BNE statement is wrong. The accumulator will never reach -19, is that added for a loop? I recompiled with -18 and -17 and everytime the branch is still out of range even though it falls within the specified bytes in memory (885 for -18)How did you find out the assembly code, this is what i tried doing :
Code: Select all
#processor 6502
org $034e ;846 (cass buffer)
.byte $a0 $00 $a9 $01 $99 $00 $1e $99 $00 $1f $a9 $06
.byte $99 $00 $96 $99 $00 $97 $c8 $d0 $ed $60
- Kweepa
- Vic 20 Scientist
- Posts: 1315
- Joined: Fri Jan 04, 2008 5:11 pm
- Location: Austin, Texas
- Occupation: Game maker
Two problems:
The 864 = $360, not $34e (= 846)
I wrote the branch as an offset. The compiler expects it to be an absolute address or a label. Try this:
The 864 = $360, not $34e (= 846)
I wrote the branch as an offset. The compiler expects it to be an absolute address or a label. Try this:
Code: Select all
LDY #0
LOOP:
LDA #1
STA $1E00,Y ; write 1 to the upper and lower pages of the screen memory
STA $1F00,Y
LDA #6
STA $9600,Y ; write 6 (blue) to the upper and lower pages of the color memory
STA $9700,Y
INY
BNE LOOP
RTS
Eureka!
That works, but how did you get those decimal numbers into hex and translate it into a program? According to my Assembly program the instructions are loaded into 0360 (i changed it) so it should just execute number after number?Or maybe I'm thinking of when you write hex as basic tokens at the beginning of BASIC RAM 4096. I still don't understand how you got that assembly program out of
810 DATA 160, 0, 169, 1, 153, 0
820 DATA 30, 153, 0, 31, 169, 6
830 DATA 153, 0, 150, 153, 0, 151
840 DATA 200, 208, 237, 96
Did you use Vicmon, I don't know how that operates I just use vice and dasm and just now have experimented with the list output file to get the actual register values i know A9 = load accumulator and a couple others. So I guess you know how to write an assembly program from just looking at the numbers in the DATA statements, calculating their hex format and formulate the proper assembly code... nice skills!
Code: Select all
------- FILE basicasm.asm LEVEL 1 PASS 1
1 0000 processor 6502
2 0000 ????
3 0360 org $0360
4 0360
5 0360 a0 00 LDY #0
6 0362 a9 01 loop LDA #1
7 0364 99 00 1e STA $1E00,Y
8 0367 99 00 1f STA $1F00,Y
9 036a a9 06 LDA #6
10 036c 99 00 96 STA $9600,Y
11 036f 99 00 97 STA $9700,Y
12 0372 c8 INY
13 0373 d0 ed BNE loop
14 0375 60 RTS
810 DATA 160, 0, 169, 1, 153, 0
820 DATA 30, 153, 0, 31, 169, 6
830 DATA 153, 0, 150, 153, 0, 151
840 DATA 200, 208, 237, 96
Did you use Vicmon, I don't know how that operates I just use vice and dasm and just now have experimented with the list output file to get the actual register values i know A9 = load accumulator and a couple others. So I guess you know how to write an assembly program from just looking at the numbers in the DATA statements, calculating their hex format and formulate the proper assembly code... nice skills!
VIC Revealed - Nick Hampshire
Nick talks about writing machine code and asks us to consider the following program, writing the first 256 characters on the screen, well here she is, and I even came up with my own conventions :
Ok well I did steal a little from the valentine program, but I figured out how to add to the accumulato -yay!
Code: Select all
;fill first page screen ram with first 256 characters, dasm/unexpanded
#processor 6502
org $1001
dc.b $0b,$10,$0a,$00,$9e,$34,$31,$30,$39,$00,$00,$00
org $100d
main
ldy #$00 ;y index 0
lda #$00 ;accumulator
.1
sta $1e00,y ;7680,0 -absolute indexed
clc
adc #$01 ;0+1 = 1
iny ;next screen mem
bne .1 ;put 256 chars in 256 mem locs
lda #$06 ;add some color to the screen
.2 ;y is returned as 0 from first loop
sta $9600,y
iny
bne .2 ;repeat if y!=0
jsr main ;do it again
Re: VIC Revealed - Nick Hampshire
Nice. Now you may want to consider some optimizations:
As you see, two loops combined into one. However if your intent was not to fill colour memory at the same time as screen memory, you may just as well keep the two separate like you did.
TYA and its reverse TAY (see also TXA and TAX) are handy instructions to transfer the content of the X and Y registers to/from the accumulator. In your program you want to print a different character at each screen position so instead of counting A separately you can just reuse the Y value.
I'm not sure why you would want to JSR main at the end, in particular since you are likely to run out of spack space after a while.
By the way, if you use DASM there are a few home-made macros you might want to take part of. In particular it is great to have a macro to generate the Basic SYS stub you have added by hand at the beginning.
Code: Select all
#processor 6502
org $1001
.byte $0b,$10,$0a,$00,$9e,$34,$31,$30,$39,$00,$00,$00
main:
ldy #$00
loop$:
tya ; transfer Y reg to A
sta $1e00,y
lda #$06
sta $9600,y
iny
bne loop$
wait:
jmp wait
TYA and its reverse TAY (see also TXA and TAX) are handy instructions to transfer the content of the X and Y registers to/from the accumulator. In your program you want to print a different character at each screen position so instead of counting A separately you can just reuse the Y value.
I'm not sure why you would want to JSR main at the end, in particular since you are likely to run out of spack space after a while.
By the way, if you use DASM there are a few home-made macros you might want to take part of. In particular it is great to have a macro to generate the Basic SYS stub you have added by hand at the beginning.
Anders Carlsson
I see, so when we load Y index with 0 the value doesn't change when the contents are transferred into the accumulator, there is no need to add new instructions and the Wait loop is just a continuous loop at the end of the program instead of executing the main loop, the last instructions are still kept intact because the program has never moved forward. That will definitely help in the future when writing multi-routine programs.
Ok, but what about lda #6 , wouldnt that change the contents and bring accumulator out of synch with the Y index register? Oh I guess not because when Y is increased INY then Y goes to 1 and the contents are transferred back into the accumulator, very clever!
Ok, but what about lda #6 , wouldnt that change the contents and bring accumulator out of synch with the Y index register? Oh I guess not because when Y is increased INY then Y goes to 1 and the contents are transferred back into the accumulator, very clever!