English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Asm / Hardware

 
 
Thread Tools
Old 05 April 2018, 17:43   #161
spudje
Registered User

 
Join Date: Dec 2014
Location: Netherlands
Posts: 919
Just out of curiosity, any progress?
spudje is offline  
Old 10 April 2018, 00:17   #162
Genlock
Out to Grass

Genlock's Avatar
 
Join Date: Jul 2010
Location: UK
Posts: 113
Quote:
Originally Posted by bloodline View Post
This is what I thought, my first build complained about windows missing a clib, so I statically compiled it into the application.

My first foray into the dark world of windows programming has been less than successful

I doing a massive code clean up now, so I will be able to easily switch out all my debugging printf() functions. Then the only external library calls will be SDL... what ch might work better on Windows.

Any luck with the clean up - or is it a total re-write ?
Genlock is offline  
Old 26 April 2018, 16:48   #163
bloodline
Registered User

bloodline's Avatar
 
Join Date: Jan 2017
Location: London
Posts: 168
Quote:
Originally Posted by Genlock View Post
Any luck with the clean up - or is it a total re-write ?
Apollogies for the lack of updates, I have been back at work since March so haven't had any time to work on it.

The clean up became a rewrite, as I was previously running all my timing from the pixel generation, but really that's the wrong way around (and really my emulator worked more by luck than design) and I've restructured it to be based around the DMA slots, which is a bit more difficult to make work as you have to priority sequence the memory accesses. To make this work I need to understand this diagram... which isn't super clear

bloodline is offline  
Old 11 May 2018, 14:10   #164
Genlock
Out to Grass

Genlock's Avatar
 
Join Date: Jul 2010
Location: UK
Posts: 113
Great to see you are still working on this,
i just wish i could help but its beyond my grey matter ..

I just love how you guys get stuck into these projects, Good luck !
Genlock is offline  
Old 26 October 2018, 22:21   #165
malko
Registered User

malko's Avatar
 
Join Date: Oct 2017
Location: CH
Posts: 1,220
Hope you are going well and that you had some time to spend on the project
malko is offline  
Old 09 February 2019, 23:20   #166
bloodline
Registered User

bloodline's Avatar
 
Join Date: Jan 2017
Location: London
Posts: 168
So, the project didn't die... I did a rewrite from scratch, with a proper DMA sequencer.

But for some reason it just wouldn't work, it would GURU during bootstrap.

I tracked the problem down to the memory sub system, so I just dropped in the original system, and the Emulator would boot, but without display. I tracked the problem down to my DMA sequenced Copper. So again I dropped in the original code and it booted with display. The problem with the old code it was it was hacked together and is hardcoded to get Kick 1.2 to boot, it won't boot any other ROM.

The problem I face at the moment is at some point (0xFC6CFC) an address of 0x0 is written to COP2LC, and then the copper (list @ 0x22F8) writes to COP2JMP... which causes the copper to write randomly to the Chipregs...

Don't know why it's doing this

Last edited by bloodline; 10 February 2019 at 01:10.
bloodline is offline  
Old 10 February 2019, 01:08   #167
bloodline
Registered User

bloodline's Avatar
 
Join Date: Jan 2017
Location: London
Posts: 168
So some more hacking around, it’s clear the Emulator is working (but without display), and my copper code seems to be running the copper list correctly... therefore I can only surmise that my beam counters are wrong.
It’s too late to try and think of some way to test my hypothesis tonight, but something about what I’m doing must be wrong.
bloodline is offline  
Old 11 February 2019, 01:14   #168
bloodline
Registered User

bloodline's Avatar
 
Join Date: Jan 2017
Location: London
Posts: 168
Reading through the HRM, I'm intrigued about the concept of "Long" lines and fields... I don't emulate this, not sure if that's going to cause problems...

here is a screenshot of the mess we have at the moment....
Attached Thumbnails
Click image for larger version

Name:	CopperProblems.png
Views:	88
Size:	38.2 KB
ID:	62024  
bloodline is offline  
Old 11 February 2019, 12:51   #169
bloodline
Registered User

bloodline's Avatar
 
Join Date: Jan 2017
Location: London
Posts: 168
Theory time:

