Jump to content
IGNORED

writing an emulator.. color issues and more


miker00lz

Recommended Posts

i started writing a 2600 emulator the other day, and am having a weird issue with colors. first of all, the emu is FAR from done. the only TIA stuff it emulates now is playfield and player0/1. anyway, when i run the sample ROM posted in one of andrew davie's tutorials from here the colors look just fine:

 

atariemu3.png

 

 

but whenever i try to run any actual game ROMs, the graphics are in greyscale.. for example here's pitfall:

 

atariemu5.png

 

 

any idea what could possibly be causing this to occur? another problem i'm having is when running pacman and some other games, the picture doesn't stay vertically stable. it looks kind of like an old TV that has the v-hold set wrong.

 

thanks for any help!

Link to comment
Share on other sites

The ROMs work fine on real hardware so you'll have to explain what your emulation code is doing to get more helpful replies.

 

oh, wow i feel stupid... i just fixed it. i wasn't returning the color bit when SWCHB was read. i just needed to RTFM better.

 

atariemu6.png

 

 

as you can see in the pic, i've still got a few issues, the biggest one being that it's drawing that log too far from towards the left. i'm wondering if it could be an issue with my countdown timer emulation, where you can set 1/8/64/1024 intervals. here are some relative snippets from my code. pardon my BASIC! i'm doing it in FreeBASIC, because i think its a really useful language for experimenting with and prototyping programs before writing in C.

 

write to timer registers code:

    Case &h294 'set 1 clk interval
     timerint = 1
     timertemp = 0
     intim = value
   Case &h295 'set 8 clk interval
     timerint = 8
     timertemp = 0
     intim = value
   Case &h296 'set 64 clk interval
     timerint = 64
     timertemp = 0
     intim = value
   Case &h297 'set 1024 clk interval
     timerint = 1024
     timertemp = 0
     intim = value

 

and this code is from my exec6502 loop, where it adds clock counts to timertemp and handles the countdown:

timertemp = timertemp + Ticks(opcode)
If timertemp >= timerint Then
intim = intim - timertemp \ timerint
timertemp = timertemp - (timertemp \ timerint) * timerint
If intim < 0 Then intim = 256 + intim '< 0 so that intim doesn't wrap around until another cycle after reaching 0 
EndIf

 

and this is where it returns the countdown value when the timer register is read:

FUNCTION Read6502% (BYVAL addr AS LONG)
SELECT CASE addr
   Case &h282 'console switches
     Read6502% = 8 'this means use color, not B/W
     Exit Function
   Case &h284 'timer count read
     If intim < 0 Then Read6502% = 0 Else Read6502% = intim
     Exit Function 
   CASE IS >= &HE000&
     addr = &H1000 + (addr AND 4095)
END SELECT

Read6502% = ram(addr)
END FUNCTION

 

and here is my main execution loop:

DO
 Do
   ops = exec6502(1)  	 
 Loop Until vsync = 0 And (vblank And 2) = 0
 LOCATE 50, 20
 PRINT "Frame" + STR$(framenum);
 framenum = framenum + 1
 For curline = 0 To 39
   wsync = 0
   ops = exec6502(76)
 Next curline
 For curline = 0 TO 191
   LOCATE 50, 1
   PRINT "Scanline" + Str$(curline) + "   ";
   wsync = 0
   ops = exec6502(23)
   RenderScanline curline
 NEXT curline
 For curline = 192 To 221
   wsync = 0	 
   ops = exec6502(76)
   If vsync <> 0 Or vblank <> 0 Then Exit For
 Next curline
Loop UNTIL INKEY$ <> ""

 

and finally, my (still very incomplete) scanline render routine.. i know it's extremely inefficient, and i can see a lot of ways to change that but like i said i'm just doing this FreeBASIC version to experiment and learn right now:

