Jump to content
IGNORED

Fairchild Channel F Tech/Programming info


TailChao

Recommended Posts

  • 4 weeks later...

Heh. I meddled in that too, out of curiosity. It was murder to find an assembler, or any info at all on the system... here's a page that I found:

 

http://www.nyx.net/~lturner/public_html/Fa...irchild_F8.html

 

And:

 

http://www.nyx.net/~lturner/public_html/F8_ins.html

 

Don't have a clue about the system itself. Try looking at some MESS source.

Link to comment
Share on other sites

  • 1 month later...

I'd like to know as well... if anyone's interested, I can probably give you the assembler with the F8 data file, it's a DOS compiler called Cross-16. The data file can be adapted for Table Assembler (I think), which would probably help alot...

 

For some reason, every site I looked at said something different as to what the Fairchild's resolution is... the cart size is 2k, though.

Link to comment
Share on other sites

I know that there has been recent progress by at least someone. First, I know that in the past, there were only about 4 Channel F roms floating around, but recently almost the complete set has been dumped. Furthermore, someone has recompiled MESS to work properly with these ROMS now, and has also wrote a multicart menu code for this.

 

During this process, an easter egg was found in Videocart #20.

 

Additionally, a Swedish collector is offering a bounty of a complete collection of carts to anyone who can program a Tetris game for the Channel F.

 

Details here:

 

http://w5.nuinternet.com/s660100106/competition/

Link to comment
Share on other sites

Here are the instructions I was sent on the Videocart #20 Easter Egg (Video Wizball):

 

First, start a game with a target score of 1 (push down to get to the SCORE prompt, twist counter-clockwise until the number is 1) then pull up to start.   It doesn't actually have to be a 1 score game, but you need to finish a game, and that's the shortest game you can play.

 

Now move your controller forward or backwards, or else the computer will play both sides.  Now win (or lose), and the computer opponent will stop moving.

 

Shoot him and then let yourself get hit by an object, while you are both gone, pull up to start over.

 

Now select GAME 43 and SCORE 67, and pull up to start. (Hex 43 = Dec 67)  

 

The programmer's name appears as a fixed object in the middle of the playfield on which all moving objects will bounce.

 

The last five bytes in the code are TRACY, the name of the programmers

daughter.

 

There is also an egg in the Democart code:

 

When you get to the end of the demo, hit buttons 1,3 and 4 at the same time. When you release them, the programmer's name is printed.

 

I will see about getting the ROMS and updated MESS files available to those that want them.

post-41-1083160340_thumb.jpg

Link to comment
Share on other sites

Here are the instructions I was sent on the Videocart #20 Easter Egg (Video Wizball):

 

First, start a game with a target score of 1 (push down to get to the SCORE prompt, twist counter-clockwise until the number is 1) then pull up to start.   It doesn't actually have to be a 1 score game, but you need to finish a game, and that's the shortest game you can play.

 

Now move your controller forward or backwards, or else the computer will play both sides.  Now win (or lose), and the computer opponent will stop moving.

 

Shoot him and then let yourself get hit by an object, while you are both gone, pull up to start over.

 

Now select GAME 43 and SCORE 67, and pull up to start. (Hex 43 = Dec 67)  

 

The programmer's name appears as a fixed object in the middle of the playfield on which all moving objects will bounce.

 

The last five bytes in the code are TRACY, the name of the programmers

daughter.

 

There is also an egg in the Democart code:

 

When you get to the end of the demo, hit buttons 1,3 and 4 at the same time. When you release them, the programmer's name is printed.

 

I will see about getting the ROMS and updated MESS files available to those that want them.

 

Wow. So, would this easter egg be before the Adventure one? I don't know when the democart came out, but it seems like it would be before then.

 

I'd be interested in those files and roms :P

Link to comment
Share on other sites

Sorry for the delay in getting back to everyone, I was having trouble setting up my FTP account on my new domain. :dunce:

 

Anyway, go here:

 

http://retrogamesrus.com/ChannelF/

 

When prompted, user name is channelf, password is zircon.

 