My DMA sequencer is a relatively simple affair. It's a just a function table, with each entry a function pointer to a DMA slot function. One function from the table is called every system cycle. The function called is whatever value is in the low byte of vhposr (i.e. the horizontal beam position).

Every cycle the lower byte of vhposr is incremented, until it reaches 0xE3 (position 227), where it wraps back to 0 and increments the upper byte of vhposr by one (the vertical position), and the CIA B TOD counter is incremented.

Internally I store the upper byte of vhposr with more than 8bits (with only the lower 8bits 0 to 7 visible when reading vhposr, and bit 8 visible as bit 0 of vposr)... This sounds complicated, but it really isn't*.

When the upper byte (plus the extra bit of vposr) of vhposr reaches 0x106 (line 262 since I'm emulating a 200 line NTSC machine for now), The counter wraps back to 0, the CIA A TOD counter is incremented, and 0x8020 is written to the intreq register (to signal to the CPU a VBL as occurred). My internal copperPC is reloaded from Cop1Loc. This means the upper byte of vhposr, counts like this ...250, 251, 252, 253, 254, 255, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, etc... weird I know, but this behaviour should be familiar to Amiga programmers.


So all even entries (0,2,4,6 etc...) in the function table point to the same function. This function checks if the copper needs to use a memory cycle, if it does it calls the copper function and then returns, if the copper is currently waiting then the CPU is given the memory cycle. (I still use immediate blits so the blitter doesn't need the DMA at this time, blits happen as soon as the size register is filled).

The copper is implemented as function which returns TRUE if the copper used the DMA slot memory cycle and FALSE if it didn't.


quick psuedocodeish example:
Code:
bool copperExecute(){
	
	static int copperCycle = 0;
	static uint16_t IR1;
	static uint16_t IR2;

	switch(copperCycle){
	
		case 0:
			IR1 = chipramW[copperPC>>1];  // here the chipram is a word array, thus the CopperPC needs to be divided by 2
			IR1 = swap16(IR1);	// big endian to little endian swap
			copperCycle = 1;
			copperPC +=2;
			return TRUE;	The copper used this DMA slot so return true, and stop this slot being used by blitter or CPU.
			break;

		case 1:
			IR2 = chipramW[copperPC>>1]; 
			IR2 = swap16(IR2);	
			copperCycle = 2;
			copperPC +=2;
			return TRUE;	The copper used this DMA slot so return true, and stop this slot being used by blitter or CPU.
			break;

		case 2:
			copperCycle = 4;  //next copper execution cycle will default to the wait/skip instruction.
		
			//if bit 0 of IR1 = 0 then the next execution cycle will be the move instruction.
			if( (IR1 & 0x1)== 0){
				copperCycle = 3
			}

			return TRUE;	// not sure if the copper should burn up a DMA slot? But I assume it does. 
			break;

		case 3:
			chipramB[0xDFF000+IR1] = IR2	// write IR2 to the required chip register
			cycle = 0; 	// reset the coppercycle
			return TRUE;	// use this DMA slot
			break;

		case 4:
			//Copper doesn't execute when b15 IR2 is clear and blitter is busy.
			if( (IR2 & 0x8000)==0 && (dmaconr & 0x4000) ==1){
				return FALSE;
			}
			
			uint16_t compare = IR1 & 0xFFFE;  //mask out the instruction bit	
			uint16_t pos = vhposr & (IR2 & 0x7FFE); // mask out the evaluation bits.
			
			//is this a skip instruction?
			if( (IR2 & 0x1) ==1){
				
				if( pos >= compare){
					copperPC +=4;  //Skip the next 4 bytes
				}
				
				copperCycle = 0;	//reset the copperCycle and simply execute the next copper instruction.
				return FALSE		//shouldn't need to burn up the DMA slot.
			}
			
			//The copper wll now just wait until the below condition is true before advancing to the next instruction.
			if(pos >= compare){
				copperCycle =0;
			}

		return FALSE;	// a wait instruction shouldn't burn up a DMA slot.
		break;
	}

	//We should never get here;
	Return FALSE:
}
I believe the above code is correct... perhaps someone more familiar with the Copper could confirm my theory? (Edit, I think my evaluation bits code in the wait/skip instruction is wrong)...


All odd entries (1,3,5,7 etc...) in the function table point to a function to handle their specific DMA function (at the moment mostly just updating the bitplane registers and then when plane 1 dat is written, I dump out 16 chunky pixels to the host display buffer).

The bitplane functions don’t start fetching until the vpos vhposr position is greater than the vpos value in the diwstrt register, and the hpos vhposr position is greater than the dffstrt value. I don’t currently use the hpos in the diwstrt register.



*The vpos and hpos counters are actually 32bit, but these are only used internally. They are bitshfted and clipped to the relevant locations in the vposr and vhposr registers at the beginning of each DMA cycle. Only the vposr and vhposr registers are visible to the emulation.

Last edited by bloodline; 11 February 2019 at 15:20.
bloodline is offline  
Old 11 February 2019, 16:43   #170
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 43
Posts: 22,335
- MOVE to chipramB: B=byte? It should be word.
- Copper MOVE does the move to custom register in second cycle (write goes directly to selected register, not to copper instruction register), there is no 3rd cycle in MOVEs. (Instruction is "decoded" when first word of MOVE is read)
- SKIP does not actually skip anything but it isn't important normally.
- When WAIT starts, it requires DMA slot. (3rd cycle). Also not important now.
- CIA TOD counters don't increase exactly at the start of field/line but it also isn't important.
- long/short fields can be ignored for now.
- KS 1.x does few COPJMP2 writes before insert disk screen appears with COP2LC containing garbage. This usually won't cause problems (nothing is visible at this point anyway, just white screen) because if copper writes to "dangerous" register with COPCON=0: copper stops until next vblank. (Guess what happens if MOVE to "dangerous register" is "SKIP'd")
- How do you detect writes to strobe registers like COPJMPx?
- Almost all internal tests are equal comparisons (main exception is copper WAIT which is >=). For example if DDFSTRT==hpos: enable bitplane DMA for this scanline.

More later, maybe..
Toni Wilen is online now  
Old 11 February 2019, 17:24   #171
bloodline
Registered User

bloodline's Avatar
 
Join Date: Jan 2017
Location: London
Posts: 168
Quote:
Originally Posted by Toni Wilen View Post
- MOVE to chipramB: B=byte? It should be word.
chipramB[] and chipramW[] are both arrays to the same memory pointer. One is 16 bit one is 8 bit:

uint8_t chipramB[524288];
uint16_t* chipramW = (uint16_t*)chipramB;

A little hack so I can address the same memory as words or as bytes. Since the write to the register is byte addressed, I used the byte array. This hack works as long as addresses are word aligned...

the code I wrote here is just psuedo code, to actually write a word to that address I would do:

uint16_t* p = (uint16_t*)&chipramB[address];
*p = value;

In my real code, writes to the chipset address space actually go through a function to catch chipset registers addresses.

Quote:
- Copper MOVE does the move to custom register in second cycle (write goes directly to selected register, not to copper instruction register), there is no 3rd cycle in MOVEs. (Instruction is "decoded" when first word of MOVE is read)
Cheers! Does this mean the entire copper move instruction is completed in 3 system cycles? Read instruction/reg, wait for odd cycle to complete, read into custom chip register?

Quote:
- SKIP does not actually skip anything but it isn't important normally.
- When WAIT starts, it requires DMA slot. (3rd cycle). Also not important now.
I think my understanding of the enable bits with this instruction is wrong.

Quote:
- CIA TOD counters don't increase exactly at the start of field/line but it also isn't important.
- long/short fields can be ignored for now.
- KS 1.x does few COPJMP2 writes before insert disk screen appears with COP2LC containing garbage. This usually won't cause problems (nothing is visible at this point anyway, just white screen) because if copper writes to "dangerous" register with COPCON=0: copper stops until next vblank. (Guess what happens if MOVE to "dangerous register" is "SKIP'd")
This makes sense.

Quote:
- How do you detect writes to strobe registers like COPJMPx?
Writes to chip set registers are implemented as a function table (register address / 2), so writing to bpl2dat for example is a very simple function which updates the register value.

Writes to registers like intreq, are more complex functions which implements the bit set/clr function then write the result to the intreqr register (also sets the CPU int level).

So an attempt to write to one of the copjmp simply calls the function to reload my internal copperPC with the value of the correct coploc register. This happens immediately.

Quote:
- Almost all internal tests are equal comparisons (main exception is copper WAIT which is >=). For example if DDFSTRT==hpos: enable bitplane DMA for this scanline.

More later, maybe..
As always, I appreciate your support and assistance with this.

Last edited by bloodline; 11 February 2019 at 18:37.
bloodline is offline  
Old 12 February 2019, 16:51   #172
bloodline
Registered User

bloodline's Avatar
 
Join Date: Jan 2017
Location: London
Posts: 168
I have done very quick rewrite based upon Toni's comments.

The operation is now 2 (even) cycle, and locks out forbidden registers, freezing operation if a write attempt is made. A call to copjmp1 resets the copperCycle variable to 0 (as well as the copperPC to cop1loc), thus restarting the copper.

The copper and blitplane DMA now work! -edit - As a bonus, both Kick1.2 and Kick1.3 now work... Kick 3 just seems to get stuck in a loop.

Time to try and get the floppy working again... It was this which prompted the rewrite.

Toni, you added a command line option to save out the Raw MFM image to one of the WinUAE beta's for me, would that option be possible as a GUI feature? Cheers.

Code:
int copperExecute(){    
    if((chipset.dmaconr & 0x280) != 0x280){
        return 0;
    }
    
    switch(internal.copperCycle){
        case 0:
            internal.IR2 = 0; // DEbug clear the IR2 reg
            internal.IR1 = internal.chipramW[internal.copperPC>>1];
            internal.IR1 = (internal.IR1 <<8) | (internal.IR1 >>8);
            internal.copperPC += 2;
            internal.copperCycle = 1;
            
            if( (internal.IR1 & 0x1) == 0x1){
                internal.copperCycle = 2;
            }
            return 1;
            break;
            
        case 1:
            internal.IR2 = internal.chipramW[internal.copperPC>>1];
            internal.copperPC += 2;
            
            internal.IR1 = (internal.IR1 >> 1) & 255;   //  divide by 2 and mask out bad bits... 
            
            if(internal.IR1<0x20){internal.copperCycle = 4;return 0;};         //pause copper until ned vbl
            if(internal.IR1<0x40){internal.copperCycle = 4;return 0;};         //as above, but will add in a COPCON test later
            
            //Move
            internal.IR2 = (internal.IR2 <<8) | (internal.IR2 >>8);
            putChipReg16[internal.IR1](internal.IR2);
            internal.copperCycle = 0;
            return 1;
            break;
            
        case 2:
            internal.IR2 = internal.chipramW[internal.copperPC>>1];
            internal.copperPC += 2;
            
            internal.IR2 = (internal.IR2 <<8) | (internal.IR2 >>8);
            
            internal.copperCycle = 3;
            
            //Skip
            if( (internal.IR2 & 1) == 1){
                
                if( chipset.vhposr >= internal.IR1){
                    internal.copperPC +=4;
                }
                internal.copperCycle = 0;
            }
            
            return 1;
            break;
            
        case 3:
            
            //Wait
            if( chipset.vhposr >= internal.IR1){
                internal.copperCycle = 0;
            }
            
            break;
        case 4:
            //Copper operation frozen until next VBL
            break;
    }
    
    return 0;
}

Last edited by bloodline; 13 February 2019 at 15:51.
bloodline is offline  
Old 13 February 2019, 21:32   #173
yesplease
Registered User

yesplease's Avatar
 
Join Date: May 2012
Location: germany
Posts: 145
Hi bloodline,
that looks pretty amazing. It is quite entertaining to read through this story. ;-) Can we maybe also peek into the code to get a deeper, e.g. more complete understanding of this DMA sequencer? Are you maybe on GitHub with this Zorro baby ?

in any case very cool stuff... ;-)
yesplease is offline  
Old 13 February 2019, 23:25   #174
bloodline
Registered User

