Jump to content
IGNORED

Can CP get overloaded?


Mike Harris

Recommended Posts

I was buzzing along last night....

 

Spending a good 11 hours making progress and everything then this racked my brain and progress came to a halt.

 

 

LD A, 1

 

CP 1
JR Z, ISIT_03S

JMP Goodies

 

CP 2

JR Z, ISIT_04S

ect...

ISIT_3S:

dostuff

 

Goodies:

blah blah

 

But no matter what I do, it will not pick 1 and goes strait to Goodies.

 

A = 1 so it should jump to ISIT_O3S

 

I was suspecting another jump over 127 or some deal but I could not find anything.

Link to comment
Share on other sites

Change the JR to JP to test your theory or use an assembler (I use TNIASM) that warns you if any of your JR statements are trying to jump too far.

Make sure nothing else is changing the value in A or the Z flag.

 

Now the argument JR vs JP:

JR - less rom/code space, but more cycles i.e. fetch PC, add offset

JP - more rom/code space, but less cycles i.e. set PC

So unless you are really desperate for space it's actually better (faster) to use JP.

And to be fair, only learnt that relatively recently myself :)

Link to comment
Share on other sites

I've tried pretty much everything and the routines work,
Just the CP statement isn't working and my mind fills in the blanks with maybe the compiler is being overloaded but every time my code screwed up it was because a previous CP went over 127 bytes.

 

All of this is part of the joystick routine and after sleeping for 12 hours I have a new mapping system that will ease room coordinates.

 

In any case this is the best If then Else that I am aware of in assembly.

I use TNIASM with Notepad ++ but I have not set it up for building and debugging.
Up until now it was just drag and drop.

I started using Sublime but I think it wanted me to buy it, register or something so I found Notepad working to my satisfaction.

 

As far as space, I am just over 6k for my rom with all environments defined.

Just trying to put the puzzle together.

Edited by Mike Harris
Link to comment
Share on other sites

Figured out a new mapping system that takes less checks and is based of a map table instead of checking room to room.

 

Now that I think about it an array works better.

Just keep your current position in a 1 byte ram location then check the table based on your current room number.
Based off the table you can determine the room you are traveling to once you hit the doorway.

Far simpler and less cpu intensive than what I was toying with.

My second issue will have to be fixed in post which is artifacts galore. I know has to be the NMI.

I draw the rooms on the fly and if I can't fix it I may go back to a simpler draw routine that doesn't use so many cycles.

 

I want to use as little rom as I can get away with to prove to myself I can but at the same time I want a quality game and I do have 32k to screw with.

 

At present I am still under 7k with only movement of players and sound to complete.

 

Total:

Rooms 30

NPC 04

Player 01

Objects you just have to find out.

Loot you just have to find out

Puzzles you just have to find out

 

The fun of discovery in a little over 6k so far.

Edited by Mike Harris
Link to comment
Share on other sites

Come on people, I need a different IF THEN ELSE Statement other than using CP

It sucks balls!

And the frustration is mounting.

bros it's new year's eve people will maybe check your post but i doubt they will take time to check their routine or post it... take a couple of beer tomorow it's another day.... cheers and happy new years to all of you guys who have the abilities to program games for the awesome colecovisiom

Link to comment
Share on other sites

I was buzzing along last night....

 

Spending a good 11 hours making progress and everything then this racked my brain and progress came to a halt.

 

 

LD A, 1

 

CP 1

JR Z, ISIT_03S

JMP Goodies

 

CP 2

JR Z, ISIT_04S

 

ect...

ISIT_3S:

dostuff

 

 

 

 

I would hope this is a mistype, but you spelled "ISIT_03S" wrong. Hopefully the compiler complains about missing labels? Certainly by the time it outputs a complete binary. Otherwise it probably entered that JR Z instruction with a 0 offset and added a fixup entry. If you use a compiler system that doesn't try to link to a single binary and just strips out the fixups, then you'd see a JR instruction that does not seem to be working since it just jumps to the next location.

 

