diff --git a/graphics.tex b/graphics.tex index da0c93aa..16d20a87 100644 --- a/graphics.tex +++ b/graphics.tex @@ -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. + 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 +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} + +No compromises and no problems we have, when we switch from BASIC to machine code. diff --git a/images/graphics/basic-01.png b/images/graphics/basic-01.png new file mode 100644 index 00000000..7ea1553e Binary files /dev/null and b/images/graphics/basic-01.png differ