Jump to content
  • entries
    39
  • comments
    57
  • views
    123,393

About this blog

Discussion of technical aspects of classic videogames

Entries in this blog

 

Pong Project

I've been working on a Pong related project and I thought I would post a screen shot:     Yes, this may look like any one of 1000 different Pong simulation programs that people have written, but this one it a little bit different. The screen shot you see here was generated by doing a chip level simulation of the Pong circuit using a general purpose digital logic simulation engine. Here a little sample of the code used to define one of the score counters:   Me.AddPart(New Nor2("F3B",

DanBoris

DanBoris

 

Pong Circuit Analysis

One of the things that I have always enjoyed about classic videogames, and classic arcade games in particular is learning how the actually operated. I have spent many an hour studying schematics of these machines to figure out exactly how they work.   Of particular interest are the earliest arcade games, since these did not have microprocessors. The graphics, sound and even game logic where implemented using just discrete logic circuits. What the designers of these machines managed to achieve

Guest

Guest

 

Telengard

One of the games I remember from the good old days with my Atari 800 computer is the dungeon crawler Telengard by Avalon Hill. The game was written in Basic so I thought it would be interesting to take a look at the code for the game. One of the most interesting parts is the way the maze if generated. The dungeon in the game is very large, it has 50 level and each level is 200 by 200 rooms. The dungeon is also the same every time you play so you can map it out as you go along. I was really curio

DanBoris

DanBoris

 

Procedure Calls 1

Let's take a break from looking at Action! math and take a look at procedure calls. We will start up with something that is trivially simple:   Proc test() Return Proc main() Test() Return     0E61: 4C 64 0E JMP $0E64 0E64: 60 RTS 0E65: 4C 68 0E JMP $0E68 0E68: 20 61 0E JSR $0E61 0E6B: 60 RTS   Our main procedure starts at 0E68 and it begins with a call to procedure Test using a JSR. The procedure Test starts at

DanBoris

DanBoris

 

OSS Action!

One of my favorite programming languages for the Atari 8-bit computers is OSS Action!. Action is a compiled, structured programming language similar to C or Pascal. One of the impressive features of Action is it’s very fast an efficient compiler. Not only does it compile programs quickly, it produced pretty tight machine code executables. I thought it would be interesting to take a look at some of the machine code that the compiler produces.   First lets look at the classic “Hello World” prog

DanBoris

DanBoris

 

7800 Sprites

One of the trickier parts of the 7800’s MARIA graphics chip is understanding how to setup the display lists and display list list (DL and DLL). Even trying to put a single sprite on the screen can be tricky. In this article I will explain how to setup these data structures to get a simple sprite on the screen.   In this example we will take a very narrow scenario just to explain the basics of how to get a sprite on the screen. I will show how to display a single 16 line high by 1 byte wide spr

DanBoris

DanBoris

 

Main Clock