Of course all of this is moot since you've found other ways to do this. But just thought I'd point that out.

Edited by ChildOfCv
Link to comment
Share on other sites

Thanks ChildofCV

I fixed all my jumps.

I rearranged my joystick routine, implemented a phenomenal mapping system which I am REALLY proud of and the only problems I have before I put characters on the screen is artifacting from the bugs in Colecovision that comes from the NMI.

 

So, I will be working on that before I put the NPC,s because I want a quality product in the end.

 

All logic is in place, all maps, all pattern data, I have wandered around my map which at present is 30 rooms.

 

Map logic is my greatest achievement in Assembly language where I defined one byte of RAM that holds current location and every time I enter a room it reads the location then checks a table with a room number and possible directions N,S,E,W.

So you can add as many rooms as can fit on a cartridge and it will call a routine that draws the room and updates your position.
The whole ROM so far is 5.82k

Now, if I can not fix my artifacting then I will have to cut back my VRAM writes which means sending larger graphic data at one time which means a larger ROM but I have 32k to play with so....

I am not sure how much sound data will be so at this point t will be a balancing act with the sound and video.

 

 

I have at least a 10 game list of ports and originality that is on my menu after this so I want to get as much out of this experience as I can.
All my titles have never been done on the Colecovision to my knowledge.

 

BTW, I got rid of all my JR Z and replaced them with JP Z but that was not my only problem. It was a combination that hopefully I will never make in the future again.

Quick tip. If you have a change to your code, do it in increments. It saves on debugging. Also make a lot of backups so you can revisit old code.
I make 4 backups on separate drives in case one dies.

52k of writing code and to have it lost due to a storm would send anyone up a wall.

 

If you come up with a cool routine.
Comment the crap out of it and save it in a separate library even if your game is changed and doesn't use it, you might want to use it down the road.

Edited by Mike Harris
Link to comment
Share on other sites

Thanks ChildofCV

 

I fixed all my jumps.

I rearranged my joystick routine, implemented a phenomenal mapping system which I am REALLY proud of and the only problems I have before I put characters on the screen is artifacting from the bugs in Colecovision that comes from the NMI.

Have your code to check the VDP interrupt flag before writing to VRAM, so you're not writing data near the end of the raster frame, causing the NMI to occur. The address of the status register is...

73C5 : VDP_STATUS_BYTE  Contents of default NMI handler
Link to comment
Share on other sites

 

In the TMS9918 book I gave you. Section 2.3 have information on the status register. You need to check the VDP status. This is the delay(1) module's code. This checks the VDP has finish drawing. You'll need this in your gameloop to keep the game running at 60 fps.

 

Source code for the delay function.

 

; delay.s

	.module delay

	; global from external code
	.globl  _nmi_flag

	; global from this code
	.globl  _delay
	; delay (unsigned icount)
	
	.area _CODE