You should see 2 files, one is all the ROMs (missing #25) and 2 BIOS files. Any rom number with the letter "g" after it is the German version.

 

The other file contains 2 recompiled MESS files, so replace the ones you have with these. I have been using the latest version of MESS, don't know if these files will work with older versions. The control keys are a bit tricky, you'll need to take a look at the control map to figure out which keys do what. Just about everything works as far as I can tell.

 

Good luck and enjoy! :D

 

Do you happen to know who, or at least where you saw that someone had made progress in programming for the system?

 

Check this guy out: http://members.cox.net/seanriddle/chanf.html

Link to comment
Share on other sites

  • 3 years later...

Thought I'd unearth this old topic because I've been messing around with the Channel F and well.. the VESWiki is gone. I've been looking over Blackbird's Pac-man sorce and wrote my own little demo but for some reason I can't get my sprite to be drawn, it's there alright though as it moves off the screen (causing that black horizontal line). Been looking my code over and over and for the life of me can't figure out why the sprite isn't being drawn in the color I specified and why it's always clear.

Link to comment
Share on other sites

Thought I'd unearth this old topic because I've been messing around with the Channel F and well.. the VESWiki is gone. I've been looking over Blackbird's Pac-man sorce and wrote my own little demo but for some reason I can't get my sprite to be drawn, it's there alright though as it moves off the screen (causing that black horizontal line). Been looking my code over and over and for the life of me can't figure out why the sprite isn't being drawn in the color I specified and why it's always clear.

Fixed it, now onto figuring out controls and adding enemy sprites... wish there were more resources.

Link to comment
Share on other sites

  • 4 weeks later...
Thought I'd unearth this old topic because I've been messing around with the Channel F and well.. the VESWiki is gone. I've been looking over Blackbird's Pac-man sorce and wrote my own little demo but for some reason I can't get my sprite to be drawn, it's there alright though as it moves off the screen (causing that black horizontal line). Been looking my code over and over and for the life of me can't figure out why the sprite isn't being drawn in the color I specified and why it's always clear.

Fixed it, now onto figuring out controls and adding enemy sprites... wish there were more resources.

 

 

Hi there!

 

I'm the co-author of Pac-Man on Channel F, I can probably help you... It would be nice to try out your program. Any screenshots?

Isn't the WIKI up again, I got an email from Blackbird a few weeks ago saying he was ready for another go at the game.

 

 

Let me know.

 

e5frog

Link to comment
Share on other sites

Thought I'd unearth this old topic because I've been messing around with the Channel F and well.. the VESWiki is gone. I've been looking over Blackbird's Pac-man sorce and wrote my own little demo but for some reason I can't get my sprite to be drawn, it's there alright though as it moves off the screen (causing that black horizontal line). Been looking my code over and over and for the life of me can't figure out why the sprite isn't being drawn in the color I specified and why it's always clear.

Fixed it, now onto figuring out controls and adding enemy sprites... wish there were more resources.

 

 

Hi there!

 

I'm the co-author of Pac-Man on Channel F, I can probably help you... It would be nice to try out your program. Any screenshots?

Isn't the WIKI up again, I got an email from Blackbird a few weeks ago saying he was ready for another go at the game.

 

 

Let me know.

 

e5frog

Theres not much to it other then the border and the sidebar, can't quite get the sprite to only move when it's reading the controller state and the collision isn't working, likes to go off the screen creating a black bar.

mycfgame.bmp

Edited by EmOneGarand
Link to comment
Share on other sites

Theres not much to it other then the border and the sidebar, can't quite get the sprite to only move when it's reading the controller state and the collision isn't working, likes to go off the screen creating a black bar.

 

 

In Pac-Man we delete and redraw the sprite every update (and also the monsters).

 

As the position is stored in two registers (or copied into before being drawn) you can read those registers and compare the value to what the values are at your extreme values. If they're too much or too litte you change the register to the closest extreme value before redrawing again.

 

Like this:

Read controller

Delete object at current position

Change coordinate registers x, y (or however you set position) according to hand controller movement

Compare new values to extreme points

Change values if outside allowed values

Draw object at new or unchanged position

 

If you store the old position in other registers and delete object just before you redraw it at the new position you'll get less flicker.

 

Let's say you have coordinates x: [0,50] and y: [0,50], after a controller movement the x register is 51, you compare it to 50 and result is greater (or compare to 51 and get equal) -> change value back to 50 and the object will stay at that position.

 

Collisions can be done the same way, compare x and y coordinates, if the coordinates are the same (or within a certain range) there's a collision. I don't know any other way to do it. You could compare one coordinate first, if it isn't close, skip checking the other one.

 

 

When the object goes outside the screen it affects (one or both) the "palette setting columns" in the screen memory which apparently gets set to Black/white at that bar/bars.

 

If you'd like some more detailed help, let me know, I can assist you better if you share your code.

 

e5frog

Link to comment
Share on other sites

Theres not much to it other then the border and the sidebar, can't quite get the sprite to only move when it's reading the controller state and the collision isn't working, likes to go off the screen creating a black bar.

 

 

In Pac-Man we delete and redraw the sprite every update (and also the monsters).

 

As the position is stored in two registers (or copied into before being drawn) you can read those registers and compare the value to what the values are at your extreme values. If they're too much or too litte you change the register to the closest extreme value before redrawing again.

 

Like this:

Read controller

Delete object at current position

Change coordinate registers x, y (or however you set position) according to hand controller movement

Compare new values to extreme points

Change values if outside allowed values

Draw object at new or unchanged position

 

If you store the old position in other registers and delete object just before you redraw it at the new position you'll get less flicker.

 

Let's say you have coordinates x: [0,50] and y: [0,50], after a controller movement the x register is 51, you compare it to 50 and result is greater (or compare to 51 and get equal) -> change value back to 50 and the object will stay at that position.

 

Collisions can be done the same way, compare x and y coordinates, if the coordinates are the same (or within a certain range) there's a collision. I don't know any other way to do it. You could compare one coordinate first, if it isn't close, skip checking the other one.

 

 

When the object goes outside the screen it affects (one or both) the "palette setting columns" in the screen memory which apparently gets set to Black/white at that bar/bars.

 

If you'd like some more detailed help, let me know, I can assist you better if you share your code.

 

e5frog

Is there a complete build of Pacman? I'd like to see how you guys coded the logic for the ghosts in particular, I've got an enemy sprite defined just don't know how to call it within the game loop

 

Also heres my source so far (theres a bit of code commented out, havn't gotten those to work with the code yet)

mattscfgame.zip

Link to comment
Share on other sites

Is there a complete build of Pacman? I'd like to see how you guys coded the logic for the ghosts in particular, I've got an enemy sprite defined just don't know how to call it within the game loop

 

Also heres my source so far (theres a bit of code commented out, havn't gotten those to work with the code yet)

 

 

Thanks, I'll have a look at it later today.

 

There is a complete and almost fully working (I've detected some bugs at random times but not been able to reproduce them). I've tried to mimic the same monster-behaviour as the original Pac-man, calculating where to go next according to certain rules. I've tried studying the original code but as we don't use the same type of blocks and coordinates I couldn't use it straight off.

 

Adding an enemy also needs adding delete and redraw of the enemy, you could use the same sprite-draw routine if you copy the coordinates to a common register before deleting and redrawing it. You need to add enemy-update somewhere before or after updating your own player (if they're supposed to run at the same speed). Using the same technique, erasing, updating coordinates and then redraw. You also need to redraw any graphics that the enemy has collided with after erasing it - as for example other enemies or background graphics will also be deleted.

 

The enemy coordinates can be set to certain rules or read preset data to move the desired way. A first try could perhaps be just to make the enemy follow player x or/and y coordinates. Like Pac-man it could perhaps aim at a point near the player or similar...

 

I'll send you some code when I manage to get home to my own computer.

 

Happy coding!

 

/ e5frog

Link to comment
Share on other sites

First thing I noticed was this:

 

setupShip:
lisu	4
lisl	3
li	SHIP_START_X
lr	I, A
li	SHIP_START_Y
lr	I, A

li	000001
lr	I, A

li  0
lr	S, A

;setupAlien1:
;lisu	4
;lisl	3
;li	ALIEN1_START_X
;lr	I, A
;li	ALIEN1_START_Y
;lr	I, A

;li	000001
;lr	I, A

;li	0
;lr	S, A

 

You're loading the Alien coordinates into the same registers as the ship's coordinates (lisu 4; lisl 3 -> OCTAL:43)

As it's commented away I don't know if the code is actually updated, just wanted to point it out. ;-)

 

Same problem in the clearAlien1-routine it loads the same coordinates as the Ship.

 

If you're only going to have one image for the ship you can remove the animation of it, it saves CPU-time.

 

Another thought is that as you're using basically a square for the playfield you can remove all the tile-checking and implement boundary-checks instead - as I described earlier. Just check that the x and y coordinates don't pass the highest and lowest allowed values.

The whole checkIntersection-routine can be replaced by a simple boundary check.

 

To start with, using subroutines are very handy, but as the game progress and you might need to increase speed - removing them and writing it directly into the code speed things up. Also the pushk and popk routines are only necessary when using several subroutines "on top of eachother". These also use a lot of CPU-time.

 

To reduce sprite-flicker try to do as little as possible between erasing and redrawing the sprites. Perhaps reading the handcontroller can be done before erasing.

 

Set up a table with all registers you intend to use and for what they are used, like this:

 

; r0-r31	general-purpose registers
; r33		level number
; r34		(unused)
; r35		pac-man x coordinate
; r36		pac-man y coordinate
; r37		pac-man direction
; r38		animation index

 

Perhaps writing the numbers octally also will help keeping track of the correct registers. ;-)

Like your Ship coordinates starts at x: OCTAL 43 which is register 35, y: r 36 (octal 44)

 

You set the ISAR register with lisu (Load ISAR upper) and lisl, then the li A, I increases ISAR when you load A from the register ISAR points to.

 

 

 

I'll try it out in MESS when I get home. ;-)

Link to comment
Share on other sites

I've assembled it with dasm and tried to run it in MESS, but it didnt start up at all, didn't know why...

 

... until I remebered that I needed to "even off" the bin-size.

 

I added these two rows last in the program - evens out to full 1024 byte units:

 

	org [$800 + [XXXX * $400] -$1]

.byte 0

 

XXXX = 2 for a 2kByte file, 4 for a 4kB size file etc.

Blackbird has added his signature last in the code:

.byte "·Blackbird· 2006"

 

But then you need to increase the number of bytes you subtract from the org-statement above (subtracts only 1 byte).

 

 

 

I see the problem now, the Ship (and a good-looking ship it is) continues to float.... I'll check it out.

 

 

 

BTW

Here's the register table for Pac-man, variables are used together with a macro to set ISAR easily:

 

;---------------------------------------------------------------------------
; Register Reference 
;---------------------------------------------------------------------------

; The registers in the F8 are used as both RAM and registers for
; this game. The reference is as follows:

; score must have a 4 in the octal one's digit, to work with score.add
; registers 020 - 027

; hi-score is backed up in RAM, registers can be 
; used for other things inside the game loop

HISCORE_REG			=	020; #16
ATTACK_COUNTER_REG	=	020; #16
ATTACK_TIMER_REG		=	021; #17
GHOSTS_RELEASED_REG	=	022; #18
GHOST_RELEASE_TIMER_REG =	023; #19

SCORE_REG			=	024; #20

; pacman registers (must be in same octet)
PACMAN_X_REG		=	030; #24
PACMAN_Y_REG		=	031; #25
PACMAN_DIRECTION_REG	=	032; #26
PACMAN_ANIMINDEX_REG	=	033; #27

; ghost registers (must be in same octet)
GHOST_TMP_REG		=	034; #28
GHOST_TMP_X_REG		=	034; #28
GHOST_TMP_Y_REG		=	035; #29
GHOST_TMP_DIR_REG		=	036; #30		b7 nested, b6 nest.out
GHOST_TMP_ANIM_REG	=	037; #31

; ghost registers (040-057)
GHOST_REG		=	040	; #32
GHOST_0_X_REG	=	040	; #32
GHOST_0_Y_REG	=	041	; #33
GHOST_0_DIR_REG	=	042	; #34
GHOST_0_ANIM_REG	=	043	; #35
GHOST_1_X_REG	=	044	; #36
GHOST_1_Y_REG	=	045	; #37
GHOST_1_DIR_REG	=	046	; #38
GHOST_1_ANIM_REG	=	047	; #39
GHOST_2_X_REG	=	050	; #40
GHOST_2_Y_REG	=	051	; #41
GHOST_2_DIR_REG	=	052	; #42
GHOST_2_ANIM_REG	=	053	; #43
GHOST_3_X_REG	=	054	; #44
GHOST_3_Y_REG	=	055	; #45
GHOST_3_DIR_REG	=	056	; #46
GHOST_3_ANIM_REG	=	057	; #47

; level registers (must be in same octet)
LEVEL_NUMBER_REG	=	060	; #48
GHOST_NUMBER_REG	=	061	; #49
PACMAN_LIVES_REG	=	062	; #50		b7 pac collision, b6 player 1/2, b5 2ply game
GHOSTS_SLOW_REG	=	063	; #51		ghost off loop b7-6, slow ghost b5
POWERPELLETS_REG	=	063	; #51		bits 4-0
GHOST_EATABLE_REG	=	064	; #52		b0 G0, b1 G1, b2 G2, b3 G3
					;	upper four bits "is eaten"
SLOW_TIMER_REG	=	065	; #53
GLOBAL_TIMER_REG	=	066	; #54

BONUS_PRIZE_REG	=	067	; #55		keeps track of when bonus prize is plotted
BONUS_PRIZE_ON	=	070	; #56

;---------------------------------------------------------------------------

 

It helps when you are programming, keeping track of what the registers are used for.

 

Using the SETISAR dasm-macro by Blackbird makes it easier to set the ISAR:

 

;-------------------------
; SETISAR
; Original Author: Blackbird
; Sets the ISAR to a register number, using lisu and lisl
SETISAR	HISCORE_REG
MAC SETISAR
lisu	[[{1}] >> 3]
lisl	[[{1}] & %111]
ENDM

 

Then you simply write this in your code:

 

	SETISAR	HISCORE_REG

 

instead of

 

	lisu	2
lisl	0

 

Changing the ISAR a lot this helps.

 

;-)

Link to comment
Share on other sites

I manged to solve your problem. As I have understood it the Ship is only supposed to move left or right?

 

 

There's a lot of unused code that can be removed. ;-)

 

 

;-------------------------;
;=========================;
;    Channel Invaders     ;
;    by Matt Alexander    ;
;                         ;
;  code based on Pac-Man  ;
;   source by Blackbird   ;
;=========================;
;-------------------------;


processor f8

;=========;
; Equates ;
;=========;

;------------;
; BIOS Calls ;
;------------;
clrscrn         =       $00d0                                   ; uses r31
delay           =       $008f
pushk           =       $0107                                   ; used to allow more subroutine stack space
popk            =       $011e
drawchar        =       $0679

;-------------------;
; Color Definitions ;
;-------------------;
red             =       $40
blue            =       $80
green           =       $00
bkg             =       $C0

;-----------------;
; RAM Definitions ;
;-----------------;
ram		= 	$2800					; use Schach RAM to hold pellet info

;--------------------;
; Register Reference ;
;--------------------;

; The registers in the f8 are used as both RAM and registers for
; this game. The reference is as follows:
;
; r0-r31	general-purpose registers
; r33		level number
; r34		(unused)
; r35		pac-man x coordinate
; r36		pac-man y coordinate
; r37		pac-man direction
; r38		animation index

;---------------;
; Object Colors ;
;---------------;

SHIP_COLOR		    =	green
SCRN_BGCOLOR		=	bkg
SCRN_FGCOLOR		=	red
;BULLET_COLOR		=	red
SIDEBAR_COLOR		=	blue
ALIEN1_COLOR		=	green
ALIEN2_COLOR		=	blue
ALIEN3_COLOR		=	red

;------------------;
; Object Variables ;
;------------------;

SHIP_START_X		=	40
SHIP_START_Y		=	40
;ALIEN1_START_X		=	20
;ALIEN1_START_y      =	70

;===================;
; Main Program Code ;
;===================;

;---------------;
; Program Entry ;
;---------------;

org	$800

cartridgeStart:
.byte	$55, $00					; cartridge header

cartridgeEntry:
lis	0						; init the h/w
outs	1
outs	4
outs	5
outs	0
               
lisu	4						; r32 = complement flag
lisl	0
lr	S, A
               
li	$c6						; set to three color, grey background
lr	3, A						; clear screen to grey
pi	clrscrn						;

;---------------;
;main
;---------------;

mainloop:

startLevel:
; draw the map
pi	drawMap
; the sidebar
pi	drawSidebar
;pi	drawAlien1
;pi  setupAlien

setupShip:
lisu	4
lisl	3
li	SHIP_START_X
lr	I, A
li	SHIP_START_Y
lr	I, A

li	000001
lr	I, A

li  0
lr	S, A

;setupAlien1:
;lisu	4
;lisl	3
;li	ALIEN1_START_X
;lr	I, A
;li	ALIEN1_START_Y
;lr	I, A

;li	000001
;lr	I, A

;li	0
;lr	S, A

playLoop:
.clearShip:
li  SCRN_BGCOLOR
lr  1, A

lisu	4
lisl	3
lr	A, S
lr	2, A

lisl	4
lr	A, S
lr	3, A

lis 0
lr	4, A

pi drawSprite

;.clearAlien1:
;li	SCRN_BGCOLOR
;lr	1, A

;lisu	4
;lisl	3
;lr	A, S
;lr	2, A

;lisl	4
;lr	A, S
;lr	3, A

;lis 0
;lr	4, A

;pi drawSprite

.checkController:
pi  shipControls

.checkDirection:
;	pi  checkIntersection
;	ci  1
;	bnz .checkDirectionEnd

lisu	4
lisl	5
lr	A, S
ns  0
bnz .checkDirectionEnd
jmp .drawShip
.checkDirectionEnd:

.updateShipFrame:
lisu	4
lisl	6
lr	A, S
inc
ci	4
bnz .updateShipFrameEnd

li  0
.updateShipFrameEnd:
lr	S, A

.moveShip

lisu	4
lisl	5
lr	A, S
lr	0, A

ni  000010
bnz .moveShipLeft
;right
lr	A, 0
ni  000001
bnz .moveShipRight
;no movement
br	.moveShipEnd


.moveShipLeft:
lisl	3
ds	S
br	.moveShipEnd

.moveShipRight:
lisl	3
lr	A, S
inc
lr	S, A
br	.moveShipEnd
.moveShipEnd:





.drawShip:
lisl	5
lr	A, S

.drawShipIsDirectionRight:
ci	000001
bnz	.drawShipDirectionLeft
lis	13
br	.drawShipDirectionEnd

.drawShipDirectionLeft:
lis	9

.drawShipDirectionEnd:
lr	4, A

lisu	4
lisl    6
lr	A, S
lr	0, A
lr	A, 4
.drawShipGetAddress:
ds  0
bm	.drawShipGetAddressEnd
inc
br	.drawShipGetAddress
.drawShipGetAddressEnd:
lr	4, A

.drawShipSprite
li  SHIP_COLOR
lr	1, A
lisu	4
lisl	3
lr	A, I
lr	2, A
lr	A, S
lr	3, A
pi	drawSprite

;.checkAlien:
;pi	alienCheck

;.alienClearedCheck:
;dci ram

;li 35
;lr 0, A

;.alienClearedLoop:
;ds	0
;bm	.alienClearedEmpty

;lm
;ci	0
;bnz .alienClearedEnd
;br	.alienClearedLoop
;.alienClearedEnd:

.playLoopDelay:
lis 10
lr  5, A
pi	delay

jmp playLoop
.playLoopEnd:
jmp mainloop

endGame:
li	4
lr	0, A

.endGameLoop:
li	$ff
lr	1, A
li	250
lr	2, A
li	58
lr	3, A

.endGameLoops1:
li	$5f
lr	5, A
pi	delay

li	$0
lr	1, A
li	250
lr	2, A
li	58
lr	3, A

.endGameLoop2:
ds	3
bm	.endGameLoop2End
pi	plot
br	.endGameLoop2

.endGameLoop2End:

li	$5f
lr	5, A
pi	delay

.endGameLoopCheck:
ds	0
bnz	.endGameLoop

.endGameEnd:
jmp mainloop

;------------------
;Alien routines
;------------------

;nada

;------------------
;------------------

;controls
readController:
; see one of the hand controllers is moved
clr
outs	0
outs	4
ins	4
com							; un-invert port data
ni	$cf						; mask off twists, since we don't use them
bnz	.readControllerEnd
outs	1
ins	1
com
ni	$cf

lr	0, A

.readControllerEnd:
pop

shipControls:
lr	K, P
pi	pushk

pi  readController

;left
lr	A, 0
ni	000010
bnz .shipControlsCheckLeft
;right
lr	A, 0
ni	000001
bnz .shipControlsCheckRight
;no direction
clr
br	.shipControlsCheckEnd

.shipControlsCheckLeft:
li	000010
br	.shipControlsCheckEnd
.shipControlsCheckRight:
li	000001

.shipControlsCheckEnd:

lisu	4
lisl	5

lr	S, A						; store direction in O:45

.shipControlsEnd:

pi	popk
pk




;background crap

plot:
; set the color using r1
lr	A, 1
outs	1

; set the column using r2
lr	A, 2
ai	4
com
outs	4

; set the row using r3
lr	A, 3
ai	4
com
outs	5

; transfer data to the screen memory
li	$60
outs	0
li	$50
outs	0

; delay until it's fully updated
lis	6
.plotDelay:	
ai	$ff
bnz	.plotDelay

pop							; return from the subroutine

drawTile:
; registers reference:
; r1 = reserved (plot color)
; r2 = reserved (plot x)
; r3 = reserved (plot y)
; r4 = color 1
; r5 = color 2
; r6 = x
; r7 = y
; r8 = loop1 (row)
; r9 = loop2 (column)
; r10 = bitmask
; r11 = graphics byte

; save the return address
lr	K, P
pi	pushk

; get the tile address
dci	tiles
; add the offset
lr	A, 5
inc							; make sure we hit 0
lr	0, A
lis	3						; three bytes for each tile
.drawTileAddressLoop:
ds	0
bz	.drawTileAddressLoopEnd
adc
br	.drawTileAddressLoop
.drawTileAddressLoopEnd:
; got the tile data, now get the graphics address
lm
lr	Qu, A
lm
lr	Ql, A
lr	DC, Q

; rearrange the registers
lr	A, 4
lr	7, A
lr	A, 3
lr	6, A
lr	A, 2
lr	5, A
lr	A, 1
lr	4, A

; start row loop
li	8
lr	8, A
.drawTileRow:
; setup the bit mask
li	%10000000					; we only want the left-most pixel
lr	10, A						; store it in r10
; and get the graphics byte
lm							; load the pixel and increase the DC
lr	11, A						; store it in r11

; start column loop
li	8
lr	9, A
.drawTileColumn:

; find out the x address
lr	A, 9						; load the new offset
com							; and subtract it from 8
inc							; via 2's complement
ai	8						; subtract A from 8, ignore carry
as	6						; add the tile's real x offset
lr	2, A						; save it for the subroutine call
; and the y address
lr	A, 8						; load the new offset
com							; and subtract it from 8
inc							; via 2's complement
ai	8						; subtract A from 8, ignore carry
as	7						; add the tile's real y offset
lr	3, A						; save it for the subroutine call

; initially load color 2
lr	A, 5
lr	1, A
; see if the pixel is on or off
lr	A, 11						; load the byte
ns	10						; mask it with the bitmask
bnz	.drawTilePixel					; if the pixel's off, use color 1
; conditionally load color 1
lr	A, 4
lr	1, A

.drawTilePixel:
pi	plot

.drawTileRollBitmask:
; roll the bitmask
lr	A, 10
sr	1
lr	10, A

.drawTileCheckLoops:
; check column loop
ds	9
bnz	.drawTileColumn

; check row loop
ds	8
bnz	.drawTileRow

pi	popk
pk							; return from the subroutine

drawMap:
; this function uses several reserve registers
; because the functions called need the immediate ones
; r17 (21o) = x counter
; r18 (22o) = y counter

; load the return address into memory
lr	K, P
pi	pushk

; load the map address into DC1
dci	maze_map
xdc

; clear address offset
lisu	2
lisl	5
clr
lr	S, A

lisl	1						; 
lis	7						; load r17 with 7 rows of tiles
lr	S, A						;
.drawMapRow:

lisl	2						;
lis	10						; load r18 with 10 tiles per row
lr	S, A						;
.drawMapColumn:

; this is the start of drawing an individual tile

; note of reference to drawTile:
; r1 = color 1
; r2 = color 2
; r3 = x (to screen)
; r4 = y (to screen)
; r5 = tile number

lisl	2						; load register r20
lr	A, S
lr	0, A						; set r0 as our row counter
li	0						; clear A to the first pixel
.drawMapGetX:
ds	0
bz	.drawMapSaveX
ai	8
br	.drawMapGetX

.drawMapSaveX:
com							; we want to display the tiles from
inc							; top to bottom, so we inverse
ai	72						; both coordinates
lr	3, A						; store the x coordinate in r3

lisl	1						; load register r19
lr	A, S
lr	0, A						; set r0 as our column counter
li	0						; clear A to zero
.drawMapGetY:
ds	0
bz	.drawMapSaveY
ai	8
br	.drawMapGetY

.drawMapSaveY:
com							; we want to display the tiles from
inc							; top to bottom, so we inverse
ai	48						; both coordinates
lr	4, A						; store the y coordinate in r4

.drawMapSetupRegisters:

; this block of code gets the next tile number
; and increases the data offset

; swap DC0 and DC1
xdc
; get and save the next tile byte
lm
lr	5, A
; swap back
xdc

; set the colors
; color 1
li	SCRN_BGCOLOR
lr	1, A						; r1
; color 2
li	SCRN_FGCOLOR
lr	2, A						; r2

; finally, call the tile function
pi	drawTile

.drawMapCheckLoops:
; check column loop
lisu	2
lisl	2
ds	D						; r18
bnz	.drawMapColumn

; check row loop
ds	S						; r17
bnz	.drawMapRow

.drawMapReturn:
; return to the program flow
pi	popk
pk							; return from the subroutine

drawSprite:
; registers reference:
; r1 = reserved (plot color)
; r2 = reserved (plot x)
; r3 = reserved (plot y)
; r4 = color
; r6 = x
; r7 = y
; r8 = loop1 (row)
; r9 = loop2 (column)
; r10 = bitmask
; r11 = graphics byte

; save the return address
lr	K, P
pi	pushk

; get the tile address
dci	sprites
; add the offset
lr	A, 4
inc							; make sure we hit 0
lr	0, A
lis	2						; two bytes for each sprite
.drawSpriteAddressLoop:
ds	0
bz	.drawSpriteAddressLoopEnd
adc
br	.drawSpriteAddressLoop
.drawSpriteAddressLoopEnd:
; got the sprite data, now get the graphics address
lm
lr	Qu, A
lm
lr	Ql, A
lr	DC, Q

; rearrange the registers
lr	A, 3
lr	7, A
lr	A, 2
lr	6, A
lr	A, 1
lr	4, A

; start row loop
li	5
lr	8, A
.drawSpriteRow:
; setup the bit mask
li	%10000000					; we only want the left-most pixel
lr	10, A						; store it in r10
; and get the graphics byte
lm							; load the pixel and increase the DC
lr	11, A						; store it in r11

; start column loop
li	5
lr	9, A
.drawSpriteColumn:

; find out the x address
lr	A, 9						; load the new offset
com							; and subtract it from 5
inc							; via 2's complement
ai	5						; subtract A from 5, ignore carry
as	6						; add the tile's real x offset
lr	2, A						; save it for the subroutine call
; and the y address
lr	A, 8						; load the new offset
com							; and subtract it from 5
inc							; via 2's complement
ai	5						; subtract A from 5, ignore carry
as	7						; add the tile's real y offset
lr	3, A						; save it for the subroutine call

; see if the pixel is on or off
lr	A, 11						; load the byte
ns	10						; mask it with the bitmask
bz	.drawSpriteRollBitmask				; if the pixel's off, don't draw anything
; conditionally load color 1
lr	A, 4
lr	1, A

.drawSpritePixel:
pi	plot

.drawSpriteRollBitmask:
; roll the bitmask
lr	A, 10
sr	1
lr	10, A

.drawSpriteCheckLoops:
; check column loop
ds	9
bnz	.drawSpriteColumn

; check row loop
ds	8
bnz	.drawSpriteRow

.drawSpriteEnd:
pi	popk
pk							; return from the subroutine

;--------------;
; Draw Sidebar ;
;--------------;

; draws the right sidebar rectangle

drawSidebar:
; save return address
lr	K, P

; set sidebar color
li	SIDEBAR_COLOR
lr	1, A

; start row loop
li	57
lr	3, A
.drawSidebarRow:
li	101
lr	2, A
.drawSidebarColumn:
pi	plot

.drawSidebarCheck:
ds	2
lr	A, 2
xi	%01010000
bnz	.drawSidebarColumn
ds	3
bp	.drawSidebarRow

;.drawSidebarText:
;dci	scoreGraphic.parameters
;pi	blitGraphic
;dci	highGraphic.parameters
;pi	blitGraphic

.drawSidebarEnd:
pk

drawScore:
; save return address
lr	K, P
pi	pushk

; load colors
li	SIDEBAR_COLOR
lr	1, A
li	blue
lr	2, A

; load position
li	78
lr	10, A
lis	6
lr	11, A

; set number counter
lis	8
lr	0, A
; and ISAR
lisu	7
lisl	4

.drawScoreLoop:
; set DC
dci	numberGraphics

; load size
lis	3
lr	5, A
lis	5
lr	6, A

; load position
lr	A, 10
lr	3, A
lr	A, 11
lr	4, A

; see if the tile is even or odd
lis	1
ns	0
bz	.drawScoreShiftByte				; if even, branch

; get lower half-byte
lis	%1111
ns	I						; set ISAR to next byte
br	.drawScoreDrawDigit
.drawScoreShiftByte:
; get upper half-byte
lr	A, S
sr	4

.drawScoreDrawDigit:
; add tile offset
sl	1
adc
; and draw the number
;pi	blit

; increase x position
lis	4
as	10
lr	10, A						; each tile is three pixels + one pixel space

; decrease the counter
ds	0
bz	.drawScoreEnd					; reached the end, break
; check to see if we're on tile 4
lis	4
xs	0
bnz	.drawScoreLoop

.drawScoreChangeRow:
li	82
lr	10, A
lis	12
lr	11, A
br	.drawScoreLoop

.drawScoreEnd:
; return from subroutine
pi	popk
pk


;-----------;
; Tile Data ;
;-----------;

; format:
; two bytes for the address of the tile
; one byte for the boundaries of the tile (00 + up + down + left + right)

tiles:
; these are regular tiles
; which can be used in any map

; tile 0
.word	tilePic_0
.byte	001111

; tile 1
.word	tilePic_1
.byte	000101

; tile 2
.word	tilePic_2
.byte	000111

; tile 3
.word	tilePic_3
.byte	000011

; tile 4
.word	tilePic_4
.byte	000110

; tile 5
.word	tilePic_5
.byte	001001

; tile 6
.word	tilePic_6
.byte	001110

; tile 7
.word	tilePic_7
.byte	001011

; tile 8
.word	tilePic_8
.byte	001101



;---------------;
; Tile Graphics ;
;---------------;

tilePic_0:
.byte	000000
.byte	000000
.byte	000000
.byte	000000
.byte	000000
.byte	000000
.byte	000000
.byte	000000

tilePic_1:
.byte	000000
.byte	111111
.byte	%01000000
.byte	%01001111
.byte	%01010000
.byte	%01010000
.byte	%01010000
.byte	%01010000

tilePic_2:
.byte	000000
.byte	%11111111
.byte	000000
.byte	%11111111
.byte	000000
.byte	000000
.byte	000000
.byte	000000

tilePic_3:
.byte	000000
.byte	%11111110
.byte	000001
.byte	%11111001
.byte	000101
.byte	000101
.byte	000101
.byte	000101

tilePic_4:
.byte	000101
.byte	000101
.byte	000101
.byte	000101
.byte	000101
.byte	000101
.byte	000101
.byte	000101

tilePic_5:
.byte	000101
.byte	000101
.byte	000101
.byte	000101
.byte	%11111001
.byte	000001
.byte	%11111110
.byte	000000

tilePic_6:
.byte	%11111111
.byte	%10010011
.byte	111000
.byte	%01101100
.byte	%11000111
.byte	000000
.byte	%11111111
.byte	000000

tilePic_7:
.byte	%01010001
.byte	%01010001
.byte	%01010000
.byte	%01010000
.byte	%01001111
.byte	%01000000
.byte	111111
.byte	000000

tilePic_8:
.byte	%01010000
.byte	%01010000
.byte	%01010000
.byte	%01010000
.byte	%01010000
.byte	%01010000
.byte	%01010000
.byte	%01010000



;------------;
; Level Data ;
;------------;

maze_map:
; level map
.byte	1,  2,  2,  2,  2,  2,  2,  2,  2,  3
.byte	8,  0,  0,  0,  0,  0,  0,  0,  0,  4
.byte	8,  0,  0,  0,  0,  0,  0,  0,  0,  4
.byte	8,  0,  0,  0,  0,  0,  0,  0,  0,  4
.byte	8,  0,  0,  0,  0,  0,  0,  0,  0,  4
.byte	8,  0,  0,  0,  0,  0,  0,  0,  0,  4
.byte	7,  6,  6,  6,  6,  6,  6,  6,  6,  5



;----------------;
; Ship Sprites   ;
;----------------;

sprites:
.word	clearSprite					; sprite 0

.word	.shipSpritesLeft				; sprite 1
.word	.shipSpritesLeft+5				; sprite 2
.word	.shipSpritesLeft+10				; sprite 3
.word	.shipSpritesLeft+15				; sprite 4

.word	.shipSpritesRight				; sprite 5
.word	.shipSpritesRight+5				; sprite 6
.word	.shipSpritesRight+10			; sprite 7
.word	.shipSpritesRight+15			; sprite 8

.word	.shipSpritesUp
.word	.shipSpritesUp+5				
.word	.shipSpritesUp+10			
.word	.shipSpritesUp+15	

.word	.shipSpritesDown
.word	.shipSpritesDown+5				
.word	.shipSpritesDown+10			
.word	.shipSpritesDown+15

.word	.alien1SpritesUp
.word	.alien1SpritesUp+5
.word	.alien1SpritesUp+10
.word	.alien1SpritesUp+15

.word	.alien1SpritesDown
.word	.alien1SpritesDown+5
.word	.alien1SpritesDown+10
.word	.alien1SpritesDown+15

.word	.alien1SpritesLeft
.word	.alien1SpritesLeft+5
.word	.alien1SpritesLeft+10
.word	.alien1SpritesLeft+15

.word	.alien1SpritesRight
.word	.alien1SpritesRight+5
.word	.alien1SpritesRight+10
.word	.alien1SpritesRight+15

clearSprite:
; 5x5 block to clear
; a drawn sprite
.byte	%11111100
.byte	%11111100
.byte	%11111100
.byte	%11111100
.byte	%11111100

shipSprites:
.shipSpritesLeft:
; sprite 0
.byte	100000
.byte	100000
.byte	%01010000
.byte	%11111000
.byte	%10101000

; sprite 1
.byte	100000
.byte	100000
.byte	%01010000
.byte	%11011000
.byte	%10101000

; sprite 2
.byte	100000
.byte	100000
.byte	%01110000
.byte	%11011000
.byte	%10101000

; sprite 3
.byte	100000
.byte	100000
.byte	%01010000
.byte	%11011000
.byte	%10101000

.shipSpritesRight:
.byte	100000
.byte	100000
.byte	%01010000
.byte	%11111000
.byte	%10101000

; sprite 1
.byte	100000
.byte	100000
.byte	%01010000
.byte	%11011000
.byte	%10101000

; sprite 2
.byte	100000
.byte	100000
.byte	%01110000
.byte	%11011000
.byte	%10101000

; sprite 3
.byte	100000
.byte	100000
.byte	%01010000
.byte	%11011000
.byte	%10101000

.shipSpritesUp:
; sprite 0
.byte	100000
.byte	100000
.byte	%01010000
.byte	%11111000
.byte	%10101000

; sprite 1
.byte	100000
.byte	100000
.byte	%01010000
.byte	%11011000
.byte	%10101000

; sprite 2
.byte	100000
.byte	100000
.byte	%01110000
.byte	%11011000
.byte	%10101000

; sprite 3
.byte	100000
.byte	100000
.byte	%01010000
.byte	%11011000
.byte	%10101000
.shipSpritesDown:
.byte	100000
.byte	100000
.byte	%01010000
.byte	%11111000
.byte	%10101000

; sprite 1
.byte	100000
.byte	100000
.byte	%01010000
.byte	%11011000
.byte	%10101000

; sprite 2
.byte	100000
.byte	100000
.byte	%01110000
.byte	%11011000
.byte	%10101000

; sprite 3
.byte	100000
.byte	100000
.byte	%01010000
.byte	%11011000
.byte	%10101000

alien1Sprites:
.alien1SpritesUp:
;sprite 1
.byte   110000
   .byte   %01111000
   .byte   %10110100
.byte   %11111100
.byte   %01001000

;sprite 2
.byte   110000
   .byte   %01111000
   .byte   %10110100
.byte   %11111100
.byte   %10000100

;sprite 3
.byte   110000
   .byte   %01111000
   .byte   %10110100
.byte   %11111100
.byte   %01001000

;sprite 4
.byte   110000
   .byte   %01111000
   .byte   %11001100
.byte   %11111100
.byte   110000

.alien1SpritesDown:
;sprite 1
.byte   110000
   .byte   %01111000
   .byte   %10110100
.byte   %11111100
.byte   %01001000

;sprite 2
.byte   110000
   .byte   %01111000
   .byte   %10110100
.byte   %11111100
.byte   %10000100

;sprite 3
.byte   110000
   .byte   %01111000
   .byte   %10110100
.byte   %11111100
.byte   %01001000

;sprite 4
.byte   110000
   .byte   %01111000
   .byte   %11001100
.byte   %11111100
.byte   110000

.alien1SpritesLeft:
;sprite 1
.byte   110000
   .byte   %01111000
   .byte   %10110100
.byte   %11111100
.byte   %01001000

;sprite 2
.byte   110000
   .byte   %01111000
   .byte   %10110100
.byte   %11111100
.byte   %10000100

;sprite 3
.byte   110000
   .byte   %01111000
   .byte   %10110100
.byte   %11111100
.byte   %01001000

;sprite 4
.byte   110000
   .byte   %01111000
   .byte   %11001100
.byte   %11111100
.byte   110000

.alien1SpritesRight:
;sprite 1
.byte   110000
   .byte   %01111000
   .byte   %10110100
.byte   %11111100
.byte   %01001000

;sprite 2
.byte   110000
   .byte   %01111000
   .byte   %10110100
.byte   %11111100
.byte   %10000100

;sprite 3
.byte   110000
   .byte   %01111000
   .byte   %10110100
.byte   %11111100
.byte   %01001000

;sprite 4
.byte   110000
   .byte   %01111000
   .byte   %11001100
.byte   %11111100
.byte   110000

;score
scoreGraphic.parameters:
.byte	red			; color 1
.byte	bkg			; color 2
.byte	78			; x position
.byte	1			; y position
.byte	19			; width
.byte	4			; height
.word	scoreGraphic.data	; address for the graphics

scoreGraphic.data:
.byte	%01100110, %01001100, %11111001, 010101
.byte	%01010001, %10100010, %10110011, %01100011
.byte	100101, %01110000

highGraphic.parameters:
.byte	red			; color 1
.byte	bkg			; color 2
.byte	78			; x position
.byte	19			; y position
.byte	16			; width
.byte	4			; height
.word	highGraphic.data	; address for the graphics

highGraphic.data:
.byte	%10101110, %01101010
.byte	%10100100, %10001010
.byte	%11100100, %10101110
.byte	%10101110, %01101010

numberGraphics:
.byte	%11110110, %11011110				; 0
.byte	%01011001, 101110				; 1
.byte	%11100111, %11001110				; 2
.byte	%11100111, %10011110				; 3
.byte	%10110111, %10010010				; 4
.byte	%11110011, %10011110				; 5
.byte	%11110011, %11011110				; 6
.byte	%11100100, %10010010				; 7
.byte	%11110111, %11011110				; 8
.byte	%11110111, %10011110				; 9

org [$800 + [2 * $400] -$1]

.byte 0

 

 

 

It compiles allright and ship moves right or left only when you hold joystick that way.

To better understand the code you could try and add more comments.

Link to comment
Share on other sites

To set the boundaries you can add a check here:

 

.moveShipLeft:
lisl	3
ds	S
br	.moveShipEnd

.moveShipRight:
lisl	3
lr	A, S
inc
lr	S, A
br	.moveShipEnd
.moveShipEnd:

 

Like this:

.moveShipLeft:
lisl	3
li	5			; load A with 5 (minimum x-coordinate)
xs	S			; exclusive or with scratchpad -> returns zero if equal 
bz	.moveShipEnd
ds	S
br	.moveShipEnd

.moveShipRight:
lisl	3
lr	A, S
inc
lr	S, A
br	.moveShipEnd
.moveShipEnd:

 

 

Same procedure with the moveShipRight. ;-)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...