ABA


"כמה שאלות לגבי גרפיקה (SVGA) ב-C:"
גירסת הדפסה        
קבוצות דיון פיתוח, תיכנות ובניית אתרים נושא #6771 מנהל    סגן המנהל    מפקח   Winner    צל"ש   מומחה  
אשכול מספר 6771
Dudenland

דרג אמינות חבר זה
   20:02   15.08.03   
אל הפורום  
  כמה שאלות לגבי גרפיקה (SVGA) ב-C:  
 
   קראתי קצת על המודים של VESA (הקרויים SuperVGA), ונתקלתי בכמה בעיות:

לפי מה שהבנתי, מצבי ה-SVGA דורשים כמות גדולה של זיכרון. נניח שאנו מתעסקים עם המוד: 640x480 (ב-256 צבעים). 256 צבעים, לוקחים 8 Bits, כלומר 1 Byte. לכן, כמות הזיכרון הדרושה למוד זה תהיה 640x480x1 = 307200. כמות זו גדולה בהרבה מכמות הזיכרון הפנויה לזיכרון המסך, שהיא כאמור עד למקסימום של 64KB (מתאימה למצב VGA 320x200 8 bits).

לכן, מחלקים את המסך ל-Banks, או Planes, כלומר לאיזורי זיכרון של 64KB (המקסימום), וכל פעם כשמציירים פיקסל על המסך, לפי המיקום של הפיקסל, מחשבים את האיזור שבו הוא צריך להיות לפי חלוקת ה-Banks, ומורים ל-BIOS לעדכן את הנקודה, לפי האיזור שבו היא נמצאת.

הבעיה שלי נובעת מכך שאני משתמש ב-Double Buffer, שאליו אני מעתיק את הפיקסלים, ולאחר סיום הסצנה, אני מעתיק (fmemcpy_) את התוכן של ה-Double Buffer לזיכרון של המסך.
אני מקבל רק איזור אחד, כלומר בערך רק רבע מן המסך.
ניסיתי להשתמש בלולאה שמשנה כל פעם את ה-Bank הנוכחי, עבור כל ה-Bankים, ואז אני מקבל את שאר האיזורים, אבל הם קטועים, כלומר רק שליש מכל איזור מצטייר.

אגב, כשאני לא משתמש ב-Double Buffer, ואני מצייר נקודה נקודה על המסך, אני מקבל את מה שרציתי, מפני שבפונקציה לציור נקודה, אני משנה את ה-Bank הנוכחי, לזה שבו נמצאת הנקודה.

למישהו יש הסבר או מדריך לשימוש ב-Double Buffer תחת SVGA?

Dudenland


                                שתף        
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד

  האשכול     מחבר     תאריך כתיבה     מספר  
  לא ממש ברור לי מה עשית ומה קורה, dryice 15.08.03 21:26 1
     את השימוש בבאפר אני כבר יודע. Dudenland 16.08.03 00:10 2
         לא חושב שהבנתי אותך, אבל ננסה: dryice 16.08.03 01:44 3
             אז ככה: Dudenland 16.08.03 14:55 4
                 חלון A זאת הכתובת 0xA000 יש גם חלון B dryice 16.08.03 15:40 5
                     כבר ניסיתי... Dudenland 16.08.03 16:46 6
                         אין לי פה דרך לבדוק את הקוד dryice 16.08.03 17:57 7
                             טוב.. אני מתחיל לעלות על כמה דברים... Dudenland 17.08.03 00:49 8

       
dryice

דרג אמינות חבר זה
   21:26   15.08.03   
אל הפורום  
  1. לא ממש ברור לי מה עשית ומה קורה,  
בתגובה להודעה מספר 0
 
   שימוש בDouble buffer לא צריך להיות בעיה, אתה בונה לך
buffer בזכרון וכותב אליו. ואז מעתיק מהBUFFER למסך בשלבים
מעתיק Bank ראשון ואז עובר לשני ומעתיק אותו וכן הלאה.
אם רק שליש מכל אזור מצויר למסך, כנראה המספר שנתת לBankswitch
הוא לא נכון.
כשאתה אומר שליש אתה מתכוון בדיוק שליש, או לפי העין בערך שליש
(ואלי דווקא רבע), נסה להכפיל בקבוע את המספרים שאתה שולח
להחלפת bank.

כמובן שאתה יכול להעלות את הקוד הרלוונטי.

שים לב שהגרעיניות של בחירת bank היא לאו דווקא 64Kb ויתכן
שבשביל להשיג בנקים לא חופפים צריך לקדם את מספר הבנק כל פעם
ב4 (או מספר אחר, תלוי במוד הספציפי)


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Dudenland

דרג אמינות חבר זה
   00:10   16.08.03   