_delay:
	pop     hl
	pop     de
	push    de
	push    hl
	ld      a,(#0x73c4)       ; check if NMI enabled
	and     #0x20
	jr      z,$3
$1:              
	ld      a,e             ; NMI enabled, check _nmi_flag
	or      d
	ret     z
	xor     a
	ld      (_nmi_flag),a
$2:      
	ld      a,(_nmi_flag)
	or      a
	jr      z,$2
	dec     de
	jr      $1
$3:      
	call    #0x1fdc           ; NMI disabled, check VDP status
$4:      
	ld      a,e
	or      d
	ret     z
$5:      
	call    #0x1fdc
	rlca
	jr      nc,$5
	dec     de
	jr      $4
Link to comment
Share on other sites

I appreciate the effort but you really have to learn Assembly, works so much better, faster and tighter code.

Yeah I should learn z80 assembly eventually then port all of my function I written in C over to that. I'm comfortable using C for Colecovision and IntyBASIC for Intellivision. Both of those uses interrupt or NMI which I don't know how to deal with in that language. I do know how to write assembly for the Atari 2600 though.

ALL fixed.

Cool. :thumbsup: I didn't want you to get frustrated and give up, but I do try to point you to the right direction. NMI is a tricky issue to solve for the Colecovision.

Link to comment
Share on other sites

So, according to the TI manual, the interrupt line is generated on each vertical refresh. Are there other times where the interrupt line is triggered?

 

If it's always during vertical refresh, then your main animation loop should be the NMI service routine. This establishes the proper timing and gives you an automatic window of undisturbed operations on the TI chip with minimal wait, if I read the manual correctly. Of course you only have 4.3ms of time to flirt with the TI on each interrupt, but you get it 50 times per second on PAL systems or 60 times per second on NTSC systems.

 

So if your NMI handler performs all the video updates first, it could theoretically do this with no fear of artifacts. If you have too many updates, you may need to keep a waiting list for the next interrupt cycle. Anyway, the remaining time could be spent doing non-graphical updates such as sound, and finally entering a HALT when you run out of things to update.

 

Is there something that would prevent this from working?

Link to comment
Share on other sites

No, you're pretty much correct, ChildOfCv.

 

Speaking generically here:

 

Since the vertical interrupt from the VDP is tied to the NMI, that means you need to work with it, not work around it.

 

There are really only two things you need to remember: the interrupt is periodic, and the interrupt is edge triggered.

 

Periodic means that if you know an interrupt /has just/ happened (whether by polling the VDP, or using the interrupt routine to set a flag), then you also know that you have a fixed number of milliseconds before it happens again. So for some tasks, it's safe to detect an NMI has occurred, and then do your VDP processing.

 

Edge Triggered means that once the interrupt triggers an NMI, it can NOT trigger another one until you clear it (by reading the VDP status register). This means you can put your VDP logic in the NMI handler and do as much work as you need to, knowing that another NMI won't interrupt you until you read the VDP status.

 

It's also possible to configure the VDP to NOT send interrupts to the Z80. It will still set the interrupt request bit in the status register, meaning you can configure it that way, and just poll when you are ready to. Be aware that since writing a VDP register takes two writes, you need to do it in one of the above ways to make sure it's not interrupted. ;)

 

Be aware that if you are polling the status register outside of the NMI, it probably won't do what you want. As soon as the bit is set, the interrupt line to the Z80 will immediately go active, taking control away from your program. If you somehow race it and get the bit before the Z80 acknowledges the interrupt... you'll also clear it. I don't know what the Z80 will do in that case, whether the interrupt is latched on receipt or only checked at pre-determined times. But most of the time, you probably won't get it unless the NMI handler does NOT clear it.

Link to comment
Share on other sites

Well Tony from Electric Adventures came to my rescue once more.

Going through his sample code I did have it right the first time because I used a function to disable NMI before my writes and everything went crazy.
So he told me that there was another part which was to re-enable them.

 

After I did that all my code works perfectly now.

 

So, my latest work is adding the loot, weapons, treasure or whatever and a pick up routine.

 

Pretty much everything is done as far as the graphics and mapping.

I now wander around a 30 room world with no issues, no lag, no artifacts, no getting stuck inside walls or barriers.

Still under 8k with all my pattern data defined, I just have to do a few things.

So, starting from 2 December last year and had to basically learn everything I would say that's not bad.

Edited by Mike Harris
Link to comment
Share on other sites

Finished a long night of coding.

 

Now, all objects in the game can be picked up and left in any room in the game.

If I leave the room it will be in the same exact spot as I left it unless it is animated.

 

It was a challenge and boiled down to better use of my ram tables.

 

 

Another challenge that I had to think about is to get rid of a sprite from the screen when you leave a room.

 

So started over with my mapping routine for objects and ended up saving a tremendous amount of cycles and a smaller rom. Still under 8k

 

Assembly Language is like a movie, every single thing on camera has to be built and arranged.

Edited by Mike Harris
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...