-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Finished the BASIC intro in the graphics chapters #542
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ | |
\chapter{Graphics} | ||
\label{cha:graphics} | ||
|
||
Let's have some fun with graphics! | ||
Let's have some fun with graphics! \\ | ||
In this part of the book, we want to examine the MEGA65's graphics modes by walking through example code in machine language and BASIC to get to know the various options of the MEGA65 in the area of graphics. First of all, it is important to know that the MEGA65 supports three different basic graphics modes: | ||
|
||
\begin{itemize} | ||
|
@@ -139,8 +139,8 @@ \subsection*{Hires} | |
Back to the Screen-RAM. Here you store \textbf{two colours} for each 8x8 block. If you split the byte into its high and low nibble, you have the chance to put a background and a foreground colour into it! The hex value \$0a for example can be seen as \$0 (high nibble) and \$a (low nibble). This way we'll get a black background and light red for the pixels in the block. In the end this means, a fullscreen hires bitmap will consume not 8 but 9 Kilobytes. 8K for the raw bitmap data as mentioned earlier and another 1K for the colours inside the Screen-RAM.\\ | ||
|
||
\subsection*{Programming simple Hires Bitmaps} | ||
|
||
Let's code! But let's do it in BASIC first before we switch over to machine language. In order to bring bitmap graphics to the screen, we need to configure the VIC IV chip. There are several things VIC needs to know before it can find and read bitmap data. You have to do the following: | ||
Let's code! \\ | ||
But let's do it in BASIC first before we switch over to machine language. In order to bring bitmap graphics to the screen, we need to configure the VIC IV chip. There are several things VIC needs to know before it can find and read bitmap data. You have to do the following: | ||
|
||
\begin{itemize} | ||
\item Make sure to have activated the VIC-registers you need (remember the MEGA65 offers different versions of the VIC-chip) | ||
|
@@ -235,7 +235,7 @@ \subsection*{Programming simple Hires Bitmaps} | |
\end{tabular} \\ | ||
\end{tabular} | ||
|
||
The logic tables above are important because they show how the bits will be modified if you put an operator on it. If you think about the idea of logical operations in the example that follows, you will see that you can use AND to reset/clear a specific bit to zero (via a mask), and use OR can be used to set the bit to 1. To be honest, this method can not only be used to set a single bit, but also to change any number of bits but to keep things simple we modify only one. Back to the "bad" poke of 96 what we've seen above, it could be better written like this: | ||
The logic tables above are important because they show how the bits will be modified if you put an operator on it. If you think about the idea of logical operations in the example that follows, you will see that you can use AND to reset/clear a specific bit to zero (via a mask) and OR to set a bit to 1. To be honest, this method can not only be used to set a single bit, but also to change any number of bits but to keep things simple we modify only one. Back to the "bad" poke of 96 what we've seen above, it could be better written like this: | ||
|
||
\begin{screenoutput} | ||
POKE $D031, PEEK($D031) AND 127 :REM RESET BIT 7 (i.e., set it to zero) | ||
|
@@ -283,9 +283,7 @@ \subsection*{Programming simple Hires Bitmaps} | |
|
||
Armed with this knowledge, we can now start configuring the VIC to show bitmap graphics. For this we have to fine-tune a number of registers but before we can start with that, we need to understand a bit more about the graphics chip, how it is organised and most importantly how it accesses the memory. | ||
|
||
\underline{Side-note}: | ||
|
||
An alternative approach available in BASIC 65 for setting/clearing bits is to use the new {\bf SETBIT} and {\bf CLRBIT} commands. For assembly coders, you have the new {\bf SMBx} (set bit x) and {\bf RMBx} (reset bit x) instructions available to you. | ||
An alternative approach available in BASIC65 for setting/clearing bits is to use the new {\bf SETBIT} and {\bf CLRBIT} commands. For assembly coders, you have the new {\bf SMBx} (set bit x) and {\bf RMBx} (reset bit x) instructions available to you. | ||
|
||
\subsection*{VIC IV organization and memory access basics} | ||
|
||
|
@@ -297,7 +295,7 @@ \subsection*{VIC IV organization and memory access basics} | |
|
||
The system can have up to 16 banks and certain banks also have certain tasks. Banks 0 and 1 are RAM, which means you can read and write to them, while banks 2 and 3 are ROM and not so easy to override. | ||
|
||
Bank 0 (from the perspective of the BASIC 65 operating system that runs when you power the system on) is called the system bank. It contains regions such as: | ||
Bank 0 (from the perspective of the BASIC65 operating system that runs when you power the system on) is called the system bank. It contains regions such as: | ||
|
||
\begin{itemize} | ||
\item The screen RAM, which occupies the memory range \$0800-\$2000 (by default) | ||
|
@@ -308,16 +306,22 @@ \subsection*{VIC IV organization and memory access basics} | |
|
||
If you want to know more about memory management in general please have a look at \bookvref{cha:memory-map}. In BASIC - sorry to say - the situation gets even more complex. Right after turning on the computer you are in Bank 128 which is a special bank with a special memory configuration. You can use the command BANK to switch between banks. A problem here is, that you can easily lose track of what is in which bank or in which bank you are currently working. It's actually a bit easier when working in machine language. For more information about the BANK-command and banks in general, please look into \bookvref{bankcommand}. Please keep in mind that you need to know about banks before you can safely use PEEK, POKE or SYS. Otherwise you may wonder why your program does not behave as expected. We will come back to this later. Back to graphics. | ||
|
||
Let's begin to write a simple BASIC program to show hires bitmap graphics. If you followed this chapter carefully up to this point, you should have no trouble understanding the following lines of code: | ||
Let's begin to write a simple BASIC program to show hires bitmap graphics. We start by using Bank 128, which is active when you turn on your MEGA65. If you followed this chapter carefully up to this point, you should have no trouble understanding the following lines of code: | ||
|
||
\begin{screenoutput} | ||
10 POKE $D020,0 : POKE $D021,0 :REM MAKE SCREEN BLACK | ||
20 POKE $D031, PEEK($D031) AND 127 :REM SET RESOLUTION | ||
30 POKE $DD02, 3 :REM MAKE VIRTUAL CIA-2 READ- AND WRITEABLE | ||
40 POKE $$DD00, PEEK($DD00) AND 252 OR 2:REM SELECT VIDEO BANK 1 | ||
20 POKE $DD02, 63 :REM MAKE VIRTUAL CIA-2 READ- AND WRITEABLE | ||
30 POKE $$DD00, PEEK($DD00) AND 252 OR 3:REM SELECT VIDEO BANK 0 | ||
40 POKE $D031, PEEK($D031) AND 127 :REM SET RESOLUTION | ||
\end{screenoutput} | ||
|
||
As you have seen in the illustration on the page before, the VIC chip divides the memory into 4 video banks of 16KB each. It is important to understand that you do not use a register of the VIC to define the video bank inside the (memory-)bank 0, instead you use the data bits 0 and 1 of \$DD00 or 56576 decimal. This used to be a register of the CIA-2 chip on the Commodore 64 but in your MEGA65 it is implemented as a virtual register. The "preparation" needed to set the video bank happens in line 30 while in the following line the video bank itself is set. By the way, when you convert the decimal value 3 (line 30) into its binary format, it is 00000011 and proves: the data bits 0 and 1 are set to 1, so reading and writing is activated. | ||
As you have seen in the illustration on the page before, the VIC chip divides the memory into 4 video banks of 16KB each. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Try to preserve whitespace layout of the source so it's easier to find the actual changes in the pull request. (We should decide whether to prefer single-line paragraphs vs. hard-wrapped paragraphs, but regardless of what we decide we should make that change comprehensively in a single change without other changes.) |
||
It is important to understand that you do not use a register of the VIC to define the video bank inside | ||
the (memory-)bank 0, instead you use the data bits 0 and 1 of \$DD00 or 56576 decimal. | ||
This used to be a register of the CIA-2 chip on the Commodore 64 but in your MEGA65 it is implemented as a | ||
virtual register. The "preparation" needed to set the video bank happens in line 20 while in the following line | ||
the video bank itself is set. By the way, when you convert the decimal value 3 (line 30) into its binary format, | ||
it is 00000011 and proves: the data bits 0 and 1 are set to 1, so according to the following table we switch into bank 0. | ||
|
||
\begin{tabular}{|c|c|l|l|} | ||
\hline | ||
|
@@ -330,4 +334,62 @@ \subsection*{VIC IV organization and memory access basics} | |
\hline | ||
\end{tabular} | ||
|
||
The table shows which bits must be set to select a video bank. | ||
Next the resolution is scaled down (line 40) by setting data bit 7 of the register \$D031 to 0 as mentioned a few | ||
pages ago. In order to bring a graphic to the screen a few more settings are required. Within the VIC bank 0 | ||
we have to specify \textbf{where} the data for our graphic is located. In case of hires graphics, the data is divided between the | ||
bitmap itself and the screen RAM. In the latter the color of the respective 8x8 block is stored. The following lines | ||
set these two locations: | ||
|
||
\begin{screenoutput} | ||
50 POKE $D018, PEEK($D018) AND 247 OR 0 :REM BITMAP DATA STARTS AT $0000 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should use a realistic example of where a program might keep bitmap graphics data. As the text says later, locating bitmap data at $0000 is never a good idea. I assume that this is trying to avoid a discussion of memory banking and using BANK 128, which leaves no room in bank 0 for bitmap graphics data. It would be better to design a realistic example with an appropriate BANK statement, then refer to the Memory chapter for an explanation. It could be argued that there is no realistic BASIC example that does bitmap graphics this way. I have mixed feelings about providing BASIC examples that illustrate a point but aren't realistic techniques. I like that BASIC requires no third-party tools and can be typed immediately by the reader. Maybe we just need to state clearly and up front when we're providing an experiment that demonstrates registers that isn't a realistic technique for programs. Alternatively, we can prepare the reader for assembly language early in the book, then use assembly language for examples throughout the book. It's a larger organizational question and I'll have to think about it some more. For now I'll let you decide whether to write a different example that demonstrates a more useful memory range vs. rewriting the text to say "you'd never do this in a real program, but just as a demonstration..." We can resolve the larger question about assmebly language examples in rewrites later. |
||
60 POKE $D018, PEEK($D018) AND 15 OR 32 :REM SCREEN RAM STARTS AT $0800 | ||
\end{screenoutput} | ||
|
||
Of course you are free to choose where in memory you store your bitmap and color data. A detailed description of how to do this and how to configure it will follow later when we have switched from BASIC to machine code. | ||
The configuration shown above is enough for now, ironically this is exactly the setting when you turn on your MEGA65 with the default bank 128 enabled. The final step is to poke our bitmap and color data into memory: | ||
|
||
\begin{screenoutput} | ||
70 POKE $0100, 0 | ||
71 POKE $0101, 120 | ||
72 POKE $0102, 204 | ||
73 POKE $0103, 204 | ||
74 POKE $0104, 252 | ||
75 POKE $0105, 204 | ||
76 POKE $0106, 204 | ||
77 POKE $0107, 204 | ||
80 POKE $0820, $A0 | ||
\end{screenoutput} | ||
|
||
In order to bring the already shown \textbf{A} from this figure | ||
|
||
\begin{center} | ||
\begin{tabular}{|C{12pt}|C{12pt}C{12pt}C{12pt}C{12pt}C{12pt}C{12pt}C{12pt}C{12pt}|R{24pt}|R{24pt}|} | ||
\hline | ||
& 7 & 6 & 5& 4& 3& 2& 1& 0 & dec & hex \\ | ||
\hline | ||
0 & \blkb & \blkb & \blkb & \blkb & \blkb & \blkb & \blkb & \blkb & 0 & 00 \\ | ||
1 & \blkb & \redb & \redb & \redb & \redb & \blkb & \blkb & \blkb & 120 & 78 \\ | ||
2 & \redb & \redb & \blkb & \blkb & \redb & \redb & \blkb & \blkb & 204 & CC \\ | ||
3 & \redb & \redb & \blkb & \blkb & \redb & \redb & \blkb & \blkb & 204 & CC \\ | ||
4 & \redb & \redb & \redb & \redb & \redb & \redb & \blkb & \blkb & 252 & FC \\ | ||
5 & \redb & \redb & \blkb & \blkb & \redb & \redb & \blkb & \blkb & 204 & CC \\ | ||
6 & \redb & \redb & \blkb & \blkb & \redb & \redb & \blkb & \blkb & 204 & CC \\ | ||
7 & \redb & \redb & \blkb & \blkb & \redb & \redb & \blkb & \blkb & 204 & CC \\ | ||
\hline | ||
\end{tabular} | ||
\end{center} | ||
|
||
to the screen, the values must be placed in memory starting at \$0000. The color information in the screen RAM (please remember, it starts at \$0800) defines | ||
the foreground and the background color of the corresponding block. In line 80 the value is split off into \textbf{A} for a light red foreground while the \textbf{0} is producing the wonderful black background. | ||
The following screenshot shows the result, our "A" appears on the screen. But does it look good? | ||
|
||
\includegraphics[width=\linewidth]{images/graphics/basic-01.png} | ||
|
||
As you can probably guess, our BASIC implementation has many problems. It is difficult for us to move freely in memory. The "A" doesn't appear | ||
at the very beginning of the screen. Look into the listing, poking starts at \$0100, not \$0000 as it should be. The reason is that the Zeropage starts at \$0000 | ||
and storing graphic data there is not really clever. You see, we have to make a lot of compromises and face many challenges when we don't use BASIC's built-in graphics commands, | ||
but work directly in memory to generate graphics. | ||
|
||
\subsection*{From BASIC to machine code} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably remove this for now. I suspect that a chapter on graphics in general (i.e. not specific to BASIC graphics commands) will be mostly register and memory manipulation, in which case the differences between PEEK/POKE and lda/sta don't justify extra material. We should think about how we want to include memory mapping in this discussion. (I intend to cover the BASIC graphics subsystems in a separate chapter and probably a separate book. If you want to contribute to that let me know, but I think that material should be separate from this chapter, because it's probably a best practice to not mix BASIC graphics commands and direct register manipulation.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah ! Thanks for this valuable feedback, I will think about it, maybe i should skip that BASIC starter. Let me think about it. :-) |
||
|
||
No compromises and no problems we have, when we switch from BASIC to machine code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't agree with this style change. We need to do a comprehensive style review for the entire doc set and build out the style guide. I would advocate for "BASIC 65" when we do that.