אל הפורום  
  2. את השימוש בבאפר אני כבר יודע.  
בתגובה להודעה מספר 1
 
   במצב הגרפי הבסיסי VGA 13h, אין לי שום בעייה, והשתמשתי, כאמור, בבאפר חיצוני אליו אני מכניס נקודות. העדכון מתבצע כך שמועתק תוכנות של הבאפר אל כתובת המסך.

במקרה של VESA, זה לא כל כך הולך לי... כלומר אני לא כל-כך מבין את העניין של ה-Banks.
כשאני שם נקודות ישר לזיכרון המסך, אני משתמש בפונקציה שמעדכנת את ה-Bank המתאים, וזה עובד.

עכשיו, נניח שיש לי פונקציה שנקראת (set_bank(int, שמשנה את ה-bank הנוכחי.
ללא באפר, בכל נקודה שציירתי על המסך, חישבתי את ה-Bank שהיה עלי להגדיר, ושיניתי לפיו, והכל עבד מצויין.

כשיש לי באפר, ויש לי פונקציה שנקראת (update_buffer(void, שאומרה להציג את תוכן הבאפר על המסך, אז מה אני צריך לעשות?

בתחילה, פשוט העתקתי את כל תוכן הבאפר לזיכרון של המסך, ואז קיבלתי, כנראה, רק bank אחד. אחר כך, עשיתי לולאה שמעתיקה את כל תוכן הבאפר n פעמים, כאשר אני משנה את ה-Bank לפי n, וקיבלתי, כאמור, מין שורות (די עבות, כמו שציינתי, בערך 2/3 Bank... לפי ראות עיני, ולא במדוייק, וזה גם לא רלוונטי), בגובה של בערך 1/8 מגובה המסך, כל אחת... כאשר הן לא צמודות... כלומר, שורה בצבע כלשהו, שורה שחורה, שורה בצבע כלשהו, שורה שחורה...
אחר-כך ניסיתי ע"י הגדרת פוינטר לפוינטר שמצביע על הבאפר, שאותו אני מקדם כל פעם ב-64KB, ומעתיק לפי השיטה האחרונה רק את התוכן שבו... זה בכלל לא עבד.

בקיצור... איך צריכה להיות בנויה הפונקציה update_buffer?

תבנית:


void update_buffer(void)
{

while(inportb(INPUT_STATUS_0) & 8);
while(!(inportb(INPUT_STATUS_0) & 8));
.
.
.
setbank(איזשהו מספר);
.
.
.
_fmemcpy(video_mem, video_buffer, video_size);
}

בבקשה תעזרו לי...

Dudenland


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
dryice

דרג אמינות חבר זה
   01:44   16.08.03   
אל הפורום  
  3. לא חושב שהבנתי אותך, אבל ננסה:  
בתגובה להודעה מספר 2
 
   יש לך BUFFER אחד גדול שאתה הקצת ויש בו תמונה, עד כאן נכון.

בשביל להציג אותו על המסך אתה מתחיל ע"י לקבוע לבנק 0.
אז אתה מעתיק את ה64KB הראשונים של החוצץ שלך לזכרון
מסך, חלון A.
אז אתה קובע לבנק הבא שיהיה בנק k אתה מעתיק 64KB נוספים,
עובר לבנק 2k, עוד 64KB אז 3k עד שנגמר.

אני לא בטוח מה ערך k הנכון, אבל אני חושד שהוא 1,4 או 16
(כמעט בטוח שהוא חזקה של 2) תבדוק ערכים נוספים.

DRYICE



                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Dudenland

דרג אמינות חבר זה
   14:55   16.08.03   
אל הפורום  
  4. אז ככה:  
בתגובה להודעה מספר 3
 
   ערכתי לאחרונה בתאריך 16.08.03 בשעה 14:58 בברכה, Dudenland
 
יש לי באפר אחד גדול בגודל של 640x480, ויש בו תמונה, על כולו.
בשביל להציג אותו למסך, קבעתי פונקציה כזו:

void update_buffer(void)
{
int bank;

for(bank = 0; bank <= (video->size >> 16); bank++)
{
while(inportb(INPUT_STATUS_0) & 8);
while(!(inportb(INPUT_STATUS_0) & 8));

setbank(bank);

_fmemcpy(video_mem, video_buffer + (bank << 16), (1 << 16));
}
}


חשוב לציין כי:
video_mem הוא פוינטר לזיכרון המסך
video_buffer הוא פוינטר ל-Buffer
video הוא מצביע למבנה שבו שמורים הנתונים של המוד הגרפי (כמו size וכו')
setbank היא פונקציה שמשנה את ה-bank הנוכחי לזה שמוצב לה בפרמטר

כשאני מבצע את זה, אני לא מקבל כלום (המסך נשאר שחור).
ניסיתי לשחק קצת עם הגדלים... וכשאני מעתיק רק 64KB - 1, אני מקבל חלק מן התמונה בכל bank, אבל חלקו השני מופרע (כל מני צבעים רנדומליים... כמו רעש).

אגב, כשעשיתי את זה בלי באפר, אז ה-bank היה k (כלומר בהפרשים של 1).
אהה... ועוד משהו... מה זה חלון A (ראיתי את המושג הזה ב-Command Reference של VESA ולא כל-כך הבנתי מה זה)...

Dudenland


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
dryice

דרג אמינות חבר זה
   15:40   16.08.03   
אל הפורום  
  5. חלון A זאת הכתובת 0xA000 יש גם חלון B  
בתגובה להודעה מספר 4
 
   השימוש בחלון B הרבה פחות נפוץ.

ניסית לקחת את הקוד שלך כמו שהוא ולשנות:
setbank(bank*4) או לחילופין כפול 16 או מספרים אחרים.

DRYICE


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Dudenland

דרג אמינות חבר זה
   16:46   16.08.03   
אל הפורום  
  6. כבר ניסיתי...  
בתגובה להודעה מספר 5
 
   וגם אמרתי לך קודם, שכשצירתי נקודות, ישר לזיכרון של המסך (ללא buffer), חישבתי נכון את ה-bank, בדיוק כמו שאני מחשב פה...

אולי במקום לדבר בלי משמעות, אני אשים את ה-source:
http://rotter.net/User_files/nor/3f3e35372f5d2ffb.txt

בשביל הפשטות, שמתי רק קוד ש"צובע" את הבאפר בצבע מסוים (שמספרו 125), בפונקציה init_mode... (במקום לשים 0... בשביל ניקוי הבאפר)...

Dudenland


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
dryice

דרג אמינות חבר זה
   17:57   16.08.03   
אל הפורום  
  7. אין לי פה דרך לבדוק את הקוד  
בתגובה להודעה מספר 6
 
   ערכתי לאחרונה בתאריך 16.08.03 בשעה 18:10 בברכה, dryice
 
אז אני רק זורק ניחושים, יכול להיות שהדרך שלך לבדוק sync
עושה בעיות, רק בשביל הבדיקה, נסה לסלק את השורות:
while(inportb(INPUT_STATUS_0) & 8);
while(!(inportb(INPUT_STATUS_0) & 8));

DRYICE

נ.ב
מצורף קוד עתיק בפסקל ששרבטתי לפני שנים רבות,
מציג קובץ bmp במוד 101h
http://rotter.net/User_files/nor/3f3e48f7327d097d.txt
אולי יהיה לך איזה תועלת.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Dudenland

דרג אמינות חבר זה
   00:49   17.08.03   
אל הפורום  
  8. טוב.. אני מתחיל לעלות על כמה דברים...  
בתגובה להודעה מספר 7
 
   ראשית, יש הרבה בעיות עם הפונקציות לטיפול בזיכרון (()fmemset_, וכו') כשעובדים עם בלוקים של 64KB... זה תמיד הופך ל-0, כלומר לא מועתק שום דבר...
במקום, אני מחלק את המידע ל-2, ומעתיק חלק חלק...

שנית, יש לי בעייה נוספת עם צביעת נקודות מסוימות: בכל פעם שאני מציב ערך כלשהו, כלומר צבע, בנקודה מסויימת שבחישוב ה-offset שלה (המיקום בבאפר) מתקבל ערך הגדול מ-64KB, הערך מועתק גם למיקום (offset - 64KB), כלומר פעמיים.
עשיתי (printf("%d", offset וקיבלתי באמת ערך של (offset - 64KB), ואחר-כך עשיתי (printf("%ld", offset וקיבלתי את הערך הרצוי (לאחר חישוב חיצוני), כלומר התכנית מחשיבה את הערך גם כ-int וגם כ-long... אין לי פיתרון לזה, וזה נראה לי מאוד מוזר...

ביתיים אני עושה כל-מני נסיונות... עד-כה, ללא הצלחה... תוכל לעזור לי עם שתי הבעיות?

אגב, בדקתי שוב פעם, ואין בעיה עם ה-sync או עם ה-bank... הם מחושבים נכון... ולפי מה שראיתי, שונה ממה שבקוד פסקל שלך... שם יש קפיצות של 15, ופה יש קפיצות של אחד...

Dudenland


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד

תגובה מהירה  למכתב מספר: 
 
___________________________________________________________________

___________________________________________________________________
למנהלים:  נעל | תייק בארכיון | מחק | העבר לפורום אחר | מחק תגובות | עגן אשכול
       



© כל הזכויות שמורות ל-רוטר.נט בע"מ rotter.net