The heart of Pong, and any of the discrete logic games is the horizontal and vertical counter. These counters continuously step through each horizontal and vertical position on the screen. The output of the counters is fed to all the other logic of the game which ultimately determines if each pixel should be on or off (or what color it should be in the case of color graphics).   Everything begins here       This is the main clock generator in Pong. The crystal (which is 14.318 MHz althoug

Guest

Guest

 

Action!: Byte Math

Next let’s look at some simple byte variable manipulation. Here is the first sample Action program:   BYTE I PROC MAIN() I=1 I=I+2 RETURN   And the assembly code   24B3: .byte $00 24B4: JMP $24B7 24B7: LDY #$01 24B9: STY $24B3 24BC: CLC 24BD: LDA $24B3 24C0: ADC #$02 24C2: STA $24B3 24C5: RTS   This code starts at memory location $24B3 which is where the global variable I is stored. Next we have a jump instruction that gets us to the MAIN procedure. Like

DanBoris

DanBoris

 

Horizontal counter

The next stage is the horizontal counter.         The 7 MHz clock signal enters F8 which is a 4-bit binary counter. The clock is divided in half producing the 1H signal which is the low bit of the horizontal counter. Each stage of F8 divides the signal in half again producing 2H, 4H, and 8H. F9 continues the division producing 16H, 32H, 64H and 128H. Finally the clock is divided in half one more time by F6 to produce 256H and an inverted version called /256H. (I use the ‘/’ before a signal

Guest

Guest

 

Vertical Counter

The next section is the vertical counter which works just like the horizontal counter. The input to the counter is the HRESET signal from the horizontal counter, so the vertical counter will increment once per horizontal scanline. The vertical counter, resets just like the horizontal, but on a count of 262, 256V + 4V + 1V + 1 (VRESET latched on the next clock pulse).

Guest

Guest

 

CARD Math Part 1

I can’t believe it’s been over a year since my last blog post, time sure does fly! I thought it was about time to get back to some posts and continue my Action! language topic.   Last time I talked about BYTE math, this time we will start looking at CARDinal math. In Action the CARD data type is a two byte unsigned value. Here is the first piece of Action! code:   CARD I PROC MAIN() I=1 I=I+1 RETURN   Here is the resulting disassembly:   0E6A: .BYTE #$00,#$00 0E6C: 4C 6F 0E J

DanBoris

DanBoris

 

CARD Math Part 2

In my last post I showed how the Action! compiler produces some pretty optimized code for CARD math under certain circumstances. This time I will show the more general case which should be pretty familiar to anyone who has done 6502 programming.   Here is the Action! program and it’s dis-assembly:   CARD I PROC MAIN() I=2 I=I+2 RETURN   0E6C: .BYTE 00,00 0E6E: 4C 71 0E JMP $0E71 ;I=2 0E71: A0 00 LDY #$00 0E73: 8C 6D 0E STY $0E6D 0E76: A9 02 L

DanBoris

DanBoris

 

Horizontal Sync

The horizontal and vertical counters are used to drive the rest of the digital logic in the circuit, but these counters cannot directly drive the synchronization of the CRT, for this horizontal and vertical sync signals are needed. Here is the circuit that generates the horizontal sync:   wishes.zip   The two H5 NAND gates form an RS flip-flip. When pin 4 goes low, pin 6 will go high and stay high, until pin 10 goes low. At the end of a scan line /H RESET will go low which will set HBLANKING

Guest

Guest

 

Paddles

There are two parts to the paddle generation circuit. There are two identical circuits (one for each player) that control the vertical position and height of the paddle, and a second circuit which controls the horizontal position and size.       The vertical circuit is based on the very versatile 555 timer chip (A9). In this case the 555 is configured in mono-stable mode. In this mode the OUT pin will go high when the TRIG input goes low, and will stay high for a period of time determined by

Guest

Guest

 

Vertical Sync

The vertical sync circuit works similar to the horizontal sync circuit. Again we have an RS flip-flop composed of two logic gates (F5), but this one is triggered by a high instead of a low. At the end of the vertical count, V RESET will go high, which will set VBLANK high which indicates the start of the vertical blank period. When the vertical counter reaches 4, the output of G5 will go low which is the vertical sync signal. When the count reaches 8, 8V goes high, the output of H5 goes low whic

Guest

Guest

 

Vertical Ball Pt II

The ball vertical motion is controlled by a slip counter just like the horizontal.       The counter is clocked by the /HSYNC signal so it will increment once per line. Since /VBLANK goes to the ENT input of B3 it will stop the count during VBLANK. When the two stages of the counter reach 255 the load signal will be triggered by B2. The upper stage of the counter is loaded with 0, and the lower portion is loaded with the output of the vertical control circuit. The values from the vertical c

DanBoris

DanBoris

 

The net

Now that we have covered the horizontal and vertical counters we can start talking about how the graphics for the game are actually generated. We will start with the simplest part, the net.       At the start of each horizontal line, /256 is high which gets clocked through F3 to one of the inputs of G3. Since the other input of G3 is connected to 256H (which is low), the output of G3 will be high thus turning the net off. When the horizontal counter reaches 256, 256H goes high, and the

Guest

Guest

 

7800 Control Register

Occasionally questions come up about the special “hidden” control register in the 7800, and I usually end up searching back through the forum archive for the answer, so I thought I’d finally document it somewhere I can find it!   The purpose of this control register is to switch the 7800 from 7800 mode to 2600 mode. The register can be written to using any address between $0000 and $001F. This address range overlaps the TIA so once the register is set you need to set the lock bit (see below) b

DanBoris

DanBoris

 

Ball Horizontal Control Part 2

As supercat observed in my last entry, I totally missed this part the first time around. Better late then never...   _pesco_pacman_v8.zip   For anyone who has played Pong, you may remember that the more times you volley the ball back and forth, the faster the ball will move. This counter counts those volleys. Each time the ball is hit by either player the counter will increment until it reaches a count of 12, at which point it will be disabled by NAND gate E1. The counter is reset by the RST

DanBoris

DanBoris

 

Score Sound

The next couple of circuits are used to generate the sounds for the game. The first sound circuit is for the score sound. This sound is played whenever either player misses the ball.       When a player misses the ball the /MISS signal will go low which will trigger the 555 timer G4. When triggered the output of G4 will go high and stay high for 242ms at which point the output will return low. When the output of the timer is high the 32V signal will be allowed to pass through NAND C3 to the

DanBoris

DanBoris

 

Score Part 1

The next section I am going to talk about is the score generation circuit. In Pong, each player has a two digit score that is displayed at the top of the screen on either side of the net. The circuit that generates the score display is a little complex, but I find it to be a very interesting design. I am going to start from the center of the circuit and work out.   At the heart of the score generator is as 7448 BCD to 7-segment decoder chip.       This chip is usually used to drive 7-segm

Guest

Guest

 

Attract Mode

The next thing I want to talk about is the attract mode, which is the mode the game is in when it’s not being played, designed to “attract” new players. Most of the schematics for this section I have posted already, so I will just describe how attract effects each section. The attract signal is generated by the game control circuit and is fed as both an active high and active low signal to various other circuits in the game.   In the paddle circuit, /ATTRACT holds the preset pin of flip-flop

DanBoris

DanBoris

 

Vertical Ball Control

Now that we have looked at the horizontal component of the ball we will look at the vertical portion. The vertical is based on a slip counter just like the horizontal so we will cover the slip counter control first. The vertical motion of the ball is influenced by two things, hitting the top or bottom of the screen, or hitting one of the paddles. When the ball hits the top or bottom of the screen, it will reverse direction, but keep the same speed. When the ball hits the paddle the effect on the

Guest

Guest

 

Hit Sound

It's been a while since I did an update to my Pong circuit analysis, but I just get distracted by other project far to easily!   The next section is the hit sound, the sound made when the ball is hit.   _corrected_pesco_pacman_roms_v6a.zip   When the ball hits either paddle the /HIT signal will go low which will clear C2 and set the /Q output high. For /HIT to go low VPOS256 has to be high, so there won’t be another positive edge on VPOS256 to clock the counter until the next frame. On the

DanBoris

DanBoris

 

Ball Horizontal Counter

The final graphic element we need to look at is the ball. Like the score this is a pretty complex, but very clever circuit.   The first part of the circuit we will look at is the horizontal counter. This circuit controls the horizontal location, motion and size of the ball. Later we will look at a similar circuit that controls the vertical.       The main part of the circuit is a 9 bit counter composed of G7 and H7, which are synchronous counters, and G6. When the counter reaches a count

Guest

Guest

×
×
  • Create New...