Thaks for the tip with the add gate!!!
i tryed other gates as "bridge" because i noticed the same bug, but they dosn´t worked
(console returns error "compare string with number" or somthing like that)
I learned a lot from the simple screen tutorial. So I thought I'd complicate it a little and try to help more of you.
This tutorial will draw 4 walls on a digital screen then draw a ball bouncing around.
Here are the steps.The reason I used an arithmetic add chip is because going straight from the screen clk to the CPU port 3 doesn't work for me. I think there are a few bugs still floating around after the latest updates. So if you are trying something and it doesn't work, try experiment with different chips to get different results.
- Spawn 1 CPU, 1 Digital Screen (Preferably large monitor), 1 input and 1 Arithmetic Add
- Attach Screen Clk to Add
- Attach Add (A) to CPU Port 3
- Attach Screen Pixel G to CPU Port 2
- Attach Screen Pixel X to CPU Port 0
- Attach Screen Pixel Y to CPU Port 1
- Attach CPU Clk to Input
Now here's the Assembly code for the CPU. You can enter this in game or save it as a txt file and load it into the CPU list.
Save location for CPU files is in the directory Steam\steamapps\%username%\garrysmod\garrysmod\dat a\CPUChip\
After the code is entered or loaded in the Wire CPU menu, compile the code by updating the spawned CPU with the new code and check it has compiled OK in the console. If you are getting a huge amount of errors in the console, update the CPU again with the same code and recheck the console.Code://OUTPUTS //PORT 0 - PIXEL X coord to screen //PORT 1 - PIXEL Y coord //PORT 2 - PIXEL G 0=off 255=on //PORT 3 - SCREEN CLOCK=1 to enable drawing //----------------------- //DEFINE VARIABLES //----------------------- DATA; alloc cx;********//Clear X coord alloc cy;********//Clear Y coord //----------------------- //START PROGRAM //----------------------- CODE; //Draw Border Lines mov eax,0;********//Initial X Coord mov ebx,2;********//Y Border Coord 1 mov ecx,29;********//Y Border Coord 2 mov port0,eax;********//Output X to screen mov port1,ebx;********//Output Y1 to screen mov port2,255;********//Draw pixels mov port3,1;********//Allow Screen drawing lineloop1: ****mov port0,eax;****//Output X to screen ****mov port1,ebx;****//Output Y1 to screen ****mov port1,ecx;****//Output Y2 to screen ****inc eax;****//increase X Coord ****cmp eax,32;****// are we at 32? X range is 0-31 jne lineloop1;********// loop until we are at 32 mov eax,2;********//Initial Y Coord mov ebx,0;********//X Border Coord 1 mov ecx,31;********//X Border Coord 2 lineloop2: ****mov port1,eax;****//Output Y to screen ****mov port0,ebx;****//Output X1 to screen ****mov port0,ecx;****//Output X2 to screen ****inc eax;****//increase Y Coord ****cmp eax,29;****// are we at 29? Y range is 2-29 jne lineloop2;********// loop until we are at 29 //Init Ball mov eax,10;********//Ball X Coord mov ebx,10;********//Ball Y Coord mov ecx,1;********//Ball X direction mov edx,1;********//Ball Y direction mov esi,0;********//Store 0 into Registry esi dec esi;********//esi=-1 for reversing ball movements later //---------------------------------- //We need to disable screen drawing //while moving pixels diagonally to //avoid left over pixels on sides //---------------------------------- mov port3,0;********//Disable Screen drawing mov port0,eax;********//Output X coord mov port1,ebx;********//Output Y coord //---------------------------------- //Now the pixel is moved to its //final location we can start //drawing again. //---------------------------------- mov port3,1;********//Allow Screen drawing //Main Loop loop: ****mov #cx,eax;****//Store coords for clearing ****mov #cy,ebx; ****add eax,ecx;****//calculate new x coord ****add ebx,edx;****//calculate new y coord ****cmp eax,30;****//is x=30 /on border ****je revx;****//yes? reverse x ****cmp eax,1;****//is x=1 /on border ****je revx;****//yes? reverse x retx:************//return from reverse x ****cmp ebx,28;****//is y=28 /on border ****je revy;****//yes? reverse y ****cmp ebx,3;****//is y=3 /on border ****je revy;****//yes? reverse y rety:************//return from reverse y ****mov port3,0;****//Disable Screen drawing //---------------------------------- //We need to disable screen drawing //while moving pixels diagonally to //avoid left over pixels on sides //---------------------------------- ****mov port0,eax;****//Update X coord ****mov port1,ebx;****//Update Y coord ****mov port2,255;****//draw pixel at new coords //---------------------------------- //Now the pixel is moved to its //final location we can start //drawing again. //---------------------------------- ****mov port3,1;****//Allow Screen drawing ****mov port3,0;****//Disable Screen drawing ****mov port0,#cx;****//move to old X coord ****mov port1,#cy;****//move to old Y coord ****mov port2,0;****//Clear pixels ****mov port3,1;****//Allow Screen drawing jmp loop; revx: ****mul ecx,esi;****//Reverse X jmp retx; revy: ****mul edx,esi;****//Reverse Y jmp rety;
It helps when starting to run a debugger on the CPU to watch the error numbers and watch the port outputs.
Now enable the input to run the CPU.
If all goes well you should see the walls appear then the ball starts moving on the screen.
Any errors, feedback, tips, code optimization etc is greatly welcome as I am still learning this as well.
Hope this helps some of you.
Thaks for the tip with the add gate!!!
i tryed other gates as "bridge" because i noticed the same bug, but they dosn´t worked
(console returns error "compare string with number" or somthing like that)
Es gibt genau 10 Typen von Menschen auf der Welt. Welche die Binär verstehen und Welche die nicht.
(german)
STOP USING BMP FILES! USE JPEG FOR YOUR SAKE!!
Yeah, just recompile again by updating the CPU with the same code. Another bug I think.(console returns error "compare string with number" or somthing like that)[/b]
Let me know if it works and I'll add this to the tutorial.
Thanks.
I can't get any arithmetic functions to work![]()
How did you do it?
Nice code, maybe soon a physics engine in Garry's mod?!?!?
Are you aware that you should place "DATA" before variables, and "CODE" before the code, or else you will have to put the allocation on the end. The alloc macro writes zero on current address, and that may screw up your codeCode://OUTPUTS //PORT 0 - PIXEL X coord to screen //PORT 1 - PIXEL Y coord //PORT 2 - PIXEL G 0=off 255=on //PORT 3 - SCREEN CLOCK=1 to enable drawing //DEFINE VARIABLES alloc cx;********//Clear X coord alloc cy;********//Clear Y coord //Draw Border Lines mov eax,0;********//Initial X Coord mov ebx,2;********//Y Border Coord 1 mov ecx,29;********//Y Border Coord 2 mov port0,eax;********//Output X to screen mov port1,ebx;********//Output Y1 to screen mov port2,255;********//Draw pixels mov port3,1;********//Allow Screen drawing
Zero means program end opcode.
Also awesome program, why don't you make pong game with it?
Ah, thanks for your help Black. I love this mod of a mod of a mod !! AwesomeZero means program end opcode.
Also awesome program, why don't you make pong game with it?[/b]![]()
Is the lack of DATA and CODE the reason the program ends as soon as I run it the first time?
I'll fix it in the tutorial.
A question for you Black. When I store -1 in a registry (mov eax,-1, when I go to compile it says 'no such label on program line xx. It thinks the -1 is a reference to a label. Is there an easy way to store negative numbers. Or should I just use the method I have in my program?
Also, in the jump op-codes is there a Jump Subroutine op-code?
My aim is to make a pong eventually, but it will be pretty slow and difficult with the Digital Screen plugin as it is. If I increase the CPU frequency to 5000 as the program is now, the Digital Screen can't keep up and leaves pixels behind. I could increase program speed by spreading the pixel commands over the code to seperate them. That will give the screen time to recieve the data from the CPU.
Does anybody know if there is documentation for the digital screens? There may be some functions that I don't know about that could make it easier to program for.
@conman420, I don't quite understand what problem you are having. Do you mean with the CPU op-codes or the arithmetic add chip?
If you mean op-code arithmetic, it's quite simple.
There are 4 main registries in the CPU that can hold numbers...
eax ebx ecx edx
These can store numbers for use in arithmetic fuctions.
So to add 1 to eax just use inc eax;
To add 62 to eax use add eax,62;
To add 2 registries together use add ecx,eax;
The result is always stored in the first registry. So in the above example ecx gets the result of the add ecx and eax function.
Thanks I figured it out eventually, I was trying to add to ports together and eventually came up with this:
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-spacere;overflow:auto'>loop:
mov eax,port1
add eax,port2
mov port0,eax
jmp loop</div>
Thanks for your help. Also Gmod pong would be awesome! Though I do agree about the limitations of the screen may make it difficult.
There is an error in assembler, when it thinks that -1 is a reference to label. Right now no negative numbers are supported, and easiest way is toetc. This will be fixed in next version.Code:mov eax,0; sub eax,63;
Yes, the lack of code and data made your program to stop as soon as it was executed. But because errors do not trigger RESET, CPU state is saved, and it would execute at next opcode when run again. Thats why usually few more power ons, and it works.
There will be something new soon - programmable screen/GPU. In fact thats screen, which you can draw on, clientside. It will support direct memory access from CPU, so speed is not a problem.
BODYPRINT, there is a sub-routine call, it works like this:
Each time you do "CALL" it pushes current program location (IP) into stack. So beware of screwing up stack in function call, or before it.Code:call something; //Execute function "something" -----some code------ something: **-----some code------ ret; //Return from call
Yeah, I saw the 'CALL' op-code, but i was thinking more along the lines of...BODYPRINT, there is a sub-routine call, it works like this:
Each time you do "CALL" it pushes current program location (IP) into stack. So beware of screwing up stack in function call, or before it.[/b]Code:call something; //Execute function "something" -----some code------ something: **-----some code------ ret; //Return from call
Code:cmp eax,10;**** //compare eax with 10 jsre function;****//if equal then jump to subroutine labeled function -----continue code---- function: -----func code here----- ret; //Return to code after jump sub routine call
Bookmarks