bloodline's Avatar
 
Join Date: Jan 2017
Location: London
Posts: 168
Quote:
Originally Posted by yesplease View Post
Hi bloodline,
that looks pretty amazing. It is quite entertaining to read through this story. ;-) Can we maybe also peek into the code to get a deeper, e.g. more complete understanding of this DMA sequencer? Are you maybe on GitHub with this Zorro baby ?

in any case very cool stuff... ;-)
Yes the clean up was so that I could put it on Github and hopefully have some help

I am happy to share the source code, but it is messy (the memory subsystem is an embarrassment, my clean elegant rewrite didn’t work), there a quite a few bit of test code in there as well, where I haven’t decided exactly how I want to approach the problem. My blitter code works but is clearly buggy (checkout the hand on the kickstart screen and also the intuition gfx), I hope a rewrite to use my new DMA sequencer will do that.

I am also happy to go into more detail on any question you have

Last edited by bloodline; 13 February 2019 at 23:53.
bloodline is offline  
Old Yesterday, 00:35   #175
Genlock
Out to Grass

Genlock's Avatar
 
Join Date: Jul 2010
Location: UK
Posts: 113
Looking good
Genlock is offline  
Old Yesterday, 10:08   #176
bloodline
Registered User

bloodline's Avatar
 
Join Date: Jan 2017
Location: London
Posts: 168
FYI, I'm just preparing the code for publishing on Github. I have decided to release it under the MPL 2.0 licence... Which I think is reasonable (though I'm not knowledgable about these things).

