Skip to content
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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 76 additions & 14 deletions graphics.tex
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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}

Expand All @@ -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:
Copy link
Collaborator

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.


\begin{itemize}
\item The screen RAM, which occupies the memory range \$0800-\$2000 (by default)
Expand All @@ -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.
Copy link
Collaborator

Choose a reason for hiding this comment

The 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
Expand All @@ -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
Copy link
Collaborator

@dansanderson dansanderson Jul 25, 2023

Choose a reason for hiding this comment

The 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}
Copy link
Collaborator

Choose a reason for hiding this comment

The 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.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.
Binary file added images/graphics/basic-01.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.