Sub RenderScanline (ByVal curline As Integer)
   FOR drawx = 0 TO 159
   	If (drawx Mod 3) = 0 Then ops = exec6502(1)
   	If resp0 = -1 Then resp0 = drawx 'set player 0 horiz pos if reset was strobed
   	If resp1 = -1 Then resp1 = drawx 'set player 1 horiz pos if reset was strobed
     pfx = drawx \ 4
     If (ctrlpf And 1) = 1 And pfx > 19 Then
       Select CASE pfx
         Case 0 TO 3: pfreg = pf0: adjust = 0
     	  Case 4 TO 11: pfreg = pf1: adjust = 4
     	  Case 12 TO 19: pfreg = pf2: adjust = 12
         Case 20 TO 23: pfreg = pf2: adjust = 20
         Case 24 TO 31: pfreg = pf1: adjust = 24
         Case ELSE: pfreg = pf0: adjust = 32
       End Select
       Select CASE pfx - adjust
         Case 7: IF (pfreg AND 128) = 128 THEN curpix = colupf ELSE curpix = colubk
         Case 6: IF (pfreg AND 64) = 64 THEN curpix = colupf ELSE curpix = colubk
         Case 5: IF (pfreg AND 32) = 32 THEN curpix = colupf ELSE curpix = colubk
         Case 4: IF (pfreg AND 16) = 16 THEN curpix = colupf ELSE curpix = colubk
         Case 3: IF (pfreg AND  = 8 THEN curpix = colupf ELSE curpix = colubk
         Case 2: IF (pfreg AND 4) = 4 THEN curpix = colupf ELSE curpix = colubk
         Case 1: IF (pfreg AND 2) = 2 THEN curpix = colupf ELSE curpix = colubk
         Case 0: IF (pfreg AND 1) = 1 THEN curpix = colupf ELSE curpix = colubk
       End Select
     Else
       Select CASE pfx
         Case 0 TO 3: pfreg = pf0: adjust = 0
     	  Case 4 TO 11: pfreg = pf1: adjust = 4
     	  Case 12 TO 19: pfreg = pf2: adjust = 12
     	  Case 20 TO 27: pfreg = pf0: adjust = 20
     	  Case 28 TO 35: pfreg = pf1: adjust = 28
     	  Case ELSE: pfreg = pf2: adjust = 36
       End Select
       Select CASE pfx - adjust
     	  Case 0: IF (pfreg AND 128) = 128 THEN curpix = colupf ELSE curpix = colubk
     	  Case 1: IF (pfreg AND 64) = 64 THEN curpix = colupf ELSE curpix = colubk
     	  Case 2: IF (pfreg AND 32) = 32 THEN curpix = colupf ELSE curpix = colubk
     	  Case 3: IF (pfreg AND 16) = 16 THEN curpix = colupf ELSE curpix = colubk
     	  Case 4: IF (pfreg AND  = 8 THEN curpix = colupf ELSE curpix = colubk
     	  Case 5: IF (pfreg AND 4) = 4 THEN curpix = colupf ELSE curpix = colubk
     	  Case 6: IF (pfreg AND 2) = 2 THEN curpix = colupf ELSE curpix = colubk
     	  Case 7: IF (pfreg AND 1) = 1 THEN curpix = colupf ELSE curpix = colubk
       End Select
     End If

     	Select Case resp1 - drawx
     		Case 0: If (grp1 And 128) = 128 Then curpix = colup1
     		Case 1: If (grp1 And 64) = 64 Then curpix = colup1
     		Case 2: If (grp1 And 32) = 32 Then curpix = colup1
     		Case 3: If (grp1 And 16) = 16 Then curpix = colup1
     		Case 4: If (grp1 And  = 8 Then curpix = colup1
     		Case 5: If (grp1 And 4) = 4 Then curpix = colup1
     		Case 6: If (grp1 And 2) = 2 Then curpix = colup1
     		Case 7: If (grp1 And 1) = 1 Then curpix = colup1
     	End Select
     
     	Select Case resp0 - drawx
     		Case 0: If (grp0 And 128) = 128 Then curpix = colup0
     		Case 1: If (grp0 And 64) = 64 Then curpix = colup0
     		Case 2: If (grp0 And 32) = 32 Then curpix = colup0
     		Case 3: If (grp0 And 16) = 16 Then curpix = colup0
     		Case 4: If (grp0 And  = 8 Then curpix = colup0
     		Case 5: If (grp0 And 4) = 4 Then curpix = colup0
     		Case 6: If (grp0 And 2) = 2 Then curpix = colup0
     		Case 7: If (grp0 And 1) = 1 Then curpix = colup0
     	End Select

     scanline(drawx) = curpix
   NEXT drawx
   FOR dr = 0 TO 159
     LINE (dr * 4, curline*2)-STEP(3, 1), scanline(dr), bf
   NEXT dr
End Sub

 

 

also, should my TIA emulation be resuming the CPU from a wsync BEFORE the 23 hblank CPU cycles, or after that and right before the next 53 CPU cycles? this is what it looks like if i make that change:

 

atariemu7.png

 

 

 

i know this post is huge, if you're still with me thanks! :)

 

btw i am aware that i need to add support for reflecting the player graphics - just haven't done it yet.

Edited by miker00lz
Link to comment
Share on other sites

also, should my TIA emulation be resuming the CPU from a wsync BEFORE the 23 hblank CPU cycles, or after that and right before the next 53 CPU cycles?

Looking good so far!

 

WSYNC makes the CPU stop and then resume again at the leading edge of the HBLANK. The TIA keeps outputting its signal regardless, and as soon as the last playfield pixel on the current line has been drawn, the CPU will resume with the first cycle of the HBLANK (if it has been paused by WSYNC). Actually, WSYNC is slightly misnamed, because HSYNC doesn't start as soon as HBLANK begins, so it's really "wait for HBLANK," not "wait for HSYNC"-- but I guess WSYNC sounded better than WBLANK!

 

Michael

Link to comment
Share on other sites

  • 2 weeks later...

Looks like you are off to a good start. Emulating the 2600 is really tricky because you have to be so precise with your timing. One thing to remember about the RIOT timers is that they count down based on the interval, but when it reaches the end of the count and rolls over, it starts counting down again at an interval of 1.

Link to comment
Share on other sites

thanks for the comments and tips guys, i haven't been working on it as much as i'd like to due to being busy at work but i have not forgotten it. i'd love to get it playable. my NES emulator worked pretty well ( http://24.107.65.240/moarnes/ - unlike my atari emu, this one's written in C ) but yeah, the atari is quite a bit more tricky regarding the timing. i didn't expect it to be like that, although it makes sense considering the much more primitive video hardware vs. the NES.

 

very few NES games really need dead-on timing. most will work fine with it way off. my timing in it is fairly close, but i still have problems with marble madness and battletoads.

 

i've also been spending a lot of time working on my x86 PC emulator, Fake86.. yes i know i have too many projects at once! Fake86 is particularly fun to work on since the CPU core is actually written from scratch by me! it wasn't easy. and it has a few bugs, but it can run a BIOS and ROM BASIC. :lol:

Edited by miker00lz
Link to comment
Share on other sites

Not to be mean, but why write an emulator when Stella emulator already exists and works great? Why not put efforts into something else like designing something that isn't out there already or even a new 2600 game perhaps..

 

That's like saying why develop cars when the Ford Model T did the job ;). Programmer's like challenges. If writing an emulator is what floats your boat then write emulators. Contributing any projects to the retro scene is always a good thing in my opinion.

  • Like 2
Link to comment
Share on other sites

Not to be mean, but why write an emulator when Stella emulator already exists and works great? Why not put efforts into something else like designing something that isn't out there already or even a new 2600 game perhaps..

 

That's like saying why develop cars when the Ford Model T did the job ;). Programmer's like challenges. If writing an emulator is what floats your boat then write emulators. Contributing any projects to the retro scene is always a good thing in my opinion.

 

And miek's really into the retro stuff. I've seen pics of the breadboard he's building an XT clone on. xD And he's gotten an IRC client *and server* running on MS-DOS (he used to run his ircd off an XT).

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