I spent yesterday trying to get the floppy emulation working, only to realise that it is almost certainly some tiny bug in my blitter code which is causing issue... The error is so subtle, it isn’t noticeable in graphics, but obviously even a single bit error will fail a disk load... So I need someone else to look it over now.

Last edited by bloodline; Yesterday at 10:20.
bloodline is offline  
Old Yesterday, 23:41   #177
bloodline
Registered User

bloodline's Avatar
 
Join Date: Jan 2017
Location: London
Posts: 168
The Github link for those interested...

https://github.com/h5n1xp/Omega

Oh yeah, I decided to call it Omega for public release, since Zorro already has meaning for us.

Last edited by bloodline; Today at 00:02.
bloodline is offline  
Old Today, 11:28   #178
deimos
Registered User

 
Join Date: Jul 2018
Location: Londonish / UK
Posts: 126
Quote:
Originally Posted by bloodline View Post
The Github link for those interested...

https://github.com/h5n1xp/Omega

Oh yeah, I decided to call it Omega for public release, since Zorro already has meaning for us.
What would someone need if they wanted to compile and run this themselves?
deimos is offline  
Old Today, 11:37   #179
bloodline
Registered User

bloodline's Avatar
 
Join Date: Jan 2017
Location: London
Posts: 168
Quote:
Originally Posted by deimos View Post
What would someone need if they wanted to compile and run this themselves?
There are no special compiler options needed, just compile all the source files, and link together with libSDL.

You will need an MFM ADF (WinUAE can produce these, see back down the thread where Toni added the command line option).

-edit-
I’m away from my laptop at the moment, but I will post my Linux build script later. It’s just one line this project will compile like compiling any SDL 2.0 code.

I had a bootable MFM ADF on my phone, so I’ve added it to the repository: raw2.adf Have fun guys

Last edited by bloodline; Today at 11:51.
bloodline is offline  
Old Today, 15:51   #180
Gorf
Registered User

 
Join Date: May 2017
Location: Munich/Bavaria
Posts: 708
Hi!

Did you hear about Michal Schulz' approach to bring AROS to the RasPI (big endian) und his new 68K-JIT?

The new (alpha) JIT is now reaching over 600MIPS on a RasPI3B+ and he was thinking of some kind of baremetal emulation layer himself:
"I need to complete this JIT ASAP and try to integrate it with AROS. Or maybe run the m68k JIT without any operating system directly on RasPi, as a bare metal kernel. What do you think?"

So maybe you both should talk?

https://www.patreon.com/posts/always-remember-24683131
Gorf is online now  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Amiga emulator for iOS steviebwoy support.OtherUAE 35 15 November 2014 11:14
Amiga emulator for a PSP? Vars191 support.OtherUAE 1 09 May 2010 03:08
Frederic's Emulator inside and Emulator thread Fred the Fop Retrogaming General Discussion 22 09 March 2006 08:31
ADF Files -> Amiga(amiga with dos Emulator) Schattenmeister support.Hardware 8 14 October 2003 01:10
Which Amiga emulator is best? Tim Janssen Amiga scene 45 15 February 2002 20:52

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 19:42.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, vBulletin Solutions Inc.
Page generated in 0.09148 seconds with